import type { Command } from 'commander'; import type { ModelClient } from '../models/types.js'; import { NativeAgent } from '../backends/index.js'; import { ToolRegistry, ToolExecutor, allBuiltinTools } from '../tools/index.js'; import { HookEngine } from '../hooks/index.js'; import { loadConfigSafe, getConfigPath } from './shared.js'; import { existsSync, readFileSync } from 'fs'; import { resolve } from 'path'; /** Create a lightweight agent for one-shot message processing. */ export function createSendAgent(deps: { modelClient: ModelClient; systemPrompt: string; enableTools?: boolean; }): NativeAgent { const config: ConstructorParameters[0] = { modelClient: deps.modelClient, systemPrompt: deps.systemPrompt, }; if (deps.enableTools !== false) { const hookEngine = new HookEngine({ confirm: [], log: [], silent: [] }); const toolRegistry = new ToolRegistry(); for (const tool of allBuiltinTools) { toolRegistry.register(tool); } const toolExecutor = new ToolExecutor(toolRegistry, hookEngine); config.toolRegistry = toolRegistry; config.toolExecutor = toolExecutor; } return new NativeAgent(config); } function loadSystemPrompt(): string { const paths = [ resolve(process.cwd(), 'SOUL.md'), resolve(import.meta.dirname, '../../SOUL.md'), ]; for (const p of paths) { if (existsSync(p)) return readFileSync(p, 'utf-8'); } return 'You are Flynn, a helpful personal AI assistant.'; } export function registerSendCommand(program: Command): void { program .command('send ') .description('Send a one-shot message and print the response') .option('-c, --config ', 'Config file path') .option('--no-tools', 'Disable tool use') .action(async (message: string, opts: { config?: string; tools?: boolean }) => { const configPath = opts.config ?? getConfigPath(); const { config, error } = loadConfigSafe(configPath); if (!config) { console.error(error); process.exit(1); } // Dynamic import to avoid loading model code eagerly const { AnthropicClient } = await import('../models/index.js'); const modelClient = new AnthropicClient({ model: config.models.default.model, apiKey: config.models.default.api_key, authToken: config.models.default.auth_token, }); const agent = createSendAgent({ modelClient, systemPrompt: loadSystemPrompt(), enableTools: opts.tools, }); try { const response = await agent.process(message); console.log(response); } catch (err) { console.error('Error:', err instanceof Error ? err.message : err); process.exit(1); } }); }