/** * Interactive Chat Command */ import inquirer from 'inquirer'; import chalk from 'chalk'; import ora from 'ora'; import { OllamaClient, ConversationManager } from '@fsfalmansour/neohub-core'; import { ConfigManager } from './config'; import { formatMarkdown } from './utils/markdown'; import { AnalyticsService } from './services/analytics'; export class ChatSession { private ollama: OllamaClient; private conversation: ConversationManager; private config: ConfigManager; private analytics: AnalyticsService; constructor() { this.config = new ConfigManager(); this.ollama = new OllamaClient(this.config.getOllamaConfig()); this.conversation = new ConversationManager(); this.analytics = new AnalyticsService(); } /** * Start interactive chat session */ async start(): Promise { console.log(chalk.bold.cyan('\nšŸ¤– NeoHub Chat Session\n')); console.log(chalk.gray('Type your message and press Enter. Type "exit" or "quit" to end.\n')); // Check Ollama connection const healthCheck = ora('Checking Ollama connection...').start(); const isHealthy = await this.ollama.healthCheck(); if (!isHealthy) { healthCheck.fail(chalk.red('Ollama is not running. Please start Ollama and try again.')); return; } const config = this.ollama.getConfig(); healthCheck.succeed(chalk.green(`Connected to Ollama (Model: ${config.model})`)); // Main chat loop // eslint-disable-next-line no-constant-condition while (true) { const { message } = await inquirer.prompt<{ message: string }>([ { type: 'input', name: 'message', message: chalk.blue('You:'), validate: (input: string): string | boolean => input.trim().length > 0 || 'Message cannot be empty', }, ]); const trimmedMessage = message.trim(); // Check for exit commands if (['exit', 'quit', 'q'].includes(trimmedMessage.toLowerCase())) { console.log(chalk.yellow('\nšŸ‘‹ Goodbye!\n')); break; } // Handle special commands if (trimmedMessage.startsWith('/')) { this.handleCommand(trimmedMessage); continue; } // Send message to AI await this.sendMessage(trimmedMessage); } } /** * Send message and get response */ private async sendMessage(message: string): Promise { this.conversation.addUserMessage(message); const spinner = ora('Thinking...').start(); const startTime = Date.now(); const config = this.ollama.getConfig(); let success = false; try { const messages = this.conversation.getMessages(); const response = await this.ollama.chat(messages); spinner.stop(); const assistantMessage = response.message.content; this.conversation.addAssistantMessage(assistantMessage); console.log(chalk.bold.green('\nNeoHub:')); console.log(formatMarkdown(assistantMessage)); console.log(''); success = true; } catch (error) { spinner.fail(chalk.red('Error: ' + (error as Error).message)); throw error; } finally { // Track analytics this.analytics.trackCommand({ command: 'chat', timestamp: startTime, model: config.model, success, durationMs: Date.now() - startTime, }); } } /** * Handle special commands */ private handleCommand(command: string): void { const parts = command.slice(1).split(' '); const cmd = parts[0]; switch (cmd) { case 'clear': { this.conversation.clear(); console.log(chalk.green('āœ“ Conversation cleared\n')); break; } case 'history': { const history = this.conversation.getHistory(); console.log(chalk.bold('\nConversation History:\n')); history.forEach((msg, idx) => { const role = msg.role === 'user' ? chalk.blue('You') : chalk.green('NeoHub'); console.log(`${idx + 1}. ${role}: ${msg.content.substring(0, 100)}...\n`); }); break; } case 'export': { const exported = this.conversation.export(); console.log(chalk.green('āœ“ Conversation exported:\n')); console.log(exported); break; } case 'model': if (parts[1]) { this.ollama.setModel(parts[1]); this.config.setOllamaConfig({ model: parts[1] }); console.log(chalk.green(`āœ“ Model changed to: ${parts[1]}\n`)); } else { const config = this.ollama.getConfig(); console.log(chalk.blue(`Current model: ${config.model}\n`)); } break; case 'help': this.showHelp(); break; default: console.log(chalk.red(`Unknown command: ${cmd}\n`)); this.showHelp(); } } /** * Show help message */ private showHelp(): void { console.log(chalk.bold('\nAvailable Commands:\n')); console.log(chalk.cyan('/clear') + ' - Clear conversation history'); console.log(chalk.cyan('/history') + ' - Show conversation history'); console.log(chalk.cyan('/export') + ' - Export conversation to JSON'); console.log(chalk.cyan('/model [name]') + ' - View or change the model'); console.log(chalk.cyan('/help') + ' - Show this help message'); console.log(chalk.cyan('exit/quit') + ' - Exit the chat session\n'); } }