UNPKG

capsule-ai-cli

Version:

The AI Model Orchestrator - Intelligent multi-model workflows with device-locked licensing

139 lines 5.51 kB
import React, { useState, useEffect } from 'react'; import { Box, useApp, useInput } from 'ink'; import { ConversationView } from './ConversationView.js'; import { InputBox } from './InputBox.js'; import { StatusBar } from './StatusBar.js'; import { CommandPalette } from './CommandPalette.js'; import { chatService } from '../../services/chat.js'; import { contextManager } from '../../services/context.js'; import { stateService } from '../../services/state.js'; import { v4 as uuidv4 } from 'uuid'; export const Prompt = () => { const { exit } = useApp(); const [messages, setMessages] = useState([]); const [currentInput, setCurrentInput] = useState(''); const [showCommandPalette, setShowCommandPalette] = useState(false); const [mode, setMode] = useState('chat'); const [isProcessing, setIsProcessing] = useState(false); const [terminalHeight, setTerminalHeight] = useState(process.stdout.rows || 24); useInput((input, key) => { if (key.ctrl && input === 'c') { exit(); } if (key.escape) { setShowCommandPalette(false); } }); useEffect(() => { const handleResize = () => { setTerminalHeight(process.stdout.rows || 24); }; process.stdout.on('resize', handleResize); return () => { process.stdout.off('resize', handleResize); }; }, []); useEffect(() => { const context = contextManager.getCurrentContext(); const loadedMessages = context.messages.map(msg => ({ id: uuidv4(), type: msg.role, content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content), timestamp: new Date() })); setMessages(loadedMessages); }, []); const handleInputChange = (input) => { setCurrentInput(input); if (input.startsWith('/')) { setShowCommandPalette(true); } else { setShowCommandPalette(false); } }; const handleSubmit = async (input) => { if (input.startsWith('/')) { return; } setCurrentInput(''); const userMessage = { id: uuidv4(), type: 'user', content: input, timestamp: new Date() }; setMessages(prev => [...prev, userMessage]); setIsProcessing(true); try { const assistantMessage = { id: uuidv4(), type: 'assistant', content: '', timestamp: new Date() }; setMessages(prev => [...prev, assistantMessage]); const stream = chatService.stream(input, { mode }); let fullContent = ''; for await (const chunk of stream) { if (chunk.delta) { fullContent += chunk.delta; setMessages(prev => prev.map(msg => msg.id === assistantMessage.id ? { ...msg, content: fullContent } : msg)); } } } catch (error) { const errorMessage = { id: uuidv4(), type: 'error', content: error.message, timestamp: new Date() }; setMessages(prev => [...prev, errorMessage]); } finally { setIsProcessing(false); } }; const handleCommandSelect = (command) => { setShowCommandPalette(false); setCurrentInput(''); switch (command) { case '/exit': exit(); break; case '/clear': setMessages([]); break; case '/new': const newContext = contextManager.createNewContext(); contextManager.setCurrentContext(newContext.id); setMessages([]); break; default: const systemMessage = { id: uuidv4(), type: 'system', content: `Command ${command} not yet implemented`, timestamp: new Date() }; setMessages(prev => [...prev, systemMessage]); } }; const statusBarHeight = 1; const inputBoxHeight = 3; const commandPaletteHeight = showCommandPalette ? 7 : 0; const conversationHeight = terminalHeight - statusBarHeight - inputBoxHeight - commandPaletteHeight - 2; const stats = contextManager.getContextStats(); const model = stateService.getModel(); const provider = stateService.getProvider(); const tokenLimit = contextManager.getTokenLimit(model); return (React.createElement(Box, { flexDirection: "column", height: terminalHeight }, React.createElement(ConversationView, { messages: messages, height: conversationHeight }), showCommandPalette && (React.createElement(CommandPalette, { query: currentInput, onSelect: handleCommandSelect, onClose: () => setShowCommandPalette(false) })), React.createElement(InputBox, { value: currentInput, onSubmit: handleSubmit, onChange: handleInputChange, placeholder: isProcessing ? "Processing..." : "Type a message or / for commands" }), React.createElement(StatusBar, { mode: mode, model: model, provider: provider, tokenCount: stats.tokenCount, tokenLimit: tokenLimit }))); }; //# sourceMappingURL=Prompt.js.map