brainy/dist/chat/ChatCLI.js
David Snelling f8c45f2d8d Initial commit: Brainy - Multi-Dimensional AI Database
Open source vector database with HNSW indexing, graph relationships,
and metadata facets. Features CLI with professional augmentation registry
integration for discovering extensions and capabilities.
2025-08-18 17:35:06 -07:00

351 lines
No EOL
16 KiB
JavaScript

/**
* ChatCLI - Command Line Interface for BrainyChat
*
* Provides a magical chat experience through the Brainy CLI with:
* - Auto-discovery of previous sessions
* - Intelligent context loading
* - Multi-agent coordination support
* - Premium memory sync integration
*/
import { BrainyChat } from './BrainyChat.js';
// Simple color utility without external dependencies
const colors = {
cyan: (text) => `\x1b[36m${text}\x1b[0m`,
green: (text) => `\x1b[32m${text}\x1b[0m`,
yellow: (text) => `\x1b[33m${text}\x1b[0m`,
blue: (text) => `\x1b[34m${text}\x1b[0m`,
gray: (text) => `\x1b[90m${text}\x1b[0m`,
red: (text) => `\x1b[31m${text}\x1b[0m`
};
export class ChatCLI {
constructor(brainy) {
this.brainy = brainy;
this.brainyChat = new BrainyChat(brainy);
}
/**
* Start an interactive chat session
* Automatically discovers and loads previous context
*/
async startInteractiveChat(options) {
console.log(colors.cyan('🧠 Brainy Chat - Local Memory & Intelligence'));
console.log();
let session = null;
if (options?.sessionId) {
// Load specific session
session = await this.brainyChat.switchToSession(options.sessionId);
if (session) {
console.log(colors.green(`📂 Loaded session: ${session.title || session.id}`));
console.log(colors.gray(` Created: ${session.createdAt.toLocaleDateString()}`));
console.log(colors.gray(` Messages: ${session.messageCount}`));
}
else {
console.log(colors.yellow(`⚠️ Session ${options.sessionId} not found, starting new session`));
}
}
else if (!options?.newSession) {
// Auto-discover last session
console.log(colors.gray('🔍 Looking for your last conversation...'));
session = await this.brainyChat.initialize();
if (session) {
console.log(colors.green(`✨ Found your last session: ${session.title || 'Untitled'}`));
console.log(colors.gray(` Last active: ${session.lastMessageAt.toLocaleString()}`));
console.log(colors.gray(` Messages: ${session.messageCount}`));
// Show recent context if memory option is enabled
if (options?.memory !== false) {
await this.showRecentContext();
}
}
else {
console.log(colors.blue('🆕 No previous sessions found, starting fresh!'));
}
}
if (!session) {
session = await this.brainyChat.startNewSession(`Chat ${new Date().toLocaleDateString()}`, ['user', options?.speaker || 'assistant']);
console.log(colors.green(`🎉 Started new session: ${session.id}`));
}
console.log();
console.log(colors.gray('💡 Tips:'));
console.log(colors.gray(' - Type /history to see conversation history'));
console.log(colors.gray(' - Type /search <query> to search all conversations'));
console.log(colors.gray(' - Type /sessions to list all sessions'));
console.log(colors.gray(' - Type /help for more commands'));
console.log(colors.gray(' - Type /quit to exit'));
console.log();
console.log(colors.blue('🚀 Want multi-agent coordination? Try: brainy cloud auth'));
console.log();
// Start interactive loop
await this.interactiveLoop(options?.speaker || 'assistant');
}
/**
* Send a single message and get response
*/
async sendMessage(message, options) {
if (options?.sessionId) {
await this.brainyChat.switchToSession(options.sessionId);
}
// Add user message
const userMessage = await this.brainyChat.addMessage(message, 'user');
console.log(colors.blue(`👤 You: ${message}`));
if (options?.noResponse) {
return [userMessage];
}
// For CLI usage, we'd integrate with whatever AI service is configured
// This is a placeholder showing the architecture
const response = await this.generateResponse(message, options?.speaker || 'assistant');
const assistantMessage = await this.brainyChat.addMessage(response, options?.speaker || 'assistant', {
model: 'claude-3-sonnet',
context: { userMessage: userMessage.id }
});
console.log(colors.green(`🤖 ${options?.speaker || 'Assistant'}: ${response}`));
return [userMessage, assistantMessage];
}
/**
* Show conversation history
*/
async showHistory(limit = 10) {
const messages = await this.brainyChat.getHistory(limit);
if (messages.length === 0) {
console.log(colors.yellow('📭 No messages in current session'));
return;
}
console.log(colors.cyan(`📜 Last ${Math.min(limit, messages.length)} messages:`));
console.log();
for (const message of messages.slice(-limit)) {
const timestamp = message.timestamp.toLocaleTimeString();
const speakerColor = message.speaker === 'user' ? colors.blue : colors.green;
const icon = message.speaker === 'user' ? '👤' : '🤖';
console.log(speakerColor(`${icon} ${message.speaker} (${timestamp}):`));
console.log(colors.gray(` ${message.content}`));
console.log();
}
}
/**
* Search across all conversations
*/
async searchConversations(query, options) {
console.log(colors.cyan(`🔍 Searching for: "${query}"`));
const results = await this.brainyChat.searchMessages(query, {
limit: options?.limit || 10,
sessionId: options?.sessionId,
semanticSearch: options?.semantic !== false
});
if (results.length === 0) {
console.log(colors.yellow('🤷 No matching messages found'));
return;
}
console.log(colors.green(`✨ Found ${results.length} matches:`));
console.log();
for (const message of results) {
const date = message.timestamp.toLocaleDateString();
const time = message.timestamp.toLocaleTimeString();
const speakerColor = message.speaker === 'user' ? colors.blue : colors.green;
const icon = message.speaker === 'user' ? '👤' : '🤖';
console.log(colors.gray(`📅 ${date} ${time} - Session: ${message.sessionId.substring(0, 8)}...`));
console.log(speakerColor(`${icon} ${message.speaker}: ${message.content}`));
console.log();
}
}
/**
* List all chat sessions
*/
async listSessions() {
const sessions = await this.brainyChat.getSessions();
if (sessions.length === 0) {
console.log(colors.yellow('📭 No chat sessions found'));
return;
}
console.log(colors.cyan(`💬 Your chat sessions (${sessions.length}):`));
console.log();
for (const session of sessions) {
const isActive = session.id === this.brainyChat.getCurrentSessionId();
const activeIndicator = isActive ? colors.green(' ● ACTIVE') : '';
const archived = session.metadata?.archived ? colors.gray(' [ARCHIVED]') : '';
console.log(colors.blue(`📂 ${session.title || 'Untitled'}${activeIndicator}${archived}`));
console.log(colors.gray(` ID: ${session.id}`));
console.log(colors.gray(` Created: ${session.createdAt.toLocaleDateString()}`));
console.log(colors.gray(` Last active: ${session.lastMessageAt.toLocaleDateString()}`));
console.log(colors.gray(` Messages: ${session.messageCount}`));
console.log(colors.gray(` Participants: ${session.participants.join(', ')}`));
console.log();
}
}
/**
* Switch to a different session
*/
async switchSession(sessionId) {
const session = await this.brainyChat.switchToSession(sessionId);
if (session) {
console.log(colors.green(`✅ Switched to session: ${session.title || session.id}`));
console.log(colors.gray(` Messages: ${session.messageCount}`));
console.log(colors.gray(` Last active: ${session.lastMessageAt.toLocaleString()}`));
}
else {
console.log(colors.red(`❌ Session ${sessionId} not found`));
}
}
/**
* Show help for chat commands
*/
showHelp() {
console.log(colors.cyan('🧠 Brainy Chat Commands:'));
console.log();
console.log(colors.blue('Basic Commands:'));
console.log(' /history [limit] - Show conversation history (default: 10 messages)');
console.log(' /search <query> - Search all conversations');
console.log(' /sessions - List all chat sessions');
console.log(' /switch <id> - Switch to a specific session');
console.log(' /new - Start a new session');
console.log(' /help - Show this help');
console.log(' /quit - Exit chat');
console.log();
console.log(colors.yellow('Local Features:'));
console.log(' ✨ Automatic session discovery');
console.log(' 🧠 Local memory across all conversations');
console.log(' 🔍 Semantic search using vector similarity');
console.log(' 📊 Standard noun/verb graph relationships');
console.log();
console.log(colors.green('Want More? Premium Features:'));
console.log(' 🤝 Multi-agent coordination');
console.log(' ☁️ Cross-device memory sync');
console.log(' 🎨 Rich web coordination UI');
console.log(' 🔄 Real-time team collaboration');
console.log();
console.log(colors.blue('Get premium: brainy cloud auth'));
console.log();
}
// Private methods
async interactiveLoop(assistantSpeaker = 'assistant') {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const askQuestion = () => {
return new Promise((resolve) => {
rl.question(colors.blue('💬 You: '), resolve);
});
};
while (true) {
try {
const input = await askQuestion();
if (input.trim() === '')
continue;
// Handle commands
if (input.startsWith('/')) {
const [command, ...args] = input.slice(1).split(' ');
switch (command.toLowerCase()) {
case 'quit':
case 'exit':
console.log(colors.cyan('👋 Thanks for chatting! Your conversation is saved.'));
rl.close();
return;
case 'history':
const limit = args[0] ? parseInt(args[0]) : 10;
await this.showHistory(limit);
break;
case 'search':
if (args.length === 0) {
console.log(colors.yellow('Usage: /search <query>'));
}
else {
await this.searchConversations(args.join(' '));
}
break;
case 'sessions':
await this.listSessions();
break;
case 'switch':
if (args.length === 0) {
console.log(colors.yellow('Usage: /switch <session-id>'));
}
else {
await this.switchSession(args[0]);
}
break;
case 'new':
const newSession = await this.brainyChat.startNewSession(`Chat ${new Date().toLocaleDateString()}`);
console.log(colors.green(`🆕 Started new session: ${newSession.id}`));
break;
case 'archive':
const sessionToArchive = args[0] || this.brainyChat.getCurrentSessionId();
if (sessionToArchive) {
try {
await this.brainyChat.archiveSession(sessionToArchive);
console.log(colors.green(`📁 Session archived: ${sessionToArchive}`));
}
catch (error) {
console.log(colors.red(`${error?.message}`));
}
}
else {
console.log(colors.yellow('No session to archive'));
}
break;
case 'summary':
const sessionToSummarize = args[0] || this.brainyChat.getCurrentSessionId();
if (sessionToSummarize) {
try {
const summary = await this.brainyChat.generateSessionSummary(sessionToSummarize);
if (summary) {
console.log(colors.green('📋 Session Summary:'));
console.log(colors.gray(summary));
}
else {
console.log(colors.yellow('No summary could be generated'));
}
}
catch (error) {
console.log(colors.red(`${error?.message}`));
}
}
else {
console.log(colors.yellow('No session to summarize'));
}
break;
case 'help':
this.showHelp();
break;
default:
console.log(colors.yellow(`Unknown command: ${command}`));
console.log(colors.gray('Type /help for available commands'));
}
}
else {
// Regular message
await this.sendMessage(input, { speaker: assistantSpeaker });
}
console.log();
}
catch (error) {
console.error(colors.red(`Error: ${error?.message}`));
}
}
}
async showRecentContext(limit = 3) {
const recentMessages = await this.brainyChat.getHistory(limit);
if (recentMessages.length > 0) {
console.log(colors.gray('💭 Recent context:'));
for (const msg of recentMessages.slice(-limit)) {
const preview = msg.content.length > 60
? msg.content.substring(0, 60) + '...'
: msg.content;
console.log(colors.gray(` ${msg.speaker}: ${preview}`));
}
console.log();
}
}
async generateResponse(message, speaker) {
// This is a placeholder for AI integration
// In a real implementation, this would call the configured AI service
// and could include multi-agent coordination
// Example responses for demonstration
const responses = [
"I remember our conversation and can help with that!",
"Based on our previous discussions, I think...",
"Let me search through our chat history for relevant context.",
"I can coordinate with other AI agents if needed for this task."
];
return responses[Math.floor(Math.random() * responses.length)];
}
}
//# sourceMappingURL=ChatCLI.js.map