UNPKG

capsule-ai-cli

Version:

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

170 lines 8.46 kB
#!/usr/bin/env node import { Command } from 'commander'; import chalk from 'chalk'; import { startWindow } from './ui/window.js'; import { configManager } from './core/config.js'; import { authService } from './services/auth.js'; import { stateService } from './services/state.js'; import { contextManager } from './services/context.js'; const version = '0.1.5'; const program = new Command(); function getTimeAgo(date) { const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000); if (seconds < 60) return 'just now'; if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`; if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`; if (seconds < 604800) return `${Math.floor(seconds / 86400)}d ago`; return date.toLocaleDateString(); } async function main() { try { await configManager.loadConfig(); program .name('capsule') .description('') .version(version) .usage('[options]') .option('--resume', 'Resume the last conversation') .option('--continue', 'Choose from previous conversations to continue') .option('--model <model>', 'Set the model to use') .option('--provider <provider>', 'Set the provider to use') .option('--task <task>', 'Execute a task in micro mode') .option('--json', 'Output task results as JSON') .option('--timeout <seconds>', 'Task execution timeout in seconds'); await program.parseAsync(process.argv); const options = program.opts(); if (!options.dev) { const status = await authService.getStatus(); stateService.setLicenseStatus(status); } if (options.task) { const { executeTaskMode } = await import('./services/task-executor.js'); const result = await executeTaskMode({ task: options.task, model: options.model, provider: options.provider, json: options.json, timeout: options.timeout ? parseInt(options.timeout) : undefined }); process.exit(result.success ? 0 : 1); } if (options.model) { stateService.setModel(options.model); } if (options.provider) { stateService.setProvider(options.provider); } if (options.resume) { const contexts = contextManager.listContexts(); if (contexts.length > 0) { const mostRecent = contexts.sort((a, b) => b.created.getTime() - a.created.getTime())[0]; contextManager.setCurrentContext(mostRecent.id); console.log(chalk.green(`✓ Resumed last conversation from ${getTimeAgo(mostRecent.created)}\n`)); const context = contextManager.getCurrentContext(); console.log(chalk.dim(`Loaded ${context.messages.length} messages`)); console.log(chalk.dim(`Token count: ${context.metadata.totalTokens}\n`)); const messages = context.messages; const recentMessages = messages.slice(-3); if (recentMessages.length > 0) { console.log(chalk.dim('Recent messages:')); recentMessages.forEach(msg => { if (msg.role === 'user' || msg.role === 'assistant') { const role = msg.role === 'user' ? chalk.blue('You:') : chalk.green('Assistant:'); const content = typeof msg.content === 'string' ? msg.content : '(multimodal content)'; const preview = content.substring(0, 80) + (content.length > 80 ? '...' : ''); console.log(`${role} ${chalk.gray(preview)}`); } }); console.log(); } } else { console.log(chalk.yellow('No previous conversations found. Starting new chat.\n')); } } if (options.continue) { const contexts = contextManager.listContexts(); if (contexts.length > 0) { console.log(chalk.yellow('\nSelect a conversation to continue:\n')); const inquirer = (await import('inquirer')).default; const sortedContexts = contexts.sort((a, b) => b.created.getTime() - a.created.getTime()); const choices = sortedContexts.map((ctx, index) => { const currentContextId = contextManager.getCurrentContext().id; contextManager.setCurrentContext(ctx.id); const messages = contextManager.getCurrentContext().messages; const firstUserMsg = messages.find(m => m.role === 'user'); let contentStr = 'Empty conversation'; if (firstUserMsg) { if (typeof firstUserMsg.content === 'string') { contentStr = firstUserMsg.content; } else if (Array.isArray(firstUserMsg.content)) { const textContent = firstUserMsg.content.find((c) => c.type === 'text'); contentStr = textContent?.text || '[multimodal content]'; } else { contentStr = '[complex content]'; } } contextManager.setCurrentContext(currentContextId); const previewText = contentStr.substring(0, 50) + (contentStr.length > 50 ? '...' : ''); const timeAgo = getTimeAgo(ctx.created); return { name: `${index + 1}. ${previewText} ${chalk.dim(`(${ctx.messageCount} messages, ${timeAgo})`)}`, value: ctx.id }; }); choices.push({ name: chalk.gray('Cancel'), value: null }); const { selectedId } = await inquirer.prompt([{ type: 'list', name: 'selectedId', message: 'Choose a conversation:', choices, pageSize: 10 }]); if (selectedId) { contextManager.setCurrentContext(selectedId); const selected = contexts.find(c => c.id === selectedId); console.log(chalk.green(`\n✓ Resumed conversation from ${getTimeAgo(selected.created)}\n`)); const context = contextManager.getCurrentContext(); console.log(chalk.dim(`Loaded ${context.messages.length} messages`)); console.log(chalk.dim(`Token count: ${context.metadata.totalTokens}\n`)); const messages = context.messages; const recentMessages = messages.slice(-3); if (recentMessages.length > 0) { console.log(chalk.dim('Recent messages:')); recentMessages.forEach(msg => { if (msg.role === 'user' || msg.role === 'assistant') { const role = msg.role === 'user' ? chalk.blue('You:') : chalk.green('Assistant:'); const content = typeof msg.content === 'string' ? msg.content : '(multimodal content)'; const preview = content.substring(0, 80) + (content.length > 80 ? '...' : ''); console.log(`${role} ${chalk.gray(preview)}`); } }); console.log(); } } else { console.log(chalk.gray('\nStarting new conversation.\n')); } } else { console.log(chalk.yellow('No previous conversations found. Starting new chat.\n')); } } await startWindow(); } catch (error) { console.error(chalk.red('Error:'), error); process.exit(1); } } main().catch((error) => { console.error(chalk.red('Unhandled error:'), error); process.exit(1); }); //# sourceMappingURL=cli.js.map