zapmyco 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["log","RendererClass","HistoryStoreClass"],"sources":["../../src/cli/repl/command-registry.ts","../../src/cli/repl/commands/agents-cmd.ts","../../src/cli/repl/commands/clear.ts","../../src/cli/repl/commands/config-cmd.ts","../../src/cli/repl/commands/help.ts","../../src/cli/repl/commands/history.ts","../../src/cli/repl/commands/quit.ts","../../src/cli/repl/commands/status.ts","../../src/cli/repl/components/custom-editor.ts","../../src/cli/repl/history-store.ts","../../src/cli/repl/input-parser.ts","../../src/cli/repl/components/output-area.ts","../../src/cli/repl/renderer.ts","../../src/cli/repl/repl-agent-tools.ts","../../src/cli/repl/theme.ts","../../src/llm/pi-ai-provider.ts","../../src/cli/repl/session.ts","../../src/cli/repl/index.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * 内置命令注册表\n *\n * 管理所有 REPL 内置命令的注册、查找和分发。\n */\n\nimport type { CommandDefinition, ParsedInput, ReplSession } from '@/cli/repl/types';\nimport { logger } from '@/infra/logger';\n\nconst log = logger.child('repl:command-registry');\n\n/**\n * 命令注册表\n */\nexport class CommandRegistry {\n private readonly commands = new Map<string, CommandDefinition>();\n private readonly aliasMap = new Map<string, string>(); // alias -> canonical name\n\n constructor(private readonly session: ReplSession) {}\n\n /**\n * 注册一个命令\n */\n register(cmd: CommandDefinition): void {\n const canonicalName = cmd.name.toLowerCase();\n\n // 检查是否已存在同名命令\n if (this.commands.has(canonicalName)) {\n log.warn(`命令 \"${canonicalName}\" 已存在,将被覆盖`);\n }\n\n this.commands.set(canonicalName, cmd);\n\n // 注册别名\n for (const alias of cmd.aliases) {\n const lowerAlias = alias.toLowerCase();\n this.aliasMap.set(lowerAlias, canonicalName);\n }\n }\n\n /**\n * 根据名称或别名查找命令\n */\n getCommand(name: string): CommandDefinition | undefined {\n const lowerName = name.toLowerCase();\n\n // 先尝试精确匹配命令名\n const direct = this.commands.get(lowerName);\n if (direct) return direct;\n\n // 再尝试别名查找\n const canonical = this.aliasMap.get(lowerName);\n if (canonical) {\n return this.commands.get(canonical);\n }\n\n return undefined;\n }\n\n /**\n * 列出所有已注册的命令\n */\n listCommands(): CommandDefinition[] {\n return Array.from(this.commands.values());\n }\n\n /**\n * 分发并执行命令\n */\n async dispatch(parsed: ParsedInput): Promise<void> {\n if (parsed.kind !== 'command') {\n log.warn('dispatch 收到了非 command 类型的输入');\n return;\n }\n\n const cmd = this.getCommand(parsed.name);\n\n if (!cmd) {\n console.log(`\\n 未知命令: /${parsed.name},输入 ${'/help'} 查看可用命令\\n`);\n return;\n }\n\n try {\n await cmd.handler(parsed.args, this.session);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n log.error(`命令 /${cmd.name} 执行出错`, {}, error as Error);\n console.log(`\\n 命令执行出错: ${message}\\n`);\n }\n }\n}\n\n/** 类型别名(供 session 内部引用) */\nexport type CommandRegistryImpl = CommandRegistry;\n","/**\n * /agents 命令\n *\n * 列出所有已注册的 Agent 及其状态。\n */\n\nimport type { CommandDefinition } from '@/cli/repl/types';\nimport type { AgentRegistration } from '@/protocol/capability';\n\n/**\n * 创建 agents 命令定义\n */\nexport function createAgentsCommand(): CommandDefinition {\n return {\n name: 'agents',\n aliases: ['ag'],\n description: '列出已注册 Agent 及其状态',\n usage: '/agents',\n handler(_args, session) {\n const agents = buildAgentList(session.config);\n const lines = session.getRenderer().renderAgents(agents);\n session.appendOutput(lines);\n },\n };\n}\n\n/**\n * 从配置构建 AgentRegistration 列表\n *\n * 当前阶段:引擎尚未完全实现,从配置中的 agents 列表构造基本信息。\n * 未来:从 Agent 注册中心获取实时状态。\n */\nfunction buildAgentList(\n config: import('@/cli/repl/types').ReplSession['config']\n): AgentRegistration[] {\n return config.agents\n .filter((agent) => agent.enabled)\n .map((agent) => {\n const result: AgentRegistration = {\n agentId: agent.id,\n displayName: agent.id,\n capabilities: [],\n status: 'online' as AgentRegistration['status'],\n currentLoad: 0,\n maxConcurrency: 3,\n };\n if (agent.endpoint !== undefined) {\n result.endpoint = agent.endpoint;\n }\n return result;\n });\n}\n","/**\n * /clear 命令\n *\n * 清屏并重置多行输入缓冲区。\n */\n\nimport type { CommandDefinition } from '@/cli/repl/types';\n\n/**\n * 创建 clear 命令定义\n */\nexport function createClearCommand(): CommandDefinition {\n return {\n name: 'clear',\n aliases: ['cl'],\n description: '清除屏幕',\n usage: '/clear',\n handler(_args, session) {\n // 清空输出区域(TUI 模式下替代 clearScreen)\n session.clearOutput();\n\n // 重置输入解析器的多行缓冲\n const s = session as unknown as { getInputParser(): { reset(): void } };\n s.getInputParser().reset();\n },\n };\n}\n","/**\n * /config 命令\n *\n * 查看当前配置信息。\n */\n\nimport type { CommandDefinition } from '@/cli/repl/types';\n\n/**\n * 创建 config 命令定义\n */\nexport function createConfigCommand(): CommandDefinition {\n return {\n name: 'config',\n aliases: ['cfg'],\n description: '查看配置 [show | get <key>]',\n usage: '/config [show | get <key>]',\n handler(args, session) {\n const config = session.config;\n const renderer = session.getRenderer();\n\n // 无参数或 \"show\" → 展示完整配置\n if (args.length === 0 || args[0] === 'show') {\n const lines = renderer.renderConfig(config);\n session.appendOutput(lines);\n return;\n }\n\n // \"get <key>\" → 获取单项配置(支持 dot-path)\n if (args[0] === 'get' && args[1]) {\n const value = getByDotPath(config, args[1]);\n if (value !== undefined) {\n const displayValue =\n args[1].toLowerCase().includes('apikey') || args[1].toLowerCase().includes('api_key')\n ? '***已配置***'\n : JSON.stringify(value, null, 2);\n session.appendOutput([``, ` ${args[1]}: ${displayValue}`, ``]);\n } else {\n session.appendOutput([\n '',\n ` 未找到配置项: ${args[1]}`,\n ' 使用 /config show 查看所有可用配置项',\n '',\n ]);\n }\n return;\n }\n\n session.appendOutput(['', ' 用法: /config [show | get <key>]', '']);\n },\n };\n}\n\n/**\n * 通过 dot-path 获取嵌套对象属性\n *\n * 例如: getByPath(config, 'llm.provider') → config.llm.provider\n */\nfunction getByDotPath(obj: Record<string, unknown>, path: string): unknown {\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n return current;\n}\n","/**\n * /help 命令\n *\n * 显示所有可用命令及用法摘要。\n */\n\nimport chalk, { Chalk } from 'chalk';\nimport type { CommandDefinition, ReplSession } from '@/cli/repl/types';\n\n/**\n * 创建 help 命令定义\n */\nexport function createHelpCommand(): CommandDefinition {\n return {\n name: 'help',\n aliases: ['h', '?'],\n description: '显示帮助信息',\n usage: '/help',\n handler(_args, session) {\n const { c } = getColorEnabled(session);\n const commands = getCommandRegistry(session).listCommands();\n const lines: string[] = ['', c.bold(' 可用命令:'), ''];\n\n for (const cmd of commands) {\n const aliasStr = cmd.aliases.length > 0 ? `, /${cmd.aliases.join(', /')}` : '';\n lines.push(` ${c.cyan.bold(`/${cmd.name}`)}${c.gray(aliasStr)}`);\n lines.push(` ${c.gray(cmd.description)}`);\n if (cmd.usage && cmd.usage !== `/${cmd.name}`) {\n lines.push(` ${c.gray(`用法: ${cmd.usage}`)}`);\n }\n lines.push('');\n }\n\n lines.push(c.gray(' ───────────────────────────────────────'));\n lines.push(c.gray(' 提示: 直接输入自然语言即可提交目标给 AI 总管执行。'));\n lines.push(c.gray(' 多行输入请在行末加 \"\\\\\" 续行。按 Ctrl+C 取消当前任务。'));\n lines.push('');\n\n session.appendOutput(lines);\n },\n };\n}\n\n// ============ 辅助函数 ============\n\nfunction getColorEnabled(session: ReplSession): { c: typeof chalk } {\n const c = session.replOptions.color\n ? chalk\n : (new Chalk({ level: 0 }) as unknown as typeof chalk);\n return { c };\n}\n\nfunction getCommandRegistry(session: ReplSession) {\n return (\n session as unknown as { getCommandRegistry(): { listCommands(): CommandDefinition[] } }\n ).getCommandRegistry();\n}\n","/**\n * /history 命令\n *\n * 查看会话历史记录。\n */\n\nimport type { CommandDefinition } from '@/cli/repl/types';\n\n/** 默认显示条数 */\nconst DEFAULT_COUNT = 10;\n\n/**\n * 创建 history 命令定义\n */\nexport function createHistoryCommand(): CommandDefinition {\n return {\n name: 'history',\n aliases: ['hi'],\n description: '查看历史记录 [n]',\n usage: '/history [n]',\n handler(args, session) {\n const store = session.getHistoryStore();\n const count = args[0] ? parseInt(args[0], 10) : DEFAULT_COUNT;\n\n if (Number.isNaN(count) || count <= 0) {\n session.appendOutput(['', ' 参数错误: 请输入有效的数字,如 /history 20', '']);\n return;\n }\n\n const entries = store.getLast(count);\n const lines = session.getRenderer().renderHistory(entries);\n session.appendOutput(lines);\n },\n };\n}\n","/**\n * /quit 命令\n *\n * 关闭 REPL 并退出进程。\n */\n\nimport type { CommandDefinition } from '@/cli/repl/types';\n\n/**\n * 创建 quit 命令定义\n */\nexport function createQuitCommand(): CommandDefinition {\n return {\n name: 'quit',\n aliases: ['exit', 'q', 'x'],\n description: '退出 REPL',\n usage: '/quit',\n async handler(_args, session) {\n await session.shutdown('用户主动退出');\n },\n };\n}\n","/**\n * /status 命令\n *\n * 显示当前会话状态和统计信息。\n */\n\nimport type { CommandDefinition } from '@/cli/repl/types';\n\n/**\n * 创建 status 命令定义\n */\nexport function createStatusCommand(): CommandDefinition {\n return {\n name: 'status',\n aliases: ['st'],\n description: '查看会话状态统计',\n usage: '/status',\n handler(_args, session) {\n const stats = session.getStats();\n const lines = session.getRenderer().renderStatus(stats);\n session.appendOutput(lines);\n },\n };\n}\n","/**\n * 自定义编辑器组件\n *\n * 继承自 pi-tui 的 Editor,添加 zapmyco 特有的快捷键处理:\n * - Ctrl+C: 取消任务 / 二次退出\n * - Ctrl+D: 退出\n * - Escape: 取消当前输入\n */\n\nimport { Editor, Key, matchesKey } from '@mariozechner/pi-tui';\n\nexport class ZapmycoEditor extends Editor {\n /** Escape 键回调 */\n onEscape?: () => void;\n\n /** Ctrl+C 回调 */\n onCtrlC?: () => void;\n\n /** Ctrl+D 回调 */\n onCtrlD?: () => void;\n\n handleInput(data: string): void {\n if (matchesKey(data, Key.escape) && this.onEscape) {\n this.onEscape();\n return;\n }\n if (matchesKey(data, Key.ctrl('c')) && this.onCtrlC) {\n this.onCtrlC();\n return;\n }\n if (matchesKey(data, Key.ctrl('d'))) {\n if (this.getText().length === 0 && this.onCtrlD) {\n this.onCtrlD();\n }\n return;\n }\n super.handleInput(data);\n }\n}\n","/**\n * 会话历史存储\n *\n * 基于内存的环形缓冲区,记录 REPL 会话中的用户输入和执行结果。\n */\n\nimport type { HistoryEntry, HistoryStore as IHistoryStore } from '@/cli/repl/types';\n\n/** 默认最大历史条数 */\nconst DEFAULT_MAX_SIZE = 100;\n\n/**\n * 历史存储类\n */\nexport class HistoryStore implements IHistoryStore {\n private entries: HistoryEntry[] = [];\n private nextId = 1;\n private readonly maxSize: number;\n\n constructor(maxSize: number = DEFAULT_MAX_SIZE) {\n this.maxSize = maxSize;\n }\n\n /** 添加条目 */\n push(entry: Omit<HistoryEntry, 'id'>): HistoryEntry {\n const newEntry: HistoryEntry = {\n ...entry,\n id: this.nextId++,\n };\n\n this.entries.push(newEntry);\n\n // 超过最大容量时淘汰最旧的条目\n if (this.entries.length > this.maxSize) {\n this.entries.shift();\n // shift 后重新编号以保持 ID 连续(可选,这里选择保持递增)\n }\n\n return newEntry;\n }\n\n /** 获取所有条目 */\n getAll(): HistoryEntry[] {\n return [...this.entries];\n }\n\n /** 获取最近 n 条 */\n getLast(n: number): HistoryEntry[] {\n const count = Math.min(n, this.entries.length);\n return this.entries.slice(-count);\n }\n\n /** 清空所有条目 */\n clear(): void {\n this.entries = [];\n // 不重置 nextId,保持 ID 唯一递增\n }\n\n /** 搜索条目(按输入内容模糊匹配) */\n search(query: string): HistoryEntry[] {\n const lowerQuery = query.toLowerCase();\n return this.entries.filter((entry) => entry.input.toLowerCase().includes(lowerQuery));\n }\n}\n\n/** 类型别名(供 session 内部引用) */\nexport type HistoryStoreImpl = HistoryStore;\n","/**\n * 输入解析器\n *\n * 将用户单行输入解析为结构化的 ParsedInput,\n * 区分命令、自然语言目标、空行和多行续行。\n */\n\nimport type { ParsedInput } from '@/cli/repl/types';\n\n/**\n * 输入解析器\n */\nexport class InputParser {\n private buffer = '';\n\n /**\n * 解析单行输入\n *\n * 规则:\n * 1. 空行 → empty\n * 2. 以 / 开头 → command\n * 3. 以 \\ 结尾 → incomplete(多行续行)\n * 4. 其他 → goal(拼接 buffer 后)\n */\n parse(line: string): ParsedInput {\n const trimmed = line.trimEnd();\n\n // 规则 1: 空行(且无缓冲内容)\n if (trimmed.length === 0 && this.buffer.length === 0) {\n return { kind: 'empty' };\n }\n\n // 规则 2: 命令(优先识别,即使有 buffer 也清空后处理)\n if (trimmed.startsWith('/')) {\n this.buffer = '';\n return this.parseCommand(trimmed);\n }\n\n // 规则 3: 续行标记\n if (trimmed.endsWith('\\\\')) {\n const content = trimmed.slice(0, -1);\n this.buffer += this.buffer ? `\\n${content}` : content;\n return { kind: 'incomplete', buffer: this.buffer };\n }\n\n // 规则 4 & 5: 完整输入(可能包含之前缓冲的多行内容)\n const fullInput = this.buffer ? `${this.buffer}\\n${trimmed}` : trimmed;\n this.buffer = '';\n\n if (fullInput.trim().length === 0) {\n return { kind: 'empty' };\n }\n\n return { kind: 'goal', rawInput: fullInput };\n }\n\n /** 重置解析状态(清空多行缓冲) */\n reset(): void {\n this.buffer = '';\n }\n\n /** 获取当前缓冲内容 */\n getBuffer(): string {\n return this.buffer;\n }\n\n /**\n * 解析命令行\n *\n * 支持引号包裹的参数:/config set key \"value with spaces\"\n */\n private parseCommand(line: string): ParsedInput {\n // 去掉开头的 /\n const withoutSlash = line.slice(1);\n\n // 使用简单的分词:支持双引号内的空格\n const tokens = this.tokenize(withoutSlash);\n\n if (tokens.length === 0) {\n return { kind: 'empty' };\n }\n\n const name = tokens[0]?.toLowerCase() ?? '';\n const args = tokens.slice(1);\n\n return { kind: 'command', name, args };\n }\n\n /**\n * 分词器\n *\n * 支持双引号包裹的参数(引号内空格不分割)。\n */\n private tokenize(input: string): string[] {\n const tokens: string[] = [];\n let current = '';\n let inQuotes = false;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (char === '\"') {\n inQuotes = !inQuotes;\n continue;\n }\n\n if (char === ' ' && !inQuotes) {\n if (current.length > 0) {\n tokens.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n // 处理最后一个 token\n if (current.length > 0) {\n tokens.push(current);\n }\n\n return tokens;\n }\n}\n","/**\n * 输出区域组件\n *\n * 负责渲染 REPL 中的所有输出内容:\n * 欢迎信息、执行结果、错误信息、系统消息等。\n */\n\nimport chalk, { Chalk } from 'chalk';\nimport type { HistoryEntry } from '@/cli/repl/types';\nimport type { ZapmycoConfig } from '@/config/types';\nimport type { FinalResult } from '@/core/result/types';\nimport type { TaskGraph } from '@/core/task/types';\nimport type { AgentRegistration } from '@/protocol/capability';\n\n/**\n * 格式化输出内容的工具类\n *\n * 从原 Renderer 中提取的纯格式化逻辑,不依赖 console.log。\n */\nexport class OutputFormatter {\n private readonly c: typeof chalk;\n private readonly cDisabled: typeof chalk;\n\n constructor(private readonly color: boolean) {\n this.c = chalk;\n // 预创建禁用颜色的实例(level: 0)\n this.cDisabled = new Chalk({ level: 0 }) as unknown as typeof chalk;\n }\n\n /** 获取 chalk 实例 */\n private getColor(colorEnabled = this.color): typeof chalk {\n return colorEnabled ? this.c : this.cDisabled;\n }\n\n /** 格式化欢迎信息 */\n formatWelcome(version: string): string[] {\n const c = this.getColor();\n return [\n '',\n ` 🍄 ${c.bold(`zapmyco@${version}`)}`,\n '',\n ' 欢迎回来!',\n '',\n c.gray('─'.repeat(90)),\n '',\n ];\n }\n\n /** 格式化错误信息 */\n formatError(error: Error): string[] {\n const c = this.getColor();\n const lines: string[] = ['', ''];\n\n const zapmycoError = error as { code?: string; context?: Record<string, unknown> };\n\n if (zapmycoError.code) {\n lines.push(`${c.red.bold(` ✗ [${zapmycoError.code}]`)} ${error.message}`);\n if (zapmycoError.context && Object.keys(zapmycoError.context).length > 0) {\n lines.push(c.gray(` 详情: ${JSON.stringify(zapmycoError.context)}`));\n }\n } else {\n lines.push(`${c.red.bold(' ✗ 执行失败:')} ${error.message}`);\n }\n\n lines.push('');\n return lines;\n }\n\n /** 格式化执行结果 */\n formatResult(result: FinalResult): string[] {\n const c = this.getColor();\n const statusIcon =\n result.overallStatus === 'success'\n ? '✅'\n : result.overallStatus === 'partial-failure'\n ? '⚠️'\n : '❌';\n\n const lines: string[] = [\n '',\n c.gray(' ┌────────────────────────────────────────────┐'),\n ` │ ${statusIcon} ${c.bold('执行完成')}`,\n c.gray(' ├────────────────────────────────────────────┤'),\n ` │ ${c.gray('目标:')} ${result.summary.slice(0, 40)}`,\n ` │ ${c.gray('状态:')} ${\n result.overallStatus === 'success'\n ? c.green('成功')\n : result.overallStatus === 'partial-failure'\n ? c.yellow('部分成功')\n : c.red('失败')\n }`,\n ` │ ${c.gray('耗时:')} ${(result.totalDuration / 1000).toFixed(1)}s · ${c.gray('Token:')} ${result.totalTokenUsage.totalTokens.toLocaleString()}`,\n ` │ ${c.gray('成本:')} $${result.totalTokenUsage.estimatedCostUsd.toFixed(4)}`,\n ];\n\n if (result.taskResults.length > 0) {\n lines.push(c.gray(' ├────────────────────────────────────────────┤'));\n lines.push(` │ ${c.bold('任务拆分')} (${result.taskResults.length} 个子任务):`);\n for (const tr of result.taskResults) {\n const icon =\n tr.status === 'success'\n ? c.green('✓')\n : tr.status === 'partial'\n ? c.yellow('~')\n : c.red('✗');\n lines.push(` │ ${icon} ${tr.taskId.slice(0, 12)}...`);\n }\n }\n\n if (result.allArtifacts.length > 0) {\n lines.push(c.gray(' ├────────────────────────────────────────────┤'));\n lines.push(` │ ${c.bold('制品:')}`);\n for (const artifact of result.allArtifacts) {\n const icon = artifact.type === 'pull-request' ? '🔗' : '📄';\n lines.push(` │ ${icon} ${artifact.description} (${artifact.reference})`);\n }\n }\n\n if (result.nextSteps && result.nextSteps.length > 0) {\n lines.push(c.gray(' ├────────────────────────────────────────────┤'));\n lines.push(` │ ${c.bold('建议:')}`);\n for (let i = 0; i < result.nextSteps.length; i++) {\n lines.push(` │ ${i + 1}. ${result.nextSteps[i]}`);\n }\n }\n\n lines.push(c.gray(' └────────────────────────────────────────────┘'));\n lines.push('');\n return lines;\n }\n\n /** 格式化任务拆分概览 */\n formatTaskGraph(graph: TaskGraph): string[] {\n const c = this.getColor();\n const lines: string[] = [\n '',\n c.bold(' 📋 任务拆分概览'),\n c.gray(` 共 ${graph.nodes.size} 个子任务,${graph.layers.length} 层并行`),\n '',\n ];\n\n for (let layerIdx = 0; layerIdx < graph.layers.length; layerIdx++) {\n const layer = graph.layers[layerIdx];\n if (!layer) continue;\n lines.push(c.gray(` 第 ${layerIdx + 1} 层 (可并行):`));\n for (const taskId of layer) {\n const task = graph.nodes.get(taskId);\n if (task) {\n const statusIcon = this.statusToIcon(task.status, c);\n lines.push(` ${statusIcon} ${c.cyan(task.name)} - ${task.description.slice(0, 50)}`);\n }\n }\n lines.push('');\n }\n\n return lines;\n }\n\n /** 格式化 Agent 列表 */\n formatAgents(agents: AgentRegistration[]): string[] {\n const c = this.getColor();\n const lines: string[] = ['', c.bold(' 🤖 已注册 Agent'), ''];\n\n if (agents.length === 0) {\n lines.push(c.gray(' 暂无已注册的 Agent'));\n lines.push('');\n return lines;\n }\n\n lines.push(\n ` ${c.bold('ID').padEnd(20)} ${c.bold('状态').padEnd(10)} ${c.bold('负载').padEnd(8)} ${c.bold('能力')}`\n );\n lines.push(c.gray(` ${'─'.repeat(60)}`));\n\n for (const agent of agents) {\n const statusDot =\n agent.status === 'online'\n ? c.green('●')\n : agent.status === 'busy'\n ? c.yellow('●')\n : c.gray('○');\n const capabilities = agent.capabilities.map((cap) => cap.name).join(', ');\n\n lines.push(\n ` ${agent.agentId.padEnd(20)} ${statusDot} ${String(agent.status).padEnd(8)} ${String(agent.currentLoad).padEnd(8)} ${capabilities}`\n );\n }\n\n lines.push('');\n return lines;\n }\n\n /** 格式化配置信息 */\n formatConfig(config: ZapmycoConfig): string[] {\n const c = this.getColor();\n const lines: string[] = ['', c.bold(' ⚙️ 当前配置'), '', c.bold(' LLM:')];\n\n lines.push(` 默认模型: ${config.llm.defaultModel}`);\n const defaultModelConfig = config.llm.models[config.llm.defaultModel];\n if (defaultModelConfig) {\n lines.push(` 提供商: ${defaultModelConfig.provider}`);\n lines.push(` 模型 ID: ${defaultModelConfig.modelId}`);\n }\n const auth = config.llm.providers[defaultModelConfig?.provider ?? 'anthropic'];\n lines.push(` API Key: ${auth?.apiKey ? c.gray('***已配置***') : c.red('(未配置)')}`);\n\n lines.push(c.bold(' 调度器:'));\n lines.push(` 最大并行: ${config.scheduler.maxConcurrency}`);\n lines.push(` 单 Agent 最大并发: ${config.scheduler.maxPerAgent}`);\n lines.push(` 任务超时: ${(config.scheduler.taskTimeoutMs / 1000 / 60).toFixed(0)} 分钟`);\n lines.push(` 最大重试: ${config.scheduler.maxRetries}`);\n\n lines.push(c.bold(' CLI:'));\n lines.push(` 颜色输出: ${config.cli.color ? c.green('开启') : c.gray('关闭')}`);\n lines.push(` 调试模式: ${config.cli.debug ? c.green('开启') : c.gray('关闭')}`);\n lines.push(` 输出格式: ${config.cli.outputFormat}`);\n\n lines.push(c.bold(' Agents:'));\n for (const agent of config.agents) {\n const statusIcon = agent.enabled ? c.green('✓') : c.gray('✗');\n lines.push(` ${statusIcon} ${agent.id}`);\n }\n\n lines.push('');\n return lines;\n }\n\n /** 格式化历史记录 */\n formatHistory(entries: HistoryEntry[]): string[] {\n const c = this.getColor();\n const lines: string[] = ['', c.bold(' 📜 会话历史'), ''];\n\n if (entries.length === 0) {\n lines.push(c.gray(' 暂无历史记录'));\n lines.push('');\n return lines;\n }\n\n for (const entry of entries) {\n const time = new Date(entry.timestamp).toTimeString().slice(0, 8);\n const inputPreview = entry.input.length > 50 ? `${entry.input.slice(0, 47)}...` : entry.input;\n\n let line = ` #${String(entry.id).padStart(3)} ${c.gray(`[${time}]`)} ${inputPreview}`;\n\n if (entry.durationMs !== undefined) {\n line += c.gray(` (${(entry.durationMs / 1000).toFixed(1)}s)`);\n }\n\n lines.push(line);\n }\n\n lines.push('');\n return lines;\n }\n\n /** 格式化会话状态 */\n formatStatus(stats: {\n totalRequests: number;\n successCount: number;\n failureCount: number;\n totalTokens: number;\n totalCostUsd: number;\n state: string;\n }): string[] {\n const c = this.getColor();\n const lines: string[] = ['', c.bold(' 📊 会话状态'), ''];\n\n const stateLabel =\n stats.state === 'idle'\n ? c.green('空闲')\n : stats.state === 'executing'\n ? c.magenta('执行中')\n : c.gray('关闭中');\n\n lines.push(` 状态: ${stateLabel}`);\n lines.push(` 总请求数: ${stats.totalRequests}`);\n lines.push(` 成功: ${c.green(String(stats.successCount))}`);\n lines.push(\n ` 失败: ${stats.failureCount > 0 ? c.red(String(stats.failureCount)) : String(stats.failureCount)}`\n );\n lines.push(` Token 消耗: ${stats.totalTokens.toLocaleString()}`);\n lines.push(` 总成本: $${stats.totalCostUsd.toFixed(4)}`);\n lines.push('');\n return lines;\n }\n\n private statusToIcon(status: string, c: typeof chalk): string {\n switch (status) {\n case 'succeeded':\n return `${c.green(' ✓')}`;\n case 'running':\n return `${c.magenta(' ⟳')}`;\n case 'failed':\n return `${c.red(' ✗')}`;\n case 'cancelled':\n return `${c.gray(' ⊘')}`;\n case 'skipped':\n return `${c.gray(' ⊘')}`;\n default:\n return `${c.gray(' ○')}`;\n }\n }\n}\n","/**\n * 终端输出渲染器(TUI 适配版)\n *\n * 在 pi-tui 架构下,Renderer 不再直接 console.log,\n * 而是将格式化后的内容追加到 OutputArea 组件中。\n */\n\nimport { OutputFormatter } from '@/cli/repl/components/output-area';\nimport type { HistoryEntry, ReplOptions, SessionStats } from '@/cli/repl/types';\nimport type { ZapmycoConfig } from '@/config/types';\nimport type { FinalResult } from '@/core/result/types';\nimport type { TaskGraph } from '@/core/task/types';\nimport type { AgentRegistration } from '@/protocol/capability';\n\n/**\n * 渲染器实现\n *\n * 协调 OutputFormatter 和 OutputArea 之间的内容输出。\n */\nexport class Renderer {\n private readonly formatter: OutputFormatter;\n\n constructor(opts: ReplOptions) {\n this.formatter = new OutputFormatter(opts.color);\n }\n\n /** 获取底层格式化器(供 OutputArea 直接使用) */\n getFormatter(): OutputFormatter {\n return this.formatter;\n }\n\n /** 渲染欢迎信息 → 返回格式化行 */\n renderWelcome(version: string): string[] {\n return this.formatter.formatWelcome(version);\n }\n\n /** 渲染错误信息 → 返回格式化行 */\n renderError(error: Error): string[] {\n return this.formatter.formatError(error);\n }\n\n /** 渲染最终执行结果 → 返回格式化行 */\n renderResult(result: FinalResult): string[] {\n return this.formatter.formatResult(result);\n }\n\n /** 渲染任务拆分概览 → 返回格式化行 */\n renderTaskGraph(graph: TaskGraph): string[] {\n return this.formatter.formatTaskGraph(graph);\n }\n\n /** 渲染 Agent 列表 → 返回格式化行 */\n renderAgents(agents: AgentRegistration[]): string[] {\n return this.formatter.formatAgents(agents);\n }\n\n /** 渲染配置信息 → 返回格式化行 */\n renderConfig(config: ZapmycoConfig): string[] {\n return this.formatter.formatConfig(config);\n }\n\n /** 渲染历史记录 → 返回格式化行 */\n renderHistory(entries: HistoryEntry[]): string[] {\n return this.formatter.formatHistory(entries);\n }\n\n /** 渲染会话状态 → 返回格式化行 */\n renderStatus(stats: SessionStats): string[] {\n return this.formatter.formatStatus(stats);\n }\n}\n\n/** 类型别名(供 session 内部引用) */\nexport type RendererImpl = Renderer;\n","/**\n * REPL Agent 工具注册表\n *\n * 定义 REPL 场景下 Agent 可用的工具集合。\n * 工具按能力域分组,支持按需加载。\n *\n * @module cli/repl/repl-agent-tools\n */\n\nimport type { ToolRegistration } from '@/core/agent-runtime';\n\n/**\n * 创建 REPL 基础工具集\n *\n * 第一阶段工具:验证 Agent 工具调用链路的端到端连通性。\n * 后续阶段在此基础扩展:文件读写、Shell 执行、Git 操作等。\n */\nexport function createReplBuiltinTools(): ToolRegistration[] {\n return [\n {\n id: 'get_current_time',\n label: '获取当前时间',\n description:\n '获取当前日期和时间。当用户询问时间、需要时间戳、或需要时间相关上下文时调用此工具。',\n execute: async () => ({\n content: [{ type: 'text', text: new Date().toISOString() }],\n details: { timestamp: Date.now() },\n }),\n },\n {\n id: 'get_workdir_info',\n label: '获取工作目录信息',\n description: '获取当前工作目录路径和系统平台信息。当需要了解当前项目位置或运行环境时调用。',\n execute: async () => ({\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n cwd: process.cwd(),\n platform: process.platform,\n arch: process.arch,\n nodeVersion: process.version,\n },\n null,\n 2\n ),\n },\n ],\n details: { cwd: process.cwd(), platform: process.platform },\n }),\n },\n {\n id: 'read_file',\n label: '读取文件',\n description: '读取指定路径的文本文件内容。参数 path 为文件绝对或相对路径。',\n parameters: {\n type: 'object',\n properties: {\n path: { type: 'string', description: '文件路径' },\n },\n required: ['path'],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n execute: async (_toolCallId: string, params: any): Promise<any> => {\n const fs = await import('node:fs/promises');\n try {\n const content = await fs.readFile(params.path, 'utf-8');\n return {\n content: [{ type: 'text', text: content }],\n details: { path: params.path, size: content.length },\n };\n } catch (error) {\n return {\n content: [\n {\n type: 'text',\n text: `读取失败: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n details: { path: params.path, error: true },\n };\n }\n },\n },\n ];\n}\n","/**\n * pi-tui 主题配置\n *\n * 定义 zapmyco TUI 的颜色方案和组件样式。\n * 风格:灰色边框 + 简洁配色,与原有 CLI 风格保持一致。\n */\n\nimport type { EditorTheme, SelectListTheme } from '@mariozechner/pi-tui';\nimport chalk, { Chalk } from 'chalk';\n\n/** 根据颜色开关获取 chalk 实例 */\nfunction makeColor(colorEnabled: boolean): typeof chalk {\n return colorEnabled ? chalk : (new Chalk({ level: 0 }) as unknown as typeof chalk);\n}\n\n/**\n * 创建 zapmyco pi-tui 主题\n */\nexport function createTheme(colorEnabled: boolean) {\n const c = makeColor(colorEnabled);\n\n /** 基础 selectList 主题 */\n const baseSelectListTheme: SelectListTheme = {\n selectedPrefix: (text: string) => c.cyan(text),\n selectedText: (text: string) => c.bold(c.cyan(text)),\n description: (text: string) => c.gray(text),\n scrollInfo: (text: string) => c.gray(text),\n noMatch: (text: string) => c.gray(text),\n };\n\n /** Editor 主题:灰色边框,匹配原有的 ─ 分隔线风格 */\n const editorTheme: EditorTheme = {\n borderColor: (text: string) => c.gray(text),\n selectList: baseSelectListTheme,\n };\n\n return {\n /** 主文本色 */\n text: (s: string) => s,\n\n /** 加粗 */\n bold: (s: string) => c.bold(s),\n\n /** 灰色/弱化文本 */\n dim: (s: string) => c.gray(s),\n\n /** 强调色 - 青色 */\n accent: (s: string) => c.cyan(s),\n\n /** 成功 - 绿色 */\n success: (s: string) => c.green(s),\n\n /** 错误 - 红色 */\n error: (s: string) => c.red(s),\n\n /** 警告 - 黄色 */\n warning: (s: string) => c.yellow(s),\n\n /** 边框色 - 灰色 */\n border: (s: string) => c.gray(s),\n\n /** Header 文本 */\n heading: (s: string) => c.bold(s),\n\n editorTheme,\n selectListTheme: baseSelectListTheme,\n };\n}\n\nexport type ZapmycoTheme = ReturnType<typeof createTheme>;\n","/**\n * PiAiProvider — 基于 @mariozechner/pi-ai 的 LLM 提供商适配器\n *\n * 将 pi-ai 的统一 LLM API 适配为 zapmyco 的 ILlmProvider 接口。\n * 支持多提供商、流式响应、工具调用和成本追踪。\n */\n\nimport type { KnownProvider } from '@mariozechner/pi-ai';\nimport {\n type AssistantMessage,\n type Context,\n complete,\n getModel,\n type Message,\n stream,\n} from '@mariozechner/pi-ai';\nimport type { LlmConfig, ModelConfig } from '@/config/types';\nimport { logger } from '@/infra/logger';\nimport { costTracker } from '@/llm/cost-tracker';\nimport type { ILlmProvider } from '@/llm/provider';\nimport type { ChatMessage, LlmCallOptions, LlmResponse } from '@/llm/types';\n\n/**\n * 解析模型标识符\n *\n * 支持格式:provider/modelId(如 anthropic/claude-sonnet-4-20250514)\n * 导出供其他模块复用(如 REPL Session 为 Agent 解析 Model 对象)\n */\nexport function parseModelKey(key: string): { provider: string; modelId: string } | null {\n const slashIndex = key.indexOf('/');\n if (slashIndex <= 0 || slashIndex >= key.length - 1) {\n return null;\n }\n return {\n provider: key.slice(0, slashIndex),\n modelId: key.slice(slashIndex + 1),\n };\n}\n\n/**\n * 将 zapmyco 的 ChatMessage 转换为 pi-ai 的 Message 数组\n */\nfunction toPiAiMessages(messages: ChatMessage[]): Message[] {\n const result: Message[] = [];\n\n for (const msg of messages) {\n // system 消息在 buildContext 中作为 systemPrompt 处理\n if (msg.role === 'system') {\n continue;\n }\n\n if (msg.role === 'user') {\n result.push({\n role: 'user',\n content: msg.content,\n timestamp: Date.now(),\n });\n } else if (msg.role === 'assistant') {\n result.push({\n role: 'assistant',\n content: [{ type: 'text', text: msg.content }],\n api: 'anthropic-messages',\n provider: 'anthropic',\n model: '',\n usage: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: 'stop',\n timestamp: Date.now(),\n } satisfies AssistantMessage);\n }\n }\n\n return result;\n}\n\n/**\n * 从消息列表中提取 system prompt\n */\nfunction extractSystemPrompt(messages: ChatMessage[]): string | undefined {\n return messages.find((m) => m.role === 'system')?.content;\n}\n\n/**\n * 构建 pi-ai 的 Context 对象\n */\nfunction buildContext(messages: ChatMessage[]): Context {\n const systemPrompt = extractSystemPrompt(messages);\n const piMessages = toPiAiMessages(messages);\n\n if (systemPrompt) {\n return { systemPrompt, messages: piMessages };\n }\n return { messages: piMessages };\n}\n\n/**\n * 构建 pi-ai 的 StreamOptions(过滤掉 undefined 值)\n */\nfunction buildStreamOptions(\n options?: LlmCallOptions,\n defaults?: { maxTokens?: number; temperature?: number },\n extra?: { apiKey?: string }\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n const temperature = options?.temperature ?? defaults?.temperature;\n if (temperature !== undefined) {\n result.temperature = temperature;\n }\n\n const maxTokens = options?.maxTokens ?? defaults?.maxTokens;\n if (maxTokens !== undefined) {\n result.maxTokens = maxTokens;\n }\n\n if (options?.timeoutMs !== undefined) {\n result.timeoutMs = options.timeoutMs;\n }\n\n if (options?.signal !== undefined) {\n result.signal = options.signal;\n }\n\n // 自定义 API Key(用于非环境变量方式配置的提供商,如 Deepseek)\n if (extra?.apiKey) {\n result.apiKey = extra.apiKey;\n }\n\n if (options?.timeoutMs !== undefined) {\n result.timeoutMs = options.timeoutMs;\n }\n\n return result;\n}\n\n/**\n * PiAiProvider — ILlmProvider 的 pi-ai 实现\n *\n * 使用方式:\n * ```typescript\n * import { PiAiProvider } from '@/llm/pi-ai-provider';\n * import type { LlmConfig } from '@/config/types';\n *\n * const provider = new PiAiProvider(config.llm);\n * const response = await provider.chat([{ role: 'user', content: 'Hello' }]);\n * ```\n */\nexport class PiAiProvider implements ILlmProvider {\n readonly providerId = 'pi-ai';\n\n private config: LlmConfig;\n private resolvedModel: ReturnType<typeof getModel> | null = null;\n\n constructor(config: LlmConfig) {\n this.config = config;\n }\n\n /** 获取或懒解析 pi-ai Model 实例 */\n private resolveModel(overrideModel?: string) {\n const modelKey = overrideModel ?? this.config.defaultModel;\n\n // 如果已缓存且 key 相同,直接返回\n if (this.resolvedModel && this.resolvedModel.id === modelKey) {\n return this.resolvedModel;\n }\n\n const parsed = parseModelKey(modelKey);\n if (!parsed) {\n throw new Error(`无效的模型标识符格式: ${modelKey},期望格式为 provider/modelId`);\n }\n\n // 优先从 models 配置中获取详细信息\n const modelConfig = this.config.models[modelKey] as ModelConfig | undefined;\n\n const provider = (modelConfig?.provider ?? parsed.provider) as KnownProvider;\n const modelId = modelConfig?.modelId ?? parsed.modelId;\n\n // 始终用同 provider 的已知模型作为基础模板(保证返回有效 Model 对象)\n const baseModelId = provider === 'anthropic' ? 'claude-sonnet-4-20250514' : modelId; // 非 anthropic provider 尝试直接获取\n\n logger.debug('解析模型', { provider, modelId, baseModelId, modelKey });\n\n try {\n // biome-ignore lint/suspicious/noExplicitAny: pi-ai 泛型约束需要运行时动态类型\n this.resolvedModel = getModel(provider as any, baseModelId as any);\n } catch {\n // 最终兜底:使用 anthropic 的已知模型作为基础\n logger.warn(`无法获取 ${provider}/${baseModelId},回退到默认基础模型`);\n // biome-ignore lint/suspicious/noExplicitAny: pi-ai 泛型约束需要运行时动态类型\n this.resolvedModel = getModel('anthropic' as any, 'claude-sonnet-4-20250514' as any);\n }\n\n // 防御性检查:确保拿到有效对象\n if (!this.resolvedModel) {\n throw new Error(`无法初始化模型 ${modelKey}:pi-ai 返回了无效的模型对象`);\n }\n\n // 无条件覆盖自定义属性\n // name 用于显示,id 是发送给 API 的模型名(必须是 API 实际接受的值)\n this.resolvedModel.name = modelKey;\n this.resolvedModel.id = modelId;\n\n if (modelConfig?.baseUrl) {\n logger.debug('覆盖模型 baseUrl', {\n original: this.resolvedModel.baseUrl,\n custom: modelConfig.baseUrl,\n });\n this.resolvedModel.baseUrl = modelConfig.baseUrl;\n }\n\n return this.resolvedModel;\n }\n\n /**\n * 获取当前模型的认证信息(API Key)\n */\n private getApiKey(modelKey: string): string | undefined {\n const modelConfig = this.config.models[modelKey] as ModelConfig | undefined;\n const providerName = modelConfig?.provider;\n\n // 优先从对应提供商的 auth 配置中获取\n if (providerName) {\n const auth = this.config.providers[providerName];\n if (auth?.apiKey) {\n return auth.apiKey;\n }\n }\n\n return undefined;\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(messages: ChatMessage[], options?: LlmCallOptions): Promise<LlmResponse> {\n const model = this.resolveModel(options?.model);\n const context = buildContext(messages);\n\n const modelKey = options?.model ?? this.config.defaultModel;\n const apiKey = this.getApiKey(modelKey);\n const streamOptions = buildStreamOptions(\n options,\n this.config.defaults,\n apiKey !== undefined ? { apiKey } : undefined\n );\n\n logger.debug('发送 LLM 请求', {\n model: model.name,\n messageCount: context.messages.length,\n });\n\n const startTime = Date.now();\n const response = await complete(model, context, streamOptions);\n const elapsedMs = Date.now() - startTime;\n\n // 提取文本内容\n const content = this.extractTextContent(response.content);\n\n // 记录成本\n costTracker.record(\n {\n inputTokens: response.usage.input,\n outputTokens: response.usage.output,\n totalTokens: response.usage.totalTokens,\n },\n model.name\n );\n\n logger.debug('LLM 响应完成', {\n model: model.name,\n inputTokens: response.usage.input,\n outputTokens: response.usage.output,\n elapsedMs,\n });\n\n const result: LlmResponse = {\n content,\n inputTokens: response.usage.input,\n outputTokens: response.usage.output,\n model: model.name,\n truncated: response.stopReason === 'length',\n };\n\n if (response.responseId !== undefined) {\n result.id = response.responseId;\n }\n\n return result;\n }\n\n /**\n * 流式聊天请求\n */\n async *chatStream(\n messages: ChatMessage[],\n options?: LlmCallOptions\n ): AsyncGenerator<string, void, unknown> {\n const model = this.resolveModel(options?.model);\n const context = buildContext(messages);\n\n const modelKey = options?.model ?? this.config.defaultModel;\n const apiKey = this.getApiKey(modelKey);\n const streamOptions = buildStreamOptions(\n options,\n this.config.defaults,\n apiKey !== undefined ? { apiKey } : undefined\n );\n\n logger.debug('发送流式 LLM 请求', {\n model: model.name,\n messageCount: context.messages.length,\n });\n\n const startTime = Date.now();\n const eventStream = stream(model, context, streamOptions);\n\n let finalUsage = { input: 0, output: 0, totalTokens: 0, costTotal: 0 };\n\n for await (const event of eventStream) {\n switch (event.type) {\n case 'text_delta':\n yield event.delta;\n break;\n\n case 'done':\n finalUsage = {\n input: event.message.usage.input,\n output: event.message.usage.output,\n totalTokens: event.message.usage.totalTokens,\n costTotal: event.message.usage.cost.total,\n };\n break;\n\n case 'error':\n logger.error('流式 LLM 请求出错', {\n model: model.name,\n reason: event.reason,\n error: event.error.errorMessage,\n });\n throw new Error(`LLM 流式请求失败: ${event.error.errorMessage ?? event.reason}`);\n }\n }\n\n const elapsedMs = Date.now() - startTime;\n\n // 记录成本\n costTracker.record(\n {\n inputTokens: finalUsage.input,\n outputTokens: finalUsage.output,\n totalTokens: finalUsage.totalTokens,\n },\n model.name\n );\n\n logger.debug('流式 LLM 响应完成', {\n model: model.name,\n inputTokens: finalUsage.input,\n outputTokens: finalUsage.output,\n elapsedMs,\n });\n }\n\n /**\n * 从 pi-ai 的 content 数组中提取纯文本\n */\n private extractTextContent(content: AssistantMessage['content']): string {\n return content\n .filter((block): block is { type: 'text'; text: string } => block.type === 'text')\n .map((block) => block.text)\n .join('');\n }\n}\n","/**\n * REPL 会话核心(pi-tui 版)\n *\n * 使用 @mariozechner/pi-tui 框架替代 readline,\n * 实现完整的 TUI 交互式 REPL:\n * - Editor 组件自带上下边框\n * - 差量渲染,无闪烁\n * - 组件化布局,可扩展\n */\n\nimport type { KnownProvider } from '@mariozechner/pi-ai';\nimport { getModel } from '@mariozechner/pi-ai';\nimport { Container, ProcessTerminal, Text, TUI, wrapTextWithAnsi } from '@mariozechner/pi-tui';\nimport { CommandRegistry } from '@/cli/repl/command-registry';\nimport { createAgentsCommand } from '@/cli/repl/commands/agents-cmd';\nimport { createClearCommand } from '@/cli/repl/commands/clear';\nimport { createConfigCommand } from '@/cli/repl/commands/config-cmd';\n// 导入内置命令\nimport { createHelpCommand } from '@/cli/repl/commands/help';\nimport { createHistoryCommand } from '@/cli/repl/commands/history';\nimport { createQuitCommand } from '@/cli/repl/commands/quit';\nimport { createStatusCommand } from '@/cli/repl/commands/status';\nimport { ZapmycoEditor } from '@/cli/repl/components/custom-editor';\nimport { HistoryStore as HistoryStoreClass } from '@/cli/repl/history-store';\nimport { InputParser } from '@/cli/repl/input-parser';\nimport { Renderer as RendererClass } from '@/cli/repl/renderer';\nimport { createReplBuiltinTools } from '@/cli/repl/repl-agent-tools';\nimport { createTheme } from '@/cli/repl/theme';\nimport type {\n HistoryStore,\n ParsedInput,\n ReplOptions,\n SessionState,\n SessionStats,\n} from '@/cli/repl/types';\nimport type { ZapmycoConfig } from '@/config/types';\nimport { createLlmBasedAgent, type LlmBasedAgent } from '@/core/agent-runtime';\nimport { __VERSION__ } from '@/infra/constants';\nimport { eventBus } from '@/infra/event-bus';\nimport { logger } from '@/infra/logger';\nimport { parseModelKey } from '@/llm/pi-ai-provider';\nimport type { ChatMessage } from '@/llm/types';\n\nconst log = logger.child('repl:session');\n\n/**\n * 输出区域组件\n *\n * 管理所有输出内容的行缓冲,实现 pi-tui 的 render 接口。\n */\nclass OutputArea extends Container {\n private lines: string[] = [];\n\n override render(width: number): string[] {\n // 对每行做自动换行,确保不超过终端宽度\n const result: string[] = [];\n for (const line of this.lines) {\n result.push(...wrapTextWithAnsi(line, width));\n }\n return result;\n }\n\n /** 追加多行内容 */\n append(lines: string[]): void {\n this.lines.push(...lines);\n this.invalidate();\n }\n\n /** 追加文本到当前行末尾(用于流式输出) */\n appendText(text: string): void {\n if (this.lines.length === 0) {\n this.lines.push(text);\n } else {\n this.lines[this.lines.length - 1] += text;\n }\n this.invalidate();\n }\n\n /** 清空所有内容 */\n clear(): void {\n this.lines = [];\n this.invalidate();\n }\n}\n\n/** 默认提示符(用于显示/格式化) */\nconst DEFAULT_PROMPT = '\\u276f ';\n\n/** 默认续行提示符 */\nconst DEFAULT_CONTINUATION_PROMPT = '... ';\n\n/**\n * REPL 会话实现\n */\nexport class ReplSession {\n private readonly tui: TUI;\n private readonly editor: ZapmycoEditor;\n private readonly outputArea: OutputArea;\n private readonly header: Text;\n private readonly footer: Text;\n private readonly options: ReplOptions;\n private _state: SessionState = 'idle';\n private readonly parser: InputParser;\n private readonly registry: CommandRegistry;\n private readonly renderer: RendererClass;\n private readonly history: HistoryStoreClass;\n private currentTaskAbort: AbortController | null = null;\n\n /** Agent 实例(会话级复用,替代直接 LLM 调用) */\n private agent: LlmBasedAgent;\n\n /** 当前正在执行的 taskId(用于取消操作) */\n private currentTaskId: string | null = null;\n\n /** 多轮对话上下文(兼容保留,Agent 内部也维护历史) */\n private conversationHistory: ChatMessage[] = [];\n\n // 会话统计\n private stats: SessionStats = {\n totalRequests: 0,\n successCount: 0,\n failureCount: 0,\n totalTokens: 0,\n totalCostUsd: 0,\n state: 'idle',\n };\n\n constructor(readonly config: ZapmycoConfig) {\n this.options = {\n color: config.cli.color,\n debug: config.cli.debug,\n maxHistorySize: 100,\n prompt: DEFAULT_PROMPT,\n continuationPrompt: DEFAULT_CONTINUATION_PROMPT,\n };\n\n // 创建主题\n const theme = createTheme(this.options.color);\n\n // 初始化 TUI\n const terminal = new ProcessTerminal();\n this.tui = new TUI(terminal);\n\n // 创建组件\n this.header = new Text('', 1, 0);\n this.outputArea = new OutputArea();\n this.footer = new Text('', 1, 0);\n this.editor = new ZapmycoEditor(this.tui, theme.editorTheme);\n\n // 组装组件树:header → outputArea → footer → editor(带边框)\n const root = new Container();\n root.addChild(this.header);\n root.addChild(this.outputArea);\n root.addChild(this.footer);\n root.addChild(this.editor);\n\n this.tui.addChild(root);\n this.tui.setFocus(this.editor);\n\n this.parser = new InputParser();\n this.registry = new CommandRegistry(this);\n this.renderer = new RendererClass(this.options);\n this.history = new HistoryStoreClass(this.options.maxHistorySize);\n\n // 初始化 Agent 实例(替代直接 LLM 调用)\n this.agent = this.createReplAgent();\n\n // 注册所有内置命令\n this.registerBuiltinCommands();\n\n // 注册 Agent 工具\n this.registerBuiltinTools();\n\n // 绑定编辑器事件\n this.setupEditorHandlers();\n\n // 设置信号处理\n this.setupSignalHandlers();\n\n // 设置事件监听\n this.setupEventListeners();\n }\n\n // ============ 公共接口(IReplSession)============\n\n get currentState(): SessionState {\n return this._state;\n }\n\n get replOptions(): Readonly<ReplOptions> {\n return this.options;\n }\n\n /** 启动 REPL 循环 */\n async start(): Promise<void> {\n this._state = 'idle';\n this.updateStatsState();\n\n // 渲染欢迎信息到输出区域\n const welcomeLines = this.renderer.renderWelcome(__VERSION__);\n this.outputArea.append(welcomeLines);\n\n // 设置 header 和 footer\n this.updateHeader();\n this.updateFooter();\n\n // 启动 TUI\n this.tui.start();\n }\n\n /** 优雅关闭会话 */\n async shutdown(reason?: string): Promise<void> {\n if (this._state === 'shutting-down') {\n return;\n }\n\n this._state = 'shutting-down';\n this.updateStatsState();\n\n log.info('REPL 关闭', { reason: reason ?? '未知' });\n\n // 取消正在执行的任务\n this.cancelCurrentTask();\n\n // 发布关闭事件\n eventBus.emit('system:shutdown', { reason });\n\n // 停止 TUI\n this.tui.stop();\n }\n\n /** 获取渲染器引用 */\n getRenderer(): import('@/cli/repl/types').Renderer {\n return this.renderer;\n }\n\n /** 获取历史存储引用 */\n getHistoryStore(): HistoryStore {\n return this.history;\n }\n\n /** 获取会话统计 */\n getStats(): SessionStats {\n return { ...this.stats };\n }\n\n /** 将内容追加到输出区域 */\n appendOutput(lines: string[]): void {\n this.outputArea.append(lines);\n this.tui.requestRender();\n }\n\n /** 清空输出区域 */\n clearOutput(): void {\n this.outputArea.clear();\n this.tui.requestRender();\n }\n\n /** 请求 TUI 重绘 */\n requestRender(): void {\n this.tui.requestRender();\n }\n\n /**\n * 执行用户目标 — 通过 Agent 执行并流式输出回复\n */\n async executeGoal(rawInput: string): Promise<import('@/core/result/types').FinalResult> {\n const startTime = Date.now();\n let historyEntry: import('@/cli/repl/types').HistoryEntry | undefined;\n const taskId = `task-${Date.now()}`;\n\n try {\n // 更新状态\n this._state = 'executing';\n this.updateStatsState();\n this.updateFooter();\n\n // 创建 AbortController 用于取消(兼容保留)\n this.currentTaskAbort = new AbortController();\n\n // 记录到历史\n historyEntry = this.history.push({\n timestamp: Date.now(),\n input: rawInput,\n });\n\n // 发布目标提交事件\n eventBus.emit('goal:submitted', {\n goalId: `goal-${startTime}`,\n rawInput,\n });\n\n // 显示用户输入\n const goalLines: string[] = ['', ` 🎯 ${rawInput}`, '', ' 💬 '];\n this.outputArea.append(goalLines);\n\n // 设置流式输出桥接:Agent EVENT_OUTPUT -> outputArea.appendText()\n const outputHandler = (event: { taskId: string; text: string }) => {\n if (event.taskId === taskId) {\n this.outputArea.appendText(event.text);\n this.tui.requestRender();\n }\n };\n\n // 监听 Agent 错误事件\n const errorHandler = (event: { taskId: string; error: Error }) => {\n if (event.taskId === taskId) {\n log.error('Agent 执行中收到 error 事件', {\n error: event.error.message,\n });\n }\n };\n\n this.agent.on(this.agent.EVENT_OUTPUT, outputHandler);\n this.agent.on(this.agent.EVENT_ERROR, errorHandler);\n this.currentTaskId = taskId;\n\n log.debug('开始通过 Agent 执行目标', {\n taskId,\n taskDescription: rawInput.slice(0, 100),\n });\n\n // 通过 Agent 执行(替代原来的 chatStream)\n const taskResult = await this.agent.execute({\n taskId,\n taskDescription: rawInput,\n workdir: process.cwd(),\n options: {\n timeout: this.config.scheduler.taskTimeoutMs,\n verbose: this.options.debug,\n },\n });\n\n // 移除监听器(防止重复绑定)\n this.agent.off(this.agent.EVENT_OUTPUT, outputHandler);\n this.agent.off(this.agent.EVENT_ERROR, errorHandler);\n\n log.debug('Agent 执行完成', {\n taskId,\n status: taskResult.status,\n hasOutput: taskResult.output != null,\n duration: Date.now() - startTime,\n });\n\n // 根据执行结果渲染到 TUI\n const outputText =\n typeof taskResult.output === 'string'\n ? taskResult.output\n : taskResult.output != null\n ? JSON.stringify(taskResult.output)\n : null;\n\n if (taskResult.status !== 'success') {\n // Agent 返回 failure:渲染错误信息\n const errorMsg = taskResult.error?.message ?? 'Agent 执行失败(无详细错误信息)';\n this.outputArea.appendText(`[错误] ${errorMsg}`);\n log.error('Agent 执行返回 failure', {\n taskId,\n error: taskResult.error,\n status: taskResult.status,\n });\n } else if (outputText) {\n // 成功且有输出:确保文本已显示(兜底,正常情况流式事件已输出)\n this.outputArea.appendText(outputText);\n }\n\n // 追加分隔线\n this.outputArea.append(['', '']);\n const duration = Date.now() - startTime;\n\n // 构建 FinalResult\n const result: import('@/core/result/types').FinalResult = {\n goalId: `goal-${startTime}`,\n overallStatus: taskResult.status === 'success' ? 'success' : 'failure',\n summary: outputText?.slice(0, 200) ?? '(无输出)',\n taskResults: [taskResult],\n allArtifacts: taskResult.artifacts ?? [],\n totalDuration: duration,\n totalTokenUsage: taskResult.tokenUsage ?? {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n estimatedCostUsd: 0,\n },\n };\n\n // 更新统计\n this.stats.totalRequests++;\n if (taskResult.status === 'success') {\n this.stats.successCount++;\n } else {\n this.stats.failureCount++;\n }\n\n // 兼容维护 conversationHistory\n this.conversationHistory.push({ role: 'user', content: rawInput });\n if (outputText) {\n this.conversationHistory.push({\n role: 'assistant',\n content: outputText,\n });\n }\n\n // 发布完成事件\n eventBus.emit('goal:completed', {\n goalId: result.goalId,\n result,\n });\n\n // 更新历史条目\n if (historyEntry) {\n historyEntry.goalId = result.goalId;\n historyEntry.durationMs = duration;\n }\n\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n log.error('目标执行失败', { input: rawInput }, err);\n\n this.stats.totalRequests++;\n this.stats.failureCount++;\n\n eventBus.emit('goal:failed', {\n goalId: `goal-${startTime}`,\n error: err,\n });\n\n // 渲染错误到输出区域\n const errorLines = this.renderer.renderError(err);\n this.outputArea.append(errorLines);\n\n // 返回失败结果\n const duration = Date.now() - startTime;\n return {\n goalId: `goal-${startTime}`,\n overallStatus: 'failure',\n summary: `执行失败: ${err.message}`,\n taskResults: [],\n allArtifacts: [],\n totalDuration: duration,\n totalTokenUsage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n estimatedCostUsd: 0,\n },\n };\n } finally {\n this._state = 'idle';\n this.updateStatsState();\n this.updateFooter();\n this.currentTaskAbort = null;\n this.currentTaskId = null;\n }\n }\n\n // ============ 内部方法(供命令处理器访问)============\n\n /** 获取命令注册表(供 help 命令使用) */\n getCommandRegistry(): unknown {\n return this.registry;\n }\n\n /** 获取输入解析器(供 clear 命令使用) */\n getInputParser(): unknown {\n return this.parser;\n }\n\n // ============ 输入处理核心 ============\n\n /**\n * 处理用户提交的输入\n *\n * 由 editor.onSubmit 触发。\n */\n async handleSubmit(line: string): Promise<void> {\n if (this._state === 'shutting-down') {\n return;\n }\n\n const parsed: ParsedInput = this.parser.parse(line);\n\n switch (parsed.kind) {\n case 'empty':\n // 空行:不做任何事\n break;\n\n case 'incomplete':\n // 多行续行:暂不特殊处理,后续可扩展\n break;\n\n case 'command': {\n // 命令分发\n await this.registry.dispatch(parsed);\n break;\n }\n\n case 'goal': {\n // 自然语言目标执行\n await this.executeGoal(parsed.rawInput);\n break;\n }\n }\n }\n\n // ============ 私有方法 ============\n\n /** 注册所有内置命令 */\n private registerBuiltinCommands(): void {\n this.registry.register(createHelpCommand());\n this.registry.register(createQuitCommand());\n this.registry.register(createClearCommand());\n this.registry.register(createHistoryCommand());\n this.registry.register(createConfigCommand());\n this.registry.register(createAgentsCommand());\n this.registry.register(createStatusCommand());\n }\n\n /**\n * 创建 REPL 专用的 Agent 实例\n *\n * Agent 复用 pi-ai 的 Model 对象进行 LLM 调用,\n * 因此需要从 config.llm 解析 model 并注入到 Agent state。\n */\n private createReplAgent(): LlmBasedAgent {\n const agent = createLlmBasedAgent({\n agentId: 'repl-chat-agent',\n displayName: 'Zapmyco AI 助手',\n capabilities: [\n {\n id: 'chat',\n name: '对话',\n description: '自然语言对话、问答、任务编排',\n category: 'chat',\n },\n ],\n runtimeConfig: this.config.agentRuntime ?? {},\n });\n\n // 将 pi-ai Model 注入到 Agent state(关键:没有这个 Agent 不知道用哪个模型)\n agent.innerAgent.state.model = this.resolveModelForAgent();\n\n // 注入 getApiKey 函数(关键:Agent 内部调用 LLM 时需要解析 API Key)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (agent.innerAgent as any).getApiKey = (_provider: string): string | undefined => {\n const modelKey = this.config.llm.defaultModel;\n const modelConfig = this.config.llm.models[modelKey] as { provider?: string } | undefined;\n const providerName = modelConfig?.provider;\n if (providerName) {\n const auth = this.config.llm.providers[providerName];\n return auth?.apiKey;\n }\n return undefined;\n };\n\n return agent;\n }\n\n /**\n * 为 Agent 解析 pi-ai Model 对象\n *\n * 复用 PiAiProvider 的模型解析逻辑(parseModelKey + getModel),\n * 但不依赖 chat/chatStream 方法。\n */\n private resolveModelForAgent() {\n const modelKey = this.config.llm.defaultModel;\n const parsed = parseModelKey(modelKey);\n if (!parsed) {\n throw new Error(`无效的模型标识符: ${modelKey}`);\n }\n\n const modelConfig = this.config.llm.models[modelKey] as\n | { provider?: string; modelId?: string; baseUrl?: string }\n | undefined;\n\n const provider = (modelConfig?.provider ?? parsed.provider) as KnownProvider;\n const modelId = modelConfig?.modelId ?? parsed.modelId;\n\n // 始终用同 provider 的已知模型作为基础模板(保证返回有效 Model 对象)\n const baseModelId = provider === 'anthropic' ? 'claude-sonnet-4-20250514' : modelId;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let model: any;\n try {\n // biome-ignore lint/suspicious/noExplicitAny: pi-ai 泛型约束需要运行时动态类型\n model = getModel(provider as any, baseModelId as any);\n } catch {\n // 最终兜底\n // biome-ignore lint/suspicious/noExplicitAny: pi-ai 泛型约束需要运行时动态类型\n model = getModel('anthropic' as any, 'claude-sonnet-4-20250514' as any);\n }\n\n if (!model) {\n throw new Error(`无法初始化模型 ${modelKey}:pi-ai 返回了无效的模型对象`);\n }\n\n // 无条件覆盖自定义属性\n model.name = modelKey;\n model.id = modelId;\n\n if (modelConfig?.baseUrl) {\n model.baseUrl = modelConfig.baseUrl;\n }\n\n return model;\n }\n\n /**\n * 注册 REPL 场景下的基础工具\n */\n private registerBuiltinTools(): void {\n this.agent.registerTools(createReplBuiltinTools());\n }\n\n /** 设置编辑器事件绑定 */\n private setupEditorHandlers(): void {\n // 提交输入\n this.editor.onSubmit = (text) => void this.handleSubmit(text);\n\n // Ctrl+C\n let ctrlCPressCount = 0;\n let ctrlCTimer: ReturnType<typeof setTimeout> | undefined;\n\n this.editor.onCtrlC = () => {\n if (this._state === 'executing') {\n // 执行中:取消任务\n this.cancelCurrentTask();\n this.outputArea.append(['', ' 任务已取消', '']);\n return;\n }\n\n // 空闲中:累计按键次数\n ctrlCPressCount++;\n if (ctrlCPressCount >= 2) {\n this.outputArea.append(['', ' 再见!', '']);\n void this.shutdown('用户连续按下 Ctrl+C');\n return;\n }\n\n this.outputArea.append(['', ' (再次按下 Ctrl+C 可强制退出)', '']);\n\n clearTimeout(ctrlCTimer);\n ctrlCTimer = setTimeout(() => {\n ctrlCPressCount = 0;\n }, 3000);\n };\n\n // Ctrl+D\n this.editor.onCtrlD = () => {\n this.outputArea.append(['', ' 再见!', '']);\n void this.shutdown('收到 EOF (Ctrl+D)');\n };\n }\n\n /** 设置信号处理 */\n private setupSignalHandlers(): void {\n process.on('SIGINT', () => {\n // 由 editor.onCtrlC 处理,这里防止进程意外退出\n });\n }\n\n /** 设置事件监听 */\n private setupEventListeners(): void {\n eventBus.on('system:shutdown', ({ reason }) => {\n log.debug(`收到系统关闭信号: ${reason ?? '未知'}`);\n });\n }\n\n /** 取消当前正在执行的任务 */\n private cancelCurrentTask(): void {\n // 通过 Agent 取消(优先)\n if (this.currentTaskId !== null) {\n void this.agent.cancel(this.currentTaskId);\n this.currentTaskId = null;\n }\n // 兼容旧的 AbortController 方式\n if (this.currentTaskAbort !== null) {\n this.currentTaskAbort.abort();\n this.currentTaskAbort = null;\n }\n }\n\n /** 更新统计中的状态字段 */\n private updateStatsState(): void {\n this.stats.state = this._state;\n }\n\n /** 更新 header 文本 */\n private updateHeader(): void {\n const theme = createTheme(this.options.color);\n this.header.setText(theme.heading(` zapmyco@${__VERSION__}`));\n }\n\n /** 更新 footer 文本 */\n private updateFooter(): void {\n const theme = createTheme(this.options.color);\n const stateLabel =\n this._state === 'idle'\n ? theme.success('空闲')\n : this._state === 'executing'\n ? theme.warning('执行中')\n : theme.dim('关闭中');\n this.footer.setText(` ${stateLabel}`);\n }\n}\n","/**\n * REPL 模块入口\n *\n * 导出 startRepl() 函数作为 REPL 交互模式的启动入口。\n */\n\nimport { ReplSession } from '@/cli/repl/session';\nimport { loadConfig } from '@/config/loader';\n\n/**\n * 启动 REPL 交互模式\n *\n * 加载配置 → 创建会话 → 进入输入循环\n */\nexport async function startRepl(): Promise<void> {\n const config = await loadConfig();\n const session = new ReplSession(config);\n await session.start();\n}\n","#!/usr/bin/env node\n\n/**\n * zapmyco CLI 入口\n *\n * AI 总管命令行界面。\n *\n * 使用方式:\n * zapmyco 进入交互式 REPL 模式\n * zapmyco run <goal> 直接执行单次目标\n * zapmyco agents 列出可用 Agent\n * zapmyco config 管理配置\n * zapmyco version 显示版本号\n */\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport { startRepl } from '@/cli/repl/index';\nimport { __VERSION__, APP_NAME } from '@/infra/constants';\n\n// ============ 主程序 ============\n\nconst program = new Command();\n\nprogram\n .name(APP_NAME)\n .description('AI 原生并行任务编排系统 -- AI 总管')\n .version(__VERSION__, '-v, --version', '显示版本号')\n .helpOption('-h, --help', '显示帮助信息');\n\n// 默认命令:进入 REPL 模式\nprogram.action(async () => {\n try {\n await startRepl();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red('REPL 启动失败:'), message);\n process.exit(1);\n }\n});\n\n// run 命令:直接执行目标\nprogram\n .command('run')\n .description('直接执行一个目标(非交互模式)')\n .argument('<goal>', '要执行的目标描述')\n .option('-j, --json', '以 JSON 格式输出结果')\n .option('--no-color', '禁用颜色输出')\n .action((goal, _options) => {\n console.log(`🎯 目标: ${goal}`);\n console.log(chalk.yellow('\\n 任务执行引擎即将推出,敬请期待!\\n'));\n });\n\n// agents 命令:列出可用 Agent\nprogram\n .command('agents')\n .description('列出已注册的 Agent 及其状态')\n .action(() => {\n console.log(chalk.cyan('\\n 已注册 Agent:\\n'));\n console.log(chalk.gray(' · code-agent 代码专家'));\n console.log(chalk.gray(' · security-scanner 安全扫描'));\n console.log(chalk.gray(' · research-agent 信息搜集'));\n console.log(chalk.gray(' · planning-agent 规划安排'));\n console.log(chalk.yellow('\\n Agent 注册中心即将完全启用\\n'));\n });\n\n// config 命令\nprogram\n .command('config')\n .description('管理配置')\n .action(() => {\n console.log(chalk.cyan('配置管理功能即将推出'));\n });\n\n// 解析命令行参数\nprogram.parse();\n"],"mappings":"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"}