import { createInterface } from 'node:readline' import { stdin as input, stdout as output } from 'node:process' import { createAgent } from '../src/agent' import { createMemorySearch, createAddMemory, filterByTimestamp, MemoryUnit } from '@memohome/memory' import { ModelClientType } from '@memohome/shared' // Load environment variables const MODEL = process.env.MODEL const BASE_URL = process.env.BASE_URL const API_KEY = process.env.API_KEY const EMBEDDING_MODEL = process.env.EMBEDDING_MODEL const MODEL_CLIENT_TYPE = process.env.MODEL_CLIENT_TYPE || 'openai' if (!MODEL || !BASE_URL || !API_KEY || !EMBEDDING_MODEL) { console.error('Error: Missing required environment variables') console.error('Required: MODEL, BASE_URL, API_KEY, EMBEDDING_MODEL') console.error('Optional: MODEL_CLIENT_TYPE (default: openai)') process.exit(1) } const USER_ID = 'cli-user' // Create memory functions const searchMemory = createMemorySearch({ model: EMBEDDING_MODEL, apiKey: API_KEY, baseURL: BASE_URL, }) const addMemory = createAddMemory({ model: EMBEDDING_MODEL, apiKey: API_KEY, baseURL: BASE_URL, }) // Create agent const agent = createAgent({ model: { modelId: MODEL, baseUrl: BASE_URL, apiKey: API_KEY, clientType: MODEL_CLIENT_TYPE as ModelClientType, name: MODEL, }, maxContextLoadTime: 60, // 60 minutes language: 'Same as user input', onReadMemory: async (from: Date, to: Date) => { return await filterByTimestamp(from, to, USER_ID) }, onSearchMemory: async (query: string) => { return await searchMemory({ user: USER_ID, query, maxResults: 5 }) }, onFinish: async (messages) => { // Save conversation to memory - type conversion handled internally const memoryUnit: MemoryUnit = { messages: messages as unknown as MemoryUnit['messages'], timestamp: new Date(), user: USER_ID, raw: '', // will be generated by addMemory } await addMemory({ memory: memoryUnit }) }, }) async function main() { console.log('šŸ¤– Agent CLI Started') console.log('Type your message and press Enter. Type "exit" to quit.\n') // Load context await agent.loadContext() const rl = createInterface({ input, output }) rl.on('line', async (line) => { const userInput = line.trim() if (userInput === 'exit' || userInput === 'quit') { console.log('\nšŸ‘‹ Goodbye!') rl.close() process.exit(0) } if (!userInput) { rl.prompt() return } try { process.stdout.write('\nšŸ¤– ') let hasOutput = false for await (const event of agent.ask(userInput)) { if (event.type === 'text-delta' && 'text' in event && event.text) { process.stdout.write(String(event.text)) hasOutput = true } else if (event.type === 'tool-call' && 'toolName' in event) { process.stdout.write(`\n[Tool: ${event.toolName}]`) hasOutput = true } } if (!hasOutput) { process.stdout.write('(No response)') } console.log('\n') } catch (error) { console.error('\nāŒ Error:', error instanceof Error ? error.message : String(error)) console.log() } rl.prompt() }) rl.setPrompt('You: ') rl.prompt() } main().catch(console.error)