// ─── Chat Command ─────────────────────────────────────────────────────────── import { createInterface } from 'readline'; import { createRuntime } from '../state/factory.js'; import { EventRenderer } from '../renderers/index.js'; import type { Message } from '../../core/provider/index.js'; import { now, type HarnessEvent } from '../../core/events/index.js'; export async function chatCommand(opts: { provider: string; model?: string; skills: string[]; verbose?: boolean; compact?: boolean; }): Promise { const renderer = new EventRenderer({ verbose: opts.verbose ?? false, compact: opts.compact ?? false }); const { runtime, eventBus, provider } = await createRuntime(opts); eventBus.on((event) => renderer.render(event)); const rl = createInterface({ input: process.stdin, output: process.stdout }); const prompt = () => new Promise((resolve) => rl.question('\x1b[36m❯\x1b[0m ', resolve)); console.log(`\x1b[90mProvider: ${provider.label} | Type your message (Ctrl+C to exit)\x1b[0m\n`); const messages: Message[] = [{ role: 'system', content: 'You are a helpful AI assistant with access to tools.' }]; while (true) { const input = await prompt(); if (!input.trim()) continue; if (input.trim() === '/quit' || input.trim() === '/exit') break; messages.push({ role: 'user', content: input }); eventBus.emit({ type: 'model.request.start', provider: provider.id, model: opts.model ?? 'default', timestamp: now() }); const startMs = Date.now(); try { for await (const event of provider.stream({ model: opts.model ?? (await provider.listModels())[0]!.id, messages, tools: runtime ? undefined : undefined, // Tools available through runtime })) { if (event.type === 'text-delta') { process.stdout.write(event.text); } else if (event.type === 'finish') { const durationMs = Date.now() - startMs; eventBus.emit({ type: 'model.request.end', provider: provider.id, model: opts.model ?? 'default', usage: event.result.usage, durationMs, timestamp: now() }); messages.push({ role: 'assistant', content: event.result.content }); if (!event.result.content.endsWith('\n')) process.stdout.write('\n'); } } } catch (err) { const errMsg = err instanceof Error ? err.message : String(err); console.error(`\x1b[31mError: ${errMsg}\x1b[0m`); } console.log(); } rl.close(); console.log('\x1b[90mGoodbye.\x1b[0m'); process.exit(0); }