|
| 1 | +#!/usr/bin/env node |
| 2 | +/** |
| 3 | + * Demo: AI Code Assistant Interface |
| 4 | + * |
| 5 | + * This demo showcases the AICodeUI component which provides a claude-code style |
| 6 | + * terminal interface with: |
| 7 | + * - Diff-based rendering (minimal flicker) |
| 8 | + * - Scrollback preservation (committed messages stay in terminal history) |
| 9 | + * - Streaming text display for AI responses |
| 10 | + * - Line editor for user input |
| 11 | + * - In-app scrolling for chat history |
| 12 | + * |
| 13 | + * Run with: pnpm dev:ai-code |
| 14 | + */ |
| 15 | + |
| 16 | +import { createAICodeUI } from '../src/ui'; |
| 17 | +import { white, dim, cyan, green } from 'yanse'; |
| 18 | + |
| 19 | +const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); |
| 20 | + |
| 21 | +// Simulated AI responses based on user input |
| 22 | +const AI_RESPONSES: Record<string, string> = { |
| 23 | + 'hello': "Hello! I'm your AI coding assistant. I can help you with:\n\n- Writing and explaining code\n- Debugging issues\n- Refactoring suggestions\n- Git workflows\n- And much more!\n\nWhat would you like help with today?", |
| 24 | + |
| 25 | + 'help': "Here are some things you can ask me:\n\n1. 'explain [code]' - I'll explain how code works\n2. 'write [description]' - I'll write code for you\n3. 'debug [error]' - I'll help debug issues\n4. 'refactor [code]' - I'll suggest improvements\n\nJust type naturally and I'll do my best to help!", |
| 26 | + |
| 27 | + 'typescript': "TypeScript is a strongly typed programming language that builds on JavaScript. Here's a quick example:\n\n```typescript\ninterface User {\n name: string;\n age: number;\n}\n\nfunction greet(user: User): string {\n return `Hello, ${user.name}!`;\n}\n```\n\nKey benefits:\n- Type safety catches errors at compile time\n- Better IDE support with autocomplete\n- Self-documenting code through types", |
| 28 | + |
| 29 | + 'git': "Here are some useful git commands:\n\n```bash\n# Create a new branch\ngit checkout -b feature/my-feature\n\n# Stage and commit changes\ngit add .\ngit commit -m \"feat: add new feature\"\n\n# Push to remote\ngit push origin feature/my-feature\n\n# Create a PR (using gh cli)\ngh pr create --title \"My Feature\" --body \"Description\"\n```\n\nWant me to explain any of these in more detail?", |
| 30 | + |
| 31 | + 'default': "I understand you're asking about that. Let me think...\n\nBased on my analysis, here's what I can tell you:\n\n1. First, consider the context of your question\n2. Then, break down the problem into smaller parts\n3. Finally, apply the appropriate solution\n\nWould you like me to elaborate on any specific aspect?", |
| 32 | +}; |
| 33 | + |
| 34 | +/** |
| 35 | + * Get a response based on user input |
| 36 | + */ |
| 37 | +function getResponse(input: string): string { |
| 38 | + const lowerInput = input.toLowerCase(); |
| 39 | + |
| 40 | + for (const [key, response] of Object.entries(AI_RESPONSES)) { |
| 41 | + if (key !== 'default' && lowerInput.includes(key)) { |
| 42 | + return response; |
| 43 | + } |
| 44 | + } |
| 45 | + |
| 46 | + return AI_RESPONSES['default']; |
| 47 | +} |
| 48 | + |
| 49 | +/** |
| 50 | + * Simulate streaming text character by character |
| 51 | + */ |
| 52 | +async function streamResponse(ui: ReturnType<typeof createAICodeUI>, text: string): Promise<void> { |
| 53 | + ui.startStream('assistant'); |
| 54 | + |
| 55 | + const words = text.split(' '); |
| 56 | + |
| 57 | + for (let i = 0; i < words.length; i++) { |
| 58 | + const word = words[i]; |
| 59 | + |
| 60 | + // Stream word character by character for realistic effect |
| 61 | + for (const char of word) { |
| 62 | + ui.appendStream(char); |
| 63 | + await sleep(15 + Math.random() * 25); // Variable typing speed |
| 64 | + } |
| 65 | + |
| 66 | + // Add space after word (except last) |
| 67 | + if (i < words.length - 1) { |
| 68 | + ui.appendStream(' '); |
| 69 | + await sleep(10); |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + // Small delay before ending stream |
| 74 | + await sleep(100); |
| 75 | + ui.endStream(); |
| 76 | +} |
| 77 | + |
| 78 | +/** |
| 79 | + * Main demo function |
| 80 | + */ |
| 81 | +async function main() { |
| 82 | + // Print welcome banner (this goes to scrollback) |
| 83 | + console.log('\n' + white('═'.repeat(60))); |
| 84 | + console.log(white(' AI Code Assistant Demo')); |
| 85 | + console.log(white(' Powered by inquirerer ViewportRenderer')); |
| 86 | + console.log(white('═'.repeat(60))); |
| 87 | + console.log(dim(' This demo showcases diff-based terminal rendering')); |
| 88 | + console.log(dim(' with scrollback preservation.')); |
| 89 | + console.log(''); |
| 90 | + console.log(cyan(' Commands:')); |
| 91 | + console.log(dim(' - Type a message and press Enter to chat')); |
| 92 | + console.log(dim(' - Use UP/DOWN arrows to scroll through history')); |
| 93 | + console.log(dim(' - Press Ctrl+C to exit')); |
| 94 | + console.log(''); |
| 95 | + console.log(green(' Try: "hello", "help", "typescript", or "git"')); |
| 96 | + console.log(white('═'.repeat(60)) + '\n'); |
| 97 | + |
| 98 | + // Create the AI Code UI |
| 99 | + const ui = createAICodeUI({ |
| 100 | + title: 'AI Code Assistant', |
| 101 | + promptPrefix: '> ', |
| 102 | + viewportHeight: 14, |
| 103 | + |
| 104 | + onSubmit: async (input) => { |
| 105 | + // Simulate thinking delay |
| 106 | + await sleep(300 + Math.random() * 500); |
| 107 | + |
| 108 | + // Get and stream the response |
| 109 | + const response = getResponse(input); |
| 110 | + await streamResponse(ui, response); |
| 111 | + }, |
| 112 | + |
| 113 | + onExit: () => { |
| 114 | + console.log('\n' + dim('Goodbye! Thanks for trying the AI Code Assistant demo.') + '\n'); |
| 115 | + process.exit(0); |
| 116 | + }, |
| 117 | + }); |
| 118 | + |
| 119 | + // Start the UI |
| 120 | + ui.start(); |
| 121 | + |
| 122 | + // Add initial system message |
| 123 | + ui.addMessage('system', 'Welcome! Type a message below to start chatting.'); |
| 124 | +} |
| 125 | + |
| 126 | +// Run the demo |
| 127 | +main().catch(err => { |
| 128 | + console.error('Error:', err); |
| 129 | + process.exit(1); |
| 130 | +}); |
0 commit comments