UNPKG

rawi

Version:

Rawi (راوي) is the developer-friendly AI CLI that brings the power of 11 major AI providers directly to your terminal. With seamless shell integration, persistent conversations, and 200+ specialized prompt templates, Rawi transforms your command line into

1 lines 16.8 kB
{"version":3,"sources":["/home/mkabumattar/work/withrawi/rawi/dist/chunk-FFLVUBDU.cjs","../src/cli/commands/chat/actions/enhanced-chat-session.ts"],"names":["startEnhancedChatSession","dbManager","options","profile","DEFAULT_PROFILE","validateProfile","credentials","validateCredentials","sessionManager","SessionManager","advancedOps","AdvancedSessionOperations","chalk"],"mappings":"AAAA;AACA,wDAAwC,wDAAyC,wDAAyC,wDAAgD,wDAAyC,wDAAyC,yFCDlO,4EACR,IAqBLA,CAAAA,CAA2B,KAAA,CACtCC,CAAAA,CACAC,CAAAA,CAAAA,EACkB,CAClB,IAAMC,CAAAA,CAAUD,CAAAA,CAAQ,OAAA,EAAWE,mBAAAA,CACnCC,iCAAAA,CAAgBF,CAASD,CAAO,CAAA,CAEhC,IAAMI,CAAAA,CAAcC,iCAAAA,CAAoBJ,CAASD,CAAO,CAAA,CAClDM,CAAAA,CAAiB,IAAIC,wBAAAA,CAAeR,CAAS,CAAA,CAC7CS,CAAAA,CAAc,IAAIC,wBAAAA,CAA0BH,CAAAA,CAAgBL,CAAO,CAAA,CAEzE,EAAA,CAAID,CAAAA,CAAQ,KAAA,CAAO,CACjB,MAAMQ,CAAAA,CAAY,cAAA,CAAeR,CAAO,CAAA,CACxC,MACF,CAAA,KAAA,EAAA,CAAWA,CAAAA,CAAQ,MAAA,CAAQ,CACzB,MAAMQ,CAAAA,CAAY,cAAA,CAAeR,CAAAA,CAAQ,MAAA,CAAQA,CAAO,CAAA,CACxD,MACF,CAAA,KAAA,EAAA,CAAWA,CAAAA,CAAQ,OAAA,CAAS,CAC1B,MAAMQ,CAAAA,CAAY,eAAA,CAAgBR,CAAAA,CAAQ,OAAO,CAAA,CACjD,MACF,CAAA,KAAA,EAAA,CAAWA,CAAAA,CAAQ,WAAA,CAAa,CAC9B,MAAMQ,CAAAA,CAAY,mBAAA,CAAoBR,CAAAA,CAAQ,WAAA,CAAaA,CAAO,CAAA,CAClE,MACF,CAEIA,CAAAA,CAAQ,OAAA,EAAA,CACV,OAAA,CAAQ,GAAA,CACNU,eAAAA,CAAM,GAAA,CACJ,CAAA,uBAAA,EAAmBN,CAAAA,CAAY,QAAQ,CAAA,EAAA,EAAKA,CAAAA,CAAY,KAAK,CAAA,CAAA,CAC/D,CACF,CAAA,CACA,OAAA,CAAQ,GAAA,CAAIM,eAAAA,CAAM,GAAA,CAAI,CAAA,mBAAA,EAAeT,CAAO,CAAA,CAAA;AAgKO;AAsBpB;AAOF,2CAAA;AAKF,kBAAA;AAaD,wBAAA;AAsFb;AA2EL,eAAA;AAqFZ,+BAAA;ADhfuvB","file":"/home/mkabumattar/work/withrawi/rawi/dist/chunk-FFLVUBDU.cjs","sourcesContent":[null,"import * as readline from 'node:readline/promises';\nimport chalk from 'chalk';\nimport type {DatabaseManager} from '../../../../core/database/manager.js';\nimport {SessionManager} from '../../../../core/session/index.js';\nimport {DEFAULT_PROFILE} from '../../../../core/shared/constants.js';\nimport {\n processActTemplate,\n validateCredentials,\n validateProfile,\n} from '../../ask/actions/index.js';\nimport type {ChatOptions} from '../types.js';\nimport {AdvancedSessionOperations} from './advanced-operations.js';\nimport {streamChatResponse} from './response-handler.js';\n\ninterface ChatMessage {\n role: 'user' | 'assistant' | 'system';\n content: string;\n provider?: string;\n model?: string;\n timestamp?: string;\n}\n\nexport const startEnhancedChatSession = async (\n dbManager: DatabaseManager,\n options: ChatOptions,\n): Promise<void> => {\n const profile = options.profile || DEFAULT_PROFILE;\n validateProfile(profile, options);\n\n const credentials = validateCredentials(profile, options);\n const sessionManager = new SessionManager(dbManager);\n const advancedOps = new AdvancedSessionOperations(sessionManager, profile);\n\n if (options.stats) {\n await advancedOps.showStatistics(options);\n return;\n } else if (options.backup) {\n await advancedOps.backupSessions(options.backup, options);\n return;\n } else if (options.restore) {\n await advancedOps.restoreSessions(options.restore);\n return;\n } else if (options.batchDelete) {\n await advancedOps.batchDeleteSessions(options.batchDelete, options);\n return;\n }\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `🔗 Connected to ${credentials.provider} (${credentials.model})`,\n ),\n );\n console.log(chalk.dim(`📁 Profile: ${profile}`));\n if (options.act) {\n console.log(chalk.dim(`🎭 Act template: ${options.act}`));\n }\n }\n\n let currentSessionId: string;\n let messages: ChatMessage[] = [];\n\n if (options.session) {\n try {\n const session = await sessionManager.getSession(options.session, profile);\n currentSessionId = session.id;\n messages = await dbManager.getMessages(currentSessionId);\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `📝 Continuing session: ${session.title || 'Untitled'} (${currentSessionId.substring(0, 8)}...)`,\n ),\n );\n console.log(\n chalk.dim(`💬 Loaded ${messages.length} previous messages`),\n );\n }\n } catch (error) {\n console.error(chalk.red(`❌ Failed to load session: ${error}`));\n return;\n }\n } else if (options.listSessions) {\n await handleSessionSelection(sessionManager, profile, options);\n return;\n } else if (options.deleteSession) {\n await handleSessionDeletion(sessionManager, options.deleteSession);\n return;\n } else if (options.exportSessions) {\n await handleSessionExport(sessionManager, profile, options);\n return;\n } else if (options.renameSession && options.newTitle) {\n await handleSessionRename(\n sessionManager,\n options.renameSession,\n options.newTitle,\n profile,\n );\n return;\n } else if (options.newSession) {\n const sessionTitle = options.act ? `${options.act} Chat` : undefined;\n currentSessionId = await sessionManager.createSession(profile, {\n title: sessionTitle,\n generateTitle: !sessionTitle,\n type: 'chat',\n });\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `🆕 Created new session: ${currentSessionId.substring(0, 8)}...`,\n ),\n );\n }\n } else {\n const advancedOps = new AdvancedSessionOperations(sessionManager, profile);\n const existingSessions = await sessionManager.listSessions({\n profile,\n limit: 10,\n type: 'chat',\n });\n\n if (existingSessions.length > 0 && !options.newSession) {\n const selectedSessionId =\n await advancedOps.selectSessionInteractively(existingSessions);\n\n if (selectedSessionId) {\n currentSessionId = selectedSessionId;\n messages = await dbManager.getMessages(currentSessionId);\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `🔄 Continuing session: ${currentSessionId.substring(0, 8)}... (${messages.length} messages)`,\n ),\n );\n }\n } else {\n const sessionTitle = options.act ? `${options.act} Chat` : undefined;\n currentSessionId = await sessionManager.createSession(profile, {\n title: sessionTitle,\n generateTitle: !sessionTitle,\n type: 'chat',\n });\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `🆕 Created new session: ${currentSessionId.substring(0, 8)}...`,\n ),\n );\n }\n }\n } else {\n const sessionTitle = options.act ? `${options.act} Chat` : undefined;\n currentSessionId = await sessionManager.createSession(profile, {\n title: sessionTitle,\n generateTitle: !sessionTitle,\n type: 'chat',\n });\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `🆕 Created new session: ${currentSessionId.substring(0, 8)}...`,\n ),\n );\n }\n }\n }\n\n if (options.act && messages.length === 0) {\n try {\n const systemPrompt = await processActTemplate(options.act, '', options);\n if (systemPrompt?.trim()) {\n const assistantMessage: ChatMessage = {\n role: 'assistant',\n content: `I'm now acting as: ${options.act}. How can I help you?`,\n provider: credentials.provider,\n model: credentials.model,\n timestamp: new Date().toISOString(),\n };\n\n messages.push(assistantMessage);\n\n await dbManager.addMessage(\n currentSessionId,\n assistantMessage.role,\n assistantMessage.content,\n credentials.provider,\n credentials.model,\n );\n\n if (options.verbose) {\n console.log(chalk.dim(`🎭 Applied act template: ${options.act}`));\n }\n }\n } catch (error) {\n console.error(chalk.red(`❌ Error applying act template: ${error}`));\n return;\n }\n }\n\n console.log(chalk.bold.blue('🤖 Welcome to Rawi Chat!'));\n console.log(\n chalk.gray(\n 'Start typing your message. Use /quit or /exit to end the chat.\\n',\n ),\n );\n\n if (options.verbose) {\n console.log(\n chalk.dim(\n `💬 Session: ${currentSessionId.substring(0, 8)}... | Type \"/help\" for commands\\n`,\n ),\n );\n }\n\n const terminal = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n try {\n while (true) {\n let userInput: string;\n\n try {\n userInput = await terminal.question(chalk.blue('You: '));\n } catch (error) {\n if (\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ERR_USE_AFTER_CLOSE'\n ) {\n console.log(chalk.yellow('\\n👋 Chat session ended (stdin closed)'));\n break;\n }\n throw error;\n }\n\n if (userInput.trim() === '/quit' || userInput.trim() === '/exit') {\n console.log(chalk.yellow('\\n👋 Goodbye!'));\n break;\n }\n\n if (userInput.trim() === '/help') {\n console.log(chalk.cyan('\\n📚 Chat Commands:'));\n console.log(chalk.gray(' /help - Show this help message'));\n console.log(chalk.gray(' /quit - Exit the chat'));\n console.log(chalk.gray(' /exit - Exit the chat'));\n console.log(chalk.gray(' /clear - Clear message history'));\n console.log(chalk.gray(' /session - Show current session info'));\n console.log(chalk.gray(' /rename - Rename current session'));\n console.log('');\n continue;\n }\n\n if (userInput.trim() === '/clear') {\n messages.length = 0;\n console.log(chalk.dim('🧹 Message history cleared (local only)\\n'));\n continue;\n }\n\n if (userInput.trim() === '/session') {\n await showSessionInfo(sessionManager, currentSessionId);\n continue;\n }\n\n if (userInput.trim().startsWith('/rename ')) {\n const newTitle = userInput.trim().substring(8).trim();\n if (newTitle) {\n await handleSessionRename(\n sessionManager,\n currentSessionId,\n newTitle,\n profile,\n );\n } else {\n console.log(\n chalk.red('❌ Please provide a new title: /rename <new title>'),\n );\n }\n continue;\n }\n\n if (userInput.trim() === '') {\n continue;\n }\n\n const userMessage: ChatMessage = {\n role: 'user',\n content: userInput.trim(),\n timestamp: new Date().toISOString(),\n };\n\n messages.push(userMessage);\n\n await dbManager.addMessage(\n currentSessionId,\n userMessage.role,\n userMessage.content,\n credentials.provider,\n credentials.model,\n );\n\n try {\n const assistantResponse = await streamChatResponse(\n credentials,\n messages,\n options,\n terminal,\n );\n\n const assistantMessage: ChatMessage = {\n role: 'assistant',\n content: assistantResponse,\n provider: credentials.provider,\n model: credentials.model,\n timestamp: new Date().toISOString(),\n };\n\n messages.push(assistantMessage);\n\n await dbManager.addMessage(\n currentSessionId,\n assistantMessage.role,\n assistantMessage.content,\n credentials.provider,\n credentials.model,\n );\n } catch (error) {\n console.error(chalk.red(`❌ Error: ${error}`));\n }\n }\n } catch (error) {\n console.error(chalk.red(`❌ Error in chat session: ${error}`));\n } finally {\n terminal.close();\n }\n};\n\nasync function handleSessionSelection(\n sessionManager: SessionManager,\n profile: string,\n options: ChatOptions,\n): Promise<void> {\n try {\n const advancedOps = new AdvancedSessionOperations(sessionManager, profile);\n\n const sessions = await sessionManager.listSessions({\n profile,\n limit: options.limit || 10,\n fromDate: options.fromDate,\n toDate: options.toDate,\n type: 'chat',\n });\n\n if (sessions.length === 0) {\n console.log(chalk.yellow('No sessions found for this profile.'));\n return;\n }\n\n if (options.listSessions) {\n const format = options.format || 'table';\n const formattedOutput = await advancedOps.formatSessions(\n sessions,\n format,\n );\n console.log(formattedOutput);\n\n if (format === 'table') {\n console.log(chalk.cyan('\\n💡 Tips:'));\n console.log(chalk.gray('• Copy the full ID from the table above'));\n console.log(\n chalk.gray('• Use: ') + chalk.white('rawi chat --session <full-id>'),\n );\n console.log(\n chalk.gray('• Or use: ') +\n chalk.white('rawi chat') +\n chalk.gray(' for interactive selection'),\n );\n }\n return;\n }\n\n const selectedSessionId =\n await advancedOps.selectSessionInteractively(sessions);\n if (selectedSessionId) {\n console.log(chalk.green(`🚀 Continuing session: ${selectedSessionId}`));\n } else {\n console.log(chalk.blue('🆕 Starting new session...'));\n }\n } catch (error) {\n console.error(chalk.red(`❌ Failed to handle session selection: ${error}`));\n }\n}\n\nasync function handleSessionDeletion(\n sessionManager: SessionManager,\n sessionId: string,\n): Promise<void> {\n try {\n const deleted = await sessionManager.deleteSession(sessionId, {\n force: true,\n });\n\n if (deleted) {\n console.log(\n chalk.green(\n `✅ Session ${sessionId.substring(0, 8)}... deleted successfully.`,\n ),\n );\n } else {\n console.log(\n chalk.yellow(\n `⚠️ Session ${sessionId.substring(0, 8)}... not found or already deleted.`,\n ),\n );\n }\n } catch (error) {\n console.error(chalk.red(`❌ Failed to delete session: ${error}`));\n }\n}\n\nasync function handleSessionExport(\n sessionManager: SessionManager,\n profile: string,\n options: ChatOptions,\n): Promise<void> {\n try {\n const advancedOps = new AdvancedSessionOperations(sessionManager, profile);\n\n const format = options.format || 'json';\n const exportFormat =\n typeof options.exportSessions === 'string' ? 'json' : format;\n\n const exportData = await sessionManager.exportSessions(\n exportFormat as 'json' | 'markdown',\n {\n profile,\n fromDate: options.fromDate,\n toDate: options.toDate,\n ...(options.limit && {limit: options.limit}),\n },\n );\n\n if (typeof options.exportSessions === 'string') {\n console.log(\n chalk.green(`✅ Sessions exported to ${options.exportSessions}`),\n );\n } else {\n const formattedOutput = await advancedOps.formatSessions(\n exportData.sessions,\n format,\n );\n console.log(formattedOutput);\n }\n } catch (error) {\n console.error(chalk.red(`❌ Failed to export sessions: ${error}`));\n }\n}\n\nasync function handleSessionRename(\n sessionManager: SessionManager,\n sessionId: string,\n newTitle: string,\n profile: string,\n): Promise<void> {\n try {\n await sessionManager.updateSessionTitle(sessionId, newTitle, profile);\n console.log(chalk.green(`✅ Session renamed to: ${newTitle}`));\n } catch (error) {\n console.error(chalk.red(`❌ Failed to rename session: ${error}`));\n }\n}\n\nasync function showSessionInfo(\n sessionManager: SessionManager,\n sessionId: string,\n): Promise<void> {\n try {\n const session = await sessionManager.getSession(sessionId);\n\n console.log(chalk.cyan('\\n📊 Current Session Info:'));\n console.log(chalk.gray('═'.repeat(30)));\n console.log(\n `${chalk.dim('ID:')} ${chalk.white(session.id.substring(0, 16))}...`,\n );\n console.log(\n `${chalk.dim('Title:')} ${chalk.white(session.title || 'Untitled')}`,\n );\n console.log(`${chalk.dim('Profile:')} ${chalk.white(session.profile)}`);\n console.log(\n `${chalk.dim('Messages:')} ${chalk.white(session.messageCount)}`,\n );\n console.log(\n `${chalk.dim('Created:')} ${chalk.gray(new Date(session.createdAt).toLocaleString())}`,\n );\n console.log(\n `${chalk.dim('Updated:')} ${chalk.gray(new Date(session.updatedAt).toLocaleString())}`,\n );\n console.log('');\n } catch (error) {\n console.error(chalk.red(`❌ Failed to get session info: ${error}`));\n }\n}\n"]}