@qxbyte/muse 0.1.3 → 0.2.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.
- package/README.md +101 -37
- package/dist/cli.js +6610 -1283
- package/dist/cli.js.map +1 -1
- package/dist/index.js +2232 -280
- package/dist/index.js.map +1 -1
- package/package.json +11 -3
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.tsx","../src/app.tsx","../src/components/BgTextInput.tsx","../src/components/StartupBanner.tsx","../src/components/MessageView.tsx","../node_modules/chalk/source/vendor/ansi-styles/index.js","../node_modules/chalk/source/vendor/supports-color/index.js","../node_modules/chalk/source/utilities.js","../node_modules/chalk/source/index.js","../src/components/PermissionPrompt.tsx","../src/components/ModelSelector.tsx","../src/components/Selector.tsx","../src/components/SessionSelector.tsx","../src/components/QuestionPicker.tsx","../src/components/SlashAutocomplete.tsx","../src/components/PermissionModeBar.tsx","../src/permission/index.ts","../src/components/FooterStatus.tsx","../src/components/ProgressBanner.tsx","../src/components/StatusLine.tsx","../src/components/Shimmer.tsx","../src/ui/termTitle.ts","../src/llm/providers/openai-compatible.ts","../src/log/index.ts","../src/types/index.ts","../src/llm/client.ts","../src/loop/todos.ts","../src/loop/agent.ts","../src/loop/system-prompt.ts","../src/loop/memory.ts","../src/config/loader.ts","../src/config/types.ts","../src/config/_env.ts","../src/config/models.ts","../src/slash/registry.ts","../src/llm/pricing.ts","../src/loop/context.ts","../src/mcp/index.ts","../src/session/jsonl.ts","../src/slash/_format.ts","../src/slash/builtin.ts","../src/tools/registry.ts","../src/tools/builtin/read.ts","../src/tools/types.ts","../src/tools/_sensitive.ts","../src/tools/builtin/write.ts","../src/tools/_diff.ts","../src/tools/builtin/edit.ts","../src/tools/builtin/bash.ts","../src/tools/builtin/grep.ts","../src/tools/builtin/glob.ts","../src/tools/builtin/todo.ts","../src/tools/builtin/webfetch.ts","../src/tools/builtin/memory.ts","../src/tools/builtin/ask-user-question.ts","../src/tools/builtin/index.ts"],"sourcesContent":["/**\n * CLI 入口。解析 argv → 加载配置 → 启动交互或单次模式。\n */\n\nimport React from \"react\";\nimport { Command } from \"commander\";\nimport { render } from \"ink\";\nimport { App } from \"./app.js\";\nimport { loadSettings } from \"./config/index.js\";\nimport { loadModelsRegistry, findEntry } from \"./config/models.js\";\nimport { createLLMClient, createLLMClientFromModelEntry, setActiveModelEnv } from \"./llm/client.js\";\nimport { ToolRegistry } from \"./tools/registry.js\";\nimport { BUILTIN_TOOLS } from \"./tools/builtin/index.js\";\nimport { PermissionGate } from \"./permission/index.js\";\nimport { Session } from \"./session/jsonl.js\";\nimport { Agent } from \"./loop/agent.js\";\nimport { buildSystemPrompt } from \"./loop/system-prompt.js\";\nimport { loadMemoryIndex } from \"./loop/memory.js\";\nimport { MuseError } from \"./types/index.js\";\nimport { log } from \"./log/index.js\";\n\nconst VERSION = \"0.1.0\";\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"muse\")\n .description(\"A TypeScript agent CLI built around OpenAI-compatible APIs. First-class support for self-hostable and Chinese LLMs.\")\n .version(VERSION, \"-v, --version\", \"print version\");\n\n program\n .argument(\"[prompt...]\", \"one-shot prompt (omit for interactive mode)\")\n .option(\"-m, --model <model>\", \"override model\")\n .option(\"-p, --provider <provider>\", \"override provider\")\n .option(\"--no-banner\", \"skip startup banner\")\n .option(\"--quiet\", \"minimal output (implies --no-banner)\")\n .option(\"--continue\", \"resume last session in this directory\")\n .option(\"--mode <mode>\", \"initial permission mode (default|acceptEdits|plan|bypassPermissions)\")\n .option(\"--debug\", \"verbose logging\")\n .action(async (promptArgs: string[], opts: CliOptions) => {\n if (opts.debug) log.setLevel(\"debug\");\n\n const cwd = process.cwd();\n const { settings, sources } = await loadSettings(cwd);\n const { registry: modelsRegistry, sources: modelsSources } = await loadModelsRegistry();\n log.debug(\"config loaded\", { settingsSources: sources, modelsSources });\n\n const model = opts.model ?? settings.llm?.model;\n const provider = opts.provider ?? settings.llm?.provider;\n\n let llm;\n let llmProviderName: string;\n let llmModelName: string;\n try {\n // models.local.json 里找到 settings.llm.model(或 -m)对应的 entry:\n // 注入 apiKey 到 process.env.MUSE_ACTIVE_API_KEY,业务通过 env 读\n const entry = modelsRegistry && model ? findEntry(modelsRegistry, model) : undefined;\n if (entry) {\n setActiveModelEnv(entry);\n llm = createLLMClientFromModelEntry(entry);\n llmProviderName = llm.providerName;\n llmModelName = llm.model;\n } else {\n // 优先级 2:回退到 settings.json 原生 provider/model + providers 配置\n if (!provider || !model) {\n die(\"No model configured. Either define one in ~/.muse/models.local.json or set llm.provider+llm.model in settings.json.\");\n }\n llm = createLLMClient({ provider, model, providers: settings.providers ?? {} });\n llmProviderName = provider;\n llmModelName = model;\n }\n } catch (err) {\n if (err instanceof MuseError) die(err.message);\n throw err;\n }\n\n const tools = new ToolRegistry();\n tools.registerAll(BUILTIN_TOOLS);\n\n const permissions = new PermissionGate(settings.permissions);\n\n // --mode 启动期指定 PermissionMode;后续 Shift+Tab / /mode 仍可切换\n if (opts.mode) {\n const valid = [\"default\", \"acceptEdits\", \"plan\", \"bypassPermissions\"] as const;\n if (!(valid as readonly string[]).includes(opts.mode)) {\n die(`Invalid --mode \"${opts.mode}\". Valid: ${valid.join(\", \")}`);\n }\n permissions.setMode(opts.mode as (typeof valid)[number]);\n }\n\n // --continue: 复用最近一次 session 的 jsonl + messages\n let session: Session;\n let initialMessages: import(\"./types/index.js\").Message[] | undefined;\n if (opts.continue) {\n const latest = await Session.findLatest(cwd);\n if (latest) {\n const opened = await Session.open(latest);\n session = opened.session;\n initialMessages = Session.messagesFromEvents(opened.events);\n log.debug(\"resumed session\", { id: latest.id, messages: initialMessages.length });\n } else {\n session = await Session.create(cwd);\n await session.append({\n type: \"session_start\",\n time: new Date().toISOString(),\n cwd,\n provider: llmProviderName,\n model: llmModelName,\n });\n }\n } else {\n session = await Session.create(cwd);\n await session.append({\n type: \"session_start\",\n time: new Date().toISOString(),\n cwd,\n provider: llmProviderName,\n model: llmModelName,\n });\n }\n\n const showBanner = !opts.quiet && opts.banner !== false;\n const lang = settings.ui?.lang ?? \"en\";\n\n // Pipe input → 拼成一次性 prompt\n const pipedInput = await readStdinIfPiped();\n const oneShotPrompt = [...(promptArgs ?? []), pipedInput].filter(Boolean).join(\"\\n\").trim();\n\n if (oneShotPrompt) {\n await runOneShot({\n llm,\n tools,\n permissions,\n session,\n cwd,\n lang,\n prompt: oneShotPrompt,\n quiet: opts.quiet ?? false,\n initialMessages,\n });\n return;\n }\n\n // Interactive mode\n const { waitUntilExit } = render(\n <App\n llm={llm}\n tools={tools}\n permissions={permissions}\n session={session}\n settings={settings}\n settingsSources={sources}\n modelsRegistry={modelsRegistry}\n modelsSources={modelsSources}\n cwd={cwd}\n lang={lang}\n showBanner={showBanner}\n initialMessages={initialMessages}\n />,\n );\n await waitUntilExit();\n });\n\n await program.parseAsync(process.argv);\n}\n\ninterface CliOptions {\n model?: string;\n provider?: string;\n banner?: boolean;\n quiet?: boolean;\n continue?: boolean;\n mode?: string;\n debug?: boolean;\n}\n\nasync function readStdinIfPiped(): Promise<string> {\n if (process.stdin.isTTY) return \"\";\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString(\"utf-8\").trim();\n}\n\nasync function runOneShot(opts: {\n llm: ReturnType<typeof createLLMClient>;\n tools: ToolRegistry;\n permissions: PermissionGate;\n session: Session;\n cwd: string;\n lang: \"en\" | \"zh-CN\";\n prompt: string;\n quiet: boolean;\n initialMessages?: import(\"./types/index.js\").Message[];\n}): Promise<void> {\n const memoryIndex = await loadMemoryIndex(opts.cwd);\n const systemPrompt = buildSystemPrompt({\n cwd: opts.cwd,\n model: opts.llm.model,\n provider: opts.llm.providerName,\n lang: opts.lang,\n toolNames: opts.tools.list().map((t) => t.name),\n memoryIndex,\n });\n const agent = new Agent({\n llm: opts.llm,\n tools: opts.tools,\n permissions: opts.permissions,\n session: opts.session,\n cwd: opts.cwd,\n systemPrompt,\n events: {\n onText: (delta) => process.stdout.write(delta),\n onToolCallStart: (_id, name) => {\n if (!opts.quiet) process.stderr.write(`\\n→ ${name}\\n`);\n },\n onError: (err) => process.stderr.write(`\\n[error] ${err.message}\\n`),\n onPermissionRequest: async (toolName, _args, summary) => {\n // 非交互模式:deny 所有需要 ask 的工具\n if (!opts.quiet) process.stderr.write(`\\n[denied: ${toolName} — ${summary}; run in interactive mode to approve]\\n`);\n return \"no\";\n },\n },\n });\n if (opts.initialMessages?.length) agent.setMessages(opts.initialMessages);\n await agent.runTurn(opts.prompt);\n process.stdout.write(\"\\n\");\n}\n\nfunction die(msg: string): never {\n process.stderr.write(`muse: ${msg}\\n`);\n process.exit(1);\n}\n\nmain().catch((err) => {\n log.error(\"fatal\", { msg: err instanceof Error ? err.message : String(err) });\n process.stderr.write(`muse: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n","/**\n * Ink 根组件:banner + 消息历史 + 输入框 + 流式响应 + slash 命令调度。\n *\n * SlashActions 在这里注入。LLM client / settings / modelsRegistry 都是 mutable state,\n * /models /config reload 通过 setLLM / setSettings / setModelsRegistry 触发 Agent 重建,\n * messages 通过 messagesRef 跨重建保留。\n */\n\nimport React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from \"react\";\nimport { Box, Text, useApp, useInput, useStdout } from \"ink\";\nimport { BgTextInput } from \"./components/BgTextInput.js\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport { pickBanner } from \"./components/StartupBanner.js\";\nimport { MessageView } from \"./components/MessageView.js\";\nimport { PermissionPrompt, type PermissionRequest } from \"./components/PermissionPrompt.js\";\nimport { ModelSelector, type ModelPickerRequest } from \"./components/ModelSelector.js\";\nimport { SessionSelector, type SessionPickerRequest } from \"./components/SessionSelector.js\";\nimport { QuestionPicker, type QuestionPickerRequest } from \"./components/QuestionPicker.js\";\nimport { SlashAutocomplete } from \"./components/SlashAutocomplete.js\";\nimport { PermissionModeBar } from \"./components/PermissionModeBar.js\";\nimport { FooterStatus } from \"./components/FooterStatus.js\";\nimport { ProgressBanner, type ProgressState } from \"./components/ProgressBanner.js\";\nimport { StatusLine } from \"./components/StatusLine.js\";\nimport { DOT } from \"./components/MessageView.js\";\nimport { setTerminalTitle, resetTerminalTitle } from \"./ui/termTitle.js\";\nimport type { LLMClient } from \"./llm/types.js\";\nimport { createLLMClient, createLLMClientFromModelEntry, setActiveModelEnv } from \"./llm/client.js\";\nimport type { ToolRegistry } from \"./tools/registry.js\";\nimport { PermissionGate, type PermissionMode, type PermissionDecision } from \"./permission/index.js\";\nimport { Session, type SessionSummary } from \"./session/jsonl.js\";\nimport { Agent } from \"./loop/agent.js\";\nimport { buildSystemPrompt } from \"./loop/system-prompt.js\";\nimport { loadMemoryIndex } from \"./loop/memory.js\";\nimport { loadSettings } from \"./config/index.js\";\nimport { loadModelsRegistry, findEntry, type ModelEntry, type ModelsRegistry } from \"./config/models.js\";\nimport type { Message, ToolMessage, TokenUsage } from \"./types/index.js\";\nimport type { Settings } from \"./config/types.js\";\nimport {\n BUILTIN_SLASH_COMMANDS,\n SlashRegistry,\n parseSlash,\n type SlashActions,\n type SlashCommand,\n type SlashCommandResult,\n} from \"./slash/index.js\";\n\nexport interface AppProps {\n llm: LLMClient;\n tools: ToolRegistry;\n permissions: PermissionGate;\n session: Session;\n settings: Settings;\n settingsSources: string[];\n modelsRegistry?: ModelsRegistry;\n modelsSources: string[];\n cwd: string;\n lang: \"en\" | \"zh-CN\";\n showBanner: boolean;\n initialMessages?: Message[];\n}\n\ninterface UIState {\n history: Message[];\n streamingText: string;\n status: \"idle\" | \"streaming\" | \"tool\";\n /** 当前正在跑的工具名(onToolCallStart 设置;下一次 stream_delta 或 turn_end 清空)。 */\n runningTool: string | null;\n /** session 累计 token(/cost 用),不是本轮快照——本轮快照走 turn* 引用 */\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n /** 本轮起点(user_submit 触发时 Date.now()),StatusLine 用;idle 时为 0 */\n turnStartTime: number;\n /** 本轮首次 text-delta 时间,StatusLine 显示 \"thought for\" 用;null 表示还未流出 text */\n turnFirstTextTime: number | null;\n /** 本轮已累计 input tokens(多轮 tool loop 累加) */\n turnInputTokens: number;\n}\n\ntype UIAction =\n | { type: \"user_submit\" }\n | { type: \"history_set\"; messages: Message[] }\n | { type: \"stream_delta\"; delta: string }\n | { type: \"stream_reset\" }\n | { type: \"set_status\"; status: UIState[\"status\"] }\n | { type: \"tool_start\"; name: string }\n | { type: \"add_usage\"; usage: TokenUsage };\n\nfunction reducer(state: UIState, action: UIAction): UIState {\n switch (action.type) {\n case \"user_submit\":\n return {\n ...state,\n streamingText: \"\",\n status: \"streaming\",\n runningTool: null,\n turnStartTime: Date.now(),\n turnFirstTextTime: null,\n turnInputTokens: 0,\n };\n case \"history_set\":\n return { ...state, history: action.messages };\n case \"stream_delta\":\n // 文本流出意味着 LLM 在思考 / 回话——若刚才在 tool 阶段,自然过渡为 streaming\n // 第一次流出时打 turnFirstTextTime 时间戳(\"thought for\" 用),冻结不再变\n return {\n ...state,\n streamingText: state.streamingText + action.delta,\n status: state.status === \"tool\" ? \"streaming\" : state.status,\n runningTool: null,\n turnFirstTextTime: state.turnFirstTextTime ?? Date.now(),\n };\n case \"stream_reset\":\n return { ...state, streamingText: \"\" };\n case \"set_status\":\n return {\n ...state,\n status: action.status,\n runningTool: action.status === \"tool\" ? state.runningTool : null,\n };\n case \"tool_start\":\n return { ...state, status: \"tool\", runningTool: action.name };\n case \"add_usage\":\n return {\n ...state,\n inputTokens: state.inputTokens + action.usage.inputTokens,\n outputTokens: state.outputTokens + action.usage.outputTokens,\n totalTokens: state.totalTokens + action.usage.totalTokens,\n turnInputTokens: state.turnInputTokens + action.usage.inputTokens,\n };\n }\n}\n\nexport function App({\n llm: initialLLM,\n tools,\n permissions: initialPermissions,\n session,\n settings: initialSettings,\n settingsSources: initialSources,\n modelsRegistry: initialModelsRegistry,\n cwd,\n lang,\n showBanner,\n initialMessages,\n}: AppProps) {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const termWidth = stdout?.columns ?? 80;\n\n const [llm, setLLM] = useState<LLMClient>(initialLLM);\n const [permissions, setPermissions] = useState<PermissionGate>(initialPermissions);\n const [settings, setSettings] = useState<Settings>(initialSettings);\n const [settingsSources, setSettingsSources] = useState<string[]>(initialSources);\n const [modelsRegistry, setModelsRegistry] = useState<ModelsRegistry | undefined>(initialModelsRegistry);\n const [mode, setMode] = useState<PermissionMode>(initialPermissions.getMode());\n\n const [state, dispatch] = useReducer(reducer, {\n history: initialMessages ?? [],\n streamingText: \"\",\n status: \"idle\",\n runningTool: null,\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n turnStartTime: 0,\n turnFirstTextTime: null,\n turnInputTokens: 0,\n });\n\n const messagesRef = useRef<Message[]>(initialMessages ?? []);\n\n const [input, setInput] = useState(\"\");\n // inputRemountKey 给 TextInput 做 remount —— ink-text-input 在 value 被外部强制修改时\n // cursor 不会跟随到末尾,bump 一个 key 让组件重挂载,新实例 cursor 默认在 value.length。\n // onChange 用 setInput 不能 bump(每次按键都 remount 会丢 cursor);只有补全 / 清空等\n // \"外部 setValue\" 操作走 commitInput。\n const [inputRemountKey, setInputRemountKey] = useState(0);\n const commitInput = (value: string) => {\n setInput(value);\n setInputRemountKey((k) => k + 1);\n };\n // 粘贴 registry:大段粘贴的原文按 id 存这里,输入框里只显示 [Pasted text #N +M lines]\n // 占位符。提交 / 入队 dequeue 时再用 expandPastes 还原成原文发给 LLM。\n // 用 ref 不用 state——内容只在 onPaste/onSubmit 的瞬时事件里读,不需要触发渲染。\n const pasteRegistryRef = useRef<{ map: Map<number, string>; nextId: number }>({\n map: new Map(),\n nextId: 1,\n });\n const handlePaste = useCallback((chunk: string): string => {\n const reg = pasteRegistryRef.current;\n const id = reg.nextId++;\n reg.map.set(id, chunk);\n const lines = chunk.split(\"\\n\").length;\n return `[Pasted text #${id} +${lines} lines]`;\n }, []);\n\n const [pending, setPending] = useState<PermissionRequest | null>(null);\n const [picker, setPicker] = useState<ModelPickerRequest | null>(null);\n const [sessionPicker, setSessionPicker] = useState<SessionPickerRequest | null>(null);\n const [questionPicker, setQuestionPicker] = useState<QuestionPickerRequest | null>(null);\n const [autocompleteIndex, setAutocompleteIndex] = useState(0);\n const [progress, setProgress] = useState<ProgressState | null>(null);\n const agentRef = useRef<Agent | null>(null);\n\n // 输入队列:模型在跑时用户继续提交的消息暂存在这里,本轮结束 onTurnEnd 自动出队跑下一轮\n // ref 作真相源(同步访问),state 用于触发 UI 重渲染显示队列预览\n const queuedInputsRef = useRef<string[]>([]);\n const [queuedInputs, setQueuedInputs] = useState<string[]>([]);\n const enqueueInput = (text: string) => {\n queuedInputsRef.current.push(text);\n setQueuedInputs([...queuedInputsRef.current]);\n };\n const dequeueInput = (): string | null => {\n if (queuedInputsRef.current.length === 0) return null;\n const front = queuedInputsRef.current.shift()!;\n setQueuedInputs([...queuedInputsRef.current]);\n return front;\n };\n\n // 输入历史:纯用户输入(不含 slash 命令),最旧 → 最新 push 到末尾\n // historyIndex: -1=未导航;0=最新;len-1=最旧\n const inputHistoryRef = useRef<string[]>(extractUserInputs(initialMessages ?? []));\n const historyIndexRef = useRef<number>(-1);\n const savedDraftRef = useRef<string>(\"\");\n\n const slash = useMemo(() => {\n const r = new SlashRegistry();\n r.registerAll(BUILTIN_SLASH_COMMANDS);\n return r;\n }, []);\n\n // input.startsWith(\"/\") && 命令名阶段(无空格)→ 显示匹配候选\n const autocomplete = useMemo<{ matches: SlashCommand[]; query: string } | null>(() => {\n if (!input.startsWith(\"/\")) return null;\n const body = input.slice(1);\n if (body.includes(\" \")) return null;\n const query = body.toLowerCase();\n const all = slash.list();\n const matches = query\n ? all.filter(\n (c) =>\n c.name.toLowerCase().includes(query) ||\n c.aliases?.some((a) => a.toLowerCase().includes(query)),\n )\n : all;\n return { matches, query };\n }, [input, slash]);\n\n // 输入变化时把高亮索引夹回合法范围\n useEffect(() => {\n const len = autocomplete?.matches.length ?? 0;\n if (autocompleteIndex >= len) setAutocompleteIndex(0);\n }, [autocomplete, autocompleteIndex]);\n\n // 终端 tab/window 标题:idle 静态项目名,busy 时旋转 spinner + 工具名。\n // 100ms tick / 10 帧 braille——切到别的窗口也能从 dock 看出 muse 还在跑。\n useEffect(() => {\n const project = basename(cwd) || \"muse\";\n const baseIdle = `muse · ${project}`;\n\n if (state.status === \"idle\") {\n setTerminalTitle(baseIdle);\n return;\n }\n\n const FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n let i = 0;\n const id = setInterval(() => {\n const frame = FRAMES[i % FRAMES.length];\n const tail = state.runningTool ? ` · ${state.runningTool}` : \"\";\n setTerminalTitle(`${frame} muse · ${project}${tail}`);\n i++;\n }, 100);\n return () => clearInterval(id);\n }, [state.status, state.runningTool, cwd]);\n\n // 卸载时清标题(避免退出后 tab 留着旧 spinner 字符)\n useEffect(() => {\n return () => resetTerminalTitle();\n }, []);\n\n const [memoryIndex, setMemoryIndex] = useState<string>(\"\");\n useEffect(() => {\n let cancelled = false;\n loadMemoryIndex(cwd).then((idx) => {\n if (!cancelled) setMemoryIndex(idx);\n });\n return () => {\n cancelled = true;\n };\n }, [cwd]);\n\n useEffect(() => {\n const systemPrompt = buildSystemPrompt({\n cwd,\n model: llm.model,\n provider: llm.providerName,\n lang,\n toolNames: tools.list().map((t) => t.name),\n memoryIndex,\n });\n\n const agent = new Agent({\n llm,\n tools,\n permissions,\n session,\n cwd,\n systemPrompt,\n events: {\n onText: (delta) => dispatch({ type: \"stream_delta\", delta }),\n onToolCallStart: (_id, name) => dispatch({ type: \"tool_start\", name }),\n // assistant 流刚结束、这一批 calls 已落到 messages 但 tool 还没开始执行:\n // 立刻同步 history,让所有 ⏺ Tool(...) 调用头一次性显示出来(之前要等第一个\n // result 才能见到任何东西,看起来像\"卡死了\")\n onAssistantTurn: () => {\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n dispatch({ type: \"stream_reset\" });\n },\n // 每个 tool result 到位就同步:result 立刻挂到对应 ⏺ 调用的 └ 树枝下方\n onToolResult: () => {\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n dispatch({ type: \"set_status\", status: \"streaming\" });\n },\n onUsage: (usage: TokenUsage) => dispatch({ type: \"add_usage\", usage }),\n onTurnEnd: () => {\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n dispatch({ type: \"stream_reset\" });\n dispatch({ type: \"set_status\", status: \"idle\" });\n\n // 队列有货:取下一条立刻开新轮(setTimeout 跳出 onTurnEnd 内部递归调栈)\n const next = dequeueInput();\n if (next) {\n setTimeout(() => {\n dispatch({ type: \"user_submit\" });\n // 队列里存的是占位符版本;dequeue 时还原成原文\n const expanded = expandPastes(next, pasteRegistryRef.current.map);\n agent.runTurn(expanded).catch((err) => {\n const m = err instanceof Error ? err.message : String(err);\n dispatch({ type: \"stream_delta\", delta: `\\n[error] ${m}\\n` });\n dispatch({ type: \"set_status\", status: \"idle\" });\n });\n }, 0);\n }\n },\n onError: (err) => {\n dispatch({ type: \"stream_delta\", delta: `\\n[error] ${err.message}\\n` });\n dispatch({ type: \"set_status\", status: \"idle\" });\n },\n onPermissionRequest: (toolName, args, summary) =>\n new Promise<PermissionDecision>((resolve) => {\n setPending({ toolName, args, summary, resolve });\n }),\n onAskQuestions: (questions) =>\n new Promise((resolve) => {\n setQuestionPicker({ questions, resolve });\n }),\n },\n });\n agent.setMessages(messagesRef.current);\n agentRef.current = agent;\n }, [llm, tools, permissions, session, cwd, lang, memoryIndex]);\n\n // 键盘:Ctrl+C 全局退出 + Shift+Tab 循环切 permission mode + autocomplete ↑↓ Tab Esc 导航\n useInput(\n (inputKey, key) => {\n if (key.ctrl && inputKey === \"c\") {\n exit();\n return;\n }\n if (key.shift && key.tab) {\n const next = permissions.cycleMode();\n setMode(next);\n return;\n }\n if (autocomplete && autocomplete.matches.length > 0) {\n const len = autocomplete.matches.length;\n if (key.upArrow) {\n setAutocompleteIndex((i) => (i - 1 + len) % len);\n } else if (key.downArrow) {\n setAutocompleteIndex((i) => (i + 1) % len);\n } else if (key.tab) {\n const picked = autocomplete.matches[autocompleteIndex];\n if (picked) commitInput(`/${picked.name}`);\n } else if (key.escape) {\n commitInput(\"\");\n }\n return;\n }\n\n // autocomplete 关闭时:↑/↓ 翻输入历史\n const hist = inputHistoryRef.current;\n if (key.upArrow && hist.length > 0) {\n const cur = historyIndexRef.current;\n if (cur === -1) savedDraftRef.current = input;\n const next = Math.min(cur + 1, hist.length - 1);\n historyIndexRef.current = next;\n commitInput(hist[hist.length - 1 - next] ?? \"\");\n } else if (key.downArrow) {\n const cur = historyIndexRef.current;\n if (cur === -1) return;\n const next = cur - 1;\n historyIndexRef.current = next;\n if (next === -1) commitInput(savedDraftRef.current);\n else commitInput(hist[hist.length - 1 - next] ?? \"\");\n }\n },\n // 模型在跑时也要响应键盘(让用户能 Ctrl+C / Shift+Tab / autocomplete 导航);\n // 仅模态弹起时让出键盘所有权\n { isActive: !pending && !picker && !sessionPicker && !questionPicker },\n );\n\n // 输入框:picker 类模态弹起时仍保持可见但失焦(\"Chat about this\" 风格),\n // 真正抢键盘的 PermissionPrompt / ModelSelector / SessionSelector 才完全隐藏\n const acceptingInput = pending === null && picker === null && sessionPicker === null && questionPicker === null;\n const inputVisible = pending === null && picker === null && sessionPicker === null;\n const inputPlaceholder = questionPicker ? \"Chat about this\" : undefined;\n\n const actions: SlashActions = useMemo(\n () => ({\n setMessages: (msgs) => {\n messagesRef.current = msgs;\n agentRef.current?.setMessages(msgs);\n dispatch({ type: \"history_set\", messages: msgs });\n },\n pickModel: (items, currentId) =>\n new Promise<ModelEntry | null>((resolve) => {\n setPicker({ items, currentId, resolve });\n }),\n pickSession: (items, currentId) =>\n new Promise<SessionSummary | null>((resolve) => {\n setSessionPicker({ items, currentId, resolve });\n }),\n switchModel: async (modelId) => {\n if (!modelsRegistry) throw new Error(\"No models registry loaded.\");\n const entry = findEntry(modelsRegistry, modelId);\n if (!entry) throw new Error(`Model id \"${modelId}\" not in registry.`);\n setActiveModelEnv(entry);\n const next = createLLMClientFromModelEntry(entry);\n setLLM(next);\n await persistActiveModel(modelId);\n },\n getMode: () => permissions.getMode(),\n setMode: (m) => {\n permissions.setMode(m);\n setMode(m);\n },\n showProgress: (opts) => {\n setProgress({\n title: opts.title,\n tips: opts.tips ?? [],\n getPercent: opts.getPercent ?? (() => 0),\n startTime: Date.now(),\n });\n },\n hideProgress: () => setProgress(null),\n reloadSettings: async () => {\n const { settings: nextSettings, sources } = await loadSettings(cwd);\n const { registry: nextModels } = await loadModelsRegistry();\n setSettings(nextSettings);\n setSettingsSources(sources);\n setPermissions(new PermissionGate(nextSettings.permissions));\n setModelsRegistry(nextModels);\n\n const wantModel = nextSettings.llm?.model;\n if (wantModel && wantModel !== llm.model) {\n try {\n const entry = nextModels ? findEntry(nextModels, wantModel) : undefined;\n if (entry) {\n setActiveModelEnv(entry);\n setLLM(createLLMClientFromModelEntry(entry));\n } else if (nextSettings.llm?.provider) {\n setLLM(\n createLLMClient({\n provider: nextSettings.llm.provider,\n model: wantModel,\n providers: nextSettings.providers ?? {},\n }),\n );\n }\n } catch {\n // 新配置当前不可用(缺 key 等);保留原 LLM 不抛断流\n }\n }\n return { settings: nextSettings, sources };\n },\n }),\n [cwd, modelsRegistry, llm.model, permissions],\n );\n\n const handleSubmit = useCallback(\n async (value: string) => {\n const trimmed = value.trim();\n if (!trimmed) return;\n\n // autocomplete 开 + 有候选 + 用户没在精确命名 → 补全到 input,不提交\n if (autocomplete && autocomplete.matches.length > 0) {\n const exact = autocomplete.matches.find(\n (c) => c.name === autocomplete.query || c.aliases?.includes(autocomplete.query),\n );\n if (!exact) {\n const picked = autocomplete.matches[autocompleteIndex] ?? autocomplete.matches[0];\n commitInput(`/${picked.name}`);\n return;\n }\n }\n\n const parsed = parseSlash(trimmed);\n if (parsed) {\n // 模型在跑时 slash 命令一律拒绝——/clear /compact /resume 会改 messages 与 agent\n // 正在跑的回复冲突;reduce 也无法把 slash 排到队列里执行(会污染 history 时序)。\n // 用户可 Ctrl+C 取消当前轮,或等结束。\n if (state.status !== \"idle\") {\n commitInput(\"\");\n return;\n }\n const cmd = slash.get(parsed.name);\n commitInput(\"\");\n if (!cmd) {\n appendAssistantText(`Unknown command: /${parsed.name}. Try /help.`);\n return;\n }\n try {\n const result = await cmd.execute({\n args: parsed.args,\n cwd,\n llm,\n session,\n settings,\n settingsSources,\n modelsRegistry,\n // 用 ref 而非 state.history:命令体可能在 await 期间调 setMessages\n // 改变 messages(如 /resume / /compact),后续 display 必须基于最新值\n history: messagesRef.current,\n tokens: {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n },\n listCommands: () => slash.list(),\n actions,\n });\n applySlashResult(result);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n appendAssistantText(`[error] /${parsed.name}: ${msg}`);\n }\n return;\n }\n\n commitInput(\"\");\n // 推入历史(去重相邻重复),重置游标\n const hist = inputHistoryRef.current;\n if (hist[hist.length - 1] !== trimmed) hist.push(trimmed);\n if (hist.length > 200) hist.shift();\n historyIndexRef.current = -1;\n savedDraftRef.current = \"\";\n\n // 模型在跑 → 入队,等本轮 onTurnEnd 出队继续\n if (state.status !== \"idle\") {\n enqueueInput(trimmed);\n return;\n }\n\n dispatch({ type: \"user_submit\" });\n // 立刻把用户消息塞进可见历史,UX 上\"瞬间出现\"——别等 Agent runTurn 结束才 history_set\n // Agent 内部也会 push 同样的 message,turn 结束时 onTurnEnd 用 agent.getMessages()\n // 同步回来一次就行,不会重复\n const expanded = expandPastes(trimmed, pasteRegistryRef.current.map);\n {\n const userMsg: Message = { role: \"user\", content: expanded };\n const next = [...messagesRef.current, userMsg];\n messagesRef.current = next;\n dispatch({ type: \"history_set\", messages: next });\n }\n try {\n await agentRef.current?.runTurn(expanded);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n dispatch({ type: \"stream_delta\", delta: `\\n[error] ${msg}\\n` });\n dispatch({ type: \"set_status\", status: \"idle\" });\n }\n },\n [slash, cwd, llm, session, settings, settingsSources, modelsRegistry, state.inputTokens, state.outputTokens, state.totalTokens, state.status, actions, autocomplete, autocompleteIndex],\n );\n\n function appendAssistantText(text: string) {\n const msg: Message = { role: \"assistant\", content: [{ type: \"text\", text }] };\n // 必须读 ref 而非闭包里的 state.history:上游可能刚通过 setMessages 改了历史\n // (/resume 加载 N 条 → applySlashResult 追加\"Resumed...\"),用 state.history\n // 会覆盖刚 load 进来的消息\n const next = [...messagesRef.current, msg];\n messagesRef.current = next;\n dispatch({ type: \"history_set\", messages: next });\n }\n\n function applySlashResult(result: SlashCommandResult) {\n if (result.exit) {\n exit();\n return;\n }\n if (result.display !== undefined) {\n appendAssistantText(result.display);\n }\n }\n\n const banner = !showBanner\n ? null\n : pickBanner(termWidth, { version: \"0.1.0\", model: llm.model, cwd: shortCwd(cwd) });\n\n // 配对 tool_use ↔ tool_result:AssistantMessage 把 result 内联渲染在 call 下方(树形);\n // 顶层 history loop 跳过已被内联的 ToolMessage 避免重复\n const { resultsByCallId, inlinedIds } = useMemo(() => {\n const byId = new Map<string, ToolMessage>();\n const used = new Set<string>();\n for (const m of state.history) {\n if (m.role === \"tool\" && m.toolUseId) byId.set(m.toolUseId, m);\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n for (const p of m.content) {\n if (p.type === \"tool_use\") used.add(p.id);\n }\n }\n }\n return { resultsByCallId: byId, inlinedIds: used };\n }, [state.history]);\n\n return (\n <Box flexDirection=\"column\">\n {banner}\n <Box flexDirection=\"column\" marginTop={1}>\n {state.history.map((msg, i) => {\n if (msg.role === \"tool\" && inlinedIds.has(msg.toolUseId)) return null;\n return <MessageView key={i} message={msg} resultsByCallId={resultsByCallId} />;\n })}\n {state.streamingText && (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color=\"cyan\">{DOT} </Text>\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text>{state.streamingText}</Text>\n </Box>\n </Box>\n )}\n </Box>\n {pending && (\n <PermissionPrompt\n request={{\n ...pending,\n resolve: (decision) => {\n pending.resolve(decision);\n setPending(null);\n },\n }}\n />\n )}\n {picker && (\n <ModelSelector\n request={{\n ...picker,\n resolve: (m) => {\n picker.resolve(m);\n setPicker(null);\n },\n }}\n />\n )}\n {sessionPicker && (\n <SessionSelector\n request={{\n ...sessionPicker,\n resolve: (s) => {\n sessionPicker.resolve(s);\n setSessionPicker(null);\n },\n }}\n />\n )}\n {questionPicker && (\n <QuestionPicker\n request={{\n questions: questionPicker.questions,\n resolve: (responses) => {\n questionPicker.resolve(responses);\n setQuestionPicker(null);\n },\n }}\n />\n )}\n {state.status !== \"idle\" && (\n <StatusLine\n startTime={state.turnStartTime}\n firstTextTime={state.turnFirstTextTime}\n inputTokens={state.turnInputTokens}\n runningTool={state.runningTool}\n lang={lang}\n />\n )}\n {progress && <ProgressBanner state={progress} />}\n {inputVisible && (\n <Box flexDirection=\"column\">\n {queuedInputs.length > 0 && (\n <Box flexDirection=\"column\" marginLeft={2} marginTop={1}>\n {queuedInputs.map((q, i) => (\n <Text key={i} color=\"yellow\" dimColor>\n {`↳ queued: ${q.length > 60 ? q.slice(0, 60) + \"…\" : q}`}\n </Text>\n ))}\n <Text dimColor>{` (will send after current turn · ${queuedInputs.length} pending)`}</Text>\n </Box>\n )}\n <Box marginTop={1} flexDirection=\"column\">\n <Text backgroundColor=\"#1c1c1c\">\n {\" \".repeat(Math.max(1, termWidth - 1))}\n </Text>\n <Box flexDirection=\"row\">\n <Text backgroundColor=\"#1c1c1c\" color=\"gray\" bold>\n {\" › \"}\n </Text>\n <BgTextInput\n key={inputRemountKey}\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n width={Math.max(10, termWidth - 4)}\n backgroundColor=\"#1c1c1c\"\n isActive={acceptingInput}\n onPaste={handlePaste}\n placeholder={inputPlaceholder}\n />\n </Box>\n <Text backgroundColor=\"#1c1c1c\">\n {\" \".repeat(Math.max(1, termWidth - 1))}\n </Text>\n </Box>\n {autocomplete && autocomplete.matches.length > 0 && (\n <SlashAutocomplete matches={autocomplete.matches} index={autocompleteIndex} />\n )}\n </Box>\n )}\n <Box flexDirection=\"column\">\n <FooterStatus\n sessionId={session.meta.id}\n model={llm.model}\n contextWindow={llm.capabilities.maxContextWindow}\n lastInputTokens={state.turnInputTokens}\n sessionInputTokens={state.inputTokens}\n sessionOutputTokens={state.outputTokens}\n termWidth={termWidth}\n />\n <PermissionModeBar mode={mode} compact={termWidth < 60} />\n </Box>\n </Box>\n );\n}\n\nfunction extractUserInputs(messages: Message[]): string[] {\n const out: string[] = [];\n for (const m of messages) {\n if (m.role !== \"user\") continue;\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n // 跳过 /compact 注入的 \"[Previous conversation summary]\" 等系统消息\n if (text.startsWith(\"[Previous conversation summary]\")) continue;\n if (text.trim()) out.push(text);\n }\n return out;\n}\n\n// 占位符格式:[Pasted text #<id> +<lines> lines]——与 Claude Code 对齐\nconst PASTE_PLACEHOLDER_RE = /\\[Pasted text #(\\d+) \\+\\d+ lines\\]/g;\n\nfunction expandPastes(value: string, map: Map<number, string>): string {\n return value.replace(PASTE_PLACEHOLDER_RE, (full, id) => {\n const text = map.get(Number(id));\n return text ?? full;\n });\n}\n\nfunction shortCwd(cwd: string): string {\n const home = homedir();\n if (cwd === home) return \"~\";\n if (cwd.startsWith(home + \"/\")) return \"~\" + cwd.slice(home.length);\n return cwd;\n}\n\n/**\n * 把当前选中的 model id 写回 ~/.muse/settings.json llm.model。\n *\n * 这是 muse 第一次\"写配置\"。策略:read-modify-write 整文件,pretty-print 2 空格。\n * 不强制 chmod —— settings.json 不放明文 key,敏感数据在 settings.local.json。\n */\nasync function persistActiveModel(modelId: string): Promise<void> {\n const path = join(homedir(), \".muse\", \"settings.json\");\n let current: Record<string, unknown> = {};\n if (existsSync(path)) {\n try {\n current = JSON.parse(await readFile(path, \"utf-8\")) as Record<string, unknown>;\n } catch {\n current = {};\n }\n }\n const llm = (current.llm as Record<string, unknown> | undefined) ?? {};\n const next = { ...current, llm: { ...llm, model: modelId } };\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, JSON.stringify(next, null, 2) + \"\\n\", \"utf-8\");\n}\n","/**\n * 自带背景色的轻量输入组件,替换 ink-text-input。\n *\n * Why:Ink 的 Box 不支持 backgroundColor 属性(只有 Text 支持),\n * 而 ink-text-input 输出的 Text 不暴露 bg 注入口。要实现\"整行高亮背景\"\n * 的输入条(对齐 Claude Code 风格),最干净的方式是自己渲染。\n *\n * 实现:单个 Text 节点,padEnd 到 width 让 bg 填满整行。\n * 光标用 inverse 字符表示,超出 width 时做左侧 viewport 裁切常驻光标可见。\n *\n * 终端列宽口径:用 charWidth() 处理 CJK / 全角等 2 列字符,避免内容超 width\n * 时换行(换行让 Ink 渲染高度变化,引起上面内容被顶上去——非常显眼的 bug)。\n *\n * 不支持:多行、IME 复合输入、emoji 代理对的精确光标位置——v0.1 范围。\n */\n\nimport React, { useState, useEffect } from \"react\";\nimport { Text, useInput } from \"ink\";\n\nexport interface BgTextInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n /** 主体内容可用宽度(\"› \" 这种前缀外),用于 padEnd 让 bg 填满整行。 */\n width: number;\n /** Tailwind 风 hex 或 Ink 颜色名。 */\n backgroundColor: string;\n /** 前景文字颜色;不传时用终端默认。 */\n color?: string;\n /** 是否启用键盘(弹模态时调用方传 false 让出键盘所有权)。 */\n isActive?: boolean;\n /**\n * 检测到一段疑似粘贴(含换行 或 > 200 字符)时回调;返回的字符串作为实际插入内容\n * 替换原始 chunk。调用方一般注册原文到 paste registry,返回 `[Pasted text #N ...]`\n * 占位符,避免 \\n 进入输入框造成多行渲染。\n */\n onPaste?: (chunk: string) => string;\n /**\n * value 为空时显示的暗淡占位文本——典型场景:弹模态时 isActive=false,\n * 输入框仍可见但失焦,用 placeholder 透出 \"Chat about this\" 之类的提示。\n */\n placeholder?: string;\n}\n\nconst BLINK_MS = 530; // 标准终端 cursor 闪烁周期\nconst PASTE_CHAR_THRESHOLD = 200;\n\nfunction looksLikePaste(input: string): boolean {\n // \\r 也算:macOS Terminal / iTerm 粘贴多段文本时换行常为 \\r 而非 \\n,\n // 落进 value 后 \\r 会被终端解释为回车(光标回行首)→ 后文覆盖前文,看着像\"丢消息\"\n return input.includes(\"\\n\") || input.includes(\"\\r\") || input.length > PASTE_CHAR_THRESHOLD;\n}\n\n// bracketed paste 转义:部分终端把粘贴包成 \\x1b[200~...\\x1b[201~,Ink 不一定剥\nfunction stripBracketedPaste(s: string): string {\n return s.replace(/\\x1b\\[20[01]~/g, \"\");\n}\n\n// 统一换行:\\r\\n → \\n、裸 \\r → \\n\n// 用途:粘贴 chunk 在注册到 registry 前先规范化,避免 \\r 流进 value / 历史 / LLM\nfunction normalizeLineEndings(s: string): string {\n return s.replace(/\\r\\n?/g, \"\\n\");\n}\n\nexport function BgTextInput({\n value,\n onChange,\n onSubmit,\n width,\n backgroundColor,\n color,\n isActive = true,\n onPaste,\n placeholder,\n}: BgTextInputProps) {\n const [cursor, setCursor] = useState(value.length);\n const [blinkOn, setBlinkOn] = useState(true);\n\n useEffect(() => {\n // value 外部改变(commitInput / remount)时把光标移到末尾或夹在合法范围\n setCursor((c) => Math.min(c, value.length));\n }, [value]);\n\n // 光标闪烁:cursor / value 变化时重启 timer 让光标\"常亮\"过编辑动作;\n // isActive=false(模态弹起)时不闪也不显\n useEffect(() => {\n if (!isActive) return;\n setBlinkOn(true);\n const id = setInterval(() => setBlinkOn((b) => !b), BLINK_MS);\n return () => clearInterval(id);\n }, [isActive, cursor, value]);\n\n useInput(\n (input, key) => {\n if (key.return) {\n onSubmit?.(value);\n return;\n }\n if (key.backspace || key.delete) {\n if (cursor === 0) return;\n const next = value.slice(0, cursor - 1) + value.slice(cursor);\n onChange(next);\n setCursor((c) => Math.max(0, c - 1));\n return;\n }\n if (key.leftArrow) {\n setCursor((c) => Math.max(0, c - 1));\n return;\n }\n if (key.rightArrow) {\n setCursor((c) => Math.min(value.length, c + 1));\n return;\n }\n if (key.ctrl && input === \"a\") {\n setCursor(0);\n return;\n }\n if (key.ctrl && input === \"e\") {\n setCursor(value.length);\n return;\n }\n // 不消费 Ctrl+C / Shift+Tab / ↑↓ / Tab / Esc / meta——交给 App 顶层 useInput\n if (key.ctrl || key.shift || key.tab || key.escape || key.upArrow || key.downArrow || key.meta) {\n return;\n }\n // 普通字符(含粘贴):在光标处插入\n if (input && !key.return) {\n // 先剥 bracketed paste 转义,再统一换行符——\\r 不处理会让后续渲染 / LLM 都吃坏\n const cleaned = normalizeLineEndings(stripBracketedPaste(input));\n if (!cleaned) return;\n // 检测疑似粘贴:交给调用方决定要不要替换成占位符\n // 避免 \\n 直接进 value 让 Text 渲染成多行,把输入框撑到看不见前文\n const insertion =\n onPaste && looksLikePaste(cleaned) ? onPaste(cleaned) : cleaned;\n const next = value.slice(0, cursor) + insertion + value.slice(cursor);\n onChange(next);\n setCursor((c) => c + insertion.length);\n }\n },\n { isActive },\n );\n\n // 光标渲染:active + blinkOn 时 inverse 高亮;blinkOff 或 inactive 时\n // 保持背景色不显光标,单元格宽度不变(避免布局抖动)\n const showCursor = isActive && blinkOn;\n\n // 空 value + 有 placeholder → 占位文本模式(暗淡显示,\"Chat about this\" 风格)\n if (value.length === 0 && placeholder) {\n // 留 1 列给光标位\n const maxW = Math.max(0, width - 1);\n let truncated = placeholder;\n while (stringWidth(truncated) > maxW && truncated.length > 0) {\n truncated = truncated.slice(0, -1);\n }\n const usedW = 1 + stringWidth(truncated);\n const padLen = Math.max(0, width - usedW);\n return (\n <Text backgroundColor={backgroundColor} color={color}>\n {showCursor ? (\n <Text backgroundColor=\"blue\" color={color} dimColor>\n {\" \"}\n </Text>\n ) : (\n <Text backgroundColor={backgroundColor} color={color}>\n {\" \"}\n </Text>\n )}\n <Text backgroundColor={backgroundColor} dimColor>\n {truncated}\n </Text>\n {\" \".repeat(padLen)}\n </Text>\n );\n }\n\n // 视口计算:保证整行可视宽度 == width,光标永远可见\n // 显示前把 \\n / \\r 换成 ↵(1 列宽可视符),避免 Ink Text 渲染成真换行 / 回车——\n // 换行会把输入框撑成多行;回车更糟,会让后文覆盖前文看着像\"消息丢了\"\n const displayValue = value.replace(/[\\n\\r]/g, \"↵\");\n const view = computeViewport(displayValue, cursor, width);\n const at = view.atChar;\n const padLen = Math.max(0, width - view.consumedWidth);\n\n return (\n <Text backgroundColor={backgroundColor} color={color}>\n {view.before}\n {showCursor ? (\n <Text backgroundColor=\"blue\" color={color} dimColor>\n {at}\n </Text>\n ) : (\n <Text backgroundColor={backgroundColor} color={color}>\n {at}\n </Text>\n )}\n {view.after}\n {\" \".repeat(padLen)}\n </Text>\n );\n}\n\n// ---------- helpers ----------\n\n/** 估计单字符在终端的列宽:CJK / 全角 = 2,控制符 = 0,其余 = 1。 */\nfunction charWidth(ch: string): number {\n const cp = ch.codePointAt(0);\n if (cp === undefined) return 0;\n if (cp < 0x20 || cp === 0x7f) return 0;\n if (\n (cp >= 0x1100 && cp <= 0x115f) || // Hangul Jamo\n (cp >= 0x2e80 && cp <= 0x303e) || // CJK Radicals\n (cp >= 0x3041 && cp <= 0x33ff) || // Hiragana / Katakana / CJK Symbols\n (cp >= 0x3400 && cp <= 0x4dbf) || // CJK Ext A\n (cp >= 0x4e00 && cp <= 0x9fff) || // CJK Unified\n (cp >= 0xa000 && cp <= 0xa4cf) || // Yi\n (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables\n (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compat\n (cp >= 0xfe30 && cp <= 0xfe4f) || // CJK Compat Forms\n (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth ASCII / Punctuation\n (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Sign\n (cp >= 0x20000 && cp <= 0x2fffd) // CJK Ext B–F\n ) {\n return 2;\n }\n return 1;\n}\n\nexport function stringWidth(s: string): number {\n let w = 0;\n for (const ch of s) w += charWidth(ch);\n return w;\n}\n\ninterface Viewport {\n before: string;\n atChar: string;\n after: string;\n consumedWidth: number;\n}\n\n/**\n * 计算视口:保证渲染宽度 == width,光标永远在可视范围内。\n * 溢出时从左侧裁掉字符让窗口右沿吃下光标。\n */\nfunction computeViewport(value: string, cursor: number, width: number): Viewport {\n const cursorAtEnd = cursor >= value.length;\n const atChar = cursorAtEnd ? \" \" : value[cursor] ?? \" \";\n const cursorCellW = charWidth(atChar);\n\n // 尝试用全量 [0, cursor) + cursor cell + (cursor+1, end] 渲染\n // 若总宽度 > width,从 before 左侧逐字符裁掉\n let beforeStart = 0;\n while (true) {\n const before = value.slice(beforeStart, cursor);\n const after = cursorAtEnd ? \"\" : value.slice(cursor + 1);\n const total = stringWidth(before) + cursorCellW + stringWidth(after);\n if (total <= width) {\n return { before, atChar, after, consumedWidth: total };\n }\n if (beforeStart >= cursor) {\n // before 已经全裁完仍超:再从 after 尾部裁\n // (cursor 后面有超长内容;少见,但 paste 一大段会触发)\n let after = cursorAtEnd ? \"\" : value.slice(cursor + 1);\n while (after.length > 0 && stringWidth(\"\") + cursorCellW + stringWidth(after) > width) {\n after = after.slice(0, -1);\n }\n return {\n before: \"\",\n atChar,\n after,\n consumedWidth: cursorCellW + stringWidth(after),\n };\n }\n beforeStart++;\n }\n}\n","/**\n * 启动 banner(彩虹 MUSE 字母版,无边框)。\n *\n * 4 个字母各 5×5 像素,间距 2 字符,logo 总宽 26 字符 × 高 5 行。\n * M 红 / U 橙 / S 黄 / E 绿(彩虹渐变);✻ 青;v 亮黄;正文白。\n * 无边框,简洁排版,对齐右侧三行信息:✻ Welcome / model / cwd。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\n// 每个字母 5 行 × 5 字符宽的像素图。S 顶/底完整 █████ 避免拐弯吐出。\nconst LETTERS = {\n M: [\"█ █\", \"██ ██\", \"█ █ █\", \"█ █\", \"█ █\"],\n U: [\"█ █\", \"█ █\", \"█ █\", \"█ █\", \" ███ \"],\n S: [\"█████\", \"█ \", \" ███ \", \" █\", \"█████\"],\n E: [\"█████\", \"█ \", \"████ \", \"█ \", \"█████\"],\n} as const;\n\nconst COLORS = {\n M: \"#EF4444\",\n U: \"#F97316\",\n S: \"#EAB308\",\n E: \"#22C55E\",\n asterisk: \"#06B6D4\",\n text: \"white\",\n versionAccent: \"#FDE047\",\n} as const;\n\nconst LETTER_GAP = 3; // 字母之间的空格(避免视觉粘连)\nconst LOGO_WIDTH = 5 * 4 + LETTER_GAP * 3; // 29\nconst GAP_WIDTH = 6; // logo 到右侧文字的间距\n\nexport interface StartupBannerProps {\n version: string;\n model: string;\n cwd: string;\n}\n\nfunction LogoLine({ row }: { row: number }) {\n // 用 Box marginLeft 显式控制字母间距:yoga flex 不会\"吃\"空格,比 Text 拼空格稳。\n return (\n <Box flexDirection=\"row\">\n <Box>\n <Text color={COLORS.M}>{LETTERS.M[row]}</Text>\n </Box>\n <Box marginLeft={LETTER_GAP}>\n <Text color={COLORS.U}>{LETTERS.U[row]}</Text>\n </Box>\n <Box marginLeft={LETTER_GAP}>\n <Text color={COLORS.S}>{LETTERS.S[row]}</Text>\n </Box>\n <Box marginLeft={LETTER_GAP}>\n <Text color={COLORS.E}>{LETTERS.E[row]}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction BannerLine({ row, children }: { row: number; children?: React.ReactNode }) {\n return (\n <Box flexDirection=\"row\">\n <Box minWidth={LOGO_WIDTH}>\n <LogoLine row={row} />\n </Box>\n <Box width={GAP_WIDTH} />\n {children ?? null}\n </Box>\n );\n}\n\nexport function StartupBanner({ version, model, cwd }: StartupBannerProps) {\n return (\n <Box flexDirection=\"column\" paddingY={0}>\n <BannerLine row={0} />\n <BannerLine row={1}>\n <Box flexDirection=\"row\">\n <Text color={COLORS.asterisk}>✻</Text>\n <Text color={COLORS.text}>{\" Welcome to Muse \"}</Text>\n <Text color={COLORS.versionAccent}>v{version}</Text>\n </Box>\n </BannerLine>\n <BannerLine row={2}>\n <Text color={COLORS.text}>model: {model}</Text>\n </BannerLine>\n <BannerLine row={3}>\n <Text color={COLORS.text}>cwd: {cwd}</Text>\n </BannerLine>\n <BannerLine row={4} />\n </Box>\n );\n}\n\n/** 紧凑模式:终端窄于 60 列时,省略 logo,仅文字。 */\nexport function CompactBanner({ version, model, cwd }: StartupBannerProps) {\n return (\n <Box flexDirection=\"column\" paddingY={0}>\n <Box flexDirection=\"row\">\n <Text color={COLORS.asterisk}>✻</Text>\n <Text color={COLORS.text}>{\" Welcome to Muse \"}</Text>\n <Text color={COLORS.versionAccent}>v{version}</Text>\n </Box>\n <Text color={COLORS.text}>model: {model}</Text>\n <Text color={COLORS.text}>cwd: {cwd}</Text>\n </Box>\n );\n}\n\n/** 单行模式:终端 < 40 列。 */\nexport function SingleLineBanner({ version, model }: Omit<StartupBannerProps, \"cwd\">) {\n return (\n <Text>\n <Text color={COLORS.text}>Muse </Text>\n <Text color={COLORS.versionAccent}>v{version}</Text>\n <Text color={COLORS.text}> · {model}</Text>\n </Text>\n );\n}\n\nexport function pickBanner(width: number, props: StartupBannerProps): React.ReactElement {\n if (width >= 60) return <StartupBanner {...props} />;\n if (width >= 40) return <CompactBanner {...props} />;\n return <SingleLineBanner version={props.version} model={props.model} />;\n}\n","/**\n * 消息展示组件。区分 user / assistant / tool 三类。\n *\n * Assistant 文本走 marked + marked-terminal,把 markdown 渲染成 ANSI 字符串后交给 Ink Text。\n * 流式中(app.tsx 的 streamingText)保持纯文本,turn 结束后由 history 重渲染替换。\n */\n\nimport React, { useMemo } from \"react\";\nimport { Box, Text, useStdout } from \"ink\";\nimport chalk from \"chalk\";\nimport { marked } from \"marked\";\n// @ts-expect-error marked-terminal 7.x 无内置 .d.ts;运行时正常\nimport { markedTerminal } from \"marked-terminal\";\nimport type { Message, ContentPart, ToolMessage } from \"../types/index.js\";\nimport type { TodoItem } from \"../tools/builtin/todo.js\";\nimport { stringWidth } from \"./BgTextInput.js\";\n\n// chalk 在 module load 时可能基于 stdout 探测把 level 锁成 0(非 TTY、CI 等场景),\n// 这会让 markedTerminal 的 chalk.bold/italic 全部返回纯文本,**项目背景** 之类原样吐出。\n// Ink 渲染到的目标是 TTY,强制至少 256 色,让 ANSI 码进得了 Text 节点。\nif (chalk.level === 0) chalk.level = 3;\n\n// 全局注册一次。markedTerminal() 接受样式参数(heading / blockquote / code 等),先用默认值。\nmarked.use(markedTerminal() as Parameters<typeof marked.use>[0]);\n\nfunction renderMarkdown(text: string): string {\n try {\n let out = marked.parse(text) as string;\n out = out.replace(/\\n+$/, \"\"); // 末尾换行去掉,免得 Ink Box 多一行空白\n\n // 修 marked-terminal 在 list item 等场景里把 **bold** / *italic* 当文本吐出来\n // 自己用正则补一刀(在 reset 处理之前做,否则 \\x1b[0m 会把 \\x1b[1m 切断)\n out = out.replace(/\\*\\*([^\\n*]+?)\\*\\*/g, (_, body) => `\\x1b[1m${body}\\x1b[22m`);\n out = out.replace(/(?<![*\\\\\\x1b])\\*([^\\n*]+?)\\*(?!\\*)/g, (_, body) => `\\x1b[3m${body}\\x1b[23m`);\n\n // marked-terminal 在每个 block 前后塞 \\x1b[0m 全 reset——这会把外层的\n // chalk.bgHex(用户消息条带)一并清掉,渲染出\"字体处没背景\"的断带。\n // 整体剥掉,让样式 close 各自的 \\x1b[22m / \\x1b[23m / \\x1b[39m 收尾即可。\n out = out.replace(/\\x1b\\[0m/g, \"\");\n\n return out;\n } catch {\n // 流到一半的 ```code 等会让 parse 抛错,退化到纯文本\n return text;\n }\n}\n\nexport function MessageView({\n message,\n resultsByCallId,\n}: {\n message: Message;\n /** 上层(app)按 toolUseId 索引的工具结果映射;AssistantMessage 据此把 result 内联到 call 下方。 */\n resultsByCallId?: Map<string, ToolMessage>;\n}) {\n switch (message.role) {\n case \"user\":\n return <UserMessage content={typeof message.content === \"string\" ? message.content : flattenText(message.content)} />;\n case \"assistant\":\n return <AssistantMessage content={message.content} resultsByCallId={resultsByCallId} />;\n case \"tool\":\n // TodoWrite 的清单已在 tool_use 调用处渲染,结果行多余 → 不重复显示\n if (message.toolName === \"TodoWrite\") return null;\n // 兜底:当结果消息没有匹配的 tool_use(理论上不会发生)独立成一行\n return (\n <ToolResultTree result={message} standalone />\n );\n case \"system\":\n return null;\n }\n}\n\nfunction flattenText(parts: ContentPart[]): string {\n return parts.filter((p): p is { type: \"text\"; text: string } => p.type === \"text\").map((p) => p.text).join(\"\\n\");\n}\n\n/**\n * 行首圆点风格统一 ⏺,颜色按消息类型区分(对齐 Claude Code):\n * user → cyan(输入指示符 \"> \" 保留,不混入圆点风格)\n * assistant → cyan ⏺ 普通对话\n * tool_use → yellow ⏺ 工具调用(一行参数 + 截断)\n * tool result → green ⏺ 执行成功\n * red ⏺ 错误\n * yellowBright⏺ warn(redirect/降级/部分成功)\n *\n * Batch 分组:同一 assistant turn 内的多个 tool_use 直接堆叠(无 marginTop),\n * 不同 turn 间靠 AssistantMessage 的 marginTop={1} 区隔。\n */\nexport const DOT = \"⏺\";\n\n/**\n * 用户消息:和输入框同款灰底条带(对齐 Claude Code)。\n * 多行内容每行都填满 bg,首行带 \"› \" 前缀,后续行用 3 空格缩进保持对齐。\n */\nconst USER_BG = \"#262626\";\n\nfunction UserMessage({ content }: { content: string }) {\n const { stdout } = useStdout();\n const termWidth = stdout?.columns ?? 80;\n const bandWidth = Math.max(1, termWidth - 1);\n const PREFIX = \" › \";\n const PREFIX_W = 3;\n\n // 先整体过 markdown,再按行切;不能先切行再过——会打断列表 / 代码块 / 表格等多行结构\n const rendered = useMemo(() => renderMarkdown(content), [content]);\n const lines = rendered.split(\"\\n\");\n const bg = chalk.bgHex(USER_BG);\n const prefixStyle = chalk.gray.bold;\n // 上下空白行:纯 bg,无文字。让消息条不至于紧贴顶/底文字行\n const padRow = bg(\" \".repeat(bandWidth));\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>{padRow}</Text>\n {lines.map((line, i) => {\n // marked-terminal 的输出含 ANSI 转义;填充宽度要按可见字符算,否则 padLen 偏大\n const visible = stringWidth(stripAnsi(line));\n const padLen = Math.max(0, bandWidth - PREFIX_W - visible);\n const prefix = i === 0 ? PREFIX : \" \";\n // 整行(prefix + content + padding)用 chalk.bgHex 包一层 ANSI bg。\n // 内嵌的 chalk.bold / fg-color 等 ANSI 只 reset fg / attr(\\x1b[22m / \\x1b[39m),\n // 不会 reset bg,所以灰底贯穿整行,不会有\"字体处没背景\"的断带。\n const fullLine = bg(prefixStyle(prefix) + line + \" \".repeat(padLen));\n return <Text key={i}>{fullLine}</Text>;\n })}\n <Text>{padRow}</Text>\n </Box>\n );\n}\n\nconst ANSI_RE = /\\x1b\\[[0-9;]*m/g;\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, \"\");\n}\n\nfunction AssistantMessage({\n content,\n resultsByCallId,\n}: {\n content: ContentPart[];\n resultsByCallId?: Map<string, ToolMessage>;\n}) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {content.map((part, i) => {\n if (part.type === \"text\") {\n return <AssistantTextPart key={i} text={part.text} />;\n }\n if (part.type === \"tool_use\") {\n if (part.name === \"TodoWrite\") {\n return <TodoList key={i} todos={extractTodos(part.args)} />;\n }\n // 把匹配的工具结果一起渲染:⏺ Tool(args) + └ result\n const result = resultsByCallId?.get(part.id);\n return <ToolCallBlock key={i} name={part.name} args={part.args} result={result} />;\n }\n return null;\n })}\n </Box>\n );\n}\n\nfunction AssistantTextPart({ text }: { text: string }) {\n const rendered = useMemo(() => renderMarkdown(text), [text]);\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\">{DOT} </Text>\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text>{rendered}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction ToolCallLine({ name, args }: { name: string; args: unknown }) {\n const argSummary = formatArgs(args);\n // wrap=\"truncate-end\" 让 args 在终端宽度内一行截断;外层 row 默认占满终端宽度。\n return (\n <Box flexDirection=\"row\">\n <Text color=\"yellow\">{DOT} </Text>\n <Text color=\"yellow\" bold>{name}</Text>\n <Box flexGrow={1} minWidth={0}>\n <Text dimColor wrap=\"truncate-end\">({argSummary})</Text>\n </Box>\n </Box>\n );\n}\n\nfunction extractTodos(args: unknown): TodoItem[] {\n if (typeof args !== \"object\" || args === null) return [];\n const todos = (args as { todos?: unknown }).todos;\n return Array.isArray(todos) ? (todos as TodoItem[]) : [];\n}\n\n// 仿 Claude Code 的 checkbox 清单:完成态打钩 + 删除线,进行中高亮,待办置灰。\nfunction TodoList({ todos }: { todos: TodoItem[] }) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box flexDirection=\"row\">\n <Text color=\"yellow\">{\"→ \"}</Text>\n <Text color=\"yellow\" bold>Todos</Text>\n </Box>\n {todos.map((todo, i) => (\n <TodoRow key={i} todo={todo} />\n ))}\n </Box>\n );\n}\n\nfunction TodoRow({ todo }: { todo: TodoItem }) {\n const label = todo.status === \"in_progress\" && todo.activeForm ? todo.activeForm : todo.content;\n switch (todo.status) {\n case \"completed\":\n return (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color=\"green\">{\"☒ \"}</Text>\n <Text dimColor strikethrough>{label}</Text>\n </Box>\n );\n case \"in_progress\":\n return (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color=\"cyan\" bold>{\"☐ \"}</Text>\n <Text color=\"cyan\" bold>{label}</Text>\n </Box>\n );\n default:\n return (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text dimColor>{\"☐ \"}</Text>\n <Text dimColor>{label}</Text>\n </Box>\n );\n }\n}\n\n/**\n * 单个工具的\"调用 + 结果\"块(仿 Claude Code 的 ●Tool(...) + └ result 树形展示)。\n * 结果 region 缩进 2 空格,首行用 └ 树枝角标,颜色按状态。\n */\nfunction ToolCallBlock({\n name,\n args,\n result,\n}: {\n name: string;\n args: unknown;\n result?: ToolMessage;\n}) {\n return (\n <Box flexDirection=\"column\">\n <ToolCallLine name={name} args={args} />\n {result && <ToolResultTree result={result} />}\n </Box>\n );\n}\n\nconst MAX_RESULT_LINES = 5;\n\n/**\n * 工具结果的树形展示:\n * - 有 summary → 一行 summary(带 \"+N lines\" 暗示更多内容)\n * - 无 summary 且 content 短 → 全展开(每行一条)\n * - 无 summary 且 content 长 → 头 MAX_RESULT_LINES 行 + \"(+M more lines)\"\n *\n * standalone 标志:用于兜底(独立成块)的情况——通常不会触发。\n */\nfunction ToolResultTree({ result, standalone = false }: { result: ToolMessage; standalone?: boolean }) {\n const isError = result.isError ?? false;\n const effective: \"success\" | \"error\" | \"warn\" = result.kind ?? (isError ? \"error\" : \"success\");\n const dotColor =\n effective === \"error\" ? \"red\" : effective === \"warn\" ? \"yellowBright\" : \"green\";\n\n // bash 等工具会把 stdout/stderr 包在 <stdout>...</stdout> 里给 LLM 区分通道;\n // UI 里把这种独立行的标签剥掉,让用户直接看到 stdout 内容\n const cleaned = stripWrapperTags(result.content);\n const rawLines = cleaned.split(\"\\n\");\n // 去尾部空行(XML 标签剥离后常剩一行空)\n while (rawLines.length > 0 && rawLines[rawLines.length - 1].trim() === \"\") rawLines.pop();\n // 去头部空行\n while (rawLines.length > 0 && rawLines[0].trim() === \"\") rawLines.shift();\n\n let displayLines: string[];\n let omitted = 0;\n\n if (result.summary) {\n const extra = rawLines.length > 1 ? ` (+${rawLines.length - 1} lines)` : \"\";\n displayLines = [result.summary + extra];\n } else if (rawLines.length === 0) {\n displayLines = [\"(no output)\"];\n } else if (rawLines.length <= MAX_RESULT_LINES) {\n displayLines = rawLines;\n } else {\n displayLines = rawLines.slice(0, MAX_RESULT_LINES);\n omitted = rawLines.length - MAX_RESULT_LINES;\n }\n\n return (\n <Box flexDirection=\"column\" marginLeft={2} marginTop={standalone ? 1 : 0}>\n {displayLines.map((line, i) => (\n <Box key={i} flexDirection=\"row\">\n <Text color={i === 0 ? dotColor : undefined}>{i === 0 ? \"└ \" : \" \"}</Text>\n <Box flexGrow={1} minWidth={0}>\n <Text dimColor wrap=\"truncate-end\">{line || \" \"}</Text>\n </Box>\n </Box>\n ))}\n {omitted > 0 && (\n <Box marginLeft={2}>\n <Text dimColor>{`(+${omitted} more lines)`}</Text>\n </Box>\n )}\n {result.diff && <DiffBlock diff={result.diff} />}\n </Box>\n );\n}\n\n/** bash 工具内容里独立成行的 <stdout>/<stderr>/<timeout>/<exit_code> 包装标签,UI 不展示。 */\nfunction stripWrapperTags(content: string): string {\n return content\n .split(\"\\n\")\n .filter((l) => !/^<\\/?(stdout|stderr|timeout|exit_code)>\\s*$/.test(l.trim()))\n .join(\"\\n\");\n}\n\nfunction DiffBlock({ diff }: { diff: string }) {\n // jsdiff createPatch 头四行:Index / === / --- / +++;省略,只渲染 hunks\n const lines = diff.split(\"\\n\");\n const start = lines.findIndex((l) => l.startsWith(\"@@\"));\n const rendered = start >= 0 ? lines.slice(start) : lines;\n return (\n <Box flexDirection=\"column\" marginLeft={2} marginTop={1}>\n {rendered.map((line, i) => {\n let color: string | undefined;\n let dim = false;\n if (line.startsWith(\"+\")) color = \"green\";\n else if (line.startsWith(\"-\")) color = \"red\";\n else if (line.startsWith(\"@@\")) {\n color = \"cyan\";\n dim = true;\n } else {\n dim = true;\n }\n return (\n <Text key={i} color={color} dimColor={dim}>\n {line || \" \"}\n </Text>\n );\n })}\n </Box>\n );\n}\n\nfunction formatArgs(args: unknown): string {\n if (typeof args !== \"object\" || args === null) return String(args);\n const entries = Object.entries(args as Record<string, unknown>);\n if (entries.length === 0) return \"\";\n const parts: string[] = [];\n for (const [k, v] of entries) {\n if (typeof v === \"string\") {\n const truncated = v.length > 40 ? v.slice(0, 40) + \"...\" : v;\n parts.push(`${k}=\"${truncated}\"`);\n } else {\n parts.push(`${k}=${JSON.stringify(v).slice(0, 40)}`);\n }\n }\n return parts.join(\", \");\n}\n","const ANSI_BACKGROUND_OFFSET = 10;\n\nconst wrapAnsi16 = (offset = 0) => code => `\\u001B[${code + offset}m`;\n\nconst wrapAnsi256 = (offset = 0) => code => `\\u001B[${38 + offset};5;${code}m`;\n\nconst wrapAnsi16m = (offset = 0) => (red, green, blue) => `\\u001B[${38 + offset};2;${red};${green};${blue}m`;\n\nconst styles = {\n\tmodifier: {\n\t\treset: [0, 0],\n\t\t// 21 isn't widely supported and 22 does the same thing\n\t\tbold: [1, 22],\n\t\tdim: [2, 22],\n\t\titalic: [3, 23],\n\t\tunderline: [4, 24],\n\t\toverline: [53, 55],\n\t\tinverse: [7, 27],\n\t\thidden: [8, 28],\n\t\tstrikethrough: [9, 29],\n\t},\n\tcolor: {\n\t\tblack: [30, 39],\n\t\tred: [31, 39],\n\t\tgreen: [32, 39],\n\t\tyellow: [33, 39],\n\t\tblue: [34, 39],\n\t\tmagenta: [35, 39],\n\t\tcyan: [36, 39],\n\t\twhite: [37, 39],\n\n\t\t// Bright color\n\t\tblackBright: [90, 39],\n\t\tgray: [90, 39], // Alias of `blackBright`\n\t\tgrey: [90, 39], // Alias of `blackBright`\n\t\tredBright: [91, 39],\n\t\tgreenBright: [92, 39],\n\t\tyellowBright: [93, 39],\n\t\tblueBright: [94, 39],\n\t\tmagentaBright: [95, 39],\n\t\tcyanBright: [96, 39],\n\t\twhiteBright: [97, 39],\n\t},\n\tbgColor: {\n\t\tbgBlack: [40, 49],\n\t\tbgRed: [41, 49],\n\t\tbgGreen: [42, 49],\n\t\tbgYellow: [43, 49],\n\t\tbgBlue: [44, 49],\n\t\tbgMagenta: [45, 49],\n\t\tbgCyan: [46, 49],\n\t\tbgWhite: [47, 49],\n\n\t\t// Bright color\n\t\tbgBlackBright: [100, 49],\n\t\tbgGray: [100, 49], // Alias of `bgBlackBright`\n\t\tbgGrey: [100, 49], // Alias of `bgBlackBright`\n\t\tbgRedBright: [101, 49],\n\t\tbgGreenBright: [102, 49],\n\t\tbgYellowBright: [103, 49],\n\t\tbgBlueBright: [104, 49],\n\t\tbgMagentaBright: [105, 49],\n\t\tbgCyanBright: [106, 49],\n\t\tbgWhiteBright: [107, 49],\n\t},\n};\n\nexport const modifierNames = Object.keys(styles.modifier);\nexport const foregroundColorNames = Object.keys(styles.color);\nexport const backgroundColorNames = Object.keys(styles.bgColor);\nexport const colorNames = [...foregroundColorNames, ...backgroundColorNames];\n\nfunction assembleStyles() {\n\tconst codes = new Map();\n\n\tfor (const [groupName, group] of Object.entries(styles)) {\n\t\tfor (const [styleName, style] of Object.entries(group)) {\n\t\t\tstyles[styleName] = {\n\t\t\t\topen: `\\u001B[${style[0]}m`,\n\t\t\t\tclose: `\\u001B[${style[1]}m`,\n\t\t\t};\n\n\t\t\tgroup[styleName] = styles[styleName];\n\n\t\t\tcodes.set(style[0], style[1]);\n\t\t}\n\n\t\tObject.defineProperty(styles, groupName, {\n\t\t\tvalue: group,\n\t\t\tenumerable: false,\n\t\t});\n\t}\n\n\tObject.defineProperty(styles, 'codes', {\n\t\tvalue: codes,\n\t\tenumerable: false,\n\t});\n\n\tstyles.color.close = '\\u001B[39m';\n\tstyles.bgColor.close = '\\u001B[49m';\n\n\tstyles.color.ansi = wrapAnsi16();\n\tstyles.color.ansi256 = wrapAnsi256();\n\tstyles.color.ansi16m = wrapAnsi16m();\n\tstyles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);\n\n\t// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js\n\tObject.defineProperties(styles, {\n\t\trgbToAnsi256: {\n\t\t\tvalue(red, green, blue) {\n\t\t\t\t// We use the extended greyscale palette here, with the exception of\n\t\t\t\t// black and white. normal palette only has 4 greyscale shades.\n\t\t\t\tif (red === green && green === blue) {\n\t\t\t\t\tif (red < 8) {\n\t\t\t\t\t\treturn 16;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (red > 248) {\n\t\t\t\t\t\treturn 231;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Math.round(((red - 8) / 247) * 24) + 232;\n\t\t\t\t}\n\n\t\t\t\treturn 16\n\t\t\t\t\t+ (36 * Math.round(red / 255 * 5))\n\t\t\t\t\t+ (6 * Math.round(green / 255 * 5))\n\t\t\t\t\t+ Math.round(blue / 255 * 5);\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToRgb: {\n\t\t\tvalue(hex) {\n\t\t\t\tconst matches = /[a-f\\d]{6}|[a-f\\d]{3}/i.exec(hex.toString(16));\n\t\t\t\tif (!matches) {\n\t\t\t\t\treturn [0, 0, 0];\n\t\t\t\t}\n\n\t\t\t\tlet [colorString] = matches;\n\n\t\t\t\tif (colorString.length === 3) {\n\t\t\t\t\tcolorString = [...colorString].map(character => character + character).join('');\n\t\t\t\t}\n\n\t\t\t\tconst integer = Number.parseInt(colorString, 16);\n\n\t\t\t\treturn [\n\t\t\t\t\t/* eslint-disable no-bitwise */\n\t\t\t\t\t(integer >> 16) & 0xFF,\n\t\t\t\t\t(integer >> 8) & 0xFF,\n\t\t\t\t\tinteger & 0xFF,\n\t\t\t\t\t/* eslint-enable no-bitwise */\n\t\t\t\t];\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi256: {\n\t\t\tvalue: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t\tansi256ToAnsi: {\n\t\t\tvalue(code) {\n\t\t\t\tif (code < 8) {\n\t\t\t\t\treturn 30 + code;\n\t\t\t\t}\n\n\t\t\t\tif (code < 16) {\n\t\t\t\t\treturn 90 + (code - 8);\n\t\t\t\t}\n\n\t\t\t\tlet red;\n\t\t\t\tlet green;\n\t\t\t\tlet blue;\n\n\t\t\t\tif (code >= 232) {\n\t\t\t\t\tred = (((code - 232) * 10) + 8) / 255;\n\t\t\t\t\tgreen = red;\n\t\t\t\t\tblue = red;\n\t\t\t\t} else {\n\t\t\t\t\tcode -= 16;\n\n\t\t\t\t\tconst remainder = code % 36;\n\n\t\t\t\t\tred = Math.floor(code / 36) / 5;\n\t\t\t\t\tgreen = Math.floor(remainder / 6) / 5;\n\t\t\t\t\tblue = (remainder % 6) / 5;\n\t\t\t\t}\n\n\t\t\t\tconst value = Math.max(red, green, blue) * 2;\n\n\t\t\t\tif (value === 0) {\n\t\t\t\t\treturn 30;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-bitwise\n\t\t\t\tlet result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));\n\n\t\t\t\tif (value === 2) {\n\t\t\t\t\tresult += 60;\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\trgbToAnsi: {\n\t\t\tvalue: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi: {\n\t\t\tvalue: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t});\n\n\treturn styles;\n}\n\nconst ansiStyles = assembleStyles();\n\nexport default ansiStyles;\n","import process from 'node:process';\nimport os from 'node:os';\nimport tty from 'node:tty';\n\n// From: https://github.com/sindresorhus/has-flag/blob/main/index.js\n/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {\nfunction hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {\n\tconst prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');\n\tconst position = argv.indexOf(prefix + flag);\n\tconst terminatorPosition = argv.indexOf('--');\n\treturn position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);\n}\n\nconst {env} = process;\n\nlet flagForceColor;\nif (\n\thasFlag('no-color')\n\t|| hasFlag('no-colors')\n\t|| hasFlag('color=false')\n\t|| hasFlag('color=never')\n) {\n\tflagForceColor = 0;\n} else if (\n\thasFlag('color')\n\t|| hasFlag('colors')\n\t|| hasFlag('color=true')\n\t|| hasFlag('color=always')\n) {\n\tflagForceColor = 1;\n}\n\nfunction envForceColor() {\n\tif ('FORCE_COLOR' in env) {\n\t\tif (env.FORCE_COLOR === 'true') {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (env.FORCE_COLOR === 'false') {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);\n\t}\n}\n\nfunction translateLevel(level) {\n\tif (level === 0) {\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tlevel,\n\t\thasBasic: true,\n\t\thas256: level >= 2,\n\t\thas16m: level >= 3,\n\t};\n}\n\nfunction _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {\n\tconst noFlagForceColor = envForceColor();\n\tif (noFlagForceColor !== undefined) {\n\t\tflagForceColor = noFlagForceColor;\n\t}\n\n\tconst forceColor = sniffFlags ? flagForceColor : noFlagForceColor;\n\n\tif (forceColor === 0) {\n\t\treturn 0;\n\t}\n\n\tif (sniffFlags) {\n\t\tif (hasFlag('color=16m')\n\t\t\t|| hasFlag('color=full')\n\t\t\t|| hasFlag('color=truecolor')) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (hasFlag('color=256')) {\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\t// Check for Azure DevOps pipelines.\n\t// Has to be above the `!streamIsTTY` check.\n\tif ('TF_BUILD' in env && 'AGENT_NAME' in env) {\n\t\treturn 1;\n\t}\n\n\tif (haveStream && !streamIsTTY && forceColor === undefined) {\n\t\treturn 0;\n\t}\n\n\tconst min = forceColor || 0;\n\n\tif (env.TERM === 'dumb') {\n\t\treturn min;\n\t}\n\n\tif (process.platform === 'win32') {\n\t\t// Windows 10 build 10586 is the first Windows release that supports 256 colors.\n\t\t// Windows 10 build 14931 is the first release that supports 16m/TrueColor.\n\t\tconst osRelease = os.release().split('.');\n\t\tif (\n\t\t\tNumber(osRelease[0]) >= 10\n\t\t\t&& Number(osRelease[2]) >= 10_586\n\t\t) {\n\t\t\treturn Number(osRelease[2]) >= 14_931 ? 3 : 2;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\tif ('CI' in env) {\n\t\tif (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn min;\n\t}\n\n\tif ('TEAMCITY_VERSION' in env) {\n\t\treturn /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;\n\t}\n\n\tif (env.COLORTERM === 'truecolor') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-kitty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-ghostty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'wezterm') {\n\t\treturn 3;\n\t}\n\n\tif ('TERM_PROGRAM' in env) {\n\t\tconst version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n\t\tswitch (env.TERM_PROGRAM) {\n\t\t\tcase 'iTerm.app': {\n\t\t\t\treturn version >= 3 ? 3 : 2;\n\t\t\t}\n\n\t\t\tcase 'Apple_Terminal': {\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (/-256(color)?$/i.test(env.TERM)) {\n\t\treturn 2;\n\t}\n\n\tif (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n\t\treturn 1;\n\t}\n\n\tif ('COLORTERM' in env) {\n\t\treturn 1;\n\t}\n\n\treturn min;\n}\n\nexport function createSupportsColor(stream, options = {}) {\n\tconst level = _supportsColor(stream, {\n\t\tstreamIsTTY: stream && stream.isTTY,\n\t\t...options,\n\t});\n\n\treturn translateLevel(level);\n}\n\nconst supportsColor = {\n\tstdout: createSupportsColor({isTTY: tty.isatty(1)}),\n\tstderr: createSupportsColor({isTTY: tty.isatty(2)}),\n};\n\nexport default supportsColor;\n","// TODO: When targeting Node.js 16, use `String.prototype.replaceAll`.\nexport function stringReplaceAll(string, substring, replacer) {\n\tlet index = string.indexOf(substring);\n\tif (index === -1) {\n\t\treturn string;\n\t}\n\n\tconst substringLength = substring.length;\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\treturnValue += string.slice(endIndex, index) + substring + replacer;\n\t\tendIndex = index + substringLength;\n\t\tindex = string.indexOf(substring, endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n\nexport function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\tconst gotCR = string[index - 1] === '\\r';\n\t\treturnValue += string.slice(endIndex, (gotCR ? index - 1 : index)) + prefix + (gotCR ? '\\r\\n' : '\\n') + postfix;\n\t\tendIndex = index + 1;\n\t\tindex = string.indexOf('\\n', endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n","import ansiStyles from '#ansi-styles';\nimport supportsColor from '#supports-color';\nimport { // eslint-disable-line import/order\n\tstringReplaceAll,\n\tstringEncaseCRLFWithFirstIndex,\n} from './utilities.js';\n\nconst {stdout: stdoutColor, stderr: stderrColor} = supportsColor;\n\nconst GENERATOR = Symbol('GENERATOR');\nconst STYLER = Symbol('STYLER');\nconst IS_EMPTY = Symbol('IS_EMPTY');\n\n// `supportsColor.level` → `ansiStyles.color[name]` mapping\nconst levelMapping = [\n\t'ansi',\n\t'ansi',\n\t'ansi256',\n\t'ansi16m',\n];\n\nconst styles = Object.create(null);\n\nconst applyOptions = (object, options = {}) => {\n\tif (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {\n\t\tthrow new Error('The `level` option should be an integer from 0 to 3');\n\t}\n\n\t// Detect level if not set manually\n\tconst colorLevel = stdoutColor ? stdoutColor.level : 0;\n\tobject.level = options.level === undefined ? colorLevel : options.level;\n};\n\nexport class Chalk {\n\tconstructor(options) {\n\t\t// eslint-disable-next-line no-constructor-return\n\t\treturn chalkFactory(options);\n\t}\n}\n\nconst chalkFactory = options => {\n\tconst chalk = (...strings) => strings.join(' ');\n\tapplyOptions(chalk, options);\n\n\tObject.setPrototypeOf(chalk, createChalk.prototype);\n\n\treturn chalk;\n};\n\nfunction createChalk(options) {\n\treturn chalkFactory(options);\n}\n\nObject.setPrototypeOf(createChalk.prototype, Function.prototype);\n\nfor (const [styleName, style] of Object.entries(ansiStyles)) {\n\tstyles[styleName] = {\n\t\tget() {\n\t\t\tconst builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);\n\t\t\tObject.defineProperty(this, styleName, {value: builder});\n\t\t\treturn builder;\n\t\t},\n\t};\n}\n\nstyles.visible = {\n\tget() {\n\t\tconst builder = createBuilder(this, this[STYLER], true);\n\t\tObject.defineProperty(this, 'visible', {value: builder});\n\t\treturn builder;\n\t},\n};\n\nconst getModelAnsi = (model, level, type, ...arguments_) => {\n\tif (model === 'rgb') {\n\t\tif (level === 'ansi16m') {\n\t\t\treturn ansiStyles[type].ansi16m(...arguments_);\n\t\t}\n\n\t\tif (level === 'ansi256') {\n\t\t\treturn ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));\n\t\t}\n\n\t\treturn ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));\n\t}\n\n\tif (model === 'hex') {\n\t\treturn getModelAnsi('rgb', level, type, ...ansiStyles.hexToRgb(...arguments_));\n\t}\n\n\treturn ansiStyles[type][model](...arguments_);\n};\n\nconst usedModels = ['rgb', 'hex', 'ansi256'];\n\nfor (const model of usedModels) {\n\tstyles[model] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'color', ...arguments_), ansiStyles.color.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n\n\tconst bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);\n\tstyles[bgModel] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'bgColor', ...arguments_), ansiStyles.bgColor.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n}\n\nconst proto = Object.defineProperties(() => {}, {\n\t...styles,\n\tlevel: {\n\t\tenumerable: true,\n\t\tget() {\n\t\t\treturn this[GENERATOR].level;\n\t\t},\n\t\tset(level) {\n\t\t\tthis[GENERATOR].level = level;\n\t\t},\n\t},\n});\n\nconst createStyler = (open, close, parent) => {\n\tlet openAll;\n\tlet closeAll;\n\tif (parent === undefined) {\n\t\topenAll = open;\n\t\tcloseAll = close;\n\t} else {\n\t\topenAll = parent.openAll + open;\n\t\tcloseAll = close + parent.closeAll;\n\t}\n\n\treturn {\n\t\topen,\n\t\tclose,\n\t\topenAll,\n\t\tcloseAll,\n\t\tparent,\n\t};\n};\n\nconst createBuilder = (self, _styler, _isEmpty) => {\n\t// Single argument is hot path, implicit coercion is faster than anything\n\t// eslint-disable-next-line no-implicit-coercion\n\tconst builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));\n\n\t// We alter the prototype because we must return a function, but there is\n\t// no way to create a function with a different prototype\n\tObject.setPrototypeOf(builder, proto);\n\n\tbuilder[GENERATOR] = self;\n\tbuilder[STYLER] = _styler;\n\tbuilder[IS_EMPTY] = _isEmpty;\n\n\treturn builder;\n};\n\nconst applyStyle = (self, string) => {\n\tif (self.level <= 0 || !string) {\n\t\treturn self[IS_EMPTY] ? '' : string;\n\t}\n\n\tlet styler = self[STYLER];\n\n\tif (styler === undefined) {\n\t\treturn string;\n\t}\n\n\tconst {openAll, closeAll} = styler;\n\tif (string.includes('\\u001B')) {\n\t\twhile (styler !== undefined) {\n\t\t\t// Replace any instances already present with a re-opening code\n\t\t\t// otherwise only the part of the string until said closing code\n\t\t\t// will be colored, and the rest will simply be 'plain'.\n\t\t\tstring = stringReplaceAll(string, styler.close, styler.open);\n\n\t\t\tstyler = styler.parent;\n\t\t}\n\t}\n\n\t// We can move both next actions out of loop, because remaining actions in loop won't have\n\t// any/visible effect on parts we add here. Close the styling before a linebreak and reopen\n\t// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92\n\tconst lfIndex = string.indexOf('\\n');\n\tif (lfIndex !== -1) {\n\t\tstring = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);\n\t}\n\n\treturn openAll + string + closeAll;\n};\n\nObject.defineProperties(createChalk.prototype, styles);\n\nconst chalk = createChalk();\nexport const chalkStderr = createChalk({level: stderrColor ? stderrColor.level : 0});\n\nexport {\n\tmodifierNames,\n\tforegroundColorNames,\n\tbackgroundColorNames,\n\tcolorNames,\n\n\t// TODO: Remove these aliases in the next major version\n\tmodifierNames as modifiers,\n\tforegroundColorNames as foregroundColors,\n\tbackgroundColorNames as backgroundColors,\n\tcolorNames as colors,\n} from './vendor/ansi-styles/index.js';\n\nexport {\n\tstdoutColor as supportsColor,\n\tstderrColor as supportsColorStderr,\n};\n\nexport default chalk;\n","/**\n * 工具调用的权限确认 prompt(v2 picker)。\n *\n * ↑/↓ 选择 + Enter 确认;快捷键 y/s/n 与 1/2/3 直接落子;Esc 等价于 no。\n *\n * 三选项:\n * 1. Yes — 本次允许\n * 2. Yes, allow <Tool> for session — 后续该 toolName 在 session 内全部 allow\n * 3. No — 拒绝\n */\n\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { PermissionDecision } from \"../permission/index.js\";\n\nexport interface PermissionRequest {\n toolName: string;\n args: unknown;\n summary: string;\n resolve: (decision: PermissionDecision) => void;\n}\n\nconst OPTIONS: { decision: PermissionDecision; labelKey: \"yes\" | \"session\" | \"no\"; shortcut: string }[] = [\n { decision: \"yes\", labelKey: \"yes\", shortcut: \"y\" },\n { decision: \"session_allow\", labelKey: \"session\", shortcut: \"s\" },\n { decision: \"no\", labelKey: \"no\", shortcut: \"n\" },\n];\n\nexport function PermissionPrompt({ request }: { request: PermissionRequest }) {\n const [index, setIndex] = useState(0);\n\n useInput((input, key) => {\n if (key.upArrow) {\n setIndex((i) => (i - 1 + OPTIONS.length) % OPTIONS.length);\n return;\n }\n if (key.downArrow) {\n setIndex((i) => (i + 1) % OPTIONS.length);\n return;\n }\n if (key.return) {\n request.resolve(OPTIONS[index].decision);\n return;\n }\n if (key.escape) {\n request.resolve(\"no\");\n return;\n }\n const lower = input?.toLowerCase?.();\n for (let i = 0; i < OPTIONS.length; i++) {\n const o = OPTIONS[i];\n if (lower === o.shortcut || input === String(i + 1)) {\n request.resolve(o.decision);\n return;\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginY={1} borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text color=\"yellow\" bold>\n ⏵ Approve {request.toolName}?\n </Text>\n <Text dimColor>{request.summary}</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {OPTIONS.map((o, i) => {\n const focused = i === index;\n const label = labelFor(o.labelKey, request.toolName);\n return (\n <Text key={o.decision} color={focused ? \"cyan\" : undefined} bold={focused}>\n {focused ? \"› \" : \" \"}\n {i + 1}. {label}{\" \"}\n <Text dimColor>({o.shortcut})</Text>\n </Text>\n );\n })}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>↑↓ select · Enter confirm · y/s/n shortcut · Esc=no</Text>\n </Box>\n </Box>\n );\n}\n\nfunction labelFor(key: \"yes\" | \"session\" | \"no\", toolName: string): string {\n switch (key) {\n case \"yes\":\n return \"Yes\";\n case \"session\":\n return `Yes, allow ${toolName} for the rest of this session`;\n case \"no\":\n return \"No\";\n }\n}\n","/**\n * 模型选择器:用 Selector 骨架实现,提供 model entry 专用行渲染。\n *\n * 由 /models 命令通过 ctx.actions.pickModel(...) 拉起。\n * 接口(ModelPickerRequest)保持稳定,便于 app.tsx 不动 actions.pickModel 调用方。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { Selector } from \"./Selector.js\";\nimport type { ModelEntry } from \"../config/models.js\";\n\nexport interface ModelPickerRequest {\n items: ModelEntry[];\n currentId?: string;\n resolve: (picked: ModelEntry | null) => void;\n}\n\nexport function ModelSelector({ request }: { request: ModelPickerRequest }) {\n const { items, currentId, resolve } = request;\n const initialIndex = Math.max(\n 0,\n items.findIndex((m) => m.id === currentId),\n );\n const labelWidth = Math.max(...items.map((m) => (m.name ?? m.id).length));\n\n return (\n <Selector\n items={items}\n initialIndex={initialIndex}\n title=\"Select model\"\n hint=\"↑↓ navigate · Enter confirm · Esc cancel\"\n onSubmit={(m) => resolve(m)}\n onCancel={() => resolve(null)}\n renderRow={(m, _focused) => (\n <ModelRow model={m} active={m.id === currentId} labelWidth={labelWidth} />\n )}\n />\n );\n}\n\nfunction ModelRow({\n model,\n active,\n labelWidth,\n}: {\n model: ModelEntry;\n active: boolean;\n labelWidth: number;\n}) {\n const dot = active ? \"●\" : \" \";\n const label = (model.name ?? model.id).padEnd(labelWidth);\n const vendor = model.vendor ? `[${model.vendor}]` : \"\";\n const caps = formatCaps(model);\n\n return (\n <Box flexDirection=\"row\">\n <Text color={active ? \"green\" : undefined}>{dot} </Text>\n <Text>{label}</Text>\n <Text dimColor>{\" \"}{vendor}</Text>\n {caps && <Text dimColor>{\" \"}{caps}</Text>}\n </Box>\n );\n}\n\nfunction formatCaps(m: ModelEntry): string {\n const flags: string[] = [];\n if (m.supportsToolCall === false) flags.push(\"no-tools\");\n if (m.supportsImages) flags.push(\"vision\");\n return flags.length ? flags.join(\" · \") : \"\";\n}\n","/**\n * 通用键盘 selector 骨架:↑↓ 导航 + Enter 确认 + Esc 取消。\n *\n * 行渲染由 renderRow 回调提供;本组件只负责:\n * - 键盘事件\n * - 焦点状态 + 滑动窗口(保证 focused 始终可见)\n * - 紫色 `›` 焦点指针(颜色 #A855F7,对齐用户截图)\n * - 标题 + 提示\n *\n * 当前调用方:ModelSelector / SessionSelector。\n * 第三处再考虑把外层 borderStyle 等做成 prop;暂时硬编码。\n */\n\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\nconst POINTER_COLOR = \"#A855F7\";\n\nexport interface SelectorProps<T> {\n items: T[];\n initialIndex?: number;\n title?: string;\n hint?: string;\n maxVisible?: number;\n renderRow: (item: T, focused: boolean) => React.ReactNode;\n onSubmit: (item: T) => void;\n onCancel: () => void;\n}\n\nexport function Selector<T>({\n items,\n initialIndex = 0,\n title,\n hint,\n maxVisible,\n renderRow,\n onSubmit,\n onCancel,\n}: SelectorProps<T>) {\n const safeInitial = Math.max(0, Math.min(initialIndex, items.length - 1));\n const [index, setIndex] = useState(safeInitial);\n\n useInput((_, key) => {\n if (key.upArrow) {\n setIndex((i) => Math.max(0, i - 1));\n } else if (key.downArrow) {\n setIndex((i) => Math.min(items.length - 1, i + 1));\n } else if (key.return) {\n onSubmit(items[index]);\n } else if (key.escape) {\n onCancel();\n }\n });\n\n const len = items.length;\n const window = maxVisible && maxVisible < len ? maxVisible : len;\n const start = Math.max(0, Math.min(index - Math.floor(window / 2), len - window));\n const end = Math.min(len, start + window);\n const visible = items.slice(start, end);\n\n return (\n <Box\n flexDirection=\"column\"\n marginTop={1}\n paddingX={1}\n borderStyle=\"round\"\n borderColor=\"cyan\"\n >\n {(title || hint) && (\n <Box marginBottom={1}>\n {title && <Text bold>{title}</Text>}\n {title && hint && <Text dimColor>{\" \"}</Text>}\n {hint && <Text dimColor>{hint}</Text>}\n </Box>\n )}\n {visible.map((item, i) => {\n const realIndex = start + i;\n const focused = realIndex === index;\n return (\n <Box key={realIndex} flexDirection=\"row\">\n <Text color={POINTER_COLOR} bold>\n {focused ? \"› \" : \" \"}\n </Text>\n {renderRow(item, focused)}\n </Box>\n );\n })}\n {window < len && (\n <Box marginTop={1}>\n <Text dimColor>\n ({start + 1}-{end} / {len})\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * Session 选择器:列出当前 cwd 下的历史会话,键盘选中加载。\n *\n * 由 /resume 命令通过 ctx.actions.pickSession(...) 拉起。\n * 行布局对齐 /resume display 文本版(id8 · time · [N msgs] · preview),\n * 视觉差异:紫色 `›` 箭头 + 边框 + 选中态。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { Selector } from \"./Selector.js\";\nimport type { SessionSummary } from \"../session/jsonl.js\";\n\nexport interface SessionPickerRequest {\n items: SessionSummary[];\n currentId?: string;\n resolve: (picked: SessionSummary | null) => void;\n}\n\nexport function SessionSelector({ request }: { request: SessionPickerRequest }) {\n const { items, currentId, resolve } = request;\n const initialIndex = Math.max(\n 0,\n items.findIndex((s) => s.id === currentId),\n );\n\n return (\n <Selector\n items={items}\n initialIndex={initialIndex}\n maxVisible={12}\n title=\"Resume session\"\n hint=\"↑↓ navigate · Enter load · Esc cancel\"\n onSubmit={(s) => resolve(s)}\n onCancel={() => resolve(null)}\n renderRow={(s) => <SessionRow session={s} active={s.id === currentId} />}\n />\n );\n}\n\nfunction SessionRow({ session, active }: { session: SessionSummary; active: boolean }) {\n const id8 = session.id.slice(0, 8);\n const time = formatTime(session.createdAt);\n const count = `[${String(session.messageCount).padStart(2)} msgs]`;\n const preview = session.preview ?? \"(empty)\";\n\n return (\n <Box flexDirection=\"row\">\n <Text color={active ? \"green\" : undefined}>{active ? \"● \" : \" \"}</Text>\n <Text>{id8}</Text>\n <Text dimColor>{\" \"}{time}</Text>\n <Text dimColor>{\" \"}{count}</Text>\n <Text>{\" \"}{preview}</Text>\n </Box>\n );\n}\n\nfunction formatTime(iso: string): string {\n const d = new Date(iso);\n if (isNaN(d.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n","/**\n * AskUserQuestion UI——完整复刻 Claude Code 的链式选择器。\n *\n * 布局:\n *\n * ─────────────────────────────────────────────────────────────────\n * ← □ Header1 □ Header2 □ Header3 ✔ Submit →\n *\n * Question text?\n *\n * 1. Option A ┌──────────────────────────────┐\n * description │ preview content for the │\n * 2. Option B │ focused option │\n * description │ (multi-line allowed) │\n * └──────────────────────────────┘\n *\n * Notes: press n to add notes\n * ─────────────────────────────────────────────────────────────────\n * Enter to select · ↑/↓ to navigate · n to add notes · Tab to switch questions · Esc to cancel\n *\n * 状态:\n * - 每题独立 optionIndex / selected / notes\n * - notesEditing 切换内联文本编辑器(Enter 保存 / Esc 退出回 picker,不取消整批)\n *\n * 键位:\n * ↑↓ 选项移动\n * ←→ / Tab 题间切换(含 Submit chip)\n * Enter option 上:单选 → 选定 + 跳下一题;多选 → toggle\n * Submit 上 → 提交\n * Space 多选 toggle\n * n 进入 notes 编辑(Enter 保存 / Esc 退出)\n * Esc picker 取消\n *\n * Tab chip 标记:\n * 单选未答 □ / 答了 ✔\n * 多选未选 □ / 选了 N 个 [N]\n * 聚焦 chip 走 FOCUS_BG 背景高亮\n *\n * 单题特化:\n * 单题不渲染 tab bar / Submit chip——单选 Enter 直提交;多选 Submit 行放选项末尾\n */\n\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { AskQuestion, AskQuestionResponse } from \"../tools/builtin/ask-user-question.js\";\n\nconst POINTER_COLOR = \"#A855F7\"; // 焦点行指针 + 焦点项 label\nconst FOCUS_BG = \"#5B5598\"; // 聚焦 chip 背景(柔和淡紫)\nconst FOCUS_FG = \"white\";\nconst SUBMIT_COLOR = \"green\";\nconst NOTES_LABEL_COLOR = \"yellow\";\nconst PREVIEW_BORDER = \"gray\";\nconst TAB_GAP = 3;\nconst PREVIEW_MIN_WIDTH = 28;\n\nexport interface QuestionPickerRequest {\n questions: AskQuestion[];\n resolve: (responses: AskQuestionResponse[]) => void;\n}\n\ninterface QState {\n optionIndex: number;\n selected: Set<number>;\n notes: string;\n notesEditing: boolean;\n /** notes 编辑中的草稿——Enter 保存到 notes / Esc 丢弃。 */\n notesDraft: string;\n}\n\nexport function QuestionPicker({ request }: { request: QuestionPickerRequest }) {\n const { questions } = request;\n const N = questions.length;\n const hasTabs = N > 1;\n const submitTabIndex = N;\n\n const [tabIndex, setTabIndex] = useState(0);\n const [states, setStates] = useState<QState[]>(() =>\n questions.map(() => ({\n optionIndex: 0,\n selected: new Set<number>(),\n notes: \"\",\n notesEditing: false,\n notesDraft: \"\",\n })),\n );\n\n const currentQ = tabIndex < N ? questions[tabIndex] : null;\n const isMulti = currentQ?.multiSelect === true;\n const onSubmitChip = hasTabs && tabIndex === submitTabIndex;\n\n // 任意 option 提供了 preview?整个题就走双栏,焦点项的 preview 渲染到右侧\n const anyPreview = !!currentQ?.options.some((o) => o.preview);\n const focusedOpt = currentQ?.options[states[tabIndex]?.optionIndex ?? 0];\n const focusedPreview = anyPreview ? focusedOpt?.preview ?? \"\" : \"\";\n\n const buildResponses = (cancelled: boolean): AskQuestionResponse[] => {\n if (cancelled) return questions.map(() => ({ cancelled: true, selections: [] }));\n return questions.map((q, qi) => ({\n cancelled: false,\n selections: Array.from(states[qi].selected)\n .sort((a, b) => a - b)\n .map((i) => q.options[i].label),\n notes: states[qi].notes,\n }));\n };\n\n const submit = () => request.resolve(buildResponses(false));\n const cancel = () => request.resolve(buildResponses(true));\n\n const updateState = (qi: number, mut: (s: QState) => QState) => {\n setStates((prev) => {\n const next = [...prev];\n next[qi] = mut(prev[qi]);\n return next;\n });\n };\n\n const toggleOption = (qi: number, oi: number) => {\n updateState(qi, (s) => {\n const sel = new Set(s.selected);\n if (sel.has(oi)) sel.delete(oi);\n else sel.add(oi);\n return { ...s, selected: sel };\n });\n };\n\n const selectSingleOption = (qi: number, oi: number) => {\n updateState(qi, (s) => ({ ...s, selected: new Set([oi]) }));\n if (!hasTabs) {\n request.resolve([\n {\n cancelled: false,\n selections: [questions[0].options[oi].label],\n notes: states[0].notes,\n },\n ]);\n return;\n }\n if (qi < N - 1) setTabIndex(qi + 1);\n else setTabIndex(submitTabIndex);\n };\n\n // 单题多选用的 Submit 行(=options.length,options 末尾)\n const singleQMultiSubmitRowIndex = !hasTabs && isMulti ? currentQ!.options.length : -1;\n const optionRowCount =\n !hasTabs && isMulti ? currentQ!.options.length + 1 : currentQ?.options.length ?? 0;\n\n const currentNotesEditing =\n tabIndex < N ? states[tabIndex].notesEditing : false;\n\n useInput((input, key) => {\n // ---------- notes 编辑模式 ----------\n if (currentNotesEditing) {\n if (key.escape) {\n updateState(tabIndex, (s) => ({ ...s, notesEditing: false, notesDraft: \"\" }));\n return;\n }\n if (key.return) {\n updateState(tabIndex, (s) => ({\n ...s,\n notesEditing: false,\n notes: s.notesDraft,\n notesDraft: \"\",\n }));\n return;\n }\n if (key.backspace || key.delete) {\n updateState(tabIndex, (s) => ({\n ...s,\n notesDraft: s.notesDraft.slice(0, -1),\n }));\n return;\n }\n if (key.ctrl || key.tab || key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.meta) {\n return;\n }\n if (input) {\n updateState(tabIndex, (s) => ({ ...s, notesDraft: s.notesDraft + input }));\n }\n return;\n }\n\n // ---------- picker 主模式 ----------\n if (key.escape) {\n cancel();\n return;\n }\n\n if (hasTabs && (key.tab || key.leftArrow || key.rightArrow)) {\n if (key.leftArrow || (key.shift && key.tab)) {\n setTabIndex((t) => Math.max(0, t - 1));\n } else {\n setTabIndex((t) => Math.min(submitTabIndex, t + 1));\n }\n return;\n }\n\n if (onSubmitChip) {\n if (key.return) submit();\n return;\n }\n\n const qi = tabIndex;\n const s = states[qi];\n\n if (key.upArrow) {\n updateState(qi, (st) => ({ ...st, optionIndex: Math.max(0, st.optionIndex - 1) }));\n return;\n }\n if (key.downArrow) {\n updateState(qi, (st) => ({\n ...st,\n optionIndex: Math.min(optionRowCount - 1, st.optionIndex + 1),\n }));\n return;\n }\n // n —— 进入 notes 编辑(任何 picker 题都允许,对齐 Claude Code)\n if (input === \"n\" && !key.ctrl && !key.meta) {\n updateState(qi, (st) => ({\n ...st,\n notesEditing: true,\n notesDraft: st.notes,\n }));\n return;\n }\n if (key.return) {\n if (!hasTabs && isMulti && s.optionIndex === singleQMultiSubmitRowIndex) {\n submit();\n return;\n }\n if (isMulti) toggleOption(qi, s.optionIndex);\n else selectSingleOption(qi, s.optionIndex);\n return;\n }\n if (isMulti && input === \" \" && s.optionIndex !== singleQMultiSubmitRowIndex) {\n toggleOption(qi, s.optionIndex);\n }\n });\n\n // ---------- render ----------\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Divider />\n {hasTabs && (\n <Box marginTop={0}>\n <TabBar questions={questions} states={states} tabIndex={tabIndex} />\n </Box>\n )}\n\n {tabIndex < N && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>{questions[tabIndex].question}</Text>\n <Box flexDirection=\"row\" marginTop={1}>\n <Box flexDirection=\"column\" flexGrow={anyPreview ? 0 : 1} flexShrink={0} marginRight={anyPreview ? 2 : 0}>\n <OptionsList\n options={questions[tabIndex].options}\n focusedIndex={states[tabIndex].optionIndex}\n selected={states[tabIndex].selected}\n isMulti={isMulti}\n submitRowIndex={singleQMultiSubmitRowIndex}\n />\n </Box>\n {anyPreview && (\n <Box flexGrow={1} minWidth={PREVIEW_MIN_WIDTH}>\n <PreviewPanel content={focusedPreview} />\n </Box>\n )}\n </Box>\n <NotesLine\n notes={states[tabIndex].notes}\n editing={states[tabIndex].notesEditing}\n draft={states[tabIndex].notesDraft}\n />\n </Box>\n )}\n\n {onSubmitChip && (\n <Box flexDirection=\"column\" marginTop={1}>\n <SubmitPreview questions={questions} states={states} />\n </Box>\n )}\n\n <Divider />\n <Box>\n <Text dimColor>{hintLine(hasTabs, isMulti, currentNotesEditing)}</Text>\n </Box>\n </Box>\n );\n}\n\n// ---------- subcomponents ----------\n\nfunction Divider() {\n // 占满终端宽度的水平细线——用 box 的 borderTop 模拟最简单\n return (\n <Box borderStyle=\"single\" borderTop borderBottom={false} borderLeft={false} borderRight={false} borderColor=\"gray\" />\n );\n}\n\nfunction TabBar({\n questions,\n states,\n tabIndex,\n}: {\n questions: AskQuestion[];\n states: QState[];\n tabIndex: number;\n}) {\n const submitIndex = questions.length;\n const canLeft = tabIndex > 0;\n const canRight = tabIndex < submitIndex;\n return (\n <Box flexDirection=\"row\" flexWrap=\"wrap\">\n <Box marginRight={1}>\n <Text dimColor={!canLeft}>{\"←\"}</Text>\n </Box>\n {questions.map((q, i) => {\n const focused = i === tabIndex;\n const isMulti = q.multiSelect === true;\n const count = states[i].selected.size;\n const answered = count > 0;\n const mark = answered ? (isMulti ? `[${count}]` : \"✔\") : \"□\";\n return (\n <Box key={i} marginRight={TAB_GAP}>\n <Text\n backgroundColor={focused ? FOCUS_BG : undefined}\n color={focused ? FOCUS_FG : undefined}\n bold={focused}\n dimColor={!focused}\n >\n {` ${mark} ${q.header} `}\n </Text>\n </Box>\n );\n })}\n <Box marginRight={1}>\n <Text\n backgroundColor={tabIndex === submitIndex ? FOCUS_BG : undefined}\n color={tabIndex === submitIndex ? FOCUS_FG : SUBMIT_COLOR}\n bold={tabIndex === submitIndex}\n dimColor={tabIndex !== submitIndex}\n >\n {\" ✔ Submit \"}\n </Text>\n </Box>\n <Text dimColor={!canRight}>{\"→\"}</Text>\n </Box>\n );\n}\n\nfunction OptionsList({\n options,\n focusedIndex,\n selected,\n isMulti,\n submitRowIndex,\n}: {\n options: AskQuestion[\"options\"];\n focusedIndex: number;\n selected: Set<number>;\n isMulti: boolean;\n submitRowIndex: number;\n}) {\n return (\n <Box flexDirection=\"column\">\n {options.map((opt, i) => {\n const focused = i === focusedIndex;\n const checked = selected.has(i);\n return (\n <Box key={i} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={POINTER_COLOR} bold>\n {focused ? \"› \" : \" \"}\n </Text>\n {isMulti && (\n <Text color={checked ? \"green\" : undefined}>{checked ? \"[x] \" : \"[ ] \"}</Text>\n )}\n <Text dimColor>{`${i + 1}. `}</Text>\n <Text color={focused ? POINTER_COLOR : undefined} bold={focused}>\n {opt.label}\n </Text>\n </Box>\n {opt.description && (\n <Box marginLeft={isMulti ? 6 : 5}>\n <Text dimColor wrap=\"truncate-end\">\n {opt.description}\n </Text>\n </Box>\n )}\n </Box>\n );\n })}\n {submitRowIndex >= 0 && (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color={POINTER_COLOR} bold>\n {focusedIndex === submitRowIndex ? \"› \" : \" \"}\n </Text>\n <Text\n color={focusedIndex === submitRowIndex ? SUBMIT_COLOR : undefined}\n bold={focusedIndex === submitRowIndex}\n dimColor={focusedIndex !== submitRowIndex}\n >\n {`── Submit (${selected.size} selected)`}\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction PreviewPanel({ content }: { content: string }) {\n const lines = content ? content.split(\"\\n\") : [\"(no preview)\"];\n return (\n <Box\n borderStyle=\"round\"\n borderColor={PREVIEW_BORDER}\n flexDirection=\"column\"\n paddingX={1}\n flexGrow={1}\n >\n {lines.map((line, i) => (\n <Text key={i} wrap=\"truncate-end\" dimColor={!content}>\n {line || \" \"}\n </Text>\n ))}\n </Box>\n );\n}\n\nfunction NotesLine({\n notes,\n editing,\n draft,\n}: {\n notes: string;\n editing: boolean;\n draft: string;\n}) {\n if (editing) {\n return (\n <Box marginTop={1} flexDirection=\"row\">\n <Text color={NOTES_LABEL_COLOR} bold>\n {\"Notes: \"}\n </Text>\n <Text>{draft}</Text>\n <Text color={POINTER_COLOR}>{\"▎\"}</Text>\n <Box flexGrow={1} marginLeft={2}>\n <Text dimColor>{\"(Enter to save · Esc to discard)\"}</Text>\n </Box>\n </Box>\n );\n }\n return (\n <Box marginTop={1} flexDirection=\"row\" justifyContent=\"center\">\n <Text color={NOTES_LABEL_COLOR} bold>\n {\"Notes: \"}\n </Text>\n {notes ? (\n <Text>{notes}</Text>\n ) : (\n <Text dimColor>{\"press n to add notes\"}</Text>\n )}\n </Box>\n );\n}\n\nfunction SubmitPreview({\n questions,\n states,\n}: {\n questions: AskQuestion[];\n states: QState[];\n}) {\n return (\n <Box flexDirection=\"column\">\n <Text bold>Review</Text>\n {questions.map((q, qi) => {\n const sel = Array.from(states[qi].selected)\n .sort((a, b) => a - b)\n .map((i) => q.options[i].label);\n const notes = states[qi].notes.trim();\n return (\n <Box key={qi} flexDirection=\"column\" marginLeft={2}>\n <Box flexDirection=\"row\">\n <Text color=\"yellow\">{`${q.header}: `}</Text>\n <Text dimColor={sel.length === 0}>\n {sel.length > 0 ? sel.join(\", \") : \"(no answer)\"}\n </Text>\n </Box>\n {notes && (\n <Box marginLeft={2} flexDirection=\"row\">\n <Text color={NOTES_LABEL_COLOR}>{\"notes: \"}</Text>\n <Text dimColor>{notes}</Text>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n}\n\nfunction hintLine(hasTabs: boolean, isMulti: boolean, editingNotes: boolean): string {\n if (editingNotes) {\n return \"Enter to save · Esc to discard · backspace to delete\";\n }\n const parts: string[] = [\"Enter to select\", \"↑/↓ to navigate\", \"n to add notes\"];\n if (hasTabs) parts.push(\"Tab to switch questions\");\n if (isMulti) parts.push(\"Space to toggle\");\n parts.push(\"Esc to cancel\");\n return parts.join(\" · \");\n}\n","/**\n * Slash 命令自动补全 overlay。\n *\n * 触发条件:input.startsWith(\"/\") && !input.includes(\" \")(用户在输入命令名阶段)\n * 进入参数阶段(空格之后)→ overlay 关闭,让用户安静地输入参数\n *\n * 显示:默认色 / + name + dim description\n * focused 行整条命令名变紫色 + bold(不用 inverse 背景条)\n * 超过 maxVisible 行折叠尾部\n *\n * 渲染由 App 控制,本组件是纯展示。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { SlashCommand } from \"../slash/index.js\";\n\nexport interface SlashAutocompleteProps {\n matches: SlashCommand[];\n index: number;\n maxVisible?: number;\n}\n\nconst DEFAULT_MAX = 10;\nconst SLASH_COLOR = \"#A855F7\";\n\nexport function SlashAutocomplete({ matches, index, maxVisible = DEFAULT_MAX }: SlashAutocompleteProps) {\n if (matches.length === 0) return null;\n\n // 窗口:保证 focused 始终可见\n const start = Math.max(0, Math.min(index - Math.floor(maxVisible / 2), matches.length - maxVisible));\n const end = Math.min(matches.length, start + maxVisible);\n const visible = matches.slice(start, end);\n\n const nameWidth = Math.max(...matches.map((c) => c.name.length));\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.map((cmd, i) => {\n const realIndex = start + i;\n return (\n <Row key={cmd.name} cmd={cmd} focused={realIndex === index} nameWidth={nameWidth} />\n );\n })}\n {matches.length > visible.length && (\n <Box marginLeft={2}>\n <Text dimColor>\n ↑↓ select · Tab/Enter accept · Esc cancel ({matches.length - visible.length} more)\n </Text>\n </Box>\n )}\n {matches.length <= visible.length && (\n <Box marginLeft={2}>\n <Text dimColor>↑↓ select · Tab/Enter accept · Esc cancel</Text>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction Row({ cmd, focused, nameWidth }: { cmd: SlashCommand; focused: boolean; nameWidth: number }) {\n const padded = cmd.name.padEnd(nameWidth);\n // focused 整条命令名变紫色 + bold;非 focused 用默认色\n return (\n <Box flexDirection=\"row\">\n <Text color={focused ? SLASH_COLOR : undefined} bold={focused}>\n {\"/\"}{padded}\n </Text>\n <Text>{\" \"}</Text>\n <Text dimColor>{cmd.description}</Text>\n </Box>\n );\n}\n","/**\n * 权限模式状态栏。固定在 TUI 输入框下方。\n *\n * 设计:见文档库 permission-modes.md §四 状态栏 UI。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { MODE_LABEL, MODE_COLOR, type PermissionMode } from \"../permission/index.js\";\n\nexport function PermissionModeBar({ mode, compact }: { mode: PermissionMode; compact?: boolean }) {\n const color = MODE_COLOR[mode];\n const label = MODE_LABEL[mode];\n const isBypass = mode === \"bypassPermissions\";\n\n if (compact) {\n const short: Record<PermissionMode, string> = {\n default: \"[default]\",\n acceptEdits: \"[edits]\",\n plan: \"[plan]\",\n bypassPermissions: \"[bypass]\",\n };\n return (\n <Box flexDirection=\"row\">\n <Text color={color} bold={isBypass}>{short[mode]}</Text>\n <Text dimColor>{\" shift+tab\"}</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"row\">\n <Text color={color} bold={isBypass}>{\"▸▸ \"}{label}</Text>\n <Text dimColor>{\" (shift+tab to cycle)\"}</Text>\n </Box>\n );\n}\n","/**\n * 权限模型:三态 allow / ask / deny,叠加 4 档 PermissionMode。\n *\n * 模式匹配(pattern):\n * - \"ToolName\" 精确匹配\n * - \"Bash(<prefix>)\" 匹配 Bash 工具 + 命令前缀\n * - \"Bash(<prefix>:*)\" 通配\n *\n * PermissionMode(详见文档库 permission-modes.md):\n * - default:完全走 settings.permissions 规则\n * - acceptEdits:Edit/Write 自动 allow,其他走 default\n * - plan:只允许 read 类工具,其他全 deny\n * - bypassPermissions:除显式 deny 与 Bash 硬 deny 外全 allow\n *\n * 危险操作(rm -rf / sudo 等)由 Bash 工具内部 HARD_DENY_PATTERNS 兜底,所有模式都不可绕过。\n */\n\nimport type { Permissions } from \"../config/types.js\";\nimport type { PermissionLevel } from \"../tools/types.js\";\n\nexport type Decision = \"allow\" | \"ask\" | \"deny\";\n\n/** 用户对 PermissionPrompt 三档选择。 */\nexport type PermissionDecision = \"yes\" | \"session_allow\" | \"no\";\n\nexport type PermissionMode = \"default\" | \"acceptEdits\" | \"plan\" | \"bypassPermissions\";\n\nexport const MODE_CYCLE: readonly PermissionMode[] = [\n \"default\",\n \"acceptEdits\",\n \"plan\",\n \"bypassPermissions\",\n] as const;\n\nexport const MODE_LABEL: Record<PermissionMode, string> = {\n default: \"default permissions on\",\n acceptEdits: \"accept edits on\",\n plan: \"plan mode on\",\n bypassPermissions: \"bypass permissions on\",\n};\n\nexport const MODE_COLOR: Record<PermissionMode, string> = {\n default: \"gray\",\n acceptEdits: \"#EAB308\",\n plan: \"#06B6D4\",\n bypassPermissions: \"#EF4444\",\n};\n\nexport interface PermissionInput {\n toolName: string;\n args: unknown;\n /** Tool 的权限级别;由 Agent loop 从 ToolRegistry 注入。Plan 模式用此区分 read/write。 */\n permission?: PermissionLevel;\n}\n\nexport class PermissionGate {\n private rules: Required<Permissions>;\n private mode: PermissionMode = \"default\";\n /** Session 级 allow:用户在 PermissionPrompt 选 \"yes, for session\" 后填充。 */\n private sessionAllow = new Set<string>();\n\n constructor(rules: Permissions = {}) {\n this.rules = {\n allow: rules.allow ?? [],\n ask: rules.ask ?? [],\n deny: rules.deny ?? [],\n defaultMode: rules.defaultMode ?? \"ask\",\n };\n }\n\n setMode(mode: PermissionMode): void {\n this.mode = mode;\n }\n\n getMode(): PermissionMode {\n return this.mode;\n }\n\n cycleMode(): PermissionMode {\n const i = MODE_CYCLE.indexOf(this.mode);\n this.mode = MODE_CYCLE[(i + 1) % MODE_CYCLE.length];\n return this.mode;\n }\n\n /** 用户在 PermissionPrompt 选 \"yes, allow for session\" 时记下。 */\n allowForSession(toolName: string): void {\n this.sessionAllow.add(toolName);\n }\n\n isSessionAllowed(toolName: string): boolean {\n return this.sessionAllow.has(toolName);\n }\n\n decide(input: PermissionInput): Decision {\n // 用户显式 deny 永远生效,所有模式不可绕过\n if (this.matches(this.rules.deny, input)) return \"deny\";\n // session 级 allow 在 deny 之后、mode 分支之前生效\n if (this.sessionAllow.has(input.toolName)) return \"allow\";\n\n switch (this.mode) {\n case \"bypassPermissions\":\n return \"allow\";\n\n case \"plan\":\n // 只允许只读工具;写/执行/网络类直接 deny\n return input.permission === \"read\" ? \"allow\" : \"deny\";\n\n case \"acceptEdits\":\n if (input.toolName === \"Edit\" || input.toolName === \"Write\") return \"allow\";\n return this.defaultDecide(input);\n\n case \"default\":\n default:\n return this.defaultDecide(input);\n }\n }\n\n private defaultDecide(input: PermissionInput): Decision {\n if (this.matches(this.rules.allow, input)) return \"allow\";\n if (this.matches(this.rules.ask, input)) return \"ask\";\n switch (this.rules.defaultMode) {\n case \"strict\":\n return \"ask\";\n case \"relaxed\":\n return \"allow\";\n case \"ask\":\n default:\n return \"ask\";\n }\n }\n\n private matches(patterns: string[], input: PermissionInput): boolean {\n for (const pattern of patterns) {\n if (this.matchOne(pattern, input)) return true;\n }\n return false;\n }\n\n private matchOne(pattern: string, input: PermissionInput): boolean {\n // \"ToolName\" 精确匹配\n if (!pattern.includes(\"(\")) {\n return pattern === input.toolName;\n }\n // \"Bash(<prefix>:*)\" 形式\n const m = pattern.match(/^([A-Za-z_][A-Za-z0-9_]*)\\(([^)]*)\\)$/);\n if (!m) return false;\n const [, toolName, sub] = m;\n if (toolName !== input.toolName) return false;\n if (input.toolName === \"Bash\" && typeof input.args === \"object\" && input.args !== null) {\n const cmd = (input.args as { command?: string }).command ?? \"\";\n if (sub.endsWith(\":*\")) {\n const prefix = sub.slice(0, -2);\n return cmd.startsWith(prefix);\n }\n return cmd === sub || cmd.startsWith(sub + \" \");\n }\n return false;\n }\n}\n","/**\n * 输入框下方的状态尾栏(对齐 Claude Code 风格)。\n *\n * 信息(从左到右):\n * @<sid8> 当前 session 短 id(首 8 字符;resume 后亦同)\n * <model> 当前模型 id\n * ctx: ████░ NN% 上下文窗口填充率(基于最近一轮 input tokens / maxContextWindow)\n * <in>/<max> 绝对值,便于核对\n * ↑<in> ↓<out> 本会话累计 token(自 app 启动后;/resume 不回灌)\n *\n * 配色(对齐 Claude Code 的 footer):\n * session id → cyan bold (如 Claude Code 的 \"Sync code...\" 标题色)\n * model → magenta (如 Claude Code 的 \"Opus 4.7 (1M context)\" 粉品红)\n * \"ctx:\" → 默认白 (label 不 dim,醒目)\n * 填充进度条 → 主题色:<70% green / 70–89% yellow / ≥90% red(\"快爆\"警告)\n * 百分比 / in/max → dim gray (次要信息)\n * \"│\" → dim gray (分隔符弱化)\n * ↑ 累计 in → green\n * ↓ 累计 out → blueBright\n *\n * 宽度策略:\n * termWidth >= 100 完整版(含累计 token)\n * 60 ≤ width < 100 精简版(去掉 ↑↓ 累计、去掉 in/max)\n * width < 60 极简版(只剩 sid · model · 进度条 NN%)\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nconst BAR_TOTAL_WIDE = 10;\nconst BAR_TOTAL_COMPACT = 6;\n\nexport interface FooterStatusProps {\n /** 当前 session id(取首 8 字符显示)。 */\n sessionId: string;\n /** 当前模型 id(如 \"deepseek-chat\")。 */\n model: string;\n /** 模型上下文窗口大小;0/未知时隐藏 ctx 字段。 */\n contextWindow: number;\n /** 最近一轮 input tokens;约等于本轮 prompt 实际占用的上下文。 */\n lastInputTokens: number;\n /** 本会话累计 input tokens。 */\n sessionInputTokens: number;\n /** 本会话累计 output tokens。 */\n sessionOutputTokens: number;\n /** 终端宽度,用于布局降级。 */\n termWidth: number;\n}\n\nexport function FooterStatus({\n sessionId,\n model,\n contextWindow,\n lastInputTokens,\n sessionInputTokens,\n sessionOutputTokens,\n termWidth,\n}: FooterStatusProps) {\n const sid = sessionId.slice(0, 8);\n const hasCtx = contextWindow > 0;\n const pct = hasCtx ? Math.min(100, Math.round((lastInputTokens / contextWindow) * 100)) : 0;\n const ctxColor: \"green\" | \"yellow\" | \"red\" = pct >= 90 ? \"red\" : pct >= 70 ? \"yellow\" : \"green\";\n\n const SEP = <Text dimColor>{\" │ \"}</Text>;\n const SEP_DOT = <Text dimColor>{\" · \"}</Text>;\n\n // 已填部分按阈值上色,未填部分恒 dim gray;0% 时整条灰\n const renderBar = (barW: number): React.ReactNode => {\n const filled = Math.round((pct / 100) * barW);\n const empty = barW - filled;\n return (\n <>\n {filled > 0 && <Text color={ctxColor}>{\"█\".repeat(filled)}</Text>}\n {empty > 0 && <Text dimColor>{\"░\".repeat(empty)}</Text>}\n </>\n );\n };\n\n // <60: 极简\n if (termWidth < 60) {\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\" bold>{sid}</Text>\n {SEP_DOT}\n <Text color=\"magenta\">{model}</Text>\n {hasCtx && (\n <>\n {SEP_DOT}\n {renderBar(BAR_TOTAL_COMPACT)}\n <Text dimColor>{` ${pct}%`}</Text>\n </>\n )}\n </Box>\n );\n }\n\n // 60–100: 精简(无累计 token、无 in/max 绝对值)\n if (termWidth < 100) {\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\" bold>{`@${sid}`}</Text>\n {SEP}\n <Text color=\"magenta\">{model}</Text>\n {hasCtx && (\n <>\n {SEP}\n <Text>{\"ctx: \"}</Text>\n {renderBar(BAR_TOTAL_COMPACT)}\n <Text dimColor>{` ${pct}%`}</Text>\n </>\n )}\n </Box>\n );\n }\n\n // ≥100: 完整\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\" bold>{`@${sid}`}</Text>\n {SEP}\n <Text color=\"magenta\">{model}</Text>\n {hasCtx && (\n <>\n {SEP}\n <Text>{\"ctx: \"}</Text>\n {renderBar(BAR_TOTAL_WIDE)}\n <Text dimColor>{` ${pct}%`}</Text>\n <Text dimColor>{` ${formatTokens(lastInputTokens)}/${formatTokens(contextWindow)}`}</Text>\n </>\n )}\n {SEP}\n <Text>{\"tok: \"}</Text>\n <Text color=\"green\">{`↑${formatTokens(sessionInputTokens)}`}</Text>\n <Text> </Text>\n <Text color=\"blueBright\">{`↓${formatTokens(sessionOutputTokens)}`}</Text>\n </Box>\n );\n}\n\nfunction formatTokens(n: number): string {\n if (n < 1000) return String(n);\n if (n < 10000) return (n / 1000).toFixed(1).replace(/\\.0$/, \"\") + \"k\";\n if (n < 1000000) return Math.round(n / 1000) + \"k\";\n return (n / 1000000).toFixed(1).replace(/\\.0$/, \"\") + \"M\";\n}\n","/**\n * 通用进度横幅:cyan 标签 + 经过秒数 + 进度条 + 旋转 tip。\n *\n * 由 SlashActions.showProgress/hideProgress 控制;目前 /compact 是首个使用者。\n *\n * 视觉对齐 Claude Code 的 /compact 体验:\n * ✦ <Title>... (Ns)\n * ▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱ 24%\n * └ Tip: <rotating>\n */\n\nimport React, { useEffect, useState } from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface ProgressState {\n title: string;\n tips: string[];\n /** 0-100;ProgressBanner 自行 clamp 与 floor。 */\n getPercent: () => number;\n startTime: number;\n}\n\nconst BAR_WIDTH = 42;\nconst TICK_MS = 400;\nconst TIP_ROTATE_SEC = 5;\n\nexport function ProgressBanner({ state }: { state: ProgressState }) {\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n const t = setInterval(() => setNow(Date.now()), TICK_MS);\n return () => clearInterval(t);\n }, []);\n\n const elapsedSec = Math.max(0, Math.floor((now - state.startTime) / 1000));\n const percent = Math.max(0, Math.min(99, Math.floor(state.getPercent())));\n const filled = Math.floor((percent / 100) * BAR_WIDTH);\n const empty = BAR_WIDTH - filled;\n const bar = \"▰\".repeat(filled) + \"▱\".repeat(empty);\n const tip = state.tips.length\n ? state.tips[Math.floor(elapsedSec / TIP_ROTATE_SEC) % state.tips.length]\n : \"\";\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box>\n <Text color=\"cyan\" bold>✦ </Text>\n <Text color=\"cyan\">{state.title}...</Text>\n <Text dimColor>{` (${elapsedSec}s)`}</Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"cyan\">{bar}</Text>\n <Text dimColor>{` ${percent}%`}</Text>\n </Box>\n {tip && (\n <Box marginLeft={2}>\n <Text dimColor>{`└ Tip: ${tip}`}</Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * 处理中的状态行(流式 / 工具执行期间常驻底部)。\n *\n * 两行设计:\n * ● Working… ✨闪烁 (12s · ↑ 1.2k tokens · thought for 4s)\n * ↳ Read(src/foo.ts) ← 仅 runningTool != null 时出现\n *\n * 主线(Working)始终在跑,扫光动画提示 \"活着\"。工具行作为子线路按需呈现。\n * 不接收 status 字段——调用方根据 status !== \"idle\" 决定是否挂载本组件。\n */\n\nimport React, { useEffect, useState } from \"react\";\nimport { Box, Text } from \"ink\";\nimport { Shimmer } from \"./Shimmer.js\";\n\nconst TICK_MS = 400;\n\nexport interface StatusLineProps {\n /** 本轮开始时间(user_submit 触发时 Date.now())。 */\n startTime: number;\n /** 首次 text-delta 时间(\"thought for\" 用);null 表示尚未流出任何 text。 */\n firstTextTime: number | null;\n /** 本轮已累计的 input tokens(usage 事件累加,>0 才显示)。 */\n inputTokens: number;\n /** 工具运行中时的工具名,null 表示不在跑工具。 */\n runningTool: string | null;\n /** UI 语言:影响标签文案。 */\n lang: \"en\" | \"zh-CN\";\n}\n\nexport function StatusLine({ startTime, firstTextTime, inputTokens, runningTool, lang }: StatusLineProps) {\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n const t = setInterval(() => setNow(Date.now()), TICK_MS);\n return () => clearInterval(t);\n }, []);\n\n const elapsedSec = Math.max(0, Math.floor((now - startTime) / 1000));\n const mainLabel = lang === \"zh-CN\" ? \"工作中\" : \"Working\";\n\n const parts: string[] = [formatDuration(elapsedSec)];\n if (inputTokens > 0) {\n parts.push(`↑ ${formatTokens(inputTokens)} tokens`);\n }\n if (firstTextTime !== null) {\n const thinkSec = Math.max(0, Math.floor((firstTextTime - startTime) / 1000));\n parts.push(\n lang === \"zh-CN\" ? `思考 ${formatDuration(thinkSec)}` : `thought for ${formatDuration(thinkSec)}`,\n );\n }\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box flexDirection=\"row\">\n <Text color=\"gray\">● </Text>\n <Shimmer text={mainLabel} />\n <Text dimColor>{` (${parts.join(\" · \")})`}</Text>\n </Box>\n {runningTool && (\n <Box flexDirection=\"row\" marginLeft={2} marginTop={0}>\n <Text dimColor>{\"↳ \"}</Text>\n <Text color=\"cyan\">{runningTool}</Text>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction formatTokens(n: number): string {\n if (n < 1000) return String(n);\n if (n < 10000) return (n / 1000).toFixed(1).replace(/\\.0$/, \"\") + \"k\";\n if (n < 1000000) return Math.round(n / 1000) + \"k\";\n return (n / 1000000).toFixed(1).replace(/\\.0$/, \"\") + \"M\";\n}\n\nfunction formatDuration(sec: number): string {\n if (sec < 60) return `${sec}s`;\n const m = Math.floor(sec / 60);\n const s = sec % 60;\n return s === 0 ? `${m}m` : `${m}m${s}s`;\n}\n","/**\n * 字面闪烁动画:一个明亮窗口从左往右扫过文字,到尾巴后有短暂间隔再从头来。\n *\n * 渲染方式:把 text 拆成单字符 <Text>,按到当前 phase 的距离上色——\n * distance 0 → bright white + bold\n * distance 1 → white\n * 其他 → dim gray\n * 一个 setInterval 推进 phase。\n *\n * 视觉效果:像扫光带掠过 \"Working\" 字样,无 spinner 字符。\n */\n\nimport React, { useEffect, useState } from \"react\";\nimport { Text } from \"ink\";\n\nconst FRAME_MS = 100;\nconst TRAIL = 4; // 扫完最后一个字符后再走几帧再绕回起点,给眼睛留间隔\n\nexport interface ShimmerProps {\n text: string;\n bold?: boolean;\n}\n\nexport function Shimmer({ text, bold = true }: ShimmerProps) {\n const chars = Array.from(text);\n const cycle = chars.length + TRAIL;\n\n const [phase, setPhase] = useState(0);\n useEffect(() => {\n const id = setInterval(() => {\n setPhase((p) => (p + 1) % cycle);\n }, FRAME_MS);\n return () => clearInterval(id);\n }, [cycle]);\n\n return (\n <Text>\n {chars.map((ch, i) => {\n const d = Math.abs(i - phase);\n if (d === 0) {\n return (\n <Text key={i} color=\"white\" bold={bold}>\n {ch}\n </Text>\n );\n }\n if (d === 1) {\n return (\n <Text key={i} color=\"white\">\n {ch}\n </Text>\n );\n }\n return (\n <Text key={i} color=\"gray\" dimColor>\n {ch}\n </Text>\n );\n })}\n </Text>\n );\n}\n","/**\n * 终端标题栏控制(OSC 0/1/2 转义序列)。\n *\n * 用途:在 OS-level tab/window 标题里放一个旋转动画 + 当前状态,\n * 让用户切到别的窗口也能从 dock / taskbar 看出 muse 还在跑(vs 卡死 / 已完成)。\n *\n * 协议:`ESC ] 0 ; <text> BEL` 同时设置 icon name 和 window title——所有主流\n * 终端都认(Terminal.app / iTerm2 / Alacritty / kitty / WezTerm / Windows Terminal)。\n *\n * 安全:非 TTY(管道、CI)和 MUSE_NO_TITLE=1 时静默;title 文本 strip 控制字符\n * 防止注入。\n */\n\nconst ENABLED = (() => {\n if (!process.stdout.isTTY) return false;\n if (process.env.MUSE_NO_TITLE === \"1\") return false;\n return true;\n})();\n\nlet lastTitle = \"\";\n\nfunction sanitize(s: string): string {\n // 删 NUL / BEL / ESC / 其它 C0 控制符——防止用户 cwd 包含恶意字节注入 title\n return s.replace(/[\\x00-\\x1f\\x7f]/g, \"\");\n}\n\n/** 设标题;与上次完全相同时跳过(减少 stdout 写流量)。 */\nexport function setTerminalTitle(title: string): void {\n if (!ENABLED) return;\n const clean = sanitize(title);\n if (clean === lastTitle) return;\n lastTitle = clean;\n process.stdout.write(`\\x1b]0;${clean}\\x07`);\n}\n\n/** 清空标题(让终端用默认值)。在进程退出前调一次。 */\nexport function resetTerminalTitle(): void {\n if (!ENABLED) return;\n lastTitle = \"\";\n process.stdout.write(`\\x1b]0;\\x07`);\n}\n","/**\n * OpenAI 兼容协议 provider。\n * 覆盖:OpenAI 官方、DeepSeek、Qwen、Moonshot (Kimi)、智谱、OpenRouter、Ollama (其 /v1 endpoint)、自建 vLLM/LocalAI 等。\n *\n * Why 自己包一层而不是直接用 @ai-sdk/openai-compatible:\n * - 抹平 stream 事件差异,统一为本仓库的 LLMEvent 类型\n * - 在 stream 中拼装 tool_call.arguments(OpenAI 流式 tool_call 是分片增量的 JSON 字符串)\n * - 留口子未来插入降级、重试、token 计数估算\n */\n\nimport { createOpenAICompatible } from \"@ai-sdk/openai-compatible\";\nimport { streamText, jsonSchema, tool, type CoreMessage, type ToolSet } from \"ai\";\nimport type {\n LLMClient,\n LLMEvent,\n ModelCapabilities,\n ProviderConfig,\n StreamOptions,\n} from \"../types.js\";\nimport type { Message, AssistantMessage, ToolDefinition } from \"../../types/index.js\";\nimport { log, redactApiKey } from \"../../log/index.js\";\n\ninterface OpenAICompatibleProviderOpts {\n providerName: string;\n baseUrl: string;\n apiKey: string;\n model: string;\n capabilities?: Partial<ModelCapabilities>;\n}\n\nconst DEFAULT_CAPABILITIES: ModelCapabilities = {\n toolCalling: true,\n parallelToolCalls: true,\n vision: false,\n jsonMode: true,\n maxContextWindow: 32_000,\n};\n\nexport class OpenAICompatibleClient implements LLMClient {\n readonly providerName: string;\n readonly model: string;\n readonly capabilities: ModelCapabilities;\n private modelProvider: ReturnType<ReturnType<typeof createOpenAICompatible>>;\n\n constructor(opts: OpenAICompatibleProviderOpts) {\n this.providerName = opts.providerName;\n this.model = opts.model;\n this.capabilities = { ...DEFAULT_CAPABILITIES, ...opts.capabilities };\n\n const provider = createOpenAICompatible({\n name: opts.providerName,\n baseURL: opts.baseUrl,\n apiKey: opts.apiKey,\n });\n this.modelProvider = provider(opts.model);\n\n log.debug(\"LLM provider initialized\", {\n provider: opts.providerName,\n model: opts.model,\n baseUrl: opts.baseUrl,\n apiKey: redactApiKey(opts.apiKey),\n });\n }\n\n async *stream(opts: StreamOptions): AsyncIterable<LLMEvent> {\n const { messages, tools, systemPrompt, temperature, maxTokens, abortSignal } = opts;\n\n const aiMessages = convertMessages(messages, systemPrompt);\n const aiTools = tools ? convertTools(tools) : undefined;\n\n // 重试:仅在还没收到任何 chunk 时(连接级错误)退避重试,最多 3 次\n let attempt = 0;\n const maxAttempts = 3;\n let result: ReturnType<typeof streamText> | undefined;\n while (true) {\n try {\n result = streamText({\n model: this.modelProvider,\n messages: aiMessages,\n tools: aiTools,\n temperature,\n maxTokens,\n abortSignal,\n });\n break;\n } catch (err) {\n if (abortSignal?.aborted) {\n yield { type: \"error\", error: err instanceof Error ? err : new Error(String(err)) };\n return;\n }\n if (!isRetryable(err) || attempt >= maxAttempts - 1) {\n yield { type: \"error\", error: err instanceof Error ? err : new Error(String(err)) };\n return;\n }\n const delay = 1000 * Math.pow(2, attempt);\n log.warn(`LLM connect failed (attempt ${attempt + 1}/${maxAttempts}); retrying in ${delay}ms`, {\n msg: err instanceof Error ? err.message : String(err),\n });\n await sleep(delay, abortSignal);\n attempt += 1;\n }\n }\n\n if (!result) {\n yield { type: \"error\", error: new Error(\"Internal: stream result is undefined after retry loop.\") };\n return;\n }\n const stream = result.fullStream;\n\n try {\n const seenToolCalls = new Set<string>();\n\n for await (const part of stream) {\n switch (part.type) {\n case \"text-delta\":\n yield { type: \"text\", delta: part.textDelta };\n break;\n\n case \"tool-call\":\n if (!seenToolCalls.has(part.toolCallId)) {\n seenToolCalls.add(part.toolCallId);\n yield { type: \"tool_call_start\", id: part.toolCallId, name: part.toolName };\n }\n yield {\n type: \"tool_call_complete\",\n id: part.toolCallId,\n name: part.toolName,\n args: part.args,\n };\n break;\n\n case \"finish\":\n yield {\n type: \"finish\",\n reason: mapFinishReason(part.finishReason),\n usage: part.usage\n ? {\n inputTokens: part.usage.promptTokens ?? 0,\n outputTokens: part.usage.completionTokens ?? 0,\n totalTokens: part.usage.totalTokens ?? 0,\n }\n : undefined,\n };\n break;\n\n case \"error\":\n yield { type: \"error\", error: part.error instanceof Error ? part.error : new Error(String(part.error)) };\n break;\n\n default:\n // 忽略其它(如 step-start / step-finish / tool-call-streaming-start 等)\n break;\n }\n }\n } catch (err) {\n yield { type: \"error\", error: err instanceof Error ? err : new Error(String(err)) };\n }\n }\n}\n\n// ---------- helpers ----------\n\nfunction convertMessages(messages: Message[], systemPrompt?: string): CoreMessage[] {\n const result: CoreMessage[] = [];\n if (systemPrompt) {\n result.push({ role: \"system\", content: systemPrompt });\n }\n for (const msg of messages) {\n switch (msg.role) {\n case \"system\":\n result.push({ role: \"system\", content: msg.content });\n break;\n case \"user\":\n if (typeof msg.content === \"string\") {\n result.push({ role: \"user\", content: msg.content });\n } else {\n const text = msg.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n result.push({ role: \"user\", content: text });\n }\n break;\n case \"assistant\":\n result.push({ role: \"assistant\", content: convertAssistantContent(msg) });\n break;\n case \"tool\":\n result.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: msg.toolUseId,\n toolName: \"_tool\",\n result: msg.content,\n isError: msg.isError ?? false,\n },\n ],\n });\n break;\n }\n }\n return result;\n}\n\ntype AssistantContent = Extract<CoreMessage, { role: \"assistant\" }>[\"content\"];\n\nfunction convertAssistantContent(msg: AssistantMessage): AssistantContent {\n const parts: Array<\n { type: \"text\"; text: string } | { type: \"tool-call\"; toolCallId: string; toolName: string; args: unknown }\n > = [];\n for (const part of msg.content) {\n if (part.type === \"text\") {\n parts.push({ type: \"text\", text: part.text });\n } else if (part.type === \"tool_use\") {\n parts.push({\n type: \"tool-call\",\n toolCallId: part.id,\n toolName: part.name,\n args: part.args,\n });\n }\n }\n // 至少要有一个内容;空数组 SDK 会报错\n if (parts.length === 0) return \"\";\n return parts as AssistantContent;\n}\n\nfunction convertTools(tools: ToolDefinition[]): ToolSet {\n const result: ToolSet = {};\n for (const t of tools) {\n result[t.name] = tool({\n description: t.description,\n parameters: jsonSchema(t.parameters as Parameters<typeof jsonSchema>[0]),\n });\n }\n return result;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const msg = err.message.toLowerCase();\n const code = (err as Error & { code?: string }).code ?? \"\";\n if (\n code === \"ECONNRESET\" ||\n code === \"ETIMEDOUT\" ||\n code === \"ENOTFOUND\" ||\n code === \"ECONNREFUSED\" ||\n code === \"EAI_AGAIN\"\n ) {\n return true;\n }\n if (\n msg.includes(\"fetch failed\") ||\n msg.includes(\"network\") ||\n msg.includes(\"socket hang up\") ||\n msg.includes(\"under maintenance\") ||\n msg.includes(\"rate limit\") ||\n msg.includes(\"429\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\")\n ) {\n return true;\n }\n return false;\n}\n\nasync function sleep(ms: number, abortSignal?: AbortSignal): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n if (abortSignal?.aborted) return reject(new Error(\"aborted\"));\n const t = setTimeout(() => {\n abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(t);\n abortSignal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"aborted\"));\n };\n abortSignal?.addEventListener(\"abort\", onAbort);\n });\n}\n\nfunction mapFinishReason(reason: string | undefined): \"stop\" | \"tool_calls\" | \"length\" | \"content_filter\" | \"error\" | \"unknown\" {\n switch (reason) {\n case \"stop\":\n case \"stop-sequence\":\n return \"stop\";\n case \"tool-calls\":\n case \"tool_calls\":\n return \"tool_calls\";\n case \"length\":\n return \"length\";\n case \"content-filter\":\n case \"content_filter\":\n return \"content_filter\";\n case \"error\":\n return \"error\";\n default:\n return \"unknown\";\n }\n}\n\n// ---------- 预设 provider 工厂 ----------\n\nexport interface PresetConfig {\n baseUrl: string;\n defaultModel: string;\n capabilities?: Partial<ModelCapabilities>;\n}\n\nexport const PRESETS: Record<string, PresetConfig> = {\n openai: {\n baseUrl: \"https://api.openai.com/v1\",\n defaultModel: \"gpt-4o-mini\",\n },\n deepseek: {\n baseUrl: \"https://api.deepseek.com/v1\",\n defaultModel: \"deepseek-chat\",\n capabilities: { maxContextWindow: 128_000 },\n },\n qwen: {\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n defaultModel: \"qwen-plus\",\n capabilities: { maxContextWindow: 128_000 },\n },\n moonshot: {\n baseUrl: \"https://api.moonshot.cn/v1\",\n defaultModel: \"moonshot-v1-32k\",\n capabilities: { maxContextWindow: 32_000 },\n },\n zhipu: {\n baseUrl: \"https://open.bigmodel.cn/api/paas/v4\",\n defaultModel: \"glm-4-flash\",\n capabilities: { maxContextWindow: 128_000 },\n },\n ollama: {\n baseUrl: \"http://localhost:11434/v1\",\n defaultModel: \"llama3.1\",\n capabilities: { maxContextWindow: 8_000 },\n },\n openrouter: {\n baseUrl: \"https://openrouter.ai/api/v1\",\n defaultModel: \"openai/gpt-4o-mini\",\n },\n};\n\nexport function createPresetClient(\n providerName: string,\n config: ProviderConfig,\n model?: string,\n): OpenAICompatibleClient {\n const preset = PRESETS[providerName];\n if (!preset) {\n throw new Error(`Unknown provider preset: ${providerName}. Available: ${Object.keys(PRESETS).join(\", \")}`);\n }\n return new OpenAICompatibleClient({\n providerName,\n baseUrl: (config.baseUrl as string | undefined) ?? preset.baseUrl,\n apiKey: (config.apiKey as string | undefined) ?? \"\",\n model: model ?? preset.defaultModel,\n capabilities: preset.capabilities,\n });\n}\n","/**\n * Logger 包装。第一版用最朴素的 console + 文件追加;后期可替换 pino。\n * Why 不直接用 pino: 简化首版依赖图,等可观测性章节再上 pino。\n */\n\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVELS: Record<LogLevel, number> = {\n trace: 10,\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\ninterface LogEntry {\n time: string;\n level: LogLevel;\n msg: string;\n [key: string]: unknown;\n}\n\nclass Logger {\n private level: LogLevel = \"info\";\n private logPath: string;\n private fileEnabled = true;\n\n constructor() {\n const date = new Date().toISOString().slice(0, 10);\n this.logPath = join(homedir(), \".muse\", \"logs\", `${date}.jsonl`);\n try {\n mkdirSync(dirname(this.logPath), { recursive: true });\n } catch {\n this.fileEnabled = false;\n }\n }\n\n setLevel(level: LogLevel) {\n this.level = level;\n }\n\n private write(level: LogLevel, msg: string, extra?: Record<string, unknown>) {\n if (LEVELS[level] < LEVELS[this.level]) return;\n const entry: LogEntry = {\n time: new Date().toISOString(),\n level,\n msg,\n ...extra,\n };\n if (this.fileEnabled) {\n try {\n appendFileSync(this.logPath, JSON.stringify(entry) + \"\\n\");\n } catch {\n // 落盘失败不阻断主流程\n }\n }\n // 仅 warn/error 默认输出到 stderr,避免污染 stdout\n if (level === \"warn\" || level === \"error\") {\n const prefix = level === \"error\" ? \"[error]\" : \"[warn]\";\n process.stderr.write(`${prefix} ${msg}\\n`);\n }\n }\n\n trace(msg: string, extra?: Record<string, unknown>) { this.write(\"trace\", msg, extra); }\n debug(msg: string, extra?: Record<string, unknown>) { this.write(\"debug\", msg, extra); }\n info(msg: string, extra?: Record<string, unknown>) { this.write(\"info\", msg, extra); }\n warn(msg: string, extra?: Record<string, unknown>) { this.write(\"warn\", msg, extra); }\n error(msg: string, extra?: Record<string, unknown>) { this.write(\"error\", msg, extra); }\n}\n\nexport const log = new Logger();\n\n/** API key 脱敏:前 4 后 4,中间打码。 */\nexport function redactApiKey(key: string | undefined): string {\n if (!key) return \"<unset>\";\n if (key.length <= 12) return \"***\";\n return `${key.slice(0, 4)}...${key.slice(-4)}`;\n}\n","/**\n * 全局共享类型。其它模块按需 re-export 子集。\n * Why 集中:避免类型循环依赖。\n */\n\n// ---------- 消息(与 LLM 交互的最小单元)----------\n\nexport type MessageRole = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\nexport interface TextPart {\n type: \"text\";\n text: string;\n}\n\nexport interface ToolUsePart {\n type: \"tool_use\";\n id: string;\n name: string;\n args: unknown;\n}\n\nexport interface ToolResultPart {\n type: \"tool_result\";\n toolUseId: string;\n content: string;\n isError?: boolean;\n}\n\nexport type ContentPart = TextPart | ToolUsePart | ToolResultPart;\n\nexport interface SystemMessage {\n role: \"system\";\n content: string;\n}\n\nexport interface UserMessage {\n role: \"user\";\n content: string | ContentPart[];\n}\n\nexport interface AssistantMessage {\n role: \"assistant\";\n content: ContentPart[];\n}\n\nexport interface ToolMessage {\n role: \"tool\";\n toolUseId: string;\n content: string;\n isError?: boolean;\n /** Unified diff for UI display only (Write/Edit). Not sent to LLM. */\n diff?: string;\n /** UI-only one-line summary; if absent, UI falls back to content first line. */\n summary?: string;\n /** UI-only status dot color: success(green) / error(red) / warn(yellow). Default derived from isError. */\n kind?: \"success\" | \"error\" | \"warn\";\n /** 产生该结果的工具名;UI 据此做工具专属渲染(如 TodoWrite 隐藏结果行)。 */\n toolName?: string;\n}\n\nexport type Message = SystemMessage | UserMessage | AssistantMessage | ToolMessage;\n\n// ---------- LLM 工具定义(暴露给模型)----------\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: Record<string, unknown>; // JSON Schema\n}\n\n// ---------- Token 用量 ----------\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n}\n\nexport type FinishReason = \"stop\" | \"tool_calls\" | \"length\" | \"content_filter\" | \"error\" | \"unknown\";\n\n// ---------- 错误 ----------\n\nexport class MuseError extends Error {\n constructor(message: string, public readonly code?: string, public readonly cause?: unknown) {\n super(message);\n this.name = \"MuseError\";\n }\n}\n\nexport class ToolError extends MuseError {\n constructor(message: string, public readonly toolName: string, cause?: unknown) {\n super(message, \"TOOL_ERROR\", cause);\n this.name = \"ToolError\";\n }\n}\n\nexport class PermissionDeniedError extends MuseError {\n constructor(public readonly toolName: string, public readonly reason: string) {\n super(`Permission denied for ${toolName}: ${reason}`, \"PERMISSION_DENIED\");\n this.name = \"PermissionDeniedError\";\n }\n}\n","/**\n * LLMClient 工厂:根据配置创建对应 provider 的客户端。\n *\n * 当前只实现 openai-compatible 协议族(覆盖 95% 国产模型 + OpenAI 本身)。\n * Anthropic 走自己的协议,留待 v0.3 加。\n */\n\nimport { createPresetClient, PRESETS, OpenAICompatibleClient } from \"./providers/index.js\";\nimport type { LLMClient, ModelCapabilities, ProviderConfig } from \"./types.js\";\nimport { MuseError } from \"../types/index.js\";\nimport type { ModelEntry } from \"../config/models.js\";\n\nexport interface CreateClientOpts {\n provider: string;\n model: string;\n providers: Record<string, ProviderConfig>;\n}\n\n/**\n * 当前 active model 的 apiKey 注入到此进程 env 字段下。\n *\n * 业务代码(LLM client)只看到 env name,不直接持有 key 副本。\n * /models 切换或启动加载时由 setActiveModelEnv() 写入;从这里读出来给 client。\n */\nexport const ACTIVE_API_KEY_ENV = \"MUSE_ACTIVE_API_KEY\";\n\n/** 把 entry 的 apiKey 注入 process.env,供 createLLMClientFromModelEntry 读取。 */\nexport function setActiveModelEnv(entry: ModelEntry): void {\n if (entry.apiKey) {\n process.env[ACTIVE_API_KEY_ENV] = entry.apiKey;\n } else {\n delete process.env[ACTIVE_API_KEY_ENV];\n }\n}\n\n/**\n * 从用户在 models.local.json 里定义的 ModelEntry 构造 LLMClient。\n *\n * apiKey 不直接传值——而是从 process.env[ACTIVE_API_KEY_ENV] 读,调用前必须先\n * setActiveModelEnv(entry) 写入。这样业务代码只看到 env name,不直接持有 key。\n *\n * vendor 字段仅用于显示(providerName 显示在 banner / /status)。\n * 当前所有 entry 走 openai-compatible 协议;未来引入其他协议时按 entry.protocol 分流。\n */\nexport function createLLMClientFromModelEntry(entry: ModelEntry): LLMClient {\n const apiKey = process.env[ACTIVE_API_KEY_ENV] ?? \"\";\n if (!apiKey && !entry.baseUrl.includes(\"localhost\")) {\n throw new MuseError(buildMissingKeyMessage(entry), \"MISSING_API_KEY\");\n }\n const capabilities: Partial<ModelCapabilities> = {};\n if (entry.supportsToolCall !== undefined) capabilities.toolCalling = entry.supportsToolCall;\n if (entry.supportsImages !== undefined) capabilities.vision = entry.supportsImages;\n if (entry.contextWindow !== undefined) capabilities.maxContextWindow = entry.contextWindow;\n\n return new OpenAICompatibleClient({\n providerName: entry.vendor ?? \"custom\",\n baseUrl: entry.baseUrl,\n apiKey,\n model: entry.id,\n capabilities,\n });\n}\n\n/**\n * 用户向报错:当 apiKey 是 ${VAR} 占位符但 VAR 没设时,告诉用户具体缺哪个 env var\n * 和三种修复方式;不是占位符 / 直接缺字段时退化为通用提示。\n */\nfunction buildMissingKeyMessage(entry: ModelEntry): string {\n const envVars = ((entry as { _apiKeyEnvVars?: string[] })._apiKeyEnvVars ?? []).filter(\n (v) => !process.env[v],\n );\n const head = `Model \"${entry.id}\" needs an API key but none was found.`;\n\n if (envVars.length > 0) {\n const list = envVars.map((v) => `$${v}`).join(\", \");\n const fixVar = envVars[0];\n return [\n head,\n ``,\n `Cause: ~/.muse/models.local.json sets apiKey to a placeholder referencing ${list},`,\n ` but the shell environment does not have ${envVars.length > 1 ? \"those variables\" : \"that variable\"} set.`,\n ``,\n `Fix (pick one):`,\n ` 1. Replace the \\${${fixVar}} placeholder in ~/.muse/models.local.json with the literal key`,\n ` (recommended — the file is local-only and never enters git).`,\n ` 2. Export the variable in your shell:`,\n ` export ${fixVar}=<your-key>`,\n ].join(\"\\n\");\n }\n\n return [\n head,\n ``,\n `Edit ~/.muse/models.local.json and set \"apiKey\" on the \"${entry.id}\" entry`,\n `(plain text is fine — the file stays local-only).`,\n ].join(\"\\n\");\n}\n\nexport function createLLMClient(opts: CreateClientOpts): LLMClient {\n const { provider, model, providers } = opts;\n const config = providers[provider];\n\n if (!config) {\n throw new MuseError(\n `Provider \"${provider}\" is not configured. Add a \"providers.${provider}\" entry to your settings.json.`,\n \"PROVIDER_NOT_CONFIGURED\",\n );\n }\n\n // 预设 provider(含国产模型)\n if (PRESETS[provider]) {\n if (!config.apiKey && provider !== \"ollama\") {\n throw new MuseError(\n `Provider \"${provider}\" requires apiKey. Set it in settings.json or via the corresponding env var.`,\n \"MISSING_API_KEY\",\n );\n }\n return createPresetClient(provider, config, model);\n }\n\n // 自定义 openai-compatible 端点\n if (config.baseUrl) {\n return new OpenAICompatibleClient({\n providerName: provider,\n baseUrl: config.baseUrl as string,\n apiKey: (config.apiKey as string | undefined) ?? \"\",\n model,\n });\n }\n\n throw new MuseError(\n `Unknown provider \"${provider}\". Either use a preset (${Object.keys(PRESETS).join(\", \")}) or set \"baseUrl\" in providers.${provider}.`,\n \"UNKNOWN_PROVIDER\",\n );\n}\n","/**\n * Session 内 Todo 清单。\n *\n * 仅存活于单次 muse 进程内,不入 JSONL 持久化(任务清单是 ephemeral 调度状态,\n * 不是对话内容;下次进程恢复 session 时 LLM 应基于历史重建清单)。\n *\n * 工具 TodoWrite 通过 ToolContext.todos 写入;buildSystemPrompt 读出注入下一轮 LLM 的视野。\n */\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\";\n\nexport interface Todo {\n content: string;\n status: TodoStatus;\n /** 进行中状态的现在分词式描述,UI 可用作 spinner 文案。 */\n activeForm?: string;\n}\n\nexport class TodoStore {\n private items: Todo[] = [];\n\n list(): Todo[] {\n return this.items.slice();\n }\n\n set(items: Todo[]): void {\n this.items = items.slice();\n }\n\n clear(): void {\n this.items = [];\n }\n\n /** 把当前清单格式化为 system prompt 段落;无任务时返回空串。 */\n toPromptSection(): string {\n if (this.items.length === 0) return \"\";\n const lines = this.items.map((t, i) => {\n const marker = t.status === \"completed\" ? \"[x]\" : t.status === \"in_progress\" ? \"[~]\" : \"[ ]\";\n return ` ${i + 1}. ${marker} ${t.content}`;\n });\n return `# Current todos\\n${lines.join(\"\\n\")}\\n\\nUpdate via TodoWrite as you make progress. Keep exactly one item in_progress at a time.`;\n }\n}\n","/**\n * Agent loop:单循环 ReAct。\n *\n * loop:\n * llm.stream(messages, tools)\n * → emit text → 累计 assistant 消息\n * → 收到 tool_call → 累计\n * → finish\n * if no tool_calls: break\n * for each tool_call:\n * check permission → execute → push tool result\n */\n\nimport type { LLMClient, LLMEvent } from \"../llm/types.js\";\nimport type { Message, AssistantMessage, ContentPart, ToolUsePart, TokenUsage } from \"../types/index.js\";\nimport type { ToolRegistry } from \"../tools/registry.js\";\nimport type { ToolContext } from \"../tools/types.js\";\nimport type { PermissionGate, Decision, PermissionDecision } from \"../permission/index.js\";\nimport type { Session } from \"../session/jsonl.js\";\nimport { TodoStore } from \"./todos.js\";\nimport { log } from \"../log/index.js\";\n\nexport interface AgentEvents {\n onText?: (delta: string) => void;\n onToolCallStart?: (id: string, name: string) => void;\n onToolCallArgs?: (id: string, args: unknown) => void;\n onToolResult?: (id: string, name: string, content: string, isError: boolean, summary?: string) => void;\n onPermissionRequest?: (toolName: string, args: unknown, summary: string) => Promise<PermissionDecision>;\n /** AskUserQuestion 工具调用时触发;resolve 把整批答案数组回填给工具。 */\n onAskQuestions?: (\n questions: import(\"../tools/builtin/ask-user-question.js\").AskQuestion[],\n ) => Promise<import(\"../tools/builtin/ask-user-question.js\").AskQuestionResponse[]>;\n onUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => void;\n /**\n * 一段 assistant 流结束、assistantMessage 已 push 进 messages,但工具还没开始执行时触发。\n * 用于 UI 立刻把这一批 tool_use calls 显示出来——避免\"流完 → 第一个 result 到达\"\n * 之间用户面对空屏。turn 直接结束(无 tool calls)的场景不会触发,走 onTurnEnd。\n */\n onAssistantTurn?: () => void;\n onTurnEnd?: () => void;\n}\n\nexport interface AgentContext {\n llm: LLMClient;\n tools: ToolRegistry;\n permissions: PermissionGate;\n session: Session;\n cwd: string;\n systemPrompt: string;\n abortSignal?: AbortSignal;\n events?: AgentEvents;\n}\n\nexport class Agent {\n private messages: Message[] = [];\n readonly todos = new TodoStore();\n\n constructor(private ctx: AgentContext) {}\n\n getMessages(): Message[] {\n return this.messages;\n }\n\n setMessages(msgs: Message[]): void {\n this.messages = msgs;\n }\n\n /** 执行一次完整的\"用户输入 → 助手响应(含工具循环) → 等待下一轮输入\"。 */\n async runTurn(userInput: string): Promise<void> {\n const userMessage: Message = { role: \"user\", content: userInput };\n this.messages.push(userMessage);\n await this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: userMessage });\n\n // 内部循环:工具调用可能多轮\n while (true) {\n const mode = this.ctx.permissions.getMode();\n const tools = this.ctx.tools.toLLMDefinitions(\n mode === \"plan\" ? (t) => t.permission === \"read\" : undefined,\n );\n // 每轮把当前 todos 注入 system prompt 末尾,让 LLM 看到自己写的清单\n const todoSection = this.todos.toPromptSection();\n const systemPrompt = todoSection\n ? `${this.ctx.systemPrompt}\\n\\n${todoSection}`\n : this.ctx.systemPrompt;\n const stream = this.ctx.llm.stream({\n messages: this.messages,\n tools,\n systemPrompt,\n abortSignal: this.ctx.abortSignal,\n });\n\n const assistantParts: ContentPart[] = [];\n const toolCallsToRun: ToolUsePart[] = [];\n let lastError: Error | undefined;\n\n for await (const ev of stream) {\n this.handleEvent(ev, assistantParts, toolCallsToRun, (e) => {\n lastError = e;\n });\n if (lastError) break;\n }\n\n if (lastError) {\n this.ctx.events?.onError?.(lastError);\n log.error(\"agent stream error\", { msg: lastError.message });\n return;\n }\n\n // 把 assistant 消息加入历史\n const assistantMessage: AssistantMessage = { role: \"assistant\", content: assistantParts };\n this.messages.push(assistantMessage);\n await this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: assistantMessage });\n\n if (toolCallsToRun.length === 0) {\n this.ctx.events?.onTurnEnd?.();\n return;\n }\n\n // 流刚结束、tool 还没跑——给 UI 一个钩子立刻展示这一批 calls\n this.ctx.events?.onAssistantTurn?.();\n\n // 执行工具调用\n for (const call of toolCallsToRun) {\n await this.runToolCall(call);\n }\n }\n }\n\n private handleEvent(\n ev: LLMEvent,\n assistantParts: ContentPart[],\n toolCallsToRun: ToolUsePart[],\n onError: (e: Error) => void,\n ): void {\n switch (ev.type) {\n case \"text\":\n // 合并到最后一个 text part 或新增\n {\n const last = assistantParts[assistantParts.length - 1];\n if (last && last.type === \"text\") {\n last.text += ev.delta;\n } else {\n assistantParts.push({ type: \"text\", text: ev.delta });\n }\n }\n this.ctx.events?.onText?.(ev.delta);\n break;\n\n case \"tool_call_start\":\n this.ctx.events?.onToolCallStart?.(ev.id, ev.name);\n break;\n\n case \"tool_call_complete\": {\n const callPart: ToolUsePart = { type: \"tool_use\", id: ev.id, name: ev.name, args: ev.args };\n assistantParts.push(callPart);\n toolCallsToRun.push(callPart);\n this.ctx.events?.onToolCallArgs?.(ev.id, ev.args);\n break;\n }\n\n case \"finish\":\n if (ev.usage) {\n this.ctx.events?.onUsage?.(ev.usage);\n this.ctx.session.append({\n type: \"usage\",\n time: new Date().toISOString(),\n usage: ev.usage,\n provider: this.ctx.llm.providerName,\n model: this.ctx.llm.model,\n });\n }\n break;\n\n case \"error\":\n onError(ev.error);\n break;\n }\n }\n\n private async runToolCall(call: ToolUsePart): Promise<void> {\n const tool = this.ctx.tools.get(call.name);\n if (!tool) {\n const result = `Tool \"${call.name}\" is not available.`;\n this.recordToolResult(call.id, call.name, result, true);\n return;\n }\n\n const summary = tool.summarize?.(call.args) ?? `${call.name}(...)`;\n const decision: Decision = this.ctx.permissions.decide({\n toolName: call.name,\n args: call.args,\n permission: tool.permission,\n });\n\n let approved = decision === \"allow\";\n if (decision === \"deny\") {\n const reason =\n this.ctx.permissions.getMode() === \"plan\"\n ? `Denied: you are in plan mode. Only read-only tools are available. Propose changes instead of executing.`\n : `Denied by policy: ${call.name}.`;\n this.recordToolResult(call.id, call.name, reason, true);\n return;\n }\n if (decision === \"ask\") {\n const userDecision =\n (await this.ctx.events?.onPermissionRequest?.(call.name, call.args, summary)) ?? \"no\";\n if (userDecision === \"no\") {\n this.recordToolResult(call.id, call.name, `User rejected ${call.name}.`, true);\n return;\n }\n if (userDecision === \"session_allow\") {\n this.ctx.permissions.allowForSession(call.name);\n }\n approved = true;\n }\n\n const toolCtx: ToolContext = {\n cwd: this.ctx.cwd,\n abortSignal: this.ctx.abortSignal,\n askPermission: async () => true, // 已在外层处理\n todos: this.todos,\n askQuestions: this.ctx.events?.onAskQuestions\n ? (qs) => this.ctx.events!.onAskQuestions!(qs)\n : undefined,\n };\n\n const result = await this.ctx.tools.execute(call.name, call.args, toolCtx);\n this.recordToolResult(call.id, call.name, result.content, result.isError ?? false, result.summary, result.diff, result.kind);\n }\n\n private recordToolResult(\n id: string,\n name: string,\n content: string,\n isError: boolean,\n summary?: string,\n diff?: string,\n kind?: \"success\" | \"error\" | \"warn\",\n ): void {\n const toolMsg: Message = {\n role: \"tool\",\n toolUseId: id,\n content,\n isError,\n toolName: name,\n ...(diff ? { diff } : {}),\n ...(summary ? { summary } : {}),\n ...(kind ? { kind } : {}),\n };\n this.messages.push(toolMsg);\n this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: toolMsg });\n this.ctx.events?.onToolResult?.(id, name, content, isError, summary);\n }\n}\n","/**\n * System prompt 构造。\n *\n * 简短、命令式:把可用工具与运行时约束直接摆出来给 LLM。\n * 中文输出由 ui.lang 控制;英文为默认。\n */\n\nimport { homedir } from \"node:os\";\n\nexport interface SystemPromptOpts {\n cwd: string;\n model: string;\n provider: string;\n lang?: \"en\" | \"zh-CN\";\n toolNames: string[];\n /** MEMORY.md index 内容(loadMemoryIndex 加载后传入);空串视为无 memory。 */\n memoryIndex?: string;\n}\n\nexport function buildSystemPrompt(opts: SystemPromptOpts): string {\n const { cwd, model, provider, lang, toolNames, memoryIndex } = opts;\n const home = homedir();\n const displayCwd = cwd.startsWith(home) ? cwd.replace(home, \"~\") : cwd;\n\n const sections: string[] = [];\n\n sections.push(`You are Muse, a CLI coding assistant. You are running on the user's local machine via a terminal interface.`);\n\n sections.push(\n `# Environment\\n` +\n `- Working directory: ${displayCwd}\\n` +\n `- LLM backend: ${provider} (${model})\\n` +\n `- Date: ${new Date().toISOString().slice(0, 10)}`,\n );\n\n sections.push(\n `# Available tools\\n` +\n toolNames.map((n) => `- ${n}`).join(\"\\n\") +\n `\\n\\nPrefer the dedicated tool over Bash when one fits (Read for file reading, Edit for partial updates, Write for new files / full rewrites, Grep for content search, Glob for file lookup).`,\n );\n\n sections.push(\n `# Behavior\\n` +\n `- Be concise. State results, not your thinking. Don't narrate every step.\\n` +\n `- Before editing a file you have not seen, Read it first.\\n` +\n `- For Write/Edit/Bash the user may need to approve — proceed normally; the host will gate dangerous calls.\\n` +\n `- If a command may be destructive (rm -rf, force push, drop table, etc.), warn first and let the user run it manually.\\n` +\n `- When the user asks a question that does not need tools, just answer.`,\n );\n\n if (toolNames.includes(\"TodoWrite\")) {\n sections.push(\n `# Task management\\n` +\n `- For non-trivial, multi-step work, use TodoWrite to plan and track progress.\\n` +\n `- Keep exactly one task in_progress; mark a task completed immediately when done.\\n` +\n `- Skip it for trivial single-step requests.`,\n );\n }\n\n if (lang === \"zh-CN\") {\n sections.push(`# Output language\\nReply in Chinese (简体中文) unless the user writes in English.`);\n }\n\n if (memoryIndex && memoryIndex.trim()) {\n sections.push(\n `# Memory (long-term)\\n` +\n `Below is MEMORY.md — your index of persistent facts about the user, project, and prior feedback. ` +\n `Each line points at a file you can MemoryRead. Use MemoryWrite to record new durable knowledge ` +\n `(user role/preferences, validated decisions, project facts, external references). Do NOT save things ` +\n `derivable from the repo or git history.\\n\\n` +\n memoryIndex,\n );\n }\n\n return sections.join(\"\\n\\n\");\n}\n","/**\n * 长期 Memory:跨 session 持久化的小段知识。\n *\n * 路径约定:~/.muse/projects/<projectHash>/memory/\n * - MEMORY.md index(每行 `- [Title](file.md) — one-line hook`)\n * - <name>.md 具体记忆,带 frontmatter\n *\n * MEMORY.md 前 200 行自动注入 system prompt,让 LLM 每轮都看到。\n *\n * 类型:user / feedback / project / reference(对齐 Claude Code)。\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\n\nexport type MemoryType = \"user\" | \"feedback\" | \"project\" | \"reference\";\n\nfunction projectHash(cwd: string): string {\n return createHash(\"sha256\").update(cwd).digest(\"hex\").slice(0, 16);\n}\n\nexport function memoryDir(cwd: string): string {\n return join(homedir(), \".muse\", \"projects\", projectHash(cwd), \"memory\");\n}\n\nexport function memoryIndexPath(cwd: string): string {\n return join(memoryDir(cwd), \"MEMORY.md\");\n}\n\nexport function memoryFilePath(cwd: string, name: string): string {\n return join(memoryDir(cwd), `${name}.md`);\n}\n\n/** 加载 MEMORY.md 前 N 行供 system prompt 注入。 */\nexport async function loadMemoryIndex(cwd: string, maxLines = 200): Promise<string> {\n const path = memoryIndexPath(cwd);\n if (!existsSync(path)) return \"\";\n try {\n const raw = await readFile(path, \"utf-8\");\n const lines = raw.split(\"\\n\");\n if (lines.length <= maxLines) return raw.trim();\n return lines.slice(0, maxLines).join(\"\\n\").trim() + `\\n... [truncated; ${lines.length - maxLines} more lines]`;\n } catch {\n return \"\";\n }\n}\n\nexport async function readMemoryFile(cwd: string, name: string): Promise<string> {\n const path = memoryFilePath(cwd, name);\n if (!existsSync(path)) {\n throw new Error(`Memory \"${name}\" does not exist at ${path}.`);\n }\n return readFile(path, \"utf-8\");\n}\n\nexport interface WriteMemoryOpts {\n name: string;\n description: string;\n type: MemoryType;\n body: string;\n}\n\n/**\n * 写一条 memory + 更新 MEMORY.md 索引。\n * - 若文件已存在,整体覆盖\n * - MEMORY.md 行匹配 `- [name](name.md) ` 前缀;存在则替换该行,否则追加\n */\nexport async function writeMemory(cwd: string, opts: WriteMemoryOpts): Promise<{ filePath: string; indexUpdated: boolean }> {\n const dir = memoryDir(cwd);\n await mkdir(dir, { recursive: true });\n\n const filePath = memoryFilePath(cwd, opts.name);\n const frontmatter = [\n \"---\",\n `name: ${opts.name}`,\n `description: ${opts.description.replace(/\\n/g, \" \").trim()}`,\n `metadata:`,\n ` type: ${opts.type}`,\n \"---\",\n ].join(\"\\n\");\n const content = `${frontmatter}\\n\\n${opts.body.trim()}\\n`;\n await writeFile(filePath, content, \"utf-8\");\n\n // 索引更新\n const indexPath = memoryIndexPath(cwd);\n let index = \"\";\n if (existsSync(indexPath)) index = await readFile(indexPath, \"utf-8\");\n const lines = index ? index.split(\"\\n\") : [];\n const linePrefix = `- [${opts.name}](${opts.name}.md)`;\n const newLine = `${linePrefix} — ${opts.description.replace(/\\n/g, \" \").trim()}`;\n const existing = lines.findIndex((l) => l.startsWith(linePrefix));\n let indexUpdated = false;\n if (existing >= 0) {\n if (lines[existing] !== newLine) {\n lines[existing] = newLine;\n indexUpdated = true;\n }\n } else {\n lines.push(newLine);\n indexUpdated = true;\n }\n if (indexUpdated) {\n const out = lines.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trimEnd() + \"\\n\";\n await writeFile(indexPath, out, \"utf-8\");\n }\n\n return { filePath, indexUpdated };\n}\n","/**\n * 配置加载:\n * 1. 内置默认值\n * 2. ~/.muse/settings.json\n * 3. <cwd>/.muse/settings.json\n * 4. <cwd>/.muse/settings.local.json\n * 5. 环境变量 (MUSE_*)\n * 6. CLI flags (在 cli.tsx 里覆盖)\n *\n * ${ENV_VAR} 占位符在加载后展开。\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { z } from \"zod\";\nimport { SettingsSchema, type Settings } from \"./types.js\";\nimport { expandEnvVars } from \"./_env.js\";\nimport { log } from \"../log/index.js\";\n\nfunction formatZodIssues(issues: z.ZodIssue[]): string {\n return issues\n .map((i) => `${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"; \");\n}\n\nconst DEFAULTS: Settings = {\n llm: {\n provider: \"deepseek\",\n model: \"deepseek-chat\",\n },\n providers: {\n deepseek: { apiKey: \"${DEEPSEEK_API_KEY}\" },\n openai: { apiKey: \"${OPENAI_API_KEY}\" },\n qwen: { apiKey: \"${DASHSCOPE_API_KEY}\" },\n moonshot: { apiKey: \"${MOONSHOT_API_KEY}\" },\n zhipu: { apiKey: \"${ZHIPU_API_KEY}\" },\n openrouter: { apiKey: \"${OPENROUTER_API_KEY}\" },\n ollama: { baseUrl: \"http://localhost:11434/v1\" },\n },\n permissions: {\n allow: [\"Read\", \"Grep\", \"Glob\", \"TodoWrite\"],\n ask: [\"Write\", \"Edit\", \"Bash\"],\n deny: [],\n defaultMode: \"ask\",\n },\n ui: {\n showBanner: true,\n lang: \"en\",\n },\n};\n\nasync function readJsonIfExists(path: string): Promise<unknown | undefined> {\n if (!existsSync(path)) return undefined;\n try {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw);\n } catch (err) {\n log.warn(`Failed to parse settings at ${path}: ${err instanceof Error ? err.message : String(err)}`);\n return undefined;\n }\n}\n\n/** 深合并:高优先级覆盖低优先级。对象递归,数组/标量覆盖。 */\nfunction deepMerge<T>(low: T, high: Partial<T>): T {\n if (high == null) return low;\n if (typeof low !== \"object\" || typeof high !== \"object\" || low === null || high === null) {\n return high as T;\n }\n if (Array.isArray(high)) return high as unknown as T;\n const result: Record<string, unknown> = { ...(low as Record<string, unknown>) };\n for (const [k, v] of Object.entries(high)) {\n const existing = (low as Record<string, unknown>)[k];\n if (\n v !== null &&\n typeof v === \"object\" &&\n !Array.isArray(v) &&\n existing !== null &&\n typeof existing === \"object\" &&\n !Array.isArray(existing)\n ) {\n result[k] = deepMerge(existing, v as Record<string, unknown>);\n } else {\n result[k] = v;\n }\n }\n return result as T;\n}\n\nexport interface LoadedSettings {\n settings: Settings;\n sources: string[];\n}\n\nexport async function loadSettings(cwd: string = process.cwd()): Promise<LoadedSettings> {\n const sources: string[] = [\"<defaults>\"];\n let merged: Settings = DEFAULTS;\n\n const candidates = [\n join(homedir(), \".muse\", \"settings.json\"),\n join(cwd, \".muse\", \"settings.json\"),\n join(cwd, \".muse\", \"settings.local.json\"),\n ];\n\n for (const path of candidates) {\n const raw = await readJsonIfExists(path);\n if (raw != null) {\n const parsed = SettingsSchema.safeParse(raw);\n if (parsed.success) {\n merged = deepMerge(merged, parsed.data);\n sources.push(path);\n } else {\n log.warn(`Invalid settings at ${path}: ${formatZodIssues(parsed.error.issues)}`);\n }\n }\n }\n\n // Env overrides for the active LLM\n if (process.env.MUSE_PROVIDER && merged.llm) {\n merged = { ...merged, llm: { ...merged.llm, provider: process.env.MUSE_PROVIDER } };\n sources.push(\"env:MUSE_PROVIDER\");\n }\n if (process.env.MUSE_MODEL && merged.llm) {\n merged = { ...merged, llm: { ...merged.llm, model: process.env.MUSE_MODEL } };\n sources.push(\"env:MUSE_MODEL\");\n }\n\n // 展开 ${ENV_VAR} 占位符\n merged = expandEnvVars(merged) as Settings;\n\n return { settings: merged, sources };\n}\n\nexport { DEFAULTS };\nexport { resolve as resolvePath };\n","/**\n * 配置 schema。对应 ~/.muse/settings.json + .muse/settings.json 的内容。\n */\n\nimport { z } from \"zod\";\n\nexport const ProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n baseUrl: z.string().optional(),\n extraHeaders: z.record(z.string()).optional(),\n}).passthrough();\n\n// 新设计:model id 由 ~/.muse/models.local.json 提供,settings.json 只保留 active 选择。\n// provider 字段仅用于\"无 models.local.json 时的 fallback 路径\"(设计文档 §8 兼容层)。\n// 因此两者都可选——/models 切换只写 model,不写 provider。\nexport const LLMConfigSchema = z.object({\n provider: z.string().optional().describe(\"Fallback provider preset (only used when no models.local.json entry matches).\"),\n model: z.string().optional().describe(\"Active model id; should match an id in models.local.json.\"),\n temperature: z.number().min(0).max(2).optional(),\n maxTokens: z.number().int().positive().optional(),\n});\n\nexport const PermissionsSchema = z.object({\n allow: z.array(z.string()).optional(),\n ask: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n defaultMode: z.enum([\"strict\", \"relaxed\", \"ask\"]).optional(),\n});\n\nexport const UISchema = z.object({\n theme: z.enum([\"dark\", \"light\"]).optional(),\n lang: z.enum([\"en\", \"zh-CN\"]).optional(),\n showBanner: z.boolean().optional(),\n});\n\nexport const SettingsSchema = z.object({\n llm: LLMConfigSchema.optional(),\n providers: z.record(ProviderConfigSchema).optional(),\n permissions: PermissionsSchema.optional(),\n ui: UISchema.optional(),\n mcpServers: z.record(z.unknown()).optional(),\n skills: z.object({\n enabled: z.boolean().optional(),\n disabled: z.array(z.string()).optional(),\n }).optional(),\n}).passthrough();\n\nexport type Settings = z.infer<typeof SettingsSchema>;\nexport type LLMConfig = z.infer<typeof LLMConfigSchema>;\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\nexport type Permissions = z.infer<typeof PermissionsSchema>;\n","/**\n * ${ENV_VAR} 占位符递归展开。\n *\n * settings.json / models.local.json 都共用这套机制,避免把明文凭证落到可入 git 的文件。\n * 未定义的 env var → 空字符串(不抛错,让上层校验\"必填字段是否非空\"决定行为)。\n */\n\nconst ENV_PATTERN = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\n\nexport function expandEnvVars(value: unknown): unknown {\n if (typeof value === \"string\") {\n return value.replace(ENV_PATTERN, (_match, name) => process.env[name] ?? \"\");\n }\n if (Array.isArray(value)) {\n return value.map(expandEnvVars);\n }\n if (value && typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n result[k] = expandEnvVars(v);\n }\n return result;\n }\n return value;\n}\n","/**\n * Models registry:用户级模型库。\n *\n * 位置:~/.muse/models.local.json (单文件,本机本地;从不入 git)\n *\n * 设计:\n * - models 数组的 id 是**用户起的名字**,不在代码里硬编码;availableModels 决定 /models\n * selector 里显示哪些\n * - apiKey 字段可以直接写明文(推荐:文件就在本机本地),也支持 ${ENV_VAR} 占位符\n * - baseUrl 是基址,SDK 自己拼 /chat/completions;用户填全 endpoint 时自动剥后缀\n * - 不存在文件 → 返回 undefined(调用方回退到 settings.json llm 配置)\n *\n * Why `.local.json` 单文件而非 `models.json`:\n * muse 0.1.x 早期是双文件(models.json git-tracked + models.local.json 本地兜底),\n * 但实际使用中并没有 \"git-track 一份不含 key 的模板\" 的场景——用户的模型清单本就\n * 是私人物件。为避免新用户被两份文件混淆,合并为单文件,沿用 `.local.json`\n * 后缀作为 \"本机本地,绝不入 git\" 的视觉提示。\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { expandEnvVars } from \"./_env.js\";\nimport { log } from \"../log/index.js\";\n\n/**\n * 内部规整后的 ModelEntry 类型。schema 解析后的对象会通过 normalize 步骤\n * 把 url/baseUrl 合一,最终 baseUrl 保证非空。业务(client / selector)只看本类型。\n */\nexport interface ModelEntry {\n id: string;\n name?: string;\n vendor?: string;\n apiKey?: string;\n baseUrl: string;\n supportsToolCall?: boolean;\n supportsImages?: boolean;\n contextWindow?: number;\n [k: string]: unknown;\n}\n\n/**\n * 输入校验:baseUrl / url 任一非空即可。\n * 用户实际写的 models.local.json 多用 `url`(OpenAI 兼容协议惯例命名),\n * 我们接受两种别名,normalize 阶段归一。\n */\nexport const ModelEntryInputSchema = z\n .object({\n id: z.string().min(1),\n name: z.string().optional(),\n vendor: z.string().optional(),\n apiKey: z.string().optional(),\n baseUrl: z.string().optional(),\n url: z.string().optional(),\n supportsToolCall: z.boolean().optional(),\n supportsImages: z.boolean().optional(),\n contextWindow: z.number().int().positive().optional(),\n })\n .passthrough()\n .refine((d) => Boolean(d.baseUrl || d.url), {\n message: \"Either 'baseUrl' or 'url' is required\",\n path: [\"baseUrl\"],\n });\n\nexport type ModelEntryInput = z.infer<typeof ModelEntryInputSchema>;\n\nexport const ModelsRegistryInputSchema = z\n .object({\n models: z.array(ModelEntryInputSchema),\n /** 不填 = 全部 models 都进 selector;填了就是 selector 子集(按顺序)。 */\n availableModels: z.array(z.string()).optional(),\n })\n .passthrough();\n\nexport type ModelsRegistryInput = z.infer<typeof ModelsRegistryInputSchema>;\n\n/** Normalize 后的 registry:models[*].baseUrl 保证非空。 */\nexport interface ModelsRegistry {\n models: ModelEntry[];\n availableModels?: string[];\n [k: string]: unknown;\n}\n\nexport interface LoadError {\n path: string;\n message: string;\n}\n\nexport interface LoadedModels {\n registry: ModelsRegistry | undefined;\n sources: string[];\n errors: LoadError[];\n}\n\nexport const MODELS_PATH = (): string => join(homedir(), \".muse\", \"models.local.json\");\n\nexport async function loadModelsRegistry(): Promise<LoadedModels> {\n const sources: string[] = [];\n const errors: LoadError[] = [];\n const path = MODELS_PATH();\n\n if (!existsSync(path)) {\n return { registry: undefined, sources, errors };\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(path, \"utf-8\"));\n } catch (err) {\n const msg = `JSON parse error: ${err instanceof Error ? err.message : String(err)}`;\n log.warn(`Failed to parse ${path}: ${msg}`);\n errors.push({ path, message: msg });\n return { registry: undefined, sources, errors };\n }\n\n const parsed = ModelsRegistryInputSchema.safeParse(raw);\n if (!parsed.success) {\n const msg = formatZodIssues(parsed.error.issues);\n log.warn(`Invalid models registry at ${path}: ${msg}`);\n errors.push({ path, message: msg });\n return { registry: undefined, sources, errors };\n }\n\n const normalized: ModelsRegistry = {\n ...parsed.data,\n models: parsed.data.models.map(normalizeModelEntry),\n };\n sources.push(path);\n const expanded = expandEnvVars(normalized) as ModelsRegistry;\n return { registry: expanded, sources, errors };\n}\n\nfunction formatZodIssues(issues: z.ZodIssue[]): string {\n return issues\n .map((i) => `${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"; \");\n}\n\n/**\n * 输入归一:url ↔ baseUrl 二选一;剥 trailing `/` 与 `/chat/completions`。\n * 经过校验后 baseUrl/url 至少一个非空(zod refine 保证),输出 baseUrl 必填。\n *\n * 同时记录 apiKey 字段里出现的 ${ENV_VAR} 占位符名(_apiKeyEnvVars),让 expand 后\n * apiKey 变空时 client.ts 能给出\"缺哪个 env var\"的精确提示。\n */\nfunction normalizeModelEntry(entry: ModelEntryInput): ModelEntry {\n let baseUrl = (entry.baseUrl ?? entry.url ?? \"\").replace(/\\/+$/, \"\");\n if (baseUrl.endsWith(\"/chat/completions\")) {\n baseUrl = baseUrl.slice(0, -\"/chat/completions\".length);\n }\n const { url: _url, ...rest } = entry;\n const apiKeyEnvVars = entry.apiKey ? extractEnvVars(entry.apiKey) : [];\n return {\n ...rest,\n baseUrl,\n ...(apiKeyEnvVars.length > 0 ? { _apiKeyEnvVars: apiKeyEnvVars } : {}),\n };\n}\n\nconst ENV_PLACEHOLDER = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\nfunction extractEnvVars(s: string): string[] {\n const out: string[] = [];\n let m: RegExpExecArray | null;\n ENV_PLACEHOLDER.lastIndex = 0;\n while ((m = ENV_PLACEHOLDER.exec(s)) !== null) out.push(m[1]);\n return out;\n}\n\n// ---------- selector / lookup helpers ----------\n\nexport function findEntry(registry: ModelsRegistry, modelId: string): ModelEntry | undefined {\n return registry.models.find((m) => m.id === modelId);\n}\n\n/** /models selector 里实际显示的条目(availableModels 缺省 = 全部 id)。 */\nexport function visibleEntries(registry: ModelsRegistry): ModelEntry[] {\n if (!registry.availableModels || registry.availableModels.length === 0) {\n return registry.models;\n }\n const result: ModelEntry[] = [];\n for (const id of registry.availableModels) {\n const e = registry.models.find((m) => m.id === id);\n if (e) result.push(e);\n }\n return result;\n}\n","/**\n * Slash 命令注册表与解析器。\n */\n\nimport type { SlashCommand } from \"./types.js\";\n\nexport class SlashRegistry {\n private byName = new Map<string, SlashCommand>();\n private order: SlashCommand[] = [];\n\n register(cmd: SlashCommand): void {\n if (this.byName.has(cmd.name)) {\n throw new Error(`Duplicate slash command: /${cmd.name}`);\n }\n this.byName.set(cmd.name, cmd);\n this.order.push(cmd);\n for (const a of cmd.aliases ?? []) {\n if (!this.byName.has(a)) this.byName.set(a, cmd);\n }\n }\n\n registerAll(cmds: SlashCommand[]): void {\n for (const c of cmds) this.register(c);\n }\n\n get(name: string): SlashCommand | undefined {\n return this.byName.get(name);\n }\n\n list(): SlashCommand[] {\n return [...this.order];\n }\n}\n\nexport interface ParsedSlash {\n name: string;\n args: string;\n}\n\n/** \"/foo bar baz\" → { name: \"foo\", args: \"bar baz\" };非 slash 返回 null。 */\nexport function parseSlash(input: string): ParsedSlash | null {\n const trimmed = input.trim();\n if (!trimmed.startsWith(\"/\") || trimmed.length < 2) return null;\n const body = trimmed.slice(1);\n const space = body.search(/\\s/);\n if (space === -1) return { name: body, args: \"\" };\n return { name: body.slice(0, space), args: body.slice(space + 1).trim() };\n}\n","/**\n * 模型单价表(USD per 1M tokens)。\n *\n * 设计文档:muse-design.md §11.2 Token / 费用统计。\n *\n * 数据来源:各 provider 公开价格页(2026 年初快照)。仅供 /cost 命令展示估算用,\n * 不保证准确性,价格变动用户可在 ~/.muse/settings.json 自定义覆盖(v0.2 起)。\n */\n\nexport interface ModelPricing {\n /** 输入 token 单价(USD per 1M)。 */\n inputPer1M: number;\n /** 输出 token 单价(USD per 1M)。 */\n outputPer1M: number;\n}\n\nconst PRICING: Record<string, Record<string, ModelPricing>> = {\n openai: {\n \"gpt-4o\": { inputPer1M: 2.5, outputPer1M: 10 },\n \"gpt-4o-mini\": { inputPer1M: 0.15, outputPer1M: 0.6 },\n \"gpt-4-turbo\": { inputPer1M: 10, outputPer1M: 30 },\n },\n deepseek: {\n \"deepseek-chat\": { inputPer1M: 0.14, outputPer1M: 0.28 },\n \"deepseek-reasoner\": { inputPer1M: 0.55, outputPer1M: 2.19 },\n },\n qwen: {\n \"qwen-plus\": { inputPer1M: 0.4, outputPer1M: 1.2 },\n \"qwen-max\": { inputPer1M: 2.8, outputPer1M: 8.4 },\n \"qwen-turbo\": { inputPer1M: 0.05, outputPer1M: 0.2 },\n },\n moonshot: {\n \"moonshot-v1-8k\": { inputPer1M: 1.68, outputPer1M: 1.68 },\n \"moonshot-v1-32k\": { inputPer1M: 3.36, outputPer1M: 3.36 },\n \"moonshot-v1-128k\": { inputPer1M: 8.4, outputPer1M: 8.4 },\n },\n zhipu: {\n \"glm-4-flash\": { inputPer1M: 0, outputPer1M: 0 },\n \"glm-4-plus\": { inputPer1M: 7, outputPer1M: 7 },\n },\n ollama: {\n // 本地模型零成本\n },\n};\n\nexport function lookupPricing(provider: string, model: string): ModelPricing | undefined {\n return PRICING[provider]?.[model];\n}\n\nexport function estimateCostUSD(\n provider: string,\n model: string,\n inputTokens: number,\n outputTokens: number,\n): number | undefined {\n const p = lookupPricing(provider, model);\n if (!p) return undefined;\n return (inputTokens / 1_000_000) * p.inputPer1M + (outputTokens / 1_000_000) * p.outputPer1M;\n}\n\n/** 把 USD 金额格式化成人类可读字符串。小于 1 美分用 micro-dollar 显示。 */\nexport function formatUSD(usd: number): string {\n if (usd === 0) return \"$0.00\";\n if (usd < 0.0001) return `<$0.0001`;\n if (usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(4)}`;\n}\n","/**\n * 上下文管理:手动 / 自动压缩对话历史。\n *\n * 设计文档:muse-design.md §5.3 上下文管理。\n *\n * 算法:\n * 1. 找一个安全切割点 cutoff:cutoff 之前是 \"older\",之后是 \"recent\"\n * 2. 安全 = 不破坏 assistant 的 tool_use ↔ 紧随的 tool 消息 配对\n * (在 tool_use 之后但 tool result 之前切,会让 LLM 看到悬挂的 tool_use)\n * 3. older 拼成转录,调 LLM 摘要成一段\n * 4. 摘要包成一条 user message(\"[Previous conversation summary] ...\"),\n * 作为新历史的开头,后接 recent\n *\n * Why user 角色而非 system:\n * - 系统提示 muse 已在 systemPrompt 单独管理;不污染它\n * - 用 user role 让 LLM 自然把它当成\"任务上下文\"继续推理\n */\n\nimport type { LLMClient } from \"../llm/types.js\";\nimport type { Message, AssistantMessage, ContentPart } from \"../types/index.js\";\n\nexport interface CompactOptions {\n llm: LLMClient;\n /** 保留最近 N 条原始消息不压缩。默认 4。 */\n keepRecent?: number;\n abortSignal?: AbortSignal;\n /** LLM 摘要流式过程中的字符进度回调(每个 text-delta 触发,传累计字符数)。 */\n onProgress?: (charsReceived: number) => void;\n}\n\nexport interface CompactResult {\n newMessages: Message[];\n summary: string;\n originalCount: number;\n newCount: number;\n /** 没有可压缩内容时为 true,messages 原样返回。 */\n noop: boolean;\n}\n\nexport async function compactMessages(\n messages: Message[],\n opts: CompactOptions,\n): Promise<CompactResult> {\n const keepRecent = opts.keepRecent ?? 4;\n const cutoff = findSafeCutoff(messages, keepRecent);\n\n if (cutoff <= 0) {\n return {\n newMessages: messages,\n summary: \"\",\n originalCount: messages.length,\n newCount: messages.length,\n noop: true,\n };\n }\n\n const older = messages.slice(0, cutoff);\n const recent = messages.slice(cutoff);\n const summary = await summarizeConversation(older, opts.llm, opts.abortSignal, opts.onProgress);\n\n const summaryMessage: Message = {\n role: \"user\",\n content:\n `[Previous conversation summary]\\n\\n${summary}\\n\\n` +\n `[End of summary. The conversation continues below.]`,\n };\n\n const newMessages: Message[] = [summaryMessage, ...recent];\n\n return {\n newMessages,\n summary,\n originalCount: messages.length,\n newCount: newMessages.length,\n noop: false,\n };\n}\n\n/**\n * 从理想切点(messages.length - keepRecent)向前找最近的安全边界。\n * 安全边界 = user 消息(自然 turn 起点),且其之前不存在悬挂的 tool_use。\n *\n * 退化策略:找不到合法切点 → 返回 0(不压缩)。\n */\nexport function findSafeCutoff(messages: Message[], keepRecent: number): number {\n if (messages.length <= keepRecent) return 0;\n const ideal = Math.max(0, messages.length - keepRecent);\n\n for (let i = ideal; i > 0; i--) {\n if (messages[i].role !== \"user\") continue;\n if (hasUnresolvedToolUse(messages.slice(0, i))) continue;\n return i;\n }\n return 0;\n}\n\n/** older 段是否有 assistant.tool_use 但缺对应 tool 消息。 */\nfunction hasUnresolvedToolUse(older: Message[]): boolean {\n const seenToolUseIds = new Set<string>();\n const seenToolResultIds = new Set<string>();\n for (const msg of older) {\n if (msg.role === \"assistant\") {\n for (const part of msg.content) {\n if (part.type === \"tool_use\") seenToolUseIds.add(part.id);\n }\n } else if (msg.role === \"tool\") {\n seenToolResultIds.add(msg.toolUseId);\n }\n }\n for (const id of seenToolUseIds) {\n if (!seenToolResultIds.has(id)) return true;\n }\n return false;\n}\n\nasync function summarizeConversation(\n older: Message[],\n llm: LLMClient,\n abortSignal?: AbortSignal,\n onProgress?: (chars: number) => void,\n): Promise<string> {\n const transcript = renderTranscript(older);\n const prompt: Message[] = [\n {\n role: \"user\",\n content:\n `Summarize the following conversation in 200-400 words. Focus on:\\n` +\n `1. The user's task and goals\\n` +\n `2. Key decisions and approaches taken\\n` +\n `3. Files or code touched (paths + what changed)\\n` +\n `4. Outstanding questions or pending work\\n\\n` +\n `Be concrete. Do not invent details. Use short bullet points where appropriate.\\n\\n` +\n `--- BEGIN CONVERSATION ---\\n${transcript}\\n--- END CONVERSATION ---`,\n },\n ];\n\n let text = \"\";\n for await (const ev of llm.stream({ messages: prompt, abortSignal })) {\n if (ev.type === \"text\") {\n text += ev.delta;\n onProgress?.(text.length);\n } else if (ev.type === \"error\") throw ev.error;\n }\n return text.trim() || \"(empty summary)\";\n}\n\nfunction renderTranscript(messages: Message[]): string {\n const lines: string[] = [];\n for (const msg of messages) {\n switch (msg.role) {\n case \"system\":\n lines.push(`[system]\\n${msg.content}\\n`);\n break;\n case \"user\":\n lines.push(`[user]\\n${typeof msg.content === \"string\" ? msg.content : flattenContent(msg.content)}\\n`);\n break;\n case \"assistant\":\n lines.push(`[assistant]\\n${renderAssistant(msg)}\\n`);\n break;\n case \"tool\":\n lines.push(`[tool result${msg.isError ? \" ERROR\" : \"\"}]\\n${msg.content}\\n`);\n break;\n }\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderAssistant(msg: AssistantMessage): string {\n const parts: string[] = [];\n for (const part of msg.content) {\n if (part.type === \"text\") parts.push(part.text);\n else if (part.type === \"tool_use\") {\n parts.push(`<tool_call name=\"${part.name}\" args=${JSON.stringify(part.args)} />`);\n }\n }\n return parts.join(\"\\n\");\n}\n\nfunction flattenContent(parts: ContentPart[]): string {\n return parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n}\n","/**\n * MCP 状态查询入口(v0.1 占位,v0.3 真接 SDK)。\n *\n * 当前仅根据 settings.mcpServers 配置返回\"已配置但未连接\"的状态。\n * /mcp 命令读这里;不依赖任何 MCP 运行时。\n */\n\nimport type { Settings } from \"../config/types.js\";\nimport type { MCPServerStatus, MCPServerConfig } from \"./types.js\";\n\nconst NOT_IMPLEMENTED = \"MCP client not implemented (planned for v0.3)\";\n\nexport function getMCPStatus(settings: Settings): MCPServerStatus[] {\n const servers = (settings.mcpServers ?? {}) as Record<string, MCPServerConfig>;\n return Object.entries(servers).map(([name, config]) => ({\n name,\n configured: true,\n connected: false,\n toolCount: 0,\n error: NOT_IMPLEMENTED,\n config,\n }));\n}\n\nexport type { MCPServerStatus, MCPServerConfig } from \"./types.js\";\n","/**\n * Session 持久化:append-only JSONL。\n * 路径:~/.muse/projects/<project-hash>/sessions/<uuid>.jsonl\n *\n * 每行一个事件:消息 / 工具调用 / 工具结果 / 使用统计 / ...\n */\n\nimport { appendFile, mkdir, readdir, readFile, stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport type { Message, TokenUsage } from \"../types/index.js\";\nimport { log } from \"../log/index.js\";\n\nexport type SessionEvent =\n | { type: \"session_start\"; time: string; cwd: string; provider: string; model: string }\n | { type: \"message\"; time: string; message: Message }\n | { type: \"usage\"; time: string; usage: TokenUsage; provider: string; model: string }\n | { type: \"session_end\"; time: string; reason: \"user_exit\" | \"error\" };\n\nexport interface SessionMeta {\n id: string;\n cwd: string;\n createdAt: string;\n path: string;\n}\n\nexport interface SessionSummary extends SessionMeta {\n /** 首个 user 消息前 60 字符。 */\n preview?: string;\n messageCount: number;\n}\n\nfunction projectHash(cwd: string): string {\n return createHash(\"sha256\").update(cwd).digest(\"hex\").slice(0, 16);\n}\n\nfunction sessionsDir(cwd: string): string {\n return join(homedir(), \".muse\", \"projects\", projectHash(cwd), \"sessions\");\n}\n\nexport class Session {\n readonly meta: SessionMeta;\n private writeQueue: Promise<void> = Promise.resolve();\n\n private constructor(meta: SessionMeta) {\n this.meta = meta;\n }\n\n static async create(cwd: string): Promise<Session> {\n const id = randomUUID();\n const dir = sessionsDir(cwd);\n await mkdir(dir, { recursive: true });\n const path = join(dir, `${id}.jsonl`);\n const meta: SessionMeta = {\n id,\n cwd,\n createdAt: new Date().toISOString(),\n path,\n };\n log.debug(\"session created\", { id, path });\n return new Session(meta);\n }\n\n static async findLatest(cwd: string): Promise<SessionMeta | undefined> {\n const list = await Session.listAll(cwd, 1);\n return list[0];\n }\n\n static async resolve(cwd: string, idOrPrefix: string): Promise<SessionMeta | undefined> {\n const dir = sessionsDir(cwd);\n if (!existsSync(dir)) return undefined;\n const entries = await readdir(dir);\n const matches = entries.filter((e) => e.endsWith(\".jsonl\") && e.startsWith(idOrPrefix));\n if (matches.length === 0) return undefined;\n if (matches.length > 1) {\n throw new Error(`Ambiguous session id \"${idOrPrefix}\" matches ${matches.length} sessions; use more characters.`);\n }\n const top = matches[0];\n const st = await stat(join(dir, top));\n return {\n id: top.replace(/\\.jsonl$/, \"\"),\n cwd,\n createdAt: st.mtime.toISOString(),\n path: join(dir, top),\n };\n }\n\n /**\n * 按修改时间倒序列出当前 cwd 下的 session,附带 preview 与消息数。\n * 读 preview 需要打开每个文件;调用方通过 limit 控制 IO 量。\n */\n static async listAll(cwd: string, limit?: number): Promise<SessionSummary[]> {\n const dir = sessionsDir(cwd);\n if (!existsSync(dir)) return [];\n const entries = await readdir(dir);\n const files = entries.filter((e) => e.endsWith(\".jsonl\"));\n if (files.length === 0) return [];\n\n const stats = await Promise.all(\n files.map(async (f) => {\n const path = join(dir, f);\n const st = await stat(path);\n return { file: f, path, mtime: st.mtime };\n }),\n );\n stats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n\n const truncated = typeof limit === \"number\" ? stats.slice(0, limit) : stats;\n\n const summaries: SessionSummary[] = [];\n for (const s of truncated) {\n const meta: SessionMeta = {\n id: s.file.replace(/\\.jsonl$/, \"\"),\n cwd,\n createdAt: s.mtime.toISOString(),\n path: s.path,\n };\n const summary = await readSummary(meta);\n summaries.push(summary);\n }\n return summaries;\n }\n\n static async open(meta: SessionMeta): Promise<{ session: Session; events: SessionEvent[] }> {\n const session = new Session(meta);\n const events = await session.readAll();\n return { session, events };\n }\n\n /** 从已加载的 events 重建 messages 数组(按时序)。 */\n static messagesFromEvents(events: SessionEvent[]): Message[] {\n const out: Message[] = [];\n for (const ev of events) {\n if (ev.type === \"message\") out.push(ev.message);\n }\n return out;\n }\n\n async append(event: SessionEvent): Promise<void> {\n const line = JSON.stringify(event) + \"\\n\";\n // 串行写入避免交错\n this.writeQueue = this.writeQueue.then(async () => {\n try {\n await mkdir(dirname(this.meta.path), { recursive: true });\n await appendFile(this.meta.path, line, \"utf-8\");\n } catch (err) {\n log.warn(`session append failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n });\n return this.writeQueue;\n }\n\n async readAll(): Promise<SessionEvent[]> {\n if (!existsSync(this.meta.path)) return [];\n const raw = await readFile(this.meta.path, \"utf-8\");\n const events: SessionEvent[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as SessionEvent);\n } catch {\n // skip corrupt lines\n }\n }\n return events;\n }\n}\n\nasync function readSummary(meta: SessionMeta): Promise<SessionSummary> {\n let events: SessionEvent[] = [];\n try {\n const raw = await readFile(meta.path, \"utf-8\");\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as SessionEvent);\n } catch {\n // skip\n }\n }\n } catch {\n // unreadable; return minimal summary\n }\n const messages = events.filter((e): e is Extract<SessionEvent, { type: \"message\" }> => e.type === \"message\");\n const firstUser = messages.find((e) => e.message.role === \"user\");\n let preview: string | undefined;\n if (firstUser) {\n const c = firstUser.message.content;\n const text = typeof c === \"string\" ? c : c.map((p) => (p.type === \"text\" ? p.text : \"\")).join(\" \").trim();\n preview = text.slice(0, 60).replace(/\\s+/g, \" \");\n }\n return { ...meta, preview, messageCount: messages.length };\n}\n","/**\n * Slash 命令体共享的格式化 helper。\n *\n * 之所以单独抽:命令文件应该薄、只编排;shortPath / 表格对齐 / flag 解析\n * 被多个命令复用,三处相似就抽(CLAUDE.md 代码风格条款)。\n */\n\nimport { homedir } from \"node:os\";\n\nexport function shortPath(p: string): string {\n const home = homedir();\n if (p === home) return \"~\";\n if (p.startsWith(home + \"/\")) return \"~\" + p.slice(home.length);\n return p;\n}\n\nexport function formatList(list: string[] | undefined): string {\n if (!list || list.length === 0) return \"(none)\";\n return list.join(\", \");\n}\n\n/**\n * 解析 \"--key val --flag pos1 pos2\" 形式。极简,够 v0.1 用:\n * - 不支持 = 形式\n * - 不支持引号转义\n * - bool flag 默认 false,出现即 true\n */\nexport function parseArgs(raw: string): { positional: string[]; flags: Record<string, string | boolean> } {\n const tokens = raw.trim().split(/\\s+/).filter(Boolean);\n const positional: string[] = [];\n const flags: Record<string, string | boolean> = {};\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n if (t.startsWith(\"--\")) {\n const key = t.slice(2);\n const next = tokens[i + 1];\n if (next && !next.startsWith(\"--\")) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n } else {\n positional.push(t);\n }\n }\n return { positional, flags };\n}\n\n/**\n * \"provider/model\" 或 \"model\" 解析。后者沿用当前 provider。\n */\nexport function parseModelSpec(\n spec: string,\n fallbackProvider: string,\n): { provider: string; model: string } {\n const slash = spec.indexOf(\"/\");\n if (slash === -1) return { provider: fallbackProvider, model: spec };\n return { provider: spec.slice(0, slash), model: spec.slice(slash + 1) };\n}\n\n/** \"yyyy-mm-dd hh:mm\" 紧凑时间。 */\nexport function formatTime(iso: string): string {\n const d = new Date(iso);\n if (isNaN(d.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n","/**\n * 内置 slash 命令:/help /clear /compact /model /config /mcp /cost /resume /quit\n *\n * 设计文档:muse-design.md §7.2 表中 9 条全部覆盖。\n *\n * 设计原则:命令体只编排(解析参数 → 调 actions / 领域模块 → 构造 display)。\n * 真正的业务(压缩、列 session、查 MCP)在各自的领域模块里。\n */\n\nimport type { SlashCommand, SlashCommandContext } from \"./types.js\";\nimport { estimateCostUSD, formatUSD, lookupPricing } from \"../llm/pricing.js\";\nimport { redactApiKey } from \"../log/index.js\";\nimport { compactMessages } from \"../loop/context.js\";\nimport { getMCPStatus } from \"../mcp/index.js\";\nimport { Session } from \"../session/jsonl.js\";\nimport { loadModelsRegistry, visibleEntries, type LoadError } from \"../config/models.js\";\nimport { shortPath, formatList, parseArgs, formatTime } from \"./_format.js\";\nimport { MODE_CYCLE, MODE_LABEL, type PermissionMode } from \"../permission/index.js\";\n\n// ----- /help -----\n\nconst HELP: SlashCommand = {\n name: \"help\",\n description: \"show available slash commands\",\n execute(ctx) {\n const cmds = ctx.listCommands();\n const heads = cmds.map(headOf);\n const width = Math.max(...heads.map((h) => h.length));\n const lines = [\"Built-in commands:\"];\n for (let i = 0; i < cmds.length; i++) {\n const aliasNote = cmds[i].aliases?.length\n ? ` (alias: ${cmds[i].aliases!.map((a) => `/${a}`).join(\", \")})`\n : \"\";\n lines.push(` /${heads[i].padEnd(width)} ${cmds[i].description}${aliasNote}`);\n }\n lines.push(\"\", \"Keys: Ctrl+C exit\");\n return { display: lines.join(\"\\n\") };\n },\n};\n\nfunction headOf(c: SlashCommand): string {\n return c.argsHint ? `${c.name} ${c.argsHint}` : c.name;\n}\n\n// ----- /clear -----\n\nconst CLEAR: SlashCommand = {\n name: \"clear\",\n description: \"clear conversation history\",\n execute(ctx) {\n ctx.actions.setMessages([]);\n return { display: \"(history cleared)\" };\n },\n};\n\n// ----- /quit -----\n\nconst QUIT: SlashCommand = {\n name: \"quit\",\n aliases: [\"exit\"],\n description: \"exit Muse\",\n execute() {\n return { exit: true };\n },\n};\n\n// ----- /cost -----\n\nconst COST: SlashCommand = {\n name: \"cost\",\n description: \"show token usage and estimated cost for this session\",\n execute(ctx) {\n const { tokens, llm } = ctx;\n const pricing = lookupPricing(llm.providerName, llm.model);\n const lines = [\n `Session cost`,\n ` provider/model: ${llm.providerName} / ${llm.model}`,\n ` input tokens: ${tokens.inputTokens.toLocaleString()}`,\n ` output tokens: ${tokens.outputTokens.toLocaleString()}`,\n ` total tokens: ${tokens.totalTokens.toLocaleString()}`,\n ];\n if (pricing) {\n const cost = estimateCostUSD(llm.providerName, llm.model, tokens.inputTokens, tokens.outputTokens) ?? 0;\n lines.push(\n ` price (per 1M): input $${pricing.inputPer1M} / output $${pricing.outputPer1M}`,\n ` estimated cost: ${formatUSD(cost)}`,\n );\n } else {\n lines.push(` estimated cost: (no pricing data for ${llm.providerName}/${llm.model})`);\n }\n return { display: lines.join(\"\\n\") };\n },\n};\n\n// ----- /compact -----\n\nconst COMPACT_TIPS = [\n \"Shift+Tab cycles permission modes (default / acceptEdits / plan / bypass)\",\n \"/mode plan drafts changes without executing them\",\n \"/cost shows token usage and estimated spend\",\n \"/resume picks up a previous session in this directory\",\n \"muse --continue resumes the last session on startup\",\n \"MemoryWrite saves persistent knowledge across sessions\",\n \"TodoWrite keeps the model honest on multi-step tasks\",\n \"Pipe to muse: cat bug.log | muse \\\"explain this\\\"\",\n \"Ctrl+C exits immediately; Esc rejects a pending tool\",\n];\n\n// 经验值:muse-design §5.3 提的 200-400 词摘要约 1.2-1.8k 字符\nconst COMPACT_ESTIMATED_CHARS = 1800;\n\nconst COMPACT: SlashCommand = {\n name: \"compact\",\n description: \"summarize older messages to free up context space\",\n argsHint: \"[--keep N]\",\n async execute(ctx) {\n if (ctx.history.length === 0) return { display: \"(empty history; nothing to compact)\" };\n const { flags } = parseArgs(ctx.args);\n const keepRecent = typeof flags.keep === \"string\" ? Math.max(1, parseInt(flags.keep, 10)) : 4;\n if (Number.isNaN(keepRecent)) return { display: `Invalid --keep value: ${flags.keep}` };\n\n // ProgressBanner 每 tick 调 getPercent;用闭包持有的 ref 让 banner 看到最新值\n const progressRef = { chars: 0 };\n ctx.actions.showProgress({\n title: \"Compacting conversation\",\n tips: COMPACT_TIPS,\n getPercent: () => (progressRef.chars / COMPACT_ESTIMATED_CHARS) * 100,\n });\n\n try {\n const result = await compactMessages(ctx.history, {\n llm: ctx.llm,\n keepRecent,\n onProgress: (chars) => {\n progressRef.chars = chars;\n },\n });\n if (result.noop) {\n return { display: `(history has ${result.originalCount} messages; not enough to compact with --keep ${keepRecent})` };\n }\n ctx.actions.setMessages(result.newMessages);\n const preview = result.summary.length > 240 ? result.summary.slice(0, 240) + \"…\" : result.summary;\n return {\n display:\n `Compacted ${result.originalCount} → ${result.newCount} messages ` +\n `(kept last ${keepRecent}).\\n\\nSummary:\\n${preview}`,\n };\n } finally {\n ctx.actions.hideProgress();\n }\n },\n};\n\n// ----- /models -----\n\nconst MODELS: SlashCommand = {\n name: \"models\",\n description: \"pick a model from ~/.muse/models.local.json (↑↓ to navigate)\",\n async execute(ctx) {\n // ctx 没拿到 registry 时同步重读一次:可能 muse 启动后用户改了文件\n let registry = ctx.modelsRegistry;\n let errors: LoadError[] = [];\n if (!registry) {\n const r = await loadModelsRegistry();\n registry = r.registry;\n errors = r.errors;\n }\n\n if (!registry) {\n if (errors.length > 0) {\n return { display: renderLoadErrors(errors) };\n }\n return { display: renderEmptyRegistryHint() };\n }\n\n const visible = visibleEntries(registry);\n if (visible.length === 0) {\n return {\n display:\n `models.local.json has no available models.\\n` +\n `Check that \"availableModels\" lists at least one id present in \"models\".`,\n };\n }\n\n const picked = await ctx.actions.pickModel(visible, ctx.llm.model);\n if (!picked) return { display: \"(cancelled)\" };\n if (picked.id === ctx.llm.model) return { display: `Already on ${picked.id}.` };\n\n try {\n await ctx.actions.switchModel(picked.id);\n return { display: `Switched to ${picked.id}${picked.vendor ? ` (${picked.vendor})` : \"\"}.` };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { display: `Failed to switch: ${msg}` };\n }\n },\n};\n\nfunction renderLoadErrors(errors: LoadError[]): string {\n return [\n `models.local.json was found but failed to load:`,\n ``,\n ...errors.flatMap((e) => [` ${shortPath(e.path)}`, ` ${e.message}`]),\n ``,\n `Fix the file above, then run /models again (it re-reads on each call).`,\n `Hint: each entry needs \"id\" and \"baseUrl\" (or \"url\"); \"apiKey\" supports \\${ENV_VAR}.`,\n ].join(\"\\n\");\n}\n\nfunction renderEmptyRegistryHint(): string {\n return [\n `No models registry found.`,\n `Create ~/.muse/models.local.json with a \"models\" array. Example:`,\n ``,\n `{`,\n ` \"models\": [`,\n ` {`,\n ` \"id\": \"<your-model-id>\",`,\n ` \"vendor\": \"<vendor-name>\",`,\n ` \"baseUrl\": \"https://...\",`,\n ` \"apiKey\": \"\\${YOUR_API_KEY}\",`,\n ` \"supportsToolCall\": true`,\n ` }`,\n ` ],`,\n ` \"availableModels\": [\"<your-model-id>\"]`,\n `}`,\n ``,\n `Then run /models again (no restart needed).`,\n ].join(\"\\n\");\n}\n\n// ----- /config -----\n\nconst CONFIG: SlashCommand = {\n name: \"config\",\n description: \"show / reload configuration (API keys redacted)\",\n argsHint: \"[reload | path]\",\n async execute(ctx) {\n const sub = ctx.args.trim();\n\n if (sub === \"reload\") {\n try {\n const { sources } = await ctx.actions.reloadSettings();\n return { display: `Reloaded from ${sources.length} sources:\\n` + sources.map((s) => ` - ${shortPath(s)}`).join(\"\\n\") };\n } catch (err) {\n return { display: `Reload failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n }\n\n if (sub === \"path\") {\n return { display: renderConfigPaths(ctx) };\n }\n\n if (sub && sub !== \"show\") {\n return { display: `Unknown subcommand: /config ${sub}. Use: /config [show|reload|path]` };\n }\n\n return { display: renderConfigShow(ctx) };\n },\n};\n\nfunction renderConfigShow(ctx: SlashCommandContext): string {\n const s = ctx.settings;\n const lines = [\n `Effective configuration`,\n ` sources:`,\n ...ctx.settingsSources.map((src) => ` - ${shortPath(src)}`),\n ``,\n ` llm:`,\n ` provider: ${s.llm?.provider ?? \"(unset)\"}`,\n ` model: ${s.llm?.model ?? \"(unset)\"}`,\n ];\n if (s.llm?.temperature !== undefined) lines.push(` temperature: ${s.llm.temperature}`);\n if (s.llm?.maxTokens !== undefined) lines.push(` maxTokens: ${s.llm.maxTokens}`);\n\n lines.push(``, ` providers (apiKey redacted):`);\n for (const [name, cfg] of Object.entries(s.providers ?? {})) {\n lines.push(` ${name}: apiKey=${redactApiKey(cfg.apiKey)} baseUrl=${cfg.baseUrl ?? \"(default)\"}`);\n }\n\n lines.push(``, ` permissions:`);\n lines.push(` defaultMode: ${s.permissions?.defaultMode ?? \"ask\"}`);\n lines.push(` allow: ${formatList(s.permissions?.allow)}`);\n lines.push(` ask: ${formatList(s.permissions?.ask)}`);\n lines.push(` deny: ${formatList(s.permissions?.deny)}`);\n\n lines.push(``, ` ui:`);\n lines.push(` lang: ${s.ui?.lang ?? \"(default)\"}`);\n lines.push(` showBanner: ${s.ui?.showBanner ?? true}`);\n\n return lines.join(\"\\n\");\n}\n\nfunction renderConfigPaths(ctx: SlashCommandContext): string {\n const home = process.env.HOME ?? \"~\";\n return [\n `Configuration file paths (high to low precedence):`,\n ` 1. CLI flags / env (MUSE_PROVIDER, MUSE_MODEL, …)`,\n ` 2. ${shortPath(`${ctx.cwd}/.muse/settings.local.json`)} (project, gitignored)`,\n ` 3. ${shortPath(`${ctx.cwd}/.muse/settings.json`)} (project, committable)`,\n ` 4. ${shortPath(`${home}/.muse/settings.json`)} (global)`,\n ` 5. <built-in defaults>`,\n ``,\n `Edit any of the above, then run /config reload (no restart needed).`,\n ].join(\"\\n\");\n}\n\n// ----- /mcp -----\n\nconst MCP: SlashCommand = {\n name: \"mcp\",\n description: \"show MCP server status\",\n execute(ctx) {\n const status = getMCPStatus(ctx.settings);\n if (status.length === 0) {\n return {\n display:\n `No MCP servers configured.\\n` +\n `Add servers under \"mcpServers\" in your settings.json.\\n` +\n `Note: MCP client integration is planned for v0.3; current /mcp only inspects configuration.`,\n };\n }\n const lines = [`MCP servers (${status.length}):`];\n for (const s of status) {\n const indicator = s.connected ? \"●\" : \"○\";\n lines.push(` ${indicator} ${s.name}`);\n lines.push(` configured: ${s.configured}`);\n lines.push(` connected: ${s.connected}${s.error ? ` (${s.error})` : \"\"}`);\n if (s.connected) lines.push(` tools: ${s.toolCount}`);\n if (s.config?.command) lines.push(` command: ${s.config.command}${s.config.args ? \" \" + s.config.args.join(\" \") : \"\"}`);\n if (s.config?.url) lines.push(` url: ${s.config.url}`);\n }\n return { display: lines.join(\"\\n\") };\n },\n};\n\n// ----- /resume -----\n\nconst RESUME: SlashCommand = {\n name: \"resume\",\n description: \"resume a past session (↑↓ to pick, or pass an id-prefix)\",\n argsHint: \"[session-id-prefix]\",\n async execute(ctx) {\n // 带参快捷路径:直接按 id 前缀加载,不弹 selector\n if (ctx.args) {\n let meta;\n try {\n meta = await Session.resolve(ctx.cwd, ctx.args);\n } catch (err) {\n return { display: err instanceof Error ? err.message : String(err) };\n }\n if (!meta) return { display: `No session matches \"${ctx.args}\".` };\n return loadAndReport(meta, ctx);\n }\n\n // 无参:列出近 20 条交给 selector\n const list = await Session.listAll(ctx.cwd, 20);\n if (list.length === 0) return { display: \"No past sessions in this directory.\" };\n\n const picked = await ctx.actions.pickSession(list, ctx.session.meta.id);\n if (!picked) return { display: \"(cancelled)\" };\n if (picked.id === ctx.session.meta.id) return { display: \"Already on this session.\" };\n\n return loadAndReport(picked, ctx);\n },\n};\n\nasync function loadAndReport(\n meta: { id: string; createdAt: string; path: string; cwd: string },\n ctx: import(\"./types.js\").SlashCommandContext,\n): Promise<{ display: string }> {\n const { events } = await Session.open(meta);\n const messages = Session.messagesFromEvents(events);\n ctx.actions.setMessages(messages);\n return {\n display: `Resumed session ${meta.id.slice(0, 8)} (${messages.length} messages from ${formatTime(meta.createdAt)}).`,\n };\n}\n\n// ----- /mode -----\n\nconst MODE_ALIASES: Record<string, PermissionMode> = {\n default: \"default\",\n normal: \"default\",\n acceptedits: \"acceptEdits\",\n \"accept-edits\": \"acceptEdits\",\n accept: \"acceptEdits\",\n edits: \"acceptEdits\",\n plan: \"plan\",\n bypass: \"bypassPermissions\",\n bypasspermissions: \"bypassPermissions\",\n};\n\nconst MODE_CMD: SlashCommand = {\n name: \"mode\",\n description: \"show or switch the permission mode (alternative to Shift+Tab)\",\n argsHint: \"[default|acceptEdits|plan|bypassPermissions]\",\n execute(ctx) {\n const arg = ctx.args.trim().toLowerCase();\n if (!arg) {\n const cur = ctx.actions.getMode();\n const lines = [`Current permission mode: ${cur} — ${MODE_LABEL[cur]}`, ``, `Available modes:`];\n for (const m of MODE_CYCLE) {\n const marker = m === cur ? \"●\" : \" \";\n lines.push(` ${marker} ${m.padEnd(20)} ${MODE_LABEL[m]}`);\n }\n lines.push(``, `Switch: /mode <name> or Shift+Tab to cycle`);\n return { display: lines.join(\"\\n\") };\n }\n const target = MODE_ALIASES[arg];\n if (!target) {\n return {\n display: `Unknown mode \"${ctx.args.trim()}\". Valid: ${MODE_CYCLE.join(\" | \")}`,\n };\n }\n if (target === ctx.actions.getMode()) return { display: `Already in ${target} mode.` };\n ctx.actions.setMode(target);\n return { display: `Switched to ${target} — ${MODE_LABEL[target]}` };\n },\n};\n\n// ----- registry -----\n\nexport const BUILTIN_SLASH_COMMANDS: SlashCommand[] = [\n HELP,\n CLEAR,\n COMPACT,\n MODELS,\n CONFIG,\n MCP,\n MODE_CMD,\n COST,\n RESUME,\n QUIT,\n];\n","/**\n * 工具注册中心:管理所有可用工具,提供查询、调用、转 LLM-tool-definition 的能力。\n */\n\nimport { z } from \"zod\";\nimport type { AnyTool, ToolContext, ToolExecuteResult } from \"./types.js\";\nimport type { ToolDefinition as LLMToolDefinition } from \"../types/index.js\";\nimport { ToolError } from \"../types/index.js\";\n\n/** zod schema → JSON Schema (subset)。仅覆盖 v0.1 需要的类型。 */\nfunction zodToJsonSchema(schema: z.ZodType<unknown>): Record<string, unknown> {\n const def = (schema as unknown as { _def: { typeName: string } })._def;\n\n if (def.typeName === \"ZodObject\") {\n const shape = (schema as unknown as z.ZodObject<Record<string, z.ZodTypeAny>>).shape;\n const properties: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as z.ZodType<unknown>);\n if (!(value as unknown as { isOptional?: () => boolean }).isOptional?.()) {\n required.push(key);\n }\n }\n return {\n type: \"object\",\n properties,\n ...(required.length > 0 ? { required } : {}),\n additionalProperties: false,\n };\n }\n\n if (def.typeName === \"ZodString\") {\n const d = def as unknown as { description?: string };\n return { type: \"string\", ...(d.description ? { description: d.description } : {}) };\n }\n\n if (def.typeName === \"ZodNumber\") {\n return { type: \"number\" };\n }\n\n if (def.typeName === \"ZodBoolean\") {\n return { type: \"boolean\" };\n }\n\n if (def.typeName === \"ZodArray\") {\n const inner = (def as unknown as { type: z.ZodType<unknown> }).type;\n return { type: \"array\", items: zodToJsonSchema(inner) };\n }\n\n if (def.typeName === \"ZodOptional\" || def.typeName === \"ZodDefault\") {\n const inner = (def as unknown as { innerType: z.ZodType<unknown> }).innerType;\n return zodToJsonSchema(inner);\n }\n\n if (def.typeName === \"ZodEnum\") {\n const values = (def as unknown as { values: string[] }).values;\n return { type: \"string\", enum: values };\n }\n\n if (def.typeName === \"ZodUnion\") {\n const opts = (def as unknown as { options: z.ZodType<unknown>[] }).options;\n return { anyOf: opts.map(zodToJsonSchema) };\n }\n\n // Fallback: 任意类型\n return {};\n}\n\nfunction getDescription(schema: z.ZodType<unknown>): string | undefined {\n return (schema as unknown as { description?: string }).description;\n}\n\nexport class ToolRegistry {\n private tools = new Map<string, AnyTool>();\n\n register(tool: AnyTool): void {\n if (this.tools.has(tool.name)) {\n throw new Error(`Tool \"${tool.name}\" already registered.`);\n }\n this.tools.set(tool.name, tool);\n }\n\n registerAll(tools: AnyTool[]): void {\n for (const tool of tools) this.register(tool);\n }\n\n get(name: string): AnyTool | undefined {\n return this.tools.get(name);\n }\n\n has(name: string): boolean {\n return this.tools.has(name);\n }\n\n list(): AnyTool[] {\n return Array.from(this.tools.values());\n }\n\n /** 转为 LLM 可读的 tool definition 数组。可选 filter(如 plan 模式过滤只读工具)。 */\n toLLMDefinitions(filter?: (tool: AnyTool) => boolean): LLMToolDefinition[] {\n let tools = this.list();\n if (filter) tools = tools.filter(filter);\n return tools.map((t) => {\n const schema = zodToJsonSchema(t.parameters);\n // 顶层描述:从 zod schema 的 .describe 拿\n const desc = getDescription(t.parameters);\n if (desc && typeof schema === \"object\" && schema !== null) {\n (schema as Record<string, unknown>).description = desc;\n }\n return {\n name: t.name,\n description: t.description,\n parameters: schema,\n };\n });\n }\n\n /** 调用工具:校验参数 → 执行。 */\n async execute(name: string, rawArgs: unknown, ctx: ToolContext): Promise<ToolExecuteResult> {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new ToolError(`Tool \"${name}\" not found.`, name);\n }\n const parseResult = tool.parameters.safeParse(rawArgs);\n if (!parseResult.success) {\n return {\n content: `Invalid arguments for ${name}: ${parseResult.error.message}`,\n isError: true,\n };\n }\n try {\n return await tool.execute(parseResult.data, ctx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { content: `Tool ${name} threw: ${msg}`, isError: true };\n }\n }\n}\n","/**\n * Read 工具:读取本地文件,支持 offset/limit 分页。\n * 返回带行号的 `cat -n` 格式,方便 LLM 引用具体行做编辑。\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { resolve, isAbsolute } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { ToolError } from \"../../types/index.js\";\nimport { checkSensitivePath } from \"../_sensitive.js\";\n\nconst ReadArgs = z.object({\n file_path: z.string().describe(\"Absolute or cwd-relative path to the file.\"),\n offset: z.number().int().min(0).optional().describe(\"Line offset (0-based).\"),\n limit: z.number().int().positive().optional().describe(\"Max lines to read. Default 2000.\"),\n});\n\nconst DEFAULT_LIMIT = 2000;\nconst MAX_LINE_LENGTH = 2000; // 单行超长时截断\n\nexport const ReadTool = defineTool({\n name: \"Read\",\n description: \"Read a file from the local filesystem. Returns content with 1-indexed line numbers (cat -n format). Use offset/limit for large files.\",\n parameters: ReadArgs,\n permission: \"read\",\n summarize: (args) => `Read(${args.file_path}${args.offset != null ? `, offset=${args.offset}` : \"\"}${args.limit != null ? `, limit=${args.limit}` : \"\"})`,\n async execute(args, ctx) {\n const path = isAbsolute(args.file_path) ? args.file_path : resolve(ctx.cwd, args.file_path);\n\n const sensitive = checkSensitivePath(path);\n if (sensitive.blocked) {\n return { content: `Refused: ${path} matches sensitive path policy (${sensitive.reason}).`, isError: true };\n }\n\n let info;\n try {\n info = await stat(path);\n } catch (err) {\n throw new ToolError(`File not found: ${path}`, \"Read\", err);\n }\n\n if (!info.isFile()) {\n throw new ToolError(`Not a regular file: ${path}`, \"Read\");\n }\n\n const content = await readFile(path, \"utf-8\");\n const lines = content.split(/\\r?\\n/);\n const offset = args.offset ?? 0;\n const limit = args.limit ?? DEFAULT_LIMIT;\n const slice = lines.slice(offset, offset + limit);\n\n const numbered = slice.map((line, i) => {\n const lineNo = offset + i + 1;\n const truncated = line.length > MAX_LINE_LENGTH ? line.slice(0, MAX_LINE_LENGTH) + \"... [truncated]\" : line;\n return `${String(lineNo).padStart(5, \" \")}\\t${truncated}`;\n });\n\n let result = numbered.join(\"\\n\");\n if (offset + limit < lines.length) {\n result += `\\n... [${lines.length - offset - limit} more lines, use offset=${offset + limit} to read next]`;\n }\n\n return {\n content: result || \"(empty file)\",\n summary: `Read ${slice.length} lines from ${args.file_path}`,\n };\n },\n});\n","/**\n * 工具系统类型。\n * 内置工具与 MCP 工具都遵循同一接口。\n */\n\nimport type { z } from \"zod\";\nimport type { TodoStore } from \"../loop/todos.js\";\nimport type { AskQuestion, AskQuestionResponse } from \"./builtin/ask-user-question.js\";\n\nexport type PermissionLevel = \"read\" | \"write\" | \"execute\" | \"network\";\n\nexport interface ToolContext {\n cwd: string;\n abortSignal?: AbortSignal;\n /** 询问用户对该工具调用的批准。返回 true=允许,false=拒绝。 */\n askPermission: (toolName: string, args: unknown, summary: string) => Promise<boolean>;\n /** 主代理可能想在工具内部发起子任务,预留口子。 */\n invokeSubagent?: (prompt: string) => Promise<string>;\n /** Session 内 todo 清单(TodoWrite 写入;system prompt 读取注入下一轮)。 */\n todos?: TodoStore;\n /**\n * AskUserQuestion 工具用:一次性弹出整批选择题(链式 tab UI)。\n * 返回数组与入参 questions 等长;Esc 取消时所有项 cancelled=true。\n */\n askQuestions?: (questions: AskQuestion[]) => Promise<AskQuestionResponse[]>;\n}\n\nexport interface ToolExecuteResult {\n /** 给 LLM 看的文本结果。 */\n content: string;\n /** 标记为错误:让 LLM 知道需要修复。 */\n isError?: boolean;\n /** 给 TUI 展示的摘要(一行)。 */\n summary?: string;\n /** Unified diff(Write/Edit 等改文件工具填),交给 UI 渲染绿/红行;不进 LLM 上下文。 */\n diff?: string;\n /** 状态点颜色(仅 UI):success 绿 / error 红 / warn 黄。不填则由 isError 推断。 */\n kind?: \"success\" | \"error\" | \"warn\";\n}\n\nexport interface ToolDefinition<TArgs = unknown> {\n name: string;\n description: string;\n /** zod schema 用于参数校验 + 自动转 JSON Schema。 */\n parameters: z.ZodType<TArgs>;\n /** 权限级别:UI 与 permission 模块据此决定 ask/allow/deny。 */\n permission: PermissionLevel;\n /** 一行摘要,给 TUI 在 \"→ ToolName(...)\" 之后显示。 */\n summarize?: (args: TArgs) => string;\n /** 实际执行函数。 */\n execute: (args: TArgs, ctx: ToolContext) => Promise<ToolExecuteResult>;\n}\n\n/** 类型擦除后的工具,用于 registry 存储 / 调用。 */\nexport interface AnyTool {\n name: string;\n description: string;\n parameters: z.ZodType<unknown>;\n permission: PermissionLevel;\n summarize?: (args: unknown) => string;\n execute: (args: unknown, ctx: ToolContext) => Promise<ToolExecuteResult>;\n}\n\nexport function defineTool<TArgs>(def: ToolDefinition<TArgs>): AnyTool {\n return {\n name: def.name,\n description: def.description,\n parameters: def.parameters as z.ZodType<unknown>,\n permission: def.permission,\n summarize: def.summarize as ((args: unknown) => string) | undefined,\n execute: def.execute as (args: unknown, ctx: ToolContext) => Promise<ToolExecuteResult>,\n };\n}\n","/**\n * 敏感文件路径默认 deny。设计文档 §12.3。\n *\n * 工具层做硬拦截(不通过 PermissionGate)。即使 settings.permissions.allow 加了 Read/Write,\n * 这层也兜底;用户要绕过必须在 PermissionGate 之外显式同意(v1.0 才考虑)。\n *\n * 规则:\n * - ~/.ssh (SSH 私钥 / known_hosts)\n * - ~/.aws (AWS 凭证)\n * - ~/.gnupg (GPG 私钥)\n * - ~/.kube/config (集群 token)\n * - .env / .env.* (任何位置的环境文件)\n * - id_rsa / id_ed25519 等私钥文件名\n */\n\nimport { homedir } from \"node:os\";\nimport { basename, resolve } from \"node:path\";\n\nconst HOME = homedir();\nconst SENSITIVE_DIRS = [\n resolve(HOME, \".ssh\"),\n resolve(HOME, \".aws\"),\n resolve(HOME, \".gnupg\"),\n resolve(HOME, \".config\", \"gh\"),\n];\nconst SENSITIVE_FILES = [\n resolve(HOME, \".kube\", \"config\"),\n resolve(HOME, \".netrc\"),\n resolve(HOME, \".pypirc\"),\n];\nconst SENSITIVE_BASENAMES = new Set([\n \"id_rsa\",\n \"id_ed25519\",\n \"id_ecdsa\",\n \"id_dsa\",\n]);\nconst ENV_PATTERN = /(?:^|\\/)\\.env(\\..+)?$/;\n\nexport interface SensitiveCheck {\n blocked: boolean;\n reason?: string;\n}\n\nexport function checkSensitivePath(path: string): SensitiveCheck {\n const abs = resolve(path);\n for (const dir of SENSITIVE_DIRS) {\n if (abs === dir || abs.startsWith(dir + \"/\")) {\n return { blocked: true, reason: `sensitive directory ${dir.replace(HOME, \"~\")}` };\n }\n }\n for (const f of SENSITIVE_FILES) {\n if (abs === f) return { blocked: true, reason: `sensitive file ${f.replace(HOME, \"~\")}` };\n }\n const base = basename(abs);\n if (SENSITIVE_BASENAMES.has(base)) {\n return { blocked: true, reason: `private key filename ${base}` };\n }\n if (ENV_PATTERN.test(abs)) {\n return { blocked: true, reason: `.env file (may contain secrets)` };\n }\n return { blocked: false };\n}\n","/**\n * Write 工具:写入文件(创建或覆盖)。\n *\n * 为防误覆盖,约定调用前必须先 Read 过同一路径(除非文件不存在)。\n * 这个约束实际由 LLM 遵守 (prompt 引导);本工具不强制,但记录到日志。\n */\n\nimport { readFile, writeFile, mkdir, stat } from \"node:fs/promises\";\nimport { resolve, isAbsolute, dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { makeUnifiedDiff } from \"../_diff.js\";\nimport { checkSensitivePath } from \"../_sensitive.js\";\n\nconst WriteArgs = z.object({\n file_path: z.string().describe(\"Absolute or cwd-relative path to the file.\"),\n content: z.string().describe(\"Full content of the file.\"),\n});\n\nexport const WriteTool = defineTool({\n name: \"Write\",\n description: \"Write a complete file to the local filesystem. Creates parent directories if needed. Overwrites existing files — prefer Edit for partial updates.\",\n parameters: WriteArgs,\n permission: \"write\",\n summarize: (args) => `Write(${args.file_path}, ${args.content.length} chars)`,\n async execute(args, ctx) {\n const path = isAbsolute(args.file_path) ? args.file_path : resolve(ctx.cwd, args.file_path);\n\n const sensitive = checkSensitivePath(path);\n if (sensitive.blocked) {\n return { content: `Refused: ${path} matches sensitive path policy (${sensitive.reason}).`, isError: true };\n }\n\n let existed = false;\n let oldContent = \"\";\n try {\n const info = await stat(path);\n existed = info.isFile();\n if (existed) oldContent = await readFile(path, \"utf-8\");\n } catch {\n // 文件不存在,正常情况\n }\n\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, args.content, \"utf-8\");\n\n const diff = makeUnifiedDiff(args.file_path, oldContent, args.content);\n\n return {\n content: existed\n ? `Overwrote ${path} (${args.content.length} bytes).`\n : `Created ${path} (${args.content.length} bytes).`,\n summary: `${existed ? \"Overwrote\" : \"Created\"} ${args.file_path}`,\n diff: diff || undefined,\n };\n },\n});\n","/**\n * 文件改动 → unified diff(jsdiff),仅给 UI 渲染用,不进 LLM 上下文。\n *\n * 上下文行数 3(GNU diff 默认);新文件 / 整体覆盖时呈现为全 + 行。\n */\n\nimport { createPatch } from \"diff\";\n\nconst MAX_DIFF_LINES = 200;\n\nexport function makeUnifiedDiff(filePath: string, oldContent: string, newContent: string): string {\n if (oldContent === newContent) return \"\";\n const patch = createPatch(filePath, oldContent, newContent, \"before\", \"after\", { context: 3 });\n return truncate(patch);\n}\n\nfunction truncate(diff: string): string {\n const lines = diff.split(\"\\n\");\n if (lines.length <= MAX_DIFF_LINES) return diff;\n return lines.slice(0, MAX_DIFF_LINES).join(\"\\n\") + `\\n... [${lines.length - MAX_DIFF_LINES} more diff lines truncated]`;\n}\n","/**\n * Edit 工具:在文件中做精确字符串替换。\n *\n * 必须先 Read 过文件(由调用方/LLM 遵守,不强制校验)。\n * old_string 必须在文件中唯一出现;replace_all=true 时不要求唯一。\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve, isAbsolute } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { ToolError } from \"../../types/index.js\";\nimport { makeUnifiedDiff } from \"../_diff.js\";\nimport { checkSensitivePath } from \"../_sensitive.js\";\n\nconst EditArgs = z.object({\n file_path: z.string().describe(\"Absolute or cwd-relative path to the file.\"),\n old_string: z.string().describe(\"Exact substring to replace. Must be unique unless replace_all=true.\"),\n new_string: z.string().describe(\"Replacement string.\"),\n replace_all: z.boolean().optional().describe(\"Replace every occurrence. Default false.\"),\n});\n\nexport const EditTool = defineTool({\n name: \"Edit\",\n description: \"Perform an exact string replacement in a file. Old string must be unique unless replace_all=true. Cheaper than Write when only a small part needs to change.\",\n parameters: EditArgs,\n permission: \"write\",\n summarize: (args) => `Edit(${args.file_path})`,\n async execute(args, ctx) {\n const path = isAbsolute(args.file_path) ? args.file_path : resolve(ctx.cwd, args.file_path);\n\n const sensitive = checkSensitivePath(path);\n if (sensitive.blocked) {\n return { content: `Refused: ${path} matches sensitive path policy (${sensitive.reason}).`, isError: true };\n }\n\n let content: string;\n try {\n content = await readFile(path, \"utf-8\");\n } catch (err) {\n throw new ToolError(`Cannot read ${path}: ${err instanceof Error ? err.message : String(err)}`, \"Edit\", err);\n }\n\n if (args.old_string === args.new_string) {\n return { content: \"old_string is identical to new_string; nothing to do.\", isError: true };\n }\n\n const occurrences = countOccurrences(content, args.old_string);\n if (occurrences === 0) {\n return {\n content: `old_string not found in ${args.file_path}. Did you read the file first? Check whitespace and indentation.`,\n isError: true,\n };\n }\n if (occurrences > 1 && !args.replace_all) {\n return {\n content: `old_string occurs ${occurrences} times in ${args.file_path}. Either expand context to make it unique, or set replace_all=true.`,\n isError: true,\n };\n }\n\n const newContent = args.replace_all\n ? content.split(args.old_string).join(args.new_string)\n : content.replace(args.old_string, args.new_string);\n\n await writeFile(path, newContent, \"utf-8\");\n\n const diff = makeUnifiedDiff(args.file_path, content, newContent);\n\n return {\n content: `Edited ${path}: replaced ${args.replace_all ? occurrences : 1} occurrence(s).`,\n summary: `Edited ${args.file_path}`,\n diff: diff || undefined,\n };\n },\n});\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n let count = 0;\n let pos = 0;\n while ((pos = haystack.indexOf(needle, pos)) !== -1) {\n count += 1;\n pos += needle.length;\n }\n return count;\n}\n","/**\n * Bash 工具:执行 shell 命令。\n *\n * 安全:内置 deny 列表(无法 allow 绕过)。\n * 上限:超时 + stdout 截断。\n */\n\nimport { execa } from \"execa\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst BashArgs = z.object({\n command: z.string().describe(\"Shell command to run. Will be executed via sh -c.\"),\n timeout: z.number().int().positive().optional().describe(\"Timeout in milliseconds. Default 120000 (2 min). Max 600000.\"),\n description: z.string().optional().describe(\"Brief description (3-10 words) for the UI.\"),\n});\n\nconst DEFAULT_TIMEOUT_MS = 120_000;\nconst MAX_TIMEOUT_MS = 600_000;\nconst MAX_OUTPUT_BYTES = 100_000;\n\n/** 即使在 allow 列表里也强制阻断的危险命令模式。 */\nconst HARD_DENY_PATTERNS: RegExp[] = [\n /\\brm\\s+-rf\\s+\\/(?:\\s|$)/, // rm -rf /\n /\\brm\\s+-rf\\s+~(?:\\/|\\s|$)/, // rm -rf ~ or ~/...\n /\\brm\\s+-rf\\s+\\*/, // rm -rf *\n /\\bdd\\s+.*of=\\/dev\\//, // dd of=/dev/*\n /\\bmkfs\\b/, // mkfs\n /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\}\\s*;\\s*:/, // fork bomb\n /\\bsudo\\b/, // sudo(v0.1 简单粗暴禁掉)\n /\\bcurl\\s+[^|]*\\|\\s*(?:sh|bash|zsh)/, // curl ... | sh\n /\\bwget\\s+[^|]*\\|\\s*(?:sh|bash|zsh)/, // wget ... | sh\n];\n\nfunction checkDangerous(command: string): { dangerous: true; reason: string } | { dangerous: false } {\n for (const pattern of HARD_DENY_PATTERNS) {\n if (pattern.test(command)) {\n return { dangerous: true, reason: `matches pattern ${pattern}` };\n }\n }\n return { dangerous: false };\n}\n\nexport const BashTool = defineTool({\n name: \"Bash\",\n description: \"Execute a shell command via sh -c. Use for git, file system listings, builds, tests, etc. Avoid interactive commands (prefer non-interactive flags). For file edits use Edit/Write, not sed/echo.\",\n parameters: BashArgs,\n permission: \"execute\",\n summarize: (args) => args.description ?? `Bash: ${args.command.length > 60 ? args.command.slice(0, 60) + \"...\" : args.command}`,\n async execute(args, ctx) {\n const danger = checkDangerous(args.command);\n if (danger.dangerous) {\n return {\n content: `Refused: command blocked by hard deny list (${danger.reason}). If you really need this, ask the user to run it manually.`,\n isError: true,\n };\n }\n\n const timeout = Math.min(args.timeout ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n try {\n const result = await execa(args.command, {\n shell: \"/bin/sh\",\n cwd: ctx.cwd,\n timeout,\n reject: false,\n stripFinalNewline: false,\n maxBuffer: MAX_OUTPUT_BYTES * 2,\n cancelSignal: ctx.abortSignal,\n });\n\n const stdout = truncate(result.stdout ?? \"\", MAX_OUTPUT_BYTES, \"stdout\");\n const stderr = truncate(result.stderr ?? \"\", MAX_OUTPUT_BYTES, \"stderr\");\n\n const parts: string[] = [];\n if (stdout) parts.push(`<stdout>\\n${stdout}\\n</stdout>`);\n if (stderr) parts.push(`<stderr>\\n${stderr}\\n</stderr>`);\n if (result.timedOut) parts.push(`<timeout>Command exceeded ${timeout}ms.</timeout>`);\n if (result.failed && !result.timedOut) parts.push(`<exit_code>${result.exitCode ?? \"unknown\"}</exit_code>`);\n\n const body = parts.length > 0 ? parts.join(\"\\n\") : \"(no output)\";\n return {\n content: body,\n isError: result.failed,\n summary: result.failed ? `Bash exited ${result.exitCode ?? \"?\"}` : `Bash ok`,\n };\n } catch (err) {\n return {\n content: `Bash threw: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n },\n});\n\nfunction truncate(text: string, max: number, label: string): string {\n if (text.length <= max) return text;\n return text.slice(0, max) + `\\n... [${label} truncated, original ${text.length} bytes]`;\n}\n","/**\n * Grep 工具:基于 ripgrep 包装(若可用),fallback 到 bash grep。\n * v0.1 简单实现:直接调 system rg / grep。\n */\n\nimport { execa } from \"execa\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst GrepArgs = z.object({\n pattern: z.string().describe(\"Regex pattern to search for.\"),\n path: z.string().optional().describe(\"File or directory to search in. Default: cwd.\"),\n glob: z.string().optional().describe('Glob filter, e.g. \"*.ts\" or \"src/**/*.tsx\".'),\n output_mode: z.enum([\"content\", \"files_with_matches\", \"count\"]).optional().describe(\"Default: files_with_matches.\"),\n context: z.number().int().min(0).max(50).optional().describe(\"Context lines around each match (use only with output_mode=content).\"),\n case_insensitive: z.boolean().optional(),\n});\n\nlet rgChecked = false;\nlet rgAvailable = false;\n\nasync function checkRipgrep(): Promise<boolean> {\n if (rgChecked) return rgAvailable;\n try {\n await execa(\"rg\", [\"--version\"], { reject: false });\n rgAvailable = true;\n } catch {\n rgAvailable = false;\n }\n rgChecked = true;\n return rgAvailable;\n}\n\nexport const GrepTool = defineTool({\n name: \"Grep\",\n description: \"Search file contents using regex. Prefer this over Bash(grep|find) — handles ignore files & is much faster on large trees.\",\n parameters: GrepArgs,\n permission: \"read\",\n summarize: (args) => `Grep(${args.pattern}${args.path ? `, ${args.path}` : \"\"})`,\n async execute(args, ctx) {\n const hasRg = await checkRipgrep();\n const mode = args.output_mode ?? \"files_with_matches\";\n\n if (hasRg) {\n const cliArgs: string[] = [];\n if (args.case_insensitive) cliArgs.push(\"-i\");\n if (mode === \"files_with_matches\") cliArgs.push(\"-l\");\n else if (mode === \"count\") cliArgs.push(\"-c\");\n else if (args.context != null) cliArgs.push(\"-C\", String(args.context));\n if (args.glob) cliArgs.push(\"--glob\", args.glob);\n cliArgs.push(\"--\", args.pattern, args.path ?? \".\");\n\n const result = await execa(\"rg\", cliArgs, { cwd: ctx.cwd, reject: false, cancelSignal: ctx.abortSignal });\n const out = (result.stdout ?? \"\").trim();\n if (result.exitCode === 0 || result.exitCode === 1) {\n return { content: out || \"(no matches)\", summary: `Grep ${args.pattern}` };\n }\n return { content: `rg failed: ${result.stderr}`, isError: true };\n }\n\n // Fallback: bash grep -r\n const cliArgs = [\"-r\", \"-n\"];\n if (args.case_insensitive) cliArgs.push(\"-i\");\n if (mode === \"files_with_matches\") cliArgs.push(\"-l\");\n else if (mode === \"count\") cliArgs.push(\"-c\");\n cliArgs.push(\"-E\", args.pattern, args.path ?? \".\");\n\n const result = await execa(\"grep\", cliArgs, { cwd: ctx.cwd, reject: false, cancelSignal: ctx.abortSignal });\n const out = (result.stdout ?? \"\").trim();\n if (result.exitCode === 0 || result.exitCode === 1) {\n return { content: out || \"(no matches)\", summary: `Grep ${args.pattern}` };\n }\n return { content: `grep failed: ${result.stderr}`, isError: true };\n },\n});\n","/**\n * Glob 工具:用 fast-glob 列出匹配文件。\n */\n\nimport fg from \"fast-glob\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst GlobArgs = z.object({\n pattern: z.string().describe('Glob pattern, e.g. \"src/**/*.ts\" or \"**/*.{md,json}\".'),\n path: z.string().optional().describe(\"Base directory to search from. Default: cwd.\"),\n limit: z.number().int().positive().max(1000).optional().describe(\"Max results. Default 100.\"),\n});\n\nconst DEFAULT_LIMIT = 100;\n\nexport const GlobTool = defineTool({\n name: \"Glob\",\n description: \"Find files by glob pattern. Returns relative paths sorted by modification time (newest first).\",\n parameters: GlobArgs,\n permission: \"read\",\n summarize: (args) => `Glob(${args.pattern}${args.path ? `, ${args.path}` : \"\"})`,\n async execute(args, ctx) {\n const cwd = args.path ?? ctx.cwd;\n const limit = args.limit ?? DEFAULT_LIMIT;\n\n const entries = await fg(args.pattern, {\n cwd,\n onlyFiles: true,\n stats: true,\n dot: false,\n ignore: [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\", \"**/.muse/**\"],\n });\n\n // 按 mtime 倒序\n entries.sort((a, b) => {\n const ta = a.stats?.mtime?.getTime() ?? 0;\n const tb = b.stats?.mtime?.getTime() ?? 0;\n return tb - ta;\n });\n\n const truncated = entries.length > limit;\n const paths = entries.slice(0, limit).map((e) => e.path);\n\n let result = paths.join(\"\\n\") || \"(no matches)\";\n if (truncated) {\n result += `\\n... [${entries.length - limit} more, increase limit to see]`;\n }\n return { content: result, summary: `Glob found ${entries.length} file(s)` };\n },\n});\n","/**\n * TodoWrite 工具:维护 session 内任务清单。\n *\n * 把完整 todos 数组替换进 ctx.todos。约定:一次只一个 in_progress;完成立即标 completed\n * 不要批;任务尽量原子。MessageView 会读 args.todos 渲染 checkbox 清单。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\";\n\nexport interface TodoItem {\n content: string;\n status: TodoStatus;\n activeForm?: string;\n}\n\nconst TodoSchema = z.object({\n content: z.string().describe(\"Imperative one-line task description (e.g. 'Run the test suite').\"),\n status: z.enum([\"pending\", \"in_progress\", \"completed\"]).describe(\"Current status.\"),\n activeForm: z.string().optional().describe(\"Present-continuous form for the spinner (e.g. 'Running the test suite').\"),\n});\n\nconst TodoWriteArgs = z.object({\n todos: z.array(TodoSchema).describe(\"Full list. Replaces the current store.\"),\n});\n\nexport const TodoWriteTool = defineTool({\n name: \"TodoWrite\",\n description:\n \"Maintain a structured task list for the current session. Pass the FULL list every call (it replaces the store). \" +\n \"Mark exactly one task in_progress at a time; mark completed immediately when done; do not batch completions. \" +\n \"Use when the task has 3+ distinct steps or is non-trivial. Skip for single trivial actions.\",\n parameters: TodoWriteArgs,\n permission: \"read\",\n summarize: (args) => `TodoWrite(${args.todos.length} items)`,\n async execute(args, ctx) {\n if (!ctx.todos) {\n return {\n content: \"TodoWrite is unavailable: this agent run has no todo store. (Internal bug; tell the user.)\",\n isError: true,\n };\n }\n ctx.todos.set(args.todos);\n const summary = args.todos\n .map((t, i) => `${i + 1}. ${t.status === \"completed\" ? \"[x]\" : t.status === \"in_progress\" ? \"[~]\" : \"[ ]\"} ${t.content}`)\n .join(\"\\n\");\n return {\n content: `Updated todos (${args.todos.length} items):\\n${summary}`,\n summary: `Todos: ${args.todos.filter((t) => t.status === \"completed\").length}/${args.todos.length} done`,\n };\n },\n});\n","/**\n * WebFetch 工具:抓 URL → 文本 / 简易 markdown。\n *\n * 安全:\n * - 拒绝本机回环 / 链接本地 / 私有网段(SSRF 防护)\n * - http → https 自动升级\n * - 30s 超时;最大 1MB 响应体\n *\n * 输出:以 HTML 解析时 strip 标签后近似 markdown;非 HTML 直接返回文本(截断)。\n *\n * 不引入 turndown:v0.1 用 minimal regex 转换,够 LLM 阅读;\n * 后续如需精细 markdown(保留 link / list 嵌套),再换专门库。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst WebFetchArgs = z.object({\n url: z.string().describe(\"Fully-qualified URL. http will be upgraded to https.\"),\n prompt: z\n .string()\n .optional()\n .describe(\n \"What information to look for. The host returns the page content; the LLM should then read it to answer the prompt.\",\n ),\n});\n\nconst MAX_RESPONSE_BYTES = 1_000_000;\nconst FETCH_TIMEOUT_MS = 30_000;\n\nconst PRIVATE_HOST_PATTERNS: RegExp[] = [\n /^localhost$/i,\n /^127\\./,\n /^0\\.0\\.0\\.0$/,\n /^169\\.254\\./,\n /^10\\./,\n /^192\\.168\\./,\n /^172\\.(1[6-9]|2[0-9]|3[0-1])\\./,\n /^::1$/,\n /^fc[0-9a-f]{2}:/i,\n /^fe80:/i,\n];\n\nfunction isPrivateHost(hostname: string): boolean {\n return PRIVATE_HOST_PATTERNS.some((p) => p.test(hostname));\n}\n\nexport const WebFetchTool = defineTool({\n name: \"WebFetch\",\n description:\n \"Fetch a URL and return its textual content (HTML stripped to a markdown-ish form). \" +\n \"Use for reading documentation, blog posts, or API specs. Private/loopback hosts are blocked. \" +\n \"If the URL redirects to a different host, the redirect target is returned for you to re-fetch.\",\n parameters: WebFetchArgs,\n permission: \"network\",\n summarize: (args) => `WebFetch(${args.url})`,\n async execute(args, ctx) {\n let target: URL;\n try {\n target = new URL(args.url);\n } catch {\n return { content: `Invalid URL: ${args.url}`, isError: true };\n }\n if (target.protocol === \"http:\") {\n target.protocol = \"https:\";\n }\n if (target.protocol !== \"https:\") {\n return { content: `Refused: only http(s) URLs are allowed.`, isError: true };\n }\n if (isPrivateHost(target.hostname)) {\n return { content: `Refused: ${target.hostname} is a private/loopback host (SSRF guard).`, isError: true };\n }\n\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n ctx.abortSignal?.addEventListener(\"abort\", onAbort);\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n try {\n const resp = await fetch(target.toString(), {\n redirect: \"manual\",\n signal: controller.signal,\n headers: { \"user-agent\": \"muse-cli/0.1\" },\n });\n\n // 跨主机 redirect → 提示重试,不自动跟随\n if (resp.status >= 300 && resp.status < 400) {\n const loc = resp.headers.get(\"location\");\n if (loc) {\n try {\n const redirectURL = new URL(loc, target);\n if (redirectURL.hostname !== target.hostname) {\n return {\n content: `Redirect to a different host: ${redirectURL.toString()}\\nRe-fetch the new URL explicitly if you trust it.`,\n summary: `Redirect to a different host: ${redirectURL.toString()}`,\n kind: \"warn\",\n };\n }\n // 同 host redirect 也提示一下,让 LLM 决定是否跟\n return {\n content: `Redirect (same host): ${redirectURL.toString()}\\nRe-fetch the new URL to continue.`,\n summary: `Redirect → ${redirectURL.pathname}`,\n kind: \"warn\",\n };\n } catch {\n return { content: `Redirect with unparseable location: ${loc}`, isError: true };\n }\n }\n }\n\n if (!resp.ok) {\n return { content: `HTTP ${resp.status} ${resp.statusText} for ${target.toString()}`, isError: true };\n }\n\n const contentType = resp.headers.get(\"content-type\") ?? \"\";\n const reader = resp.body?.getReader();\n if (!reader) return { content: `Empty response body.`, isError: true };\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n if (value) {\n total += value.byteLength;\n if (total > MAX_RESPONSE_BYTES) {\n await reader.cancel();\n chunks.push(value.slice(0, value.byteLength - (total - MAX_RESPONSE_BYTES)));\n break;\n }\n chunks.push(value);\n }\n }\n const body = new TextDecoder(\"utf-8\", { fatal: false }).decode(Buffer.concat(chunks.map((c) => Buffer.from(c))));\n\n let processed = body;\n if (/^text\\/html|application\\/xhtml/i.test(contentType)) {\n processed = htmlToText(body);\n }\n\n const summary = args.prompt\n ? `# WebFetch result for: ${args.prompt}`\n : `Fetched ${target.hostname} (${total} bytes${total >= MAX_RESPONSE_BYTES ? \", truncated\" : \"\"})`;\n const truncated = processed.length > 200_000 ? processed.slice(0, 200_000) + \"\\n\\n... [truncated]\" : processed;\n const preface = args.prompt ? `# WebFetch result for: ${args.prompt}\\n\\nSource: ${target.toString()}\\n\\n` : `Source: ${target.toString()}\\n\\n`;\n return { content: preface + truncated, summary };\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n return { content: `WebFetch aborted (timeout or user cancel).`, isError: true };\n }\n return { content: `WebFetch failed: ${err instanceof Error ? err.message : String(err)}`, isError: true };\n } finally {\n clearTimeout(timer);\n ctx.abortSignal?.removeEventListener(\"abort\", onAbort);\n }\n },\n});\n\n/**\n * 极简 HTML → 文本:删 script/style,保留段落 / 列表 / 标题 / 链接。\n * 不追求精确——给 LLM 看的近似版本即可。\n */\nexport function htmlToText(html: string): string {\n let s = html;\n // 删 script / style / svg / noscript\n s = s.replace(/<(script|style|svg|noscript)\\b[^>]*>[\\s\\S]*?<\\/\\1>/gi, \"\");\n // 注释\n s = s.replace(/<!--[\\s\\S]*?-->/g, \"\");\n // 标题\n s = s.replace(/<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>/gi, (_m, lvl: string, txt: string) => {\n return `\\n\\n${\"#\".repeat(parseInt(lvl, 10))} ${stripTags(txt).trim()}\\n\\n`;\n });\n // a 链接\n s = s.replace(/<a\\b[^>]*href=[\"']([^\"']+)[\"'][^>]*>([\\s\\S]*?)<\\/a>/gi, (_m, href: string, txt: string) => {\n const label = stripTags(txt).trim();\n return label ? `[${label}](${href})` : href;\n });\n // 列表项\n s = s.replace(/<li\\b[^>]*>([\\s\\S]*?)<\\/li>/gi, (_m, txt: string) => `\\n- ${stripTags(txt).trim()}`);\n // 段落 / 块级\n s = s.replace(/<(p|div|section|article|header|footer|main|aside|nav|pre|blockquote|br|hr)\\b[^>]*>/gi, \"\\n\");\n s = s.replace(/<\\/(p|div|section|article|header|footer|main|aside|nav|pre|blockquote)>/gi, \"\\n\");\n // code 行内\n s = s.replace(/<code\\b[^>]*>([\\s\\S]*?)<\\/code>/gi, (_m, txt: string) => `\\`${stripTags(txt)}\\``);\n // 删剩余标签\n s = stripTags(s);\n // entity 简版\n s = s\n .replace(/ /g, \" \")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\");\n // 合并多空行\n s = s.replace(/\\n{3,}/g, \"\\n\\n\").trim();\n return s;\n}\n\nfunction stripTags(s: string): string {\n return s.replace(/<[^>]+>/g, \"\");\n}\n","/**\n * MemoryWrite / MemoryRead 工具:长期 memory 操作。\n *\n * Memory 设计与 Claude Code 对齐:四种类型(user / feedback / project / reference),\n * 文件路径在 ~/.muse/projects/<hash>/memory/,MEMORY.md 索引注入到 system prompt。\n *\n * 由 ctx.cwd 决定项目身份;切目录后 memory 自动隔离。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { readMemoryFile, writeMemory, type MemoryType } from \"../../loop/memory.js\";\n\nconst TYPES: [MemoryType, ...MemoryType[]] = [\"user\", \"feedback\", \"project\", \"reference\"];\n\nconst MemoryWriteArgs = z.object({\n name: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-_]*$/i, \"must be a kebab- or snake-style slug\")\n .describe(\"Short kebab/snake slug; used as filename (<name>.md) and index key.\"),\n description: z\n .string()\n .describe(\"One-line summary used in MEMORY.md index (decides future relevance).\"),\n type: z.enum(TYPES).describe(\"user | feedback | project | reference\"),\n body: z.string().describe(\"Memory content (markdown). For feedback/project, lead with the rule/fact then **Why:** and **How to apply:** lines.\"),\n});\n\nexport const MemoryWriteTool = defineTool({\n name: \"MemoryWrite\",\n description:\n \"Save a long-term memory file under ~/.muse/projects/<hash>/memory/<name>.md and update MEMORY.md index. \" +\n \"Use for: user role/preferences, validated approach decisions (feedback), project facts (auto-convert relative dates), external system references. \" +\n \"Do NOT save: code patterns derivable from the repo, git history, fix recipes, ephemeral task state.\",\n parameters: MemoryWriteArgs,\n permission: \"write\",\n summarize: (args) => `MemoryWrite(${args.name}, type=${args.type})`,\n async execute(args, ctx) {\n const { filePath, indexUpdated } = await writeMemory(ctx.cwd, {\n name: args.name,\n description: args.description,\n type: args.type as MemoryType,\n body: args.body,\n });\n return {\n content: `Saved memory \"${args.name}\" (${args.type}) → ${filePath}${indexUpdated ? \"\\nMEMORY.md updated.\" : \"\"}`,\n summary: `MemoryWrite ${args.name}`,\n };\n },\n});\n\nconst MemoryReadArgs = z.object({\n name: z.string().describe(\"Memory slug to read (no .md extension).\"),\n});\n\nexport const MemoryReadTool = defineTool({\n name: \"MemoryRead\",\n description:\n \"Read a specific long-term memory file by name. Use after seeing it referenced in MEMORY.md (which is auto-injected into the system prompt).\",\n parameters: MemoryReadArgs,\n permission: \"read\",\n summarize: (args) => `MemoryRead(${args.name})`,\n async execute(args, ctx) {\n try {\n const content = await readMemoryFile(ctx.cwd, args.name);\n return { content, summary: `MemoryRead ${args.name}` };\n } catch (err) {\n return { content: err instanceof Error ? err.message : String(err), isError: true };\n }\n },\n});\n","/**\n * AskUserQuestion 工具:在 agent loop 内同步弹出选择题让用户作答。\n *\n * 流程:tool.execute → ctx.askQuestion(req) → App 渲染 QuestionPicker → 用户 ↑↓ 选 + Enter\n * → resolve 把结果传回 → tool 把答案拼成文本喂给 LLM。Esc 取消会返回 cancelled=true。\n *\n * 一次调用可塞多个 questions(仿 Claude Code),逐题展示,任一题 Esc 视为整批取消。\n *\n * 注意:tool 本身不调任何外部资源,permission 用 read(不弹权限确认)。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nexport const AskQuestionOptionSchema = z.object({\n label: z.string().min(1).describe(\"Option text shown to the user. Concise (1-5 words).\"),\n description: z\n .string()\n .optional()\n .describe(\"Optional one-line explanation of what this option means.\"),\n preview: z\n .string()\n .optional()\n .describe(\n \"Optional rich preview rendered in a right-side panel when this option is focused. \" +\n \"Use for code/diagram/config snippets that help compare options visually. \" +\n \"Multi-line text supported.\",\n ),\n});\n\nexport const AskQuestionSchema = z.object({\n question: z.string().min(1).describe(\"Full question text (end with ?).\"),\n header: z\n .string()\n .min(1)\n .max(16)\n .describe(\"Very short label (chip), max 12 chars. E.g. 'Auth method'.\"),\n options: z\n .array(AskQuestionOptionSchema)\n .min(2)\n .max(4)\n .describe(\"2-4 options. Mutually exclusive unless multiSelect=true.\"),\n multiSelect: z\n .boolean()\n .optional()\n .describe(\"Allow multiple selections. Default false.\"),\n});\n\nexport type AskQuestion = z.infer<typeof AskQuestionSchema>;\nexport type AskQuestionOption = z.infer<typeof AskQuestionOptionSchema>;\n\nexport interface AskQuestionResponse {\n cancelled: boolean;\n /** 单选:单元素数组;多选:所选 label 列表。cancelled=true 时为空。 */\n selections: string[];\n /** 用户对该题用 'n' 添加的自由备注。空字符串表示未填。 */\n notes?: string;\n}\n\nconst AskUserQuestionArgs = z.object({\n questions: z\n .array(AskQuestionSchema)\n .min(1)\n .max(4)\n .describe(\"1-4 questions to ask the user sequentially.\"),\n});\n\nexport const AskUserQuestionTool = defineTool({\n name: \"AskUserQuestion\",\n description:\n \"Ask the user one or more multiple-choice questions when their input is needed to proceed. \" +\n \"Each question has 2-4 options. Use multiSelect=true for non-mutually-exclusive choices. \" +\n \"Prefer this over plain-text questions when the answer space is bounded. \" +\n \"If the user presses Esc, the entire batch is treated as cancelled.\",\n parameters: AskUserQuestionArgs,\n permission: \"read\",\n summarize: (args) =>\n `AskUserQuestion(${args.questions.length} question${args.questions.length === 1 ? \"\" : \"s\"})`,\n async execute(args, ctx) {\n if (!ctx.askQuestions) {\n return {\n content:\n \"AskUserQuestion is unavailable: this agent run has no question handler. \" +\n \"(Internal bug; tell the user.)\",\n isError: true,\n };\n }\n\n const responses = await ctx.askQuestions(args.questions);\n // Esc 取消时所有项 cancelled=true(UI 一次性返回整批)\n if (responses.length > 0 && responses[0].cancelled) {\n return {\n content: \"User cancelled (Esc). No answers were collected.\",\n isError: false,\n };\n }\n\n const blocks = args.questions.map((q, qi) => {\n const r = responses[qi];\n const sel = r?.selections ?? [];\n const ans = sel.length === 0 ? \"(no answer)\" : sel.join(\", \");\n const notes = r?.notes?.trim();\n return notes ? `Q: ${q.question}\\nA: ${ans}\\nNotes: ${notes}` : `Q: ${q.question}\\nA: ${ans}`;\n });\n\n return {\n content: blocks.join(\"\\n\\n\"),\n summary: `Asked ${args.questions.length} question${args.questions.length === 1 ? \"\" : \"s\"}`,\n };\n },\n});\n","import type { AnyTool } from \"../types.js\";\nimport { ReadTool } from \"./read.js\";\nimport { WriteTool } from \"./write.js\";\nimport { EditTool } from \"./edit.js\";\nimport { BashTool } from \"./bash.js\";\nimport { GrepTool } from \"./grep.js\";\nimport { GlobTool } from \"./glob.js\";\nimport { TodoWriteTool } from \"./todo.js\";\nimport { WebFetchTool } from \"./webfetch.js\";\nimport { MemoryReadTool, MemoryWriteTool } from \"./memory.js\";\nimport { AskUserQuestionTool } from \"./ask-user-question.js\";\n\nexport {\n ReadTool,\n WriteTool,\n EditTool,\n BashTool,\n GrepTool,\n GlobTool,\n TodoWriteTool,\n WebFetchTool,\n MemoryReadTool,\n MemoryWriteTool,\n AskUserQuestionTool,\n};\n\nexport const BUILTIN_TOOLS: AnyTool[] = [\n ReadTool,\n WriteTool,\n EditTool,\n BashTool,\n GrepTool,\n GlobTool,\n TodoWriteTool,\n WebFetchTool,\n MemoryReadTool,\n MemoryWriteTool,\n AskUserQuestionTool,\n];\n"],"mappings":"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","names":["useEffect","useMemo","useState","Box","Text","useInput","useStdout","padLen","after","mkdir","readFile","writeFile","existsSync","homedir","dirname","join","Text","jsx","jsxs","Box","Text","process","styles","chalk","styles","jsx","jsxs","Box","Text","useState","Box","Text","useInput","jsx","jsxs","Box","Text","useState","Box","Text","useInput","jsx","jsxs","jsx","jsxs","resolve","Box","Text","Box","Text","jsx","jsxs","resolve","Box","Text","useState","Box","Text","useInput","jsx","jsxs","POINTER_COLOR","s","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","Box","Text","jsx","jsxs","useEffect","useState","Box","Text","jsx","jsxs","useEffect","useState","Box","Text","useEffect","useState","Text","jsx","jsx","jsxs","TICK_MS","useState","useEffect","formatTokens","Box","Text","resolve","tool","result","homedir","homedir","join","readFile","existsSync","homedir","join","existsSync","readFile","join","homedir","readFile","existsSync","homedir","join","z","z","join","homedir","existsSync","readFile","formatZodIssues","mkdir","readFile","existsSync","homedir","dirname","join","createHash","projectHash","createHash","join","homedir","mkdir","existsSync","dirname","readFile","homedir","formatTime","formatTime","jsx","jsxs","useStdout","useState","useMemo","useEffect","resolve","useInput","Box","Text","homedir","join","existsSync","readFile","mkdir","dirname","writeFile","tool","readFile","stat","resolve","z","homedir","basename","resolve","ENV_PATTERN","z","resolve","stat","readFile","readFile","writeFile","mkdir","stat","resolve","isAbsolute","dirname","z","z","isAbsolute","resolve","stat","readFile","mkdir","dirname","writeFile","readFile","writeFile","resolve","isAbsolute","z","z","isAbsolute","resolve","readFile","writeFile","z","z","truncate","execa","z","z","execa","cliArgs","result","out","z","z","DEFAULT_LIMIT","z","z","z","z","z","z","z","z","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.tsx","../src/app.tsx","../src/components/BgTextInput.tsx","../src/clipboard/image.ts","../src/log/index.ts","../src/components/StartupBanner.tsx","../src/components/MessageView.tsx","../node_modules/chalk/source/vendor/ansi-styles/index.js","../node_modules/chalk/source/vendor/supports-color/index.js","../node_modules/chalk/source/utilities.js","../node_modules/chalk/source/index.js","../src/preprocess/render/markdown.ts","../src/preprocess/render/index.ts","../src/ui/theme.ts","../src/components/Shimmer.tsx","../src/components/PermissionPrompt.tsx","../src/components/ModelSelector.tsx","../src/components/Selector.tsx","../src/components/SessionSelector.tsx","../src/components/QuestionPicker.tsx","../src/components/BtwOverlay.tsx","../src/components/SlashAutocomplete.tsx","../src/components/AtFileAutocomplete.tsx","../src/preprocess/input/at-source.ts","../src/components/PermissionModeBar.tsx","../src/permission/index.ts","../src/components/FooterStatus.tsx","../src/components/ProgressBanner.tsx","../src/components/StatusLine.tsx","../src/components/StreamingMarkdown.tsx","../src/preprocess/render/stream-markdown.ts","../src/ui/termTitle.ts","../src/llm/providers/openai-compatible.ts","../src/types/index.ts","../src/llm/client.ts","../src/loop/todos.ts","../src/preprocess/types.ts","../src/preprocess/pipeline.ts","../src/loop/system-prompt.ts","../src/loop/hierarchy.ts","../src/preprocess/request/build-system-prompt.ts","../src/loop/memory-index.ts","../src/loop/memory.ts","../src/loop/embedding/hash-bag.ts","../src/loop/embedding/openai-compatible.ts","../src/loop/embedding/local-transformers.ts","../src/loop/embedding/presets.ts","../src/loop/embedding/index.ts","../src/preprocess/tokenize.ts","../src/preprocess/request/inject-memory.ts","../src/preprocess/request/inject-todos.ts","../src/preprocess/request/apply-mode-filter.ts","../src/preprocess/request/clear-stale-tool-results.ts","../src/preprocess/hooks.ts","../src/loop/prompts/summarize.ts","../src/loop/context.ts","../src/preprocess/request/trim-history.ts","../src/preprocess/request/budget-guard.ts","../src/preprocess/request/ctx.ts","../src/preprocess/request/index.ts","../src/loop/agent.ts","../src/preprocess/result/detect-binary.ts","../src/preprocess/truncate.ts","../src/preprocess/result/truncate.ts","../src/preprocess/result/summarize.ts","../src/preprocess/result/normalize-error.ts","../src/preprocess/redact.ts","../src/preprocess/result/redact.ts","../src/preprocess/result/inject-diff.ts","../src/preprocess/result/ctx.ts","../src/preprocess/result/index.ts","../src/slash/registry.ts","../src/preprocess/input/slash-dispatch.ts","../src/preprocess/input/paste-expand.ts","../src/preprocess/input/at-file-expand.ts","../src/tools/_sensitive.ts","../src/preprocess/input/at-image.ts","../src/preprocess/input/expand-image-placeholder.ts","../src/preprocess/input/template-expand.ts","../src/preprocess/input/validate-length.ts","../src/preprocess/input/redact-pre-scan.ts","../src/preprocess/input/ctx.ts","../src/preprocess/input/index.ts","../src/config/loader.ts","../src/config/types.ts","../src/config/_env.ts","../src/version.ts","../src/config/models.ts","../src/llm/pricing.ts","../src/mcp/index.ts","../src/session/jsonl.ts","../src/slash/_format.ts","../src/slash/builtin.ts","../src/tools/registry.ts","../src/tools/builtin/read.ts","../src/tools/types.ts","../src/tools/builtin/write.ts","../src/tools/_diff.ts","../src/tools/builtin/edit.ts","../src/tools/builtin/bash.ts","../src/tools/builtin/grep.ts","../src/tools/builtin/glob.ts","../src/tools/builtin/todo.ts","../src/tools/builtin/webfetch.ts","../src/tools/builtin/memory.ts","../src/tools/builtin/ask-user-question.ts","../src/tools/builtin/index.ts"],"sourcesContent":["/**\n * CLI 入口。解析 argv → 加载配置 → 启动交互或单次模式。\n */\n\nimport React from \"react\";\nimport { Command } from \"commander\";\nimport { render } from \"ink\";\nimport { App } from \"./app.js\";\nimport { loadSettings } from \"./config/index.js\";\nimport { loadModelsRegistry, findEntry } from \"./config/models.js\";\nimport { createLLMClient, createLLMClientFromModelEntry, setActiveModelEnv } from \"./llm/client.js\";\nimport { ToolRegistry } from \"./tools/registry.js\";\nimport { BUILTIN_TOOLS } from \"./tools/builtin/index.js\";\nimport { PermissionGate } from \"./permission/index.js\";\nimport { Session } from \"./session/jsonl.js\";\nimport { Agent } from \"./loop/agent.js\";\nimport { TodoStore } from \"./loop/todos.js\";\nimport { loadMemoryIndex } from \"./loop/memory.js\";\nimport { loadHierarchy } from \"./loop/hierarchy.js\";\nimport { buildMemoryIndex, type MemoryIndex } from \"./loop/memory-index.js\";\nimport { InputPipeline, createInputCtx, buildUserMessage } from \"./preprocess/input/index.js\";\nimport { RequestPipeline } from \"./preprocess/request/index.js\";\nimport { ResultPipeline } from \"./preprocess/result/index.js\";\nimport { runHooks } from \"./preprocess/hooks.js\";\nimport { PipelineBlockedError } from \"./preprocess/pipeline.js\";\nimport { MuseError } from \"./types/index.js\";\nimport { log } from \"./log/index.js\";\nimport { VERSION } from \"./version.js\";\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"muse\")\n .description(\"A TypeScript agent CLI built around OpenAI-compatible APIs. First-class support for self-hostable and Chinese LLMs.\")\n .version(VERSION, \"-v, --version\", \"print version\");\n\n program\n .argument(\"[prompt...]\", \"one-shot prompt (omit for interactive mode)\")\n .option(\"-m, --model <model>\", \"override model\")\n .option(\"-p, --provider <provider>\", \"override provider\")\n .option(\"--no-banner\", \"skip startup banner\")\n .option(\"--quiet\", \"minimal output (implies --no-banner)\")\n .option(\"--continue\", \"resume last session in this directory\")\n .option(\"--mode <mode>\", \"initial permission mode (default|acceptEdits|plan|bypassPermissions)\")\n .option(\"--debug\", \"verbose logging\")\n .action(async (promptArgs: string[], opts: CliOptions) => {\n if (opts.debug) log.setLevel(\"debug\");\n\n const cwd = process.cwd();\n const { settings, sources } = await loadSettings(cwd);\n const { registry: modelsRegistry, sources: modelsSources } = await loadModelsRegistry();\n log.debug(\"config loaded\", { settingsSources: sources, modelsSources });\n\n const model = opts.model ?? settings.llm?.model;\n const provider = opts.provider ?? settings.llm?.provider;\n\n let llm;\n let llmProviderName: string;\n let llmModelName: string;\n try {\n // models.local.json 里找到 settings.llm.model(或 -m)对应的 entry:\n // 注入 apiKey 到 process.env.MUSE_ACTIVE_API_KEY,业务通过 env 读\n const entry = modelsRegistry && model ? findEntry(modelsRegistry, model) : undefined;\n if (entry) {\n setActiveModelEnv(entry);\n llm = createLLMClientFromModelEntry(entry);\n llmProviderName = llm.providerName;\n llmModelName = llm.model;\n } else if (modelsRegistry && model) {\n // 有 registry 但 model id 在里面找不到 — 大概率是 settings.llm.model 跟\n // models.local.json 里 entry.id 不一致(常见原因:用户改了一边没改另一边)。\n //\n // **不要** 静默 fallback 到 settings.providers + DEFAULTS 的默认 provider —\n // 那会绕一圈报\"缺 DEEPSEEK_API_KEY\",让用户摸不着头脑。直接给清晰错。\n const availableIds = modelsRegistry.models.map((m) => m.id);\n const lines = [\n `Active model \"${model}\" not found in ~/.muse/models.local.json.`,\n ``,\n `Available ids:`,\n ...availableIds.map((id) => ` - ${id}`),\n ``,\n `Fix one of these:`,\n ` 1) Edit ~/.muse/settings.json: set \"llm.model\" to one of the ids above.`,\n ` 2) Edit ~/.muse/models.local.json: rename an entry.id to match \"${model}\".`,\n ` 3) Run muse with --model <id> to override once.`,\n ];\n die(lines.join(\"\\n\"));\n } else {\n // 没 registry / settings.llm.model 没设 → 回退到 settings.json 原生 provider/model\n if (!provider || !model) {\n die(\"No model configured. Either define one in ~/.muse/models.local.json or set llm.provider+llm.model in settings.json.\");\n }\n llm = createLLMClient({ provider, model, providers: settings.providers ?? {} });\n llmProviderName = provider;\n llmModelName = model;\n }\n } catch (err) {\n if (err instanceof MuseError) die(err.message);\n throw err;\n }\n\n const tools = new ToolRegistry();\n tools.registerAll(BUILTIN_TOOLS);\n\n const permissions = new PermissionGate(settings.permissions);\n\n // --mode 启动期指定 PermissionMode;后续 Shift+Tab / /mode 仍可切换\n if (opts.mode) {\n const valid = [\"default\", \"acceptEdits\", \"plan\", \"bypassPermissions\"] as const;\n if (!(valid as readonly string[]).includes(opts.mode)) {\n die(`Invalid --mode \"${opts.mode}\". Valid: ${valid.join(\", \")}`);\n }\n permissions.setMode(opts.mode as (typeof valid)[number]);\n }\n\n // --continue: 复用最近一次 session 的 jsonl + messages\n let session: Session;\n let initialMessages: import(\"./types/index.js\").Message[] | undefined;\n if (opts.continue) {\n const latest = await Session.findLatest(cwd);\n if (latest) {\n const opened = await Session.open(latest);\n session = opened.session;\n initialMessages = Session.messagesFromEvents(opened.events);\n log.debug(\"resumed session\", { id: latest.id, messages: initialMessages.length });\n } else {\n session = await Session.create(cwd);\n await session.append({\n type: \"session_start\",\n time: new Date().toISOString(),\n cwd,\n provider: llmProviderName,\n model: llmModelName,\n });\n }\n } else {\n session = await Session.create(cwd);\n await session.append({\n type: \"session_start\",\n time: new Date().toISOString(),\n cwd,\n provider: llmProviderName,\n model: llmModelName,\n });\n }\n\n const showBanner = !opts.quiet && opts.banner !== false;\n const lang = settings.ui?.lang ?? \"en\";\n\n // Pipe input → 拼成一次性 prompt\n const pipedInput = await readStdinIfPiped();\n const oneShotPrompt = [...(promptArgs ?? []), pipedInput].filter(Boolean).join(\"\\n\").trim();\n\n if (oneShotPrompt) {\n await runOneShot({\n llm,\n tools,\n permissions,\n session,\n settings,\n modelsRegistry,\n cwd,\n lang,\n prompt: oneShotPrompt,\n quiet: opts.quiet ?? false,\n initialMessages,\n });\n return;\n }\n\n // Interactive mode\n const { waitUntilExit } = render(\n <App\n llm={llm}\n tools={tools}\n permissions={permissions}\n session={session}\n settings={settings}\n settingsSources={sources}\n modelsRegistry={modelsRegistry}\n modelsSources={modelsSources}\n cwd={cwd}\n lang={lang}\n showBanner={showBanner}\n initialMessages={initialMessages}\n />,\n );\n await waitUntilExit();\n });\n\n await program.parseAsync(process.argv);\n}\n\ninterface CliOptions {\n model?: string;\n provider?: string;\n banner?: boolean;\n quiet?: boolean;\n continue?: boolean;\n mode?: string;\n debug?: boolean;\n}\n\nasync function readStdinIfPiped(): Promise<string> {\n if (process.stdin.isTTY) return \"\";\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString(\"utf-8\").trim();\n}\n\nasync function runOneShot(opts: {\n llm: ReturnType<typeof createLLMClient>;\n tools: ToolRegistry;\n permissions: PermissionGate;\n session: Session;\n settings: import(\"./config/types.js\").Settings;\n modelsRegistry?: import(\"./config/models.js\").ModelsRegistry;\n cwd: string;\n lang: \"en\" | \"zh-CN\";\n prompt: string;\n quiet: boolean;\n initialMessages?: import(\"./types/index.js\").Message[];\n}): Promise<void> {\n const memoryIndex = await loadMemoryIndex(opts.cwd);\n const hierarchy = await loadHierarchy(opts.cwd);\n // II-5:启用时构建 memory embedding index(失败完全降级,不阻塞 muse 启动)\n let memoryEmbeddingIndex: MemoryIndex | undefined;\n if (opts.settings.memory?.embedding?.enabled) {\n try {\n memoryEmbeddingIndex = await buildMemoryIndex(opts.cwd, {\n config: opts.settings.memory.embedding,\n });\n if (!opts.quiet) {\n const entries = memoryEmbeddingIndex.entries.length;\n process.stderr.write(\n `[memory] embedding ready: provider=${memoryEmbeddingIndex.provider.id}, indexed ${entries} memor${entries === 1 ? \"y\" : \"ies\"}\\n`,\n );\n }\n } catch (err) {\n if (!opts.quiet) {\n process.stderr.write(\n `[memory] embedding init failed: ${(err as Error).message}\\n` +\n `[memory] falling back to MEMORY.md full-text mode (memory still works, just keyword-based).\\n` +\n ` Run \\`/memory diagnose\\` inside muse for details and fix suggestions.\\n`,\n );\n }\n }\n }\n const sessionStartTime = Date.now();\n\n // SessionStart hook\n let extraSystemPrompt = \"\";\n try {\n const out = await runHooks(\n \"SessionStart\",\n { cwd: opts.cwd, mode: opts.permissions.getMode(), modelId: opts.llm.model },\n opts.settings.hooks,\n );\n if (typeof out.extraSystemPrompt === \"string\") extraSystemPrompt = out.extraSystemPrompt;\n } catch (err) {\n if (!opts.quiet) process.stderr.write(`[SessionStart hook error] ${(err as Error).message}\\n`);\n }\n\n // InputPipeline:CLI 单次场景没有 paste registry,paste-expand 自然 noop\n const activeEntry = opts.modelsRegistry ? findEntry(opts.modelsRegistry, opts.llm.model) : undefined;\n const inputCtx = createInputCtx({\n raw: opts.prompt,\n source: \"argv\",\n cwd: opts.cwd,\n mode: opts.permissions.getMode(),\n settings: opts.settings.preprocess?.input,\n capabilities: { supportsImages: activeEntry?.supportsImages ?? false },\n });\n const inputPipeline = InputPipeline({ disable: opts.settings.preprocess?.disable });\n try {\n await inputPipeline.run(inputCtx);\n } catch (err) {\n process.stderr.write(`[input pipeline error] ${(err as Error).message}\\n`);\n return;\n }\n // slash 命令在 one-shot 模式无意义,提示后退出\n if (inputCtx.slashCommand) {\n process.stderr.write(`[ignored] slash commands are only available in interactive mode.\\n`);\n return;\n }\n if (!opts.quiet) {\n for (const w of inputCtx.warnings) process.stderr.write(`[${w.stage}] ${w.message}\\n`);\n }\n\n // UserPromptSubmit hook\n try {\n const hookOut = await runHooks(\n \"UserPromptSubmit\",\n { text: inputCtx.text, attachments: inputCtx.attachments, source: inputCtx.source },\n opts.settings.hooks,\n );\n if (typeof hookOut.text === \"string\") inputCtx.text = hookOut.text;\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n process.stderr.write(`[blocked by UserPromptSubmit hook] ${err.reason}\\n`);\n return;\n }\n process.stderr.write(`[UserPromptSubmit hook error] ${(err as Error).message}\\n`);\n return;\n }\n\n const todos = new TodoStore();\n const requestPipeline = RequestPipeline({ disable: opts.settings.preprocess?.disable });\n const resultPipeline = ResultPipeline({ disable: opts.settings.preprocess?.disable });\n\n const agent = new Agent({\n llm: opts.llm,\n tools: opts.tools,\n permissions: opts.permissions,\n session: opts.session,\n cwd: opts.cwd,\n todos,\n requestPipeline,\n requestServices: {\n todos,\n memoryIndex,\n hierarchy,\n memoryEmbeddingIndex,\n memoryEmbeddingTopK: opts.settings.memory?.embedding?.topK,\n memoryEmbeddingMinCount: opts.settings.memory?.embedding?.minMemoryCount,\n toolRegistry: opts.tools,\n lang: opts.lang,\n provider: opts.llm.providerName,\n extraSystemPrompt,\n },\n resultPipeline,\n resultSettings: opts.settings.preprocess?.result,\n hooks: opts.settings.hooks,\n events: {\n onText: (delta) => process.stdout.write(delta),\n onToolCallStart: (_id, name) => {\n if (!opts.quiet) process.stderr.write(`\\n→ ${name}\\n`);\n },\n onError: (err) => process.stderr.write(`\\n[error] ${err.message}\\n`),\n onPermissionRequest: async (toolName, _args, summary) => {\n // 非交互模式:deny 所有需要 ask 的工具\n if (!opts.quiet) process.stderr.write(`\\n[denied: ${toolName} — ${summary}; run in interactive mode to approve]\\n`);\n return \"no\";\n },\n },\n });\n if (opts.initialMessages?.length) agent.setMessages(opts.initialMessages);\n await agent.runTurn(buildUserMessage(inputCtx));\n process.stdout.write(\"\\n\");\n\n // SessionEnd hook(fire-and-forget;不影响退出码)\n try {\n await runHooks(\n \"SessionEnd\",\n { durationMs: Date.now() - sessionStartTime, turnCount: 1 },\n opts.settings.hooks,\n );\n } catch {}\n}\n\nfunction die(msg: string): never {\n process.stderr.write(`muse: ${msg}\\n`);\n process.exit(1);\n}\n\nmain().catch((err) => {\n log.error(\"fatal\", { msg: err instanceof Error ? err.message : String(err) });\n process.stderr.write(`muse: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n","/**\n * Ink 根组件:banner + 消息历史 + 输入框 + 流式响应 + slash 命令调度。\n *\n * SlashActions 在这里注入。LLM client / settings / modelsRegistry 都是 mutable state,\n * /model /config reload 通过 setLLM / setSettings / setModelsRegistry 触发 Agent 重建,\n * messages 通过 messagesRef 跨重建保留。\n */\n\nimport React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from \"react\";\nimport { Box, Static, Text, useApp, useInput, useStdout } from \"ink\";\nimport { BgTextInput, stringWidth } from \"./components/BgTextInput.js\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { pickBanner } from \"./components/StartupBanner.js\";\nimport { MessageView, BatchedToolBlock, BATCHABLE_TOOLS, TodoList, extractTodos, extractListTitle, type BatchedToolUse } from \"./components/MessageView.js\";\nimport { PermissionPrompt, type PermissionRequest } from \"./components/PermissionPrompt.js\";\nimport { ModelSelector, type ModelPickerRequest } from \"./components/ModelSelector.js\";\nimport { SessionSelector, type SessionPickerRequest } from \"./components/SessionSelector.js\";\nimport { QuestionPicker, type QuestionPickerRequest } from \"./components/QuestionPicker.js\";\nimport { BtwOverlay, type BtwRequest } from \"./components/BtwOverlay.js\";\nimport { SlashAutocomplete } from \"./components/SlashAutocomplete.js\";\nimport { AtFileAutocomplete } from \"./components/AtFileAutocomplete.js\";\nimport { queryAtCandidates, type AtCandidate } from \"./preprocess/input/at-source.js\";\nimport { PermissionModeBar } from \"./components/PermissionModeBar.js\";\nimport { FooterStatus } from \"./components/FooterStatus.js\";\nimport { ProgressBanner, type ProgressState } from \"./components/ProgressBanner.js\";\nimport { StatusLine } from \"./components/StatusLine.js\";\nimport { DOT } from \"./components/MessageView.js\";\nimport { StreamingMarkdown } from \"./components/StreamingMarkdown.js\";\nimport { setTerminalTitle, resetTerminalTitle } from \"./ui/termTitle.js\";\nimport type { LLMClient } from \"./llm/types.js\";\nimport { createLLMClient, createLLMClientFromModelEntry, setActiveModelEnv } from \"./llm/client.js\";\nimport type { ToolRegistry } from \"./tools/registry.js\";\nimport { PermissionGate, type PermissionMode, type PermissionDecision } from \"./permission/index.js\";\nimport { Session, type SessionSummary } from \"./session/jsonl.js\";\nimport { Agent } from \"./loop/agent.js\";\nimport { loadMemoryIndex } from \"./loop/memory.js\";\nimport { loadHierarchy, type HierarchyLayer } from \"./loop/hierarchy.js\";\nimport { buildMemoryIndex, type MemoryIndex } from \"./loop/memory-index.js\";\nimport { TodoStore } from \"./loop/todos.js\";\nimport { InputPipeline, createInputCtx, buildUserMessage, type InputCtx } from \"./preprocess/input/index.js\";\nimport { RequestPipeline } from \"./preprocess/request/index.js\";\nimport { ResultPipeline } from \"./preprocess/result/index.js\";\nimport { runHooks } from \"./preprocess/hooks.js\";\nimport { PipelineBlockedError } from \"./preprocess/pipeline.js\";\nimport { loadSettings } from \"./config/index.js\";\nimport { VERSION } from \"./version.js\";\nimport { loadModelsRegistry, findEntry, type ModelEntry, type ModelsRegistry } from \"./config/models.js\";\nimport type { Message, ToolMessage, TokenUsage, ContentPart, ToolUsePart } from \"./types/index.js\";\nimport type { Settings } from \"./config/types.js\";\nimport {\n BUILTIN_SLASH_COMMANDS,\n SlashRegistry,\n type SlashActions,\n type SlashCommand,\n type SlashCommandResult,\n} from \"./slash/index.js\";\n\nexport interface AppProps {\n llm: LLMClient;\n tools: ToolRegistry;\n permissions: PermissionGate;\n session: Session;\n settings: Settings;\n settingsSources: string[];\n modelsRegistry?: ModelsRegistry;\n modelsSources: string[];\n cwd: string;\n lang: \"en\" | \"zh-CN\";\n showBanner: boolean;\n initialMessages?: Message[];\n}\n\ninterface UIState {\n history: Message[];\n streamingText: string;\n status: \"idle\" | \"streaming\" | \"tool\";\n /** Esc 主动中断后的灰字提示文字(null 表示不显示);下次 user_submit 自动清。 */\n stoppedNote: string | null;\n /** 当前正在跑的工具名(onToolCallStart 设置;下一次 stream_delta 或 turn_end 清空)。 */\n runningTool: string | null;\n /** 最近一次 onToolCallStart 的 tool_use id;BatchedToolBlock 据此选 active row。\n * 语义:\"hold 上一个直到下一个真的开始\"——LLM 思考 / 等权限 / hook 期间继续显示\n * 最近一次开始执行过的 row,避免 firstPending 立刻跳到下一个未启动的工具。\n * user_submit 时清零(新 turn 不复用旧 id)。 */\n lastStartedToolId: string | null;\n /** session 累计 token(/cost 用),不是本轮快照——本轮快照走 turn* 引用 */\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n /** 本轮起点(user_submit 触发时 Date.now()),StatusLine 用;idle 时为 0 */\n turnStartTime: number;\n /** 本轮首次 text-delta 时间,StatusLine 显示 \"thought for\" 用;null 表示还未流出 text */\n turnFirstTextTime: number | null;\n /** 本轮已累计 input tokens(多轮 tool loop 累加) */\n turnInputTokens: number;\n /** history[0..stableUntilIdx-1] 已属过往 turn,可走 Static(Ink 一次 emit 不再重画),\n * 消除每次 tool result 到位时的全 history 重渲染闪屏。每次 user_submit 时更新。 */\n stableUntilIdx: number;\n /** 本轮 sticky TodoList 的\"起点\":只显示 history[todosSinceTurnIdx..] 之间最新一次 TodoWrite 的 todos。\n * 每次 user_submit 时重置到当前 history 长度——旧 turn 的 TodoList 立即从底部消失。\n * 这样实现 \"TodoList 固定在输入框上方,跨工具调用持续可见\" 的体验。 */\n todosSinceTurnIdx: number;\n /** turn 结束标记:每次 onTurnEnd 记录\"该 turn 结束时 history 长度 + 时长\",\n * 渲染时在对应位置插入 `✶ Churned for Xm Ys` 灰色行(turn 末尾摘要)。\n * 不进 session JSONL,resume 时旧 turn 的 churned 标记会丢,新 turn 仍会记录。 */\n turnEnds: Array<{ atHistoryLen: number; durationMs: number }>;\n}\n\ntype UIAction =\n | { type: \"user_submit\"; stableUntil: number }\n | { type: \"history_set\"; messages: Message[] }\n | { type: \"stream_delta\"; delta: string }\n | { type: \"stream_reset\" }\n | { type: \"set_status\"; status: UIState[\"status\"] }\n | { type: \"tool_start\"; name: string; id: string }\n | { type: \"add_usage\"; usage: TokenUsage }\n | { type: \"estimate\"; inputTokens: number }\n | { type: \"set_stopped\"; note: string | null }\n | { type: \"record_turn_end\"; atHistoryLen: number; durationMs: number };\n\nfunction reducer(state: UIState, action: UIAction): UIState {\n switch (action.type) {\n case \"user_submit\":\n return {\n ...state,\n streamingText: \"\",\n status: \"streaming\",\n runningTool: null,\n turnStartTime: Date.now(),\n turnFirstTextTime: null,\n turnInputTokens: 0,\n stoppedNote: null, // 新一轮开始,清掉上一轮 abort 残留提示\n stableUntilIdx: action.stableUntil, // 之前所有 turn 落定,可以丢进 Static\n lastStartedToolId: null, // 新 turn 不复用旧 tool id\n todosSinceTurnIdx: action.stableUntil, // 旧 todos 立即从底部消失,等新 turn 的 TodoWrite\n };\n case \"history_set\": {\n // 智能去重:如果 history 末尾的 assistant message 已经包含 streamingText 的内容,\n // 自动清空 streamingText 避免\"屏幕上+history 各显示一份\"的重复。\n // 这条主要给 abort 路径用:abort 不 stream_reset → streamingText 保留显示;\n // 一旦 Agent 把已流出 text push 进 history(可能含 [interrupted] 标识),自动接管显示。\n let nextStreamingText = state.streamingText;\n if (state.streamingText.trim()) {\n const last = action.messages[action.messages.length - 1];\n if (last?.role === \"assistant\" && Array.isArray(last.content)) {\n const lastText = last.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n if (lastText.includes(state.streamingText.trim())) {\n nextStreamingText = \"\";\n }\n }\n }\n // 自动推进 stableUntilIdx:缩短 dynamic 区高度,缓解长 turn 内 Ink 整树重绘闪屏。\n // 策略:倒着找\"最后一个含未完成 tool_use\"的 assistant message idx;它本身 + 之后的\n // tool result 留 dynamic(active batch 还在变),其余进 Static。无未完成 → 全 Static。\n // 副作用:Ink Static 增量 commit 时已完成 batch 整体上推到 stdout 顶部 — 视觉上像\n // \"滚屏\",但比每 16ms 整段 dynamic 重画闪屏好。\n let nextStable = state.stableUntilIdx;\n let activeAssistantIdx = -1;\n for (let i = action.messages.length - 1; i >= 0; i--) {\n const m = action.messages[i];\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n const toolUses = m.content.filter(\n (p): p is { type: \"tool_use\"; id: string; name: string; args: unknown } =>\n p.type === \"tool_use\",\n );\n if (toolUses.length > 0) {\n const allDone = toolUses.every((p) =>\n action.messages.some(\n (mm) => mm.role === \"tool\" && (mm as { toolUseId?: string }).toolUseId === p.id,\n ),\n );\n if (!allDone) activeAssistantIdx = i;\n break;\n }\n }\n }\n if (activeAssistantIdx >= 0) {\n nextStable = Math.max(nextStable, activeAssistantIdx);\n } else {\n nextStable = Math.max(nextStable, action.messages.length);\n }\n return {\n ...state,\n history: action.messages,\n streamingText: nextStreamingText,\n stableUntilIdx: nextStable,\n };\n }\n case \"stream_delta\":\n // 文本流出意味着 LLM 在思考 / 回话——若刚才在 tool 阶段,自然过渡为 streaming\n // 第一次流出时打 turnFirstTextTime 时间戳(\"thought for\" 用),冻结不再变\n return {\n ...state,\n streamingText: state.streamingText + action.delta,\n status: state.status === \"tool\" ? \"streaming\" : state.status,\n runningTool: null,\n turnFirstTextTime: state.turnFirstTextTime ?? Date.now(),\n };\n case \"stream_reset\":\n return { ...state, streamingText: \"\" };\n case \"set_status\":\n return {\n ...state,\n status: action.status,\n runningTool: action.status === \"tool\" ? state.runningTool : null,\n };\n case \"tool_start\":\n return { ...state, status: \"tool\", runningTool: action.name, lastStartedToolId: action.id };\n case \"add_usage\":\n return {\n ...state,\n // session 累计:每次 LLM call 的 input/output 都累加,代表本次会话总计费量\n inputTokens: state.inputTokens + action.usage.inputTokens,\n outputTokens: state.outputTokens + action.usage.outputTokens,\n totalTokens: state.totalTokens + action.usage.totalTokens,\n // 本轮 ctx 快照:用最新一次 LLM call 的 inputTokens 覆盖,代表\"当前 context 占用\"。\n // 不累加(累加错把多轮 tool loop 的每次 input 叠在一起,ctx% 爆表)。\n turnInputTokens: action.usage.inputTokens,\n };\n case \"estimate\":\n // 流式开始前的估算,只更新本轮 ctx 快照,不进 session 累计\n return { ...state, turnInputTokens: action.inputTokens };\n case \"set_stopped\":\n return { ...state, stoppedNote: action.note };\n case \"record_turn_end\":\n return {\n ...state,\n turnEnds: [\n ...state.turnEnds,\n { atHistoryLen: action.atHistoryLen, durationMs: action.durationMs },\n ],\n };\n }\n}\n\nexport function App({\n llm: initialLLM,\n tools,\n permissions: initialPermissions,\n session,\n settings: initialSettings,\n settingsSources: initialSources,\n modelsRegistry: initialModelsRegistry,\n cwd,\n lang,\n showBanner,\n initialMessages,\n}: AppProps) {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const termWidth = stdout?.columns ?? 80;\n\n const [llm, setLLM] = useState<LLMClient>(initialLLM);\n const [permissions, setPermissions] = useState<PermissionGate>(initialPermissions);\n const [settings, setSettings] = useState<Settings>(initialSettings);\n const [settingsSources, setSettingsSources] = useState<string[]>(initialSources);\n const [modelsRegistry, setModelsRegistry] = useState<ModelsRegistry | undefined>(initialModelsRegistry);\n const [mode, setMode] = useState<PermissionMode>(initialPermissions.getMode());\n\n const [state, dispatch] = useReducer(reducer, {\n history: initialMessages ?? [],\n streamingText: \"\",\n status: \"idle\",\n runningTool: null,\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n turnStartTime: 0,\n turnFirstTextTime: null,\n turnInputTokens: 0,\n stoppedNote: null,\n // 启动时 initialMessages(/resume 加载或 --continue)整段当稳定历史:不会再改\n stableUntilIdx: initialMessages?.length ?? 0,\n lastStartedToolId: null,\n todosSinceTurnIdx: initialMessages?.length ?? 0,\n turnEnds: [],\n });\n\n const messagesRef = useRef<Message[]>(initialMessages ?? []);\n\n const [input, setInput] = useState(\"\");\n // inputRemountKey 给 TextInput 做 remount —— ink-text-input 在 value 被外部强制修改时\n // cursor 不会跟随到末尾,bump 一个 key 让组件重挂载,新实例 cursor 默认在 value.length。\n // onChange 用 setInput 不能 bump(每次按键都 remount 会丢 cursor);只有补全 / 清空等\n // \"外部 setValue\" 操作走 commitInput。\n const [inputRemountKey, setInputRemountKey] = useState(0);\n const commitInput = (value: string) => {\n setInput(value);\n setInputRemountKey((k) => k + 1);\n };\n // 粘贴 registry:大段粘贴的原文按 id 存这里,输入框里只显示 [Pasted text #N +M lines]\n // 占位符。提交时由 InputPipeline 的 paste-expand stage 还原成原文发给 LLM。\n // 用 ref 不用 state——内容只在 onPaste/onSubmit 的瞬时事件里读,不需要触发渲染。\n const pasteRegistryRef = useRef<{ map: Map<number, string>; nextId: number }>({\n map: new Map(),\n nextId: 1,\n });\n const handlePaste = useCallback((chunk: string): string => {\n const reg = pasteRegistryRef.current;\n const id = reg.nextId++;\n reg.map.set(id, chunk);\n const lines = chunk.split(\"\\n\").length;\n return `[Pasted text #${id} +${lines} lines]`;\n }, []);\n\n // 图片 registry:Cmd+V 直接粘图(BgTextInput 同步检测剪贴板)。\n // 输入框里只显示 [Image #N] 占位符,提交时由 InputPipeline 的\n // expand-image-placeholder stage 还原为 ImagePart。\n const imageRegistryRef = useRef<{\n map: Map<number, { data: Buffer; mediaType: \"image/png\" }>;\n nextId: number;\n }>({ map: new Map(), nextId: 1 });\n const handlePasteImage = useCallback((data: Buffer, mediaType: \"image/png\"): string => {\n const reg = imageRegistryRef.current;\n const id = reg.nextId++;\n reg.map.set(id, { data, mediaType });\n return `[Image #${id}]`;\n }, []);\n\n const [pending, setPending] = useState<PermissionRequest | null>(null);\n const [picker, setPicker] = useState<ModelPickerRequest | null>(null);\n const [sessionPicker, setSessionPicker] = useState<SessionPickerRequest | null>(null);\n const [questionPicker, setQuestionPicker] = useState<QuestionPickerRequest | null>(null);\n const [btwRequest, setBtwRequest] = useState<BtwRequest | null>(null);\n const [autocompleteIndex, setAutocompleteIndex] = useState(0);\n const [progress, setProgress] = useState<ProgressState | null>(null);\n const agentRef = useRef<Agent | null>(null);\n\n // 本轮 abort controller:handleSubmit 开始时新建,Esc 触发 abort,onTurnEnd 清空\n const turnAbortRef = useRef<AbortController | null>(null);\n\n // 双击 Esc rewind 检测:第一次 Esc 落入 idle 状态时记下时间戳;500ms 内再 Esc → rewind\n const lastEscRef = useRef<number>(0);\n const ESC_DOUBLE_WINDOW_MS = 500;\n const [escHint, setEscHint] = useState<string | null>(null); // \"Press Esc again to rewind\"\n\n // 引导(guidance)队列预览:模型在跑时用户继续提交的消息进 agent.enqueueGuidance,\n // 这里只是 UI 镜像供\"↳ 引导\"小框显示。Agent 主循环每轮 flushGuidance 后会触发\n // onGuidanceInjected → 这里清空。\n type GuidanceItem = string | ContentPart[];\n const [guidanceQueue, setGuidanceQueue] = useState<GuidanceItem[]>([]);\n\n // 输入历史:纯用户输入(不含 slash 命令),最旧 → 最新 push 到末尾\n // historyIndex: -1=未导航;0=最新;len-1=最旧\n const inputHistoryRef = useRef<string[]>(extractUserInputs(initialMessages ?? []));\n const historyIndexRef = useRef<number>(-1);\n const savedDraftRef = useRef<string>(\"\");\n\n const slash = useMemo(() => {\n const r = new SlashRegistry();\n r.registerAll(BUILTIN_SLASH_COMMANDS);\n return r;\n }, []);\n\n // input.startsWith(\"/\") && 命令名阶段(无空格)→ 显示匹配候选\n const autocomplete = useMemo<{ matches: SlashCommand[]; query: string } | null>(() => {\n if (!input.startsWith(\"/\")) return null;\n const body = input.slice(1);\n if (body.includes(\" \")) return null;\n const query = body.toLowerCase();\n const all = slash.list();\n const matches = query\n ? all.filter(\n (c) =>\n c.name.toLowerCase().includes(query) ||\n c.aliases?.some((a) => a.toLowerCase().includes(query)),\n )\n : all;\n return { matches, query };\n }, [input, slash]);\n\n // 输入变化时把高亮索引夹回合法范围\n useEffect(() => {\n const len = autocomplete?.matches.length ?? 0;\n if (autocompleteIndex >= len) setAutocompleteIndex(0);\n }, [autocomplete, autocompleteIndex]);\n\n // @ 引用 fuzzy 补全。\n // 检测光标位置往前找最后一个 `@`,后面没有空白前的段是 query。input 为简化用\n // 整串末尾的 `@xxx` 段(不跟踪光标,与 SlashAutocomplete 一致)。\n const atQuery = useMemo<string | null>(() => {\n // slash 模式已激活时不触发 @\n if (input.startsWith(\"/\")) return null;\n // 找最后一个 @,要求它前面是行首或空白\n const idx = input.lastIndexOf(\"@\");\n if (idx < 0) return null;\n if (idx > 0 && !/\\s/.test(input[idx - 1])) return null;\n const tail = input.slice(idx + 1);\n if (/\\s/.test(tail)) return null;\n return tail;\n }, [input]);\n\n const [atMatches, setAtMatches] = useState<AtCandidate[]>([]);\n const [atIndex, setAtIndex] = useState(0);\n useEffect(() => {\n if (atQuery === null) {\n setAtMatches([]);\n return;\n }\n let cancelled = false;\n queryAtCandidates(cwd, atQuery)\n .then((cands) => {\n if (!cancelled) setAtMatches(cands);\n })\n .catch(() => {\n if (!cancelled) setAtMatches([]);\n });\n return () => {\n cancelled = true;\n };\n }, [atQuery, cwd]);\n useEffect(() => {\n if (atIndex >= atMatches.length) setAtIndex(0);\n }, [atMatches, atIndex]);\n\n /** 选中候选 → 替换 input 末尾的 @query 段。dir 末尾加 `/` 让用户继续展开。 */\n const acceptAtCandidate = useCallback(\n (cand: AtCandidate) => {\n const idx = input.lastIndexOf(\"@\");\n if (idx < 0) return;\n const prefix = input.slice(0, idx);\n const replacement = cand.isDir ? `@${cand.rel}/` : `@${cand.rel} `;\n commitInput(prefix + replacement);\n },\n [input],\n );\n\n // 终端 tab/window 标题:idle 静态项目名,busy 时旋转 spinner + 工具名。\n // 100ms tick / 10 帧 braille——切到别的窗口也能从 dock 看出 muse 还在跑。\n useEffect(() => {\n const project = basename(cwd) || \"muse\";\n const baseIdle = `muse · ${project}`;\n\n if (state.status === \"idle\") {\n setTerminalTitle(baseIdle);\n return;\n }\n\n const FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n let i = 0;\n const id = setInterval(() => {\n const frame = FRAMES[i % FRAMES.length];\n const tail = state.runningTool ? ` · ${state.runningTool}` : \"\";\n setTerminalTitle(`${frame} muse · ${project}${tail}`);\n i++;\n }, 100);\n return () => clearInterval(id);\n }, [state.status, state.runningTool, cwd]);\n\n // 卸载时清标题(避免退出后 tab 留着旧 spinner 字符)\n useEffect(() => {\n return () => resetTerminalTitle();\n }, []);\n\n const [memoryIndex, setMemoryIndex] = useState<string>(\"\");\n useEffect(() => {\n let cancelled = false;\n loadMemoryIndex(cwd).then((idx) => {\n if (!cancelled) setMemoryIndex(idx);\n });\n return () => {\n cancelled = true;\n };\n }, [cwd]);\n\n // II-1:hierarchy(MUSE.md / AGENTS.md 5 层)— turn 起前一次性加载,变更 cwd 时重读\n const [hierarchy, setHierarchy] = useState<HierarchyLayer[]>([]);\n useEffect(() => {\n let cancelled = false;\n loadHierarchy(cwd).then((layers) => {\n if (!cancelled) setHierarchy(layers);\n });\n return () => {\n cancelled = true;\n };\n }, [cwd]);\n\n // II-5:memory embedding index(启用时启动 + cwd / settings 变化时重建,失败完全降级)\n const [memoryEmbeddingIndex, setMemoryEmbeddingIndex] = useState<MemoryIndex | undefined>(undefined);\n const [memoryEmbeddingError, setMemoryEmbeddingError] = useState<string | undefined>(undefined);\n const embeddingEnabled = settings.memory?.embedding?.enabled === true;\n const embeddingProviderKind = settings.memory?.embedding?.provider;\n useEffect(() => {\n if (!embeddingEnabled) {\n setMemoryEmbeddingIndex(undefined);\n setMemoryEmbeddingError(undefined);\n return;\n }\n let cancelled = false;\n buildMemoryIndex(cwd, { config: settings.memory?.embedding })\n .then((idx) => {\n if (cancelled) return;\n setMemoryEmbeddingIndex(idx);\n setMemoryEmbeddingError(undefined);\n })\n .catch((err) => {\n if (cancelled) return;\n setMemoryEmbeddingIndex(undefined);\n setMemoryEmbeddingError((err as Error).message ?? String(err));\n });\n return () => {\n cancelled = true;\n };\n }, [cwd, embeddingEnabled, embeddingProviderKind, settings.memory?.embedding?.preset, settings.memory?.embedding?.model, settings.memory?.embedding?.dim, settings.memory?.embedding?.baseUrl]);\n\n // SessionStart / SessionEnd hooks\n const [sessionExtraPrompt, setSessionExtraPrompt] = useState<string>(\"\");\n const turnCountRef = useRef<number>(0);\n const sessionStartTimeRef = useRef<number>(Date.now());\n /** 本轮开始时刻;handleSubmit 入口设置,onTurnEnd 计算 churned duration 用。\n * 用 ref 而非闭包 state(state 在异步 onTurnEnd 闭包里可能 stale)。 */\n const turnStartTimeRef = useRef<number>(0);\n useEffect(() => {\n let cancelled = false;\n runHooks(\n \"SessionStart\",\n { cwd, mode: permissions.getMode(), modelId: llm.model },\n settings.hooks,\n )\n .then((out) => {\n if (cancelled) return;\n if (typeof out.extraSystemPrompt === \"string\") setSessionExtraPrompt(out.extraSystemPrompt);\n })\n .catch(() => {});\n return () => {\n cancelled = true;\n // SessionEnd:fire-and-forget\n const durationMs = Date.now() - sessionStartTimeRef.current;\n runHooks(\n \"SessionEnd\",\n { durationMs, turnCount: turnCountRef.current },\n settings.hooks,\n ).catch(() => {});\n };\n }, [cwd, llm.model, settings.hooks]);\n\n useEffect(() => {\n const todos = new TodoStore();\n const requestPipeline = RequestPipeline({\n disable: settings.preprocess?.disable,\n });\n const resultPipeline = ResultPipeline({\n disable: settings.preprocess?.disable,\n });\n\n const agent = new Agent({\n llm,\n tools,\n permissions,\n session,\n cwd,\n todos,\n requestPipeline,\n requestServices: {\n todos,\n memoryIndex,\n hierarchy,\n memoryEmbeddingIndex,\n memoryEmbeddingTopK: settings.memory?.embedding?.topK,\n memoryEmbeddingMinCount: settings.memory?.embedding?.minMemoryCount,\n toolRegistry: tools,\n lang,\n provider: llm.providerName,\n extraSystemPrompt: sessionExtraPrompt,\n },\n resultPipeline,\n resultSettings: settings.preprocess?.result,\n hooks: settings.hooks,\n events: {\n onText: (delta) => dispatch({ type: \"stream_delta\", delta }),\n onToolCallStart: (id, name) => dispatch({ type: \"tool_start\", name, id }),\n // assistant 流刚结束、这一批 calls 已落到 messages 但 tool 还没开始执行:\n // 立刻同步 history,让所有 ⏺ Tool(...) 调用头一次性显示出来(之前要等第一个\n // result 才能见到任何东西,看起来像\"卡死了\")\n onAssistantTurn: () => {\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n dispatch({ type: \"stream_reset\" });\n },\n // 每个 tool result 到位就同步:result 立刻挂到对应 ⏺ 调用的 └ 树枝下方\n onToolResult: () => {\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n dispatch({ type: \"set_status\", status: \"streaming\" });\n },\n onUsage: (usage: TokenUsage) => dispatch({ type: \"add_usage\", usage }),\n onEstimate: (inputTokens) => dispatch({ type: \"estimate\", inputTokens }),\n onTurnEnd: () => {\n turnCountRef.current++;\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n // 记录本 turn 的 churned duration(start 来自 handleSubmit 设的 ref);\n // 渲染时根据 atHistoryLen 在对应位置插入 \"✶ Churned for Xm Ys\" 灰色行\n if (turnStartTimeRef.current > 0) {\n const duration = Date.now() - turnStartTimeRef.current;\n dispatch({\n type: \"record_turn_end\",\n atHistoryLen: msgs.length,\n durationMs: duration,\n });\n turnStartTimeRef.current = 0;\n }\n // abort 触发的 onTurnEnd 不主动 stream_reset:保留 streamingText 让用户看到已流出内容。\n // 上面 history_set 内含智能去重,如果 history 已包含该 text 会自动清 streamingText\n // 避免双显示;Agent 没成功 push 时(corner case),streamingText 兜底保留。\n if (!turnAbortRef.current?.signal.aborted) {\n dispatch({ type: \"stream_reset\" });\n }\n dispatch({ type: \"set_status\", status: \"idle\" });\n },\n // Agent 在新一轮 stream 启动前 flush 队列 + 注入 messages → 清 UI 镜像。\n // 同时 history 也已经被 Agent push 了那条 user 消息,这里同步一下让\"引导内容\"\n // 立刻在历史里以普通 user message 形式出现(便于用户回看)。\n onGuidanceInjected: () => {\n setGuidanceQueue([]);\n const msgs = [...agent.getMessages()];\n messagesRef.current = msgs;\n dispatch({ type: \"history_set\", messages: msgs });\n },\n onError: (err) => {\n if (turnAbortRef.current?.signal.aborted || isAbortLike(err)) {\n // 不 stream_reset,保留已流出内容;reducer 内 history_set 智能去重\n dispatch({ type: \"set_status\", status: \"idle\" });\n dispatch({ type: \"set_stopped\", note: \"⏹ Stopped by Esc\" });\n return;\n }\n // 不再拼 [error] 到 streamingText,改成灰字 stoppedNote(跟 Esc 提示同款),\n // 避免红字跟模型回答混在同一个 ● 块里。下一次 user_submit 自动清。\n dispatch({ type: \"set_stopped\", note: formatErrorForUser(err.message) });\n dispatch({ type: \"set_status\", status: \"idle\" });\n },\n onPermissionRequest: (toolName, args, summary) =>\n new Promise<PermissionDecision>((resolve) => {\n setPending({ toolName, args, summary, resolve });\n }),\n onAskQuestions: (questions) =>\n new Promise((resolve) => {\n setQuestionPicker({ questions, resolve });\n }),\n },\n });\n agent.setMessages(messagesRef.current);\n agentRef.current = agent;\n }, [llm, tools, permissions, session, cwd, lang, memoryIndex, hierarchy, memoryEmbeddingIndex, sessionExtraPrompt]);\n\n // 键盘:Ctrl+C 全局退出 + Shift+Tab 循环切 permission mode + autocomplete ↑↓ Tab Esc 导航\n useInput(\n (inputKey, key) => {\n if (key.ctrl && inputKey === \"c\") {\n exit();\n return;\n }\n if (key.shift && key.tab) {\n const next = permissions.cycleMode();\n setMode(next);\n return;\n }\n\n // Esc 处理(优先级高于补全/历史,但低于 autocomplete 自身的 Esc 处理):\n // - 非 idle 状态:\n // · 若有\"引导\"队列待注入 → 先清队列(轻撤销),不中断当前 turn\n // · 队列空 → 中断当前 stream / 工具执行\n // - idle 状态(无 autocomplete):双击 500ms 内 rewind 上一轮\n if (key.escape && !(autocomplete && autocomplete.matches.length > 0) && !(atQuery !== null && atMatches.length > 0)) {\n if (state.status !== \"idle\") {\n if (guidanceQueue.length > 0) {\n agentRef.current?.clearGuidance();\n setGuidanceQueue([]);\n setEscHint(\"guidance cleared\");\n setTimeout(() => setEscHint(null), 1500);\n return;\n }\n turnAbortRef.current?.abort();\n setEscHint(null);\n return;\n }\n // idle 状态:双击检测\n const now = Date.now();\n if (now - lastEscRef.current < ESC_DOUBLE_WINDOW_MS) {\n // 双击 → rewind\n lastEscRef.current = 0;\n setEscHint(null);\n const ok = rewindLastTurn();\n if (!ok) setEscHint(\"(nothing to rewind)\");\n return;\n }\n // 单击 → 提示 + 等第二下\n lastEscRef.current = now;\n setEscHint(\"Press Esc again to rewind last turn\");\n setTimeout(() => {\n if (Date.now() - lastEscRef.current >= ESC_DOUBLE_WINDOW_MS) {\n setEscHint(null);\n }\n }, ESC_DOUBLE_WINDOW_MS + 50);\n return;\n }\n\n if (autocomplete && autocomplete.matches.length > 0) {\n const len = autocomplete.matches.length;\n if (key.upArrow) {\n setAutocompleteIndex((i) => (i - 1 + len) % len);\n } else if (key.downArrow) {\n setAutocompleteIndex((i) => (i + 1) % len);\n } else if (key.tab) {\n const picked = autocomplete.matches[autocompleteIndex];\n if (picked) commitInput(`/${picked.name}`);\n } else if (key.escape) {\n commitInput(\"\");\n }\n return;\n }\n\n // @ 引用自动补全\n if (atQuery !== null && atMatches.length > 0) {\n const len = atMatches.length;\n if (key.upArrow) {\n setAtIndex((i) => (i - 1 + len) % len);\n } else if (key.downArrow) {\n setAtIndex((i) => (i + 1) % len);\n } else if (key.tab || (key.return && false /* Enter 由 onSubmit 处理 */)) {\n // Tab 接受当前焦点\n const picked = atMatches[atIndex];\n if (picked) acceptAtCandidate(picked);\n } else if (key.escape) {\n // 退出补全 picker:删掉 @ 之后的字符,保留 @\n const idx = input.lastIndexOf(\"@\");\n if (idx >= 0) commitInput(input.slice(0, idx));\n }\n return;\n }\n\n // autocomplete 关闭时:↑/↓ 翻输入历史\n const hist = inputHistoryRef.current;\n if (key.upArrow && hist.length > 0) {\n const cur = historyIndexRef.current;\n if (cur === -1) savedDraftRef.current = input;\n const next = Math.min(cur + 1, hist.length - 1);\n historyIndexRef.current = next;\n commitInput(hist[hist.length - 1 - next] ?? \"\");\n } else if (key.downArrow) {\n const cur = historyIndexRef.current;\n if (cur === -1) return;\n const next = cur - 1;\n historyIndexRef.current = next;\n if (next === -1) commitInput(savedDraftRef.current);\n else commitInput(hist[hist.length - 1 - next] ?? \"\");\n }\n },\n // 模型在跑时也要响应键盘(让用户能 Ctrl+C / Shift+Tab / autocomplete 导航);\n // 仅模态弹起时让出键盘所有权\n { isActive: !pending && !picker && !sessionPicker && !questionPicker && !btwRequest },\n );\n\n // 输入框:picker 类模态弹起时仍保持可见但失焦(\"Chat about this\" 风格),\n // 真正抢键盘的 PermissionPrompt / ModelSelector / SessionSelector / BtwOverlay 才完全隐藏\n const acceptingInput = pending === null && picker === null && sessionPicker === null && questionPicker === null && btwRequest === null;\n const inputVisible = pending === null && picker === null && sessionPicker === null && btwRequest === null;\n const inputPlaceholder = questionPicker ? \"Chat about this\" : undefined;\n\n const actions: SlashActions = useMemo(\n () => ({\n setMessages: (msgs) => {\n messagesRef.current = msgs;\n agentRef.current?.setMessages(msgs);\n dispatch({ type: \"history_set\", messages: msgs });\n },\n pickModel: (items, currentId) =>\n new Promise<ModelEntry | null>((resolve) => {\n setPicker({ items, currentId, resolve });\n }),\n pickSession: (items, currentId) =>\n new Promise<SessionSummary | null>((resolve) => {\n setSessionPicker({ items, currentId, resolve });\n }),\n switchModel: async (modelId) => {\n if (!modelsRegistry) throw new Error(\"No models registry loaded.\");\n const entry = findEntry(modelsRegistry, modelId);\n if (!entry) throw new Error(`Model id \"${modelId}\" not in registry.`);\n setActiveModelEnv(entry);\n const next = createLLMClientFromModelEntry(entry);\n setLLM(next);\n await persistActiveModel(modelId);\n },\n getMode: () => permissions.getMode(),\n setMode: (m) => {\n permissions.setMode(m);\n setMode(m);\n },\n showProgress: (opts) => {\n setProgress({\n title: opts.title,\n tips: opts.tips ?? [],\n getPercent: opts.getPercent ?? (() => 0),\n startTime: Date.now(),\n });\n },\n hideProgress: () => setProgress(null),\n askBtw: (question) =>\n new Promise<void>((resolve) => {\n // history 锁定在 /btw 触发的瞬间——后续即使主对话有新消息,/btw 看到的也是当时的快照\n setBtwRequest({ question, history: messagesRef.current, resolve });\n }),\n openInEditor: (filePath) =>\n new Promise<void>((resolve, reject) => {\n // 让出 TTY 给外部编辑器(vi/vim/nano/code 等)。\n // Ink 暂停 raw mode → spawn editor with stdio:inherit → 退出后恢复。\n // vi 系编辑器会接管 stdin/stdout,Ink 自动暂停渲染;退出后 Ink 看到 stdin 恢复 redraw。\n const editor = process.env.VISUAL || process.env.EDITOR || \"vi\";\n try {\n if (process.stdin.isTTY) process.stdin.setRawMode?.(false);\n } catch {}\n const child = spawn(editor, [filePath], { stdio: \"inherit\" });\n child.on(\"exit\", (code) => {\n try {\n if (process.stdin.isTTY) process.stdin.setRawMode?.(true);\n } catch {}\n if (code === 0) resolve();\n else reject(new Error(`editor \"${editor}\" exited with code ${code}`));\n });\n child.on(\"error\", (err) => {\n try {\n if (process.stdin.isTTY) process.stdin.setRawMode?.(true);\n } catch {}\n reject(new Error(`editor \"${editor}\" failed: ${err.message}`));\n });\n }),\n reloadSettings: async () => {\n const { settings: nextSettings, sources } = await loadSettings(cwd);\n const { registry: nextModels } = await loadModelsRegistry();\n setSettings(nextSettings);\n setSettingsSources(sources);\n setPermissions(new PermissionGate(nextSettings.permissions));\n setModelsRegistry(nextModels);\n\n const wantModel = nextSettings.llm?.model;\n if (wantModel && wantModel !== llm.model) {\n try {\n const entry = nextModels ? findEntry(nextModels, wantModel) : undefined;\n if (entry) {\n setActiveModelEnv(entry);\n setLLM(createLLMClientFromModelEntry(entry));\n } else if (nextSettings.llm?.provider) {\n setLLM(\n createLLMClient({\n provider: nextSettings.llm.provider,\n model: wantModel,\n providers: nextSettings.providers ?? {},\n }),\n );\n }\n } catch {\n // 新配置当前不可用(缺 key 等);保留原 LLM 不抛断流\n }\n }\n return { settings: nextSettings, sources };\n },\n }),\n [cwd, modelsRegistry, llm.model, permissions],\n );\n\n const handleSubmit = useCallback(\n async (value: string) => {\n const rawValue = value.trim();\n if (!rawValue) return;\n // 裸 \"exit\" 视同 \"/exit\",方便从 shell 习惯过来的用户直接退出\n const trimmed = rawValue === \"exit\" ? \"/exit\" : rawValue;\n\n // autocomplete 开 + 有候选 + 用户没在精确命名 → 补全到 input,不提交\n if (autocomplete && autocomplete.matches.length > 0) {\n const exact = autocomplete.matches.find(\n (c) => c.name === autocomplete.query || c.aliases?.includes(autocomplete.query),\n );\n if (!exact) {\n const picked = autocomplete.matches[autocompleteIndex] ?? autocomplete.matches[0];\n commitInput(`/${picked.name}`);\n return;\n }\n }\n\n // @ autocomplete 开 + 有候选 → Enter 接受焦点而非提交\n if (atQuery !== null && atMatches.length > 0) {\n const picked = atMatches[atIndex];\n if (picked) {\n acceptAtCandidate(picked);\n return;\n }\n }\n\n // InputPipeline:slash-dispatch / paste-expand / at-file-expand / at-image /\n // template-expand / validate-length / redact-pre-scan\n const activeEntry = modelsRegistry ? findEntry(modelsRegistry, llm.model) : undefined;\n const inputCtx = createInputCtx({\n raw: trimmed,\n source: \"tty\",\n cwd,\n mode: permissions.getMode(),\n settings: settings.preprocess?.input,\n capabilities: { supportsImages: activeEntry?.supportsImages ?? false },\n });\n const pipeline = InputPipeline({\n pasteRegistry: pasteRegistryRef.current.map,\n imageRegistry: imageRegistryRef.current.map,\n disable: settings.preprocess?.disable,\n });\n try {\n await pipeline.run(inputCtx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n appendAssistantText(`[input pipeline error] ${msg}`);\n commitInput(\"\");\n return;\n }\n\n // pipeline 产出的告警(超长截断 / 脱敏命中 / @file 跳过等)显示给用户\n if (inputCtx.warnings.length > 0) {\n const msg = inputCtx.warnings.map((w) => `[${w.stage}] ${w.message}`).join(\"\\n\");\n appendAssistantText(msg);\n }\n\n // UserPromptSubmit hook:slash 命令不触发(slash 走系统自处理路径,不上 LLM)\n if (!inputCtx.slashCommand) {\n try {\n const hookOut = await runHooks(\n \"UserPromptSubmit\",\n { text: inputCtx.text, attachments: inputCtx.attachments, source: inputCtx.source },\n settings.hooks,\n );\n if (typeof hookOut.text === \"string\") inputCtx.text = hookOut.text;\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n appendAssistantText(`[blocked by UserPromptSubmit hook] ${err.reason}`);\n commitInput(\"\");\n return;\n }\n const msg = err instanceof Error ? err.message : String(err);\n appendAssistantText(`[UserPromptSubmit hook error] ${msg}`);\n commitInput(\"\");\n return;\n }\n }\n\n if (inputCtx.slashCommand) {\n // 模型在跑时 slash 命令一律拒绝——/clear /compact /resume 会改 messages 与 agent\n // 正在跑的回复冲突;reduce 也无法把 slash 排到队列里执行(会污染 history 时序)。\n if (state.status !== \"idle\") {\n commitInput(\"\");\n return;\n }\n const cmd = slash.get(inputCtx.slashCommand.name);\n commitInput(\"\");\n if (!cmd) {\n appendAssistantText(`Unknown command: /${inputCtx.slashCommand.name}. Try /help.`);\n return;\n }\n try {\n const result = await cmd.execute({\n args: inputCtx.slashCommand.args,\n cwd,\n llm,\n session,\n settings,\n settingsSources,\n modelsRegistry,\n history: messagesRef.current,\n tokens: {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.totalTokens,\n },\n listCommands: () => slash.list(),\n actions,\n });\n applySlashResult(result);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n appendAssistantText(`[error] /${inputCtx.slashCommand.name}: ${msg}`);\n }\n return;\n }\n\n commitInput(\"\");\n // 推入历史(去重相邻重复),重置游标。历史里存原文(用户在 ↑ 翻历史时见原始 trimmed)。\n const hist = inputHistoryRef.current;\n if (hist[hist.length - 1] !== trimmed) hist.push(trimmed);\n if (hist.length > 200) hist.shift();\n historyIndexRef.current = -1;\n savedDraftRef.current = \"\";\n\n // pipeline 输出组装成 user content:无附件→string;有附件→ContentPart[]\n const userContent = buildUserMessage(inputCtx);\n\n // 阻断空消息:InputPipeline 把占位符 / 模板等全消掉后,可能 text 空 + 无 attachment;\n // 直接送 LLM 会让模型\"自由发挥\"(看到空 user message 自己猜要干嘛)。\n const isEmpty =\n typeof userContent === \"string\"\n ? userContent.trim().length === 0\n : userContent.every(\n (p) => p.type !== \"file\" && p.type !== \"image\" && (p.type !== \"text\" || p.text.trim().length === 0),\n );\n if (isEmpty) {\n appendAssistantText(\n inputCtx.warnings.length > 0\n ? `(empty message after preprocessing — see warnings above; nothing sent)`\n : `(empty message — nothing sent)`,\n );\n return;\n }\n\n // 模型在跑 → 进 Agent 的 guidance 队列(注入到当前 turn,不开新 turn)。\n // Agent 主循环下一轮 stream 启动前 flushGuidance 会把它合并成一条 user 消息\n // 塞进 messages,然后触发 onGuidanceInjected → 这里 setGuidanceQueue([]) 清预览。\n if (state.status !== \"idle\") {\n agentRef.current?.enqueueGuidance(userContent);\n setGuidanceQueue((q) => [...q, userContent]);\n return;\n }\n\n dispatch({ type: \"user_submit\", stableUntil: messagesRef.current.length });\n turnStartTimeRef.current = Date.now(); // churned duration 基准\n // 立刻把用户消息塞进可见历史,UX 上\"瞬间出现\"\n {\n const userMsg: Message = { role: \"user\", content: userContent };\n const next = [...messagesRef.current, userMsg];\n messagesRef.current = next;\n dispatch({ type: \"history_set\", messages: next });\n }\n // 新建本轮 abort controller,Esc 触发它 → Agent 内 LLM stream + 工具 execa 联动中断\n const ctrl = (turnAbortRef.current = new AbortController());\n try {\n await agentRef.current?.runTurn(userContent, ctrl.signal);\n } catch (err) {\n if (ctrl.signal.aborted || isAbortLike(err)) {\n // 用户主动 Esc:Agent 内已经把已流出内容标 [interrupted] 持久化,这里只清屏\n dispatch({ type: \"stream_reset\" });\n dispatch({ type: \"set_status\", status: \"idle\" });\n } else {\n const msg = err instanceof Error ? err.message : String(err);\n dispatch({ type: \"set_stopped\", note: formatErrorForUser(msg) });\n dispatch({ type: \"set_status\", status: \"idle\" });\n }\n } finally {\n if (turnAbortRef.current === ctrl) turnAbortRef.current = null;\n }\n },\n [slash, cwd, llm, session, settings, settingsSources, modelsRegistry, state.inputTokens, state.outputTokens, state.totalTokens, state.status, actions, autocomplete, autocompleteIndex, atQuery, atMatches, atIndex, acceptAtCandidate, permissions],\n );\n\n function appendAssistantText(text: string) {\n const msg: Message = { role: \"assistant\", content: [{ type: \"text\", text }] };\n // 必须读 ref 而非闭包里的 state.history:上游可能刚通过 setMessages 改了历史\n // (/resume 加载 N 条 → applySlashResult 追加\"Resumed...\"),用 state.history\n // 会覆盖刚 load 进来的消息\n const next = [...messagesRef.current, msg];\n messagesRef.current = next;\n dispatch({ type: \"history_set\", messages: next });\n }\n\n function applySlashResult(result: SlashCommandResult) {\n if (result.exit) {\n // exit 带 display(/exit 的告别语):append 进 history → React 渲染 ● <text>,\n // 延后一帧再 unmount。Ink unmount 不主动清屏,最后一帧(含告别语)保留在终端。\n // 80ms = 5 帧,足够 React commit + Ink emit 完成。\n if (result.display !== undefined) {\n appendAssistantText(result.display);\n setTimeout(() => exit(), 80);\n } else {\n exit();\n }\n return;\n }\n if (result.display !== undefined) {\n appendAssistantText(result.display);\n }\n }\n\n /**\n * 双 Esc rewind:找最后一条 user message,把它的文本塞回输入框,删除它和它之后的所有消息。\n * 这是 \"Double Esc time-machine\" 形态的简化版(muse 没做 file checkpoint)。\n * 返 true 表示成功 rewind,false 表示没东西可 rewind。\n */\n function rewindLastTurn(): boolean {\n const msgs = messagesRef.current;\n // 倒着找最后一条 user message\n let userIdx = -1;\n for (let i = msgs.length - 1; i >= 0; i--) {\n if (msgs[i].role === \"user\") {\n userIdx = i;\n break;\n }\n }\n if (userIdx < 0) return false;\n const userMsg = msgs[userIdx];\n const text = typeof userMsg.content === \"string\"\n ? userMsg.content\n : userMsg.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n // 删该 user message 自己 + 之后所有\n const next = msgs.slice(0, userIdx);\n messagesRef.current = next;\n agentRef.current?.setMessages(next);\n dispatch({ type: \"history_set\", messages: next });\n // 塞回输入框\n commitInput(text);\n return true;\n }\n\n // Banner 直接挂在根 column 内,在 React reconcile 里属于稳定子树不会重 mount。\n // (曾经试过包 <Static>,Ink 在嵌套 Box children 渲染时可能不输出 banner,改回直接挂。)\n const banner = !showBanner\n ? null\n : pickBanner(termWidth, { version: VERSION, model: llm.model, cwd: shortCwd(cwd) });\n\n // 配对 tool_use ↔ tool_result:AssistantMessage 把 result 内联渲染在 call 下方(树形);\n // 顶层 history loop 跳过已被内联的 ToolMessage 避免重复。\n // 注意:tool message 在 batch 模式下也算\"已内联\"(由 BatchedToolBlock 接管显示),\n // 所以 inlinedIds 在下面 useMemo 里建立后,batch grouping 与 render 都依赖它。\n const { resultsByCallId, inlinedIds } = useMemo(() => {\n const byId = new Map<string, ToolMessage>();\n const used = new Set<string>();\n for (const m of state.history) {\n if (m.role === \"tool\" && m.toolUseId) byId.set(m.toolUseId, m);\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n for (const p of m.content) {\n if (p.type === \"tool_use\") used.add(p.id);\n }\n }\n }\n return { resultsByCallId: byId, inlinedIds: used };\n }, [state.history]);\n\n // Batch 聚合 + TodoWrite 去重:\n // 1) 连续 \"只含 tool_use(且非 TodoWrite)\" 的 assistant message 合并为 BatchedToolBlock\n // (muse 的 agent 串行 tool loop——每个工具单独一条 assistant message,散开体验差)\n // 2) TodoWrite 是 in-place 状态更新语义:history 里 N 次 TodoWrite 只渲染最后一次的 → Todos,\n // 前面的 TodoWrite-only message 全部跳过(避免多个 → Todos 块刷屏)\n // maxSrcIdx:group 涉及的 history index 上界,用于 Static 切分(< stableUntilIdx → 进 Static)\n type RenderGroup =\n | { kind: \"msg\"; key: string; msg: Message; maxSrcIdx: number }\n | { kind: \"batch\"; key: string; uses: BatchedToolUse[]; maxSrcIdx: number }\n // banner 作为 Static 第一项,跟历史一起被 hoist 到 stdout 顶部。\n // 否则 banner 在 Static 节点之前的 dynamic 区域,Ink 5 在 Static commit 时\n // 会把 Static 内容 hoist 到 banner 之上,视觉上 banner 跑到历史中间。\n | { kind: \"banner\"; key: string; maxSrcIdx: number }\n // 每个 turn 末尾的灰色摘要行(`✶ Churned for Xm Ys`),来自 state.turnEnds\n | { kind: \"churned\"; key: string; durationMs: number; maxSrcIdx: number };\n // 反扫找最后一次 TodoWrite 的 part id —— part 级去重的锚点(grouping + MessageView 共用)\n const latestTodoWritePartId = useMemo(() => {\n for (let i = state.history.length - 1; i >= 0; i--) {\n const m = state.history[i];\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n // 一条 message 里可能有多个 TodoWrite,取最后一个\n for (let j = m.content.length - 1; j >= 0; j--) {\n const p = m.content[j];\n if (p.type === \"tool_use\" && p.name === \"TodoWrite\") return p.id;\n }\n }\n }\n return undefined;\n }, [state.history]);\n\n // sticky TodoList(底部固定):扫 history[todosSinceTurnIdx..] 之间最新一次 TodoWrite 的 args\n // 历史区 TodoWrite 不再渲染(AssistantMessage 跳过),全部交给底部 sticky 显示\n const stickyTodos = useMemo(() => {\n for (let i = state.history.length - 1; i >= state.todosSinceTurnIdx; i--) {\n const m = state.history[i];\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n for (let j = m.content.length - 1; j >= 0; j--) {\n const p = m.content[j];\n if (p.type === \"tool_use\" && p.name === \"TodoWrite\") {\n return { args: p.args, key: p.id };\n }\n }\n }\n }\n return null;\n }, [state.history, state.todosSinceTurnIdx]);\n\n const renderGroups = useMemo(() => {\n // 反扫找最后一次出现 TodoWrite 的 assistant message index\n let lastTodoWriteIdx = -1;\n for (let i = state.history.length - 1; i >= 0; i--) {\n const m = state.history[i];\n if (m.role === \"assistant\" && Array.isArray(m.content)) {\n if (m.content.some((p) => p.type === \"tool_use\" && p.name === \"TodoWrite\")) {\n lastTodoWriteIdx = i;\n break;\n }\n }\n }\n const groups: RenderGroup[] = [];\n let pending: Array<{ part: ToolUsePart; result?: ToolMessage; srcIndex: number; srcMsg: Message }> = [];\n const flush = () => {\n if (pending.length === 0) return;\n const maxSrc = pending[pending.length - 1].srcIndex;\n if (pending.length === 1) {\n groups.push({ kind: \"msg\", key: `msg-${pending[0].srcIndex}`, msg: pending[0].srcMsg, maxSrcIdx: maxSrc });\n } else {\n groups.push({\n kind: \"batch\",\n key: `batch-${pending[0].srcIndex}-${maxSrc}`,\n uses: pending.map((p) => ({ part: p.part, result: p.result })),\n maxSrcIdx: maxSrc,\n });\n }\n pending = [];\n };\n for (let i = 0; i < state.history.length; i++) {\n const msg = state.history[i];\n if (msg.role === \"tool\" && msg.toolUseId && inlinedIds.has(msg.toolUseId)) continue;\n // 跳过所有 TodoWrite-only assistant message:TodoWrite 现在全部交给底部 sticky TodoList\n // 渲染,历史区不再显示(固定底部体验)\n if (msg.role === \"assistant\" && Array.isArray(msg.content)) {\n const isTodoWriteOnly =\n msg.content.length > 0 &&\n msg.content.every((p) => p.type === \"tool_use\" && p.name === \"TodoWrite\");\n if (isTodoWriteOnly) {\n flush();\n continue;\n }\n }\n if (msg.role === \"assistant\" && Array.isArray(msg.content)) {\n // 只对\"纯读 / 无副作用\"工具做 message-level batch 聚合:Read/Glob/Grep/MemoryRead\n // Edit/Write/Bash/WebFetch/AskUserQuestion/TodoWrite 等有 side effect 的工具\n // 必须独立显示(diff / 输出 / 副作用确认是用户必看的产物),不能进 batch 折叠。\n const onlyBatchable =\n msg.content.length > 0 &&\n msg.content.every((p) => p.type === \"tool_use\" && BATCHABLE_TOOLS.has(p.name));\n if (onlyBatchable) {\n for (const p of msg.content) {\n if (p.type === \"tool_use\") {\n pending.push({ part: p, result: resultsByCallId.get(p.id), srcIndex: i, srcMsg: msg });\n }\n }\n continue;\n }\n }\n flush();\n groups.push({ kind: \"msg\", key: `msg-${i}`, msg, maxSrcIdx: i });\n }\n flush();\n // 把 turnEnds 转 churned group 插入到对应 history 位置之后:\n // turnEnd.atHistoryLen = N → 渲染在 maxSrcIdx === N-1 的 group 之后\n if (state.turnEnds.length > 0) {\n const merged: RenderGroup[] = [];\n let teIdx = 0;\n for (const g of groups) {\n merged.push(g);\n // 检查后续 turnEnds 是否应该插在该 group 之后\n while (\n teIdx < state.turnEnds.length &&\n state.turnEnds[teIdx].atHistoryLen <= g.maxSrcIdx + 1\n ) {\n const te = state.turnEnds[teIdx];\n merged.push({\n kind: \"churned\",\n key: `churned-${te.atHistoryLen}-${teIdx}`,\n durationMs: te.durationMs,\n maxSrcIdx: g.maxSrcIdx,\n });\n teIdx++;\n }\n }\n // 剩余 turnEnds(超出当前 history 范围,理论上不会发生)\n while (teIdx < state.turnEnds.length) {\n const te = state.turnEnds[teIdx];\n merged.push({\n kind: \"churned\",\n key: `churned-${te.atHistoryLen}-${teIdx}`,\n durationMs: te.durationMs,\n maxSrcIdx: state.history.length - 1,\n });\n teIdx++;\n }\n return merged;\n }\n return groups;\n }, [state.history, resultsByCallId, inlinedIds, state.turnEnds]);\n\n // 按 stableUntilIdx 切分 renderGroups:稳定 groups 走 Static,不再参与重画;动态 groups 走普通渲染。\n // 这是修复\"工具快速完成时全 history 重绘 → 闪屏\"的关键(详见 实现日志)。\n // **banner 也走 Static**(prepend 第一项),否则 Ink 5 会把后续增量 commit 的 Static 内容\n // hoist 到 banner 之上,视觉上\"banner 跑到中间\"(实现日志 2026-06-07 banner-static 一节)。\n const { staticGroups, dynamicGroups } = useMemo(() => {\n const cutoff = state.stableUntilIdx;\n const staticG: typeof renderGroups = [];\n const dynamicG: typeof renderGroups = [];\n if (showBanner) {\n // maxSrcIdx=-1 表示永远落在 cutoff 之前 → 始终归 Static\n staticG.push({ kind: \"banner\", key: \"banner-static\", maxSrcIdx: -1 });\n }\n for (const g of renderGroups) {\n if (g.maxSrcIdx < cutoff) staticG.push(g);\n else dynamicG.push(g);\n }\n return { staticGroups: staticG, dynamicGroups: dynamicG };\n }, [renderGroups, state.stableUntilIdx, showBanner]);\n\n return (\n <Box flexDirection=\"column\">\n {/* 稳定历史 + banner(若启用)一起走 Static:Ink 一次 emit 到 stdout,后续 state 变化\n 不再 reconcile/repaint 这些行 → 消除闪屏 + 防 banner 被 Static commit hoist 推到中间。 */}\n <Static items={staticGroups}>\n {(g) =>\n g.kind === \"banner\" ? (\n <React.Fragment key={g.key}>{banner}</React.Fragment>\n ) : g.kind === \"batch\" ? (\n <BatchedToolBlock key={g.key} uses={g.uses} />\n ) : g.kind === \"churned\" ? (\n <ChurnedLine key={g.key} durationMs={g.durationMs} />\n ) : (\n <MessageView\n key={g.key}\n message={g.msg}\n resultsByCallId={resultsByCallId}\n latestTodoWritePartId={latestTodoWritePartId}\n />\n )\n }\n </Static>\n <Box flexDirection=\"column\" marginTop={1}>\n {dynamicGroups.map((g) => {\n // banner 永远 maxSrcIdx=-1 → 始终在 staticGroups,不会出现在 dynamic;TS narrowing 用\n if (g.kind === \"banner\") return null;\n if (g.kind === \"batch\") {\n return <BatchedToolBlock key={g.key} uses={g.uses} lastStartedToolId={state.lastStartedToolId} />;\n }\n if (g.kind === \"churned\") {\n return <ChurnedLine key={g.key} durationMs={g.durationMs} />;\n }\n return (\n <MessageView\n key={g.key}\n message={g.msg}\n resultsByCallId={resultsByCallId}\n latestTodoWritePartId={latestTodoWritePartId}\n />\n );\n })}\n {state.streamingText && (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color=\"cyan\">{DOT} </Text>\n <Box flexDirection=\"column\" flexGrow={1}>\n {/* 流式 markdown 渲染:已闭合 block(段/代码块/list)实时渲染成 ANSI\n 样式;未闭合段保留纯文本。Block 级缓存(React.memo + useMemo)\n 让闭合后的旧 block 不重 parse、不重 render — Ink 看到同样的 Text\n child 也会减少 erase,显著降低长输出的闪屏(业界同样思路)。 */}\n <StreamingMarkdown text={state.streamingText} />\n </Box>\n </Box>\n )}\n </Box>\n {pending && (\n <PermissionPrompt\n request={{\n ...pending,\n resolve: (decision) => {\n pending.resolve(decision);\n setPending(null);\n },\n }}\n />\n )}\n {picker && (\n <ModelSelector\n request={{\n ...picker,\n resolve: (m) => {\n picker.resolve(m);\n setPicker(null);\n },\n }}\n />\n )}\n {sessionPicker && (\n <SessionSelector\n request={{\n ...sessionPicker,\n resolve: (s) => {\n sessionPicker.resolve(s);\n setSessionPicker(null);\n },\n }}\n />\n )}\n {questionPicker && (\n <QuestionPicker\n request={{\n questions: questionPicker.questions,\n resolve: (responses) => {\n questionPicker.resolve(responses);\n setQuestionPicker(null);\n },\n }}\n />\n )}\n {btwRequest && (\n <BtwOverlay\n request={{\n ...btwRequest,\n resolve: () => {\n btwRequest.resolve();\n setBtwRequest(null);\n },\n }}\n llm={llm}\n />\n )}\n {/* Sticky TodoList:固定在输入框上方(状态行之上),跨工具调用持续可见。\n 每次 user_submit 时 todosSinceTurnIdx 重置 → 旧 turn 的 todos 立即消失。\n turn 内 LLM 调 TodoWrite 后这里实时更新;turn 结束(全 completed)仍显示\n 到下次用户输入。 */}\n {stickyTodos && (\n <TodoList\n key={stickyTodos.key}\n todos={extractTodos(stickyTodos.args)}\n listTitle={extractListTitle(stickyTodos.args)}\n />\n )}\n {state.status !== \"idle\" && (\n <StatusLine\n startTime={state.turnStartTime}\n firstTextTime={state.turnFirstTextTime}\n inputTokens={state.turnInputTokens}\n runningTool={state.runningTool}\n lang={lang}\n />\n )}\n {progress && <ProgressBanner state={progress} />}\n {state.stoppedNote && (\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>{state.stoppedNote}</Text>\n </Box>\n )}\n {inputVisible && (\n <Box flexDirection=\"column\">\n {guidanceQueue.length > 0 && (() => {\n // 引导框 #404040 灰底(输入框 #1c1c1c,亮度差 36),\n // 左 4 cells marginLeft 缩进 + 右侧总宽留 4 cells 空 → 左右两端都比输入框短。\n // 固定宽度(不再跟内容长度变);内容超过宽度截 70 字符 + \"…\"。\n const INDENT = 4;\n const RIGHT_PAD = 4;\n const innerWidth = Math.max(20, termWidth - 1 - INDENT - RIGHT_PAD);\n return (\n <Box flexDirection=\"column\" marginTop={1} marginLeft={INDENT}>\n {guidanceQueue.map((q, i) => {\n const preview = previewUserContent(q);\n const shown = preview.length > 70 ? preview.slice(0, 70) + \"…\" : preview;\n const text = ` ↳ 引导 ${shown}`;\n // stringWidth 算上 CJK 双宽;pad 用空格补到 innerWidth cells\n const padCells = Math.max(1, innerWidth - stringWidth(text));\n return (\n <Box key={i} flexDirection=\"row\">\n <Text backgroundColor=\"#404040\">{text + \" \".repeat(padCells)}</Text>\n </Box>\n );\n })}\n </Box>\n );\n })()}\n {/* 有 guidance 时输入框贴紧;无 guidance 时回到 marginTop=1 */}\n <Box marginTop={guidanceQueue.length > 0 ? 0 : 1} flexDirection=\"column\">\n <Text backgroundColor=\"#1c1c1c\">\n {\" \".repeat(Math.max(1, termWidth - 1))}\n </Text>\n <Box flexDirection=\"row\">\n <Text backgroundColor=\"#1c1c1c\" color=\"gray\" bold>\n {\" › \"}\n </Text>\n <BgTextInput\n key={inputRemountKey}\n value={input}\n onChange={setInput}\n onSubmit={handleSubmit}\n width={Math.max(10, termWidth - 4)}\n backgroundColor=\"#1c1c1c\"\n isActive={acceptingInput}\n onPaste={handlePaste}\n onPasteImage={handlePasteImage}\n placeholder={inputPlaceholder}\n />\n </Box>\n <Text backgroundColor=\"#1c1c1c\">\n {\" \".repeat(Math.max(1, termWidth - 1))}\n </Text>\n </Box>\n {autocomplete && autocomplete.matches.length > 0 && (\n <SlashAutocomplete matches={autocomplete.matches} index={autocompleteIndex} />\n )}\n {atQuery !== null && atMatches.length > 0 && (\n <AtFileAutocomplete matches={atMatches} index={atIndex} />\n )}\n </Box>\n )}\n <Box flexDirection=\"column\">\n <FooterStatus\n sessionId={session.meta.id}\n model={llm.model}\n contextWindow={llm.capabilities.maxContextWindow}\n lastInputTokens={state.turnInputTokens}\n sessionInputTokens={state.inputTokens}\n sessionOutputTokens={state.outputTokens}\n termWidth={termWidth}\n />\n <PermissionModeBar mode={mode} compact={termWidth < 60} />\n {escHint && (\n <Box flexDirection=\"row\">\n <Text dimColor>{escHint}</Text>\n </Box>\n )}\n </Box>\n </Box>\n );\n}\n\nfunction extractUserInputs(messages: Message[]): string[] {\n const out: string[] = [];\n for (const m of messages) {\n if (m.role !== \"user\") continue;\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n // 跳过 /compact 注入的 \"[Previous conversation summary]\" 等系统消息\n if (text.startsWith(\"[Previous conversation summary]\")) continue;\n if (text.trim()) out.push(text);\n }\n return out;\n}\n\n/** 队列 / 历史预览:从 string 或 ContentPart[] 抽一段可读字符。 */\n/**\n * 判断错误是否是用户主动 abort 的(Esc/Ctrl+C)。覆盖 Vercel SDK \"This operation was aborted\"\n * 这种 name 不是 AbortError 但 message 带关键字的 case。\n */\n/**\n * 把 LLM / provider 抛出来的错误转成给用户看的灰字提示。\n * - \"unavailable tool 'X'\" 这类是切换 mode 后历史里仍有禁用工具的 server 拒绝;\n * 告诉用户\"模型试图调用 X(当前模式不允许)\",避免红字 [error] 跟模型回答混在一起\n * - 其他错误保留原文(英文一句),前缀 ⚠\n */\nfunction formatErrorForUser(message: string): string {\n const m = message.trim();\n // server 端拒绝:`...unavailable tool 'Edit'...`\n const unavail = m.match(/unavailable tool ['\"]?([A-Za-z_][\\w]*)['\"]?/i);\n if (unavail) {\n return `⚠ 模型试图调用 ${unavail[1]},当前模式不允许;请切换模式或换种问法`;\n }\n // 通用网络 / 超时归类\n if (/timeout|timed out|ETIMEDOUT/i.test(m)) return `⚠ 请求超时,请重试`;\n if (/ECONNREFUSED|ENOTFOUND|ECONNRESET/i.test(m)) return `⚠ 网络无法连接 provider`;\n if (/rate limit|429/i.test(m)) return `⚠ 触发 provider 限流,稍候重试`;\n return `⚠ ${m}`;\n}\n\nfunction isAbortLike(err: unknown): boolean {\n if (!err) return false;\n if (err instanceof Error) {\n if (err.name === \"AbortError\") return true;\n const code = (err as Error & { code?: string }).code;\n if (code === \"ABORT_ERR\" || code === \"ECANCELED\") return true;\n const msg = err.message.toLowerCase();\n if (msg.includes(\"aborted\") || msg.includes(\"cancelled\") || msg.includes(\"canceled\")) return true;\n }\n return false;\n}\n\n/** 单个 turn 结尾的灰色摘要行,`✶ Churned for Xm Ys` 风格。 */\nfunction ChurnedLine({ durationMs }: { durationMs: number }) {\n return (\n <Box marginTop={1}>\n <Text dimColor>{`✶ Churned for ${formatChurnedDuration(durationMs)}`}</Text>\n </Box>\n );\n}\n\nfunction formatChurnedDuration(ms: number): string {\n const sec = Math.max(0, Math.round(ms / 1000));\n if (sec < 60) return `${sec}s`;\n const m = Math.floor(sec / 60);\n const s = sec % 60;\n return s === 0 ? `${m}m` : `${m}m ${s}s`;\n}\n\nfunction previewUserContent(input: string | ContentPart[]): string {\n if (typeof input === \"string\") return input;\n const text = input\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\" \")\n .trim();\n const fileCount = input.filter((p) => p.type === \"file\").length;\n const imageCount = input.filter((p) => p.type === \"image\").length;\n const tags: string[] = [];\n if (fileCount > 0) tags.push(`📎 ${fileCount}`);\n if (imageCount > 0) tags.push(`🖼 ${imageCount}`);\n return tags.length > 0 ? `${text} (${tags.join(\", \")})` : text;\n}\n\nfunction shortCwd(cwd: string): string {\n const home = homedir();\n if (cwd === home) return \"~\";\n if (cwd.startsWith(home + \"/\")) return \"~\" + cwd.slice(home.length);\n return cwd;\n}\n\n/**\n * 把当前选中的 model id 写回 ~/.muse/settings.json llm.model。\n *\n * 这是 muse 第一次\"写配置\"。策略:read-modify-write 整文件,pretty-print 2 空格。\n * 不强制 chmod —— settings.json 不放明文 key,敏感数据在 settings.local.json。\n */\nasync function persistActiveModel(modelId: string): Promise<void> {\n const path = join(homedir(), \".muse\", \"settings.json\");\n let current: Record<string, unknown> = {};\n if (existsSync(path)) {\n try {\n current = JSON.parse(await readFile(path, \"utf-8\")) as Record<string, unknown>;\n } catch {\n current = {};\n }\n }\n const llm = (current.llm as Record<string, unknown> | undefined) ?? {};\n const next = { ...current, llm: { ...llm, model: modelId } };\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, JSON.stringify(next, null, 2) + \"\\n\", \"utf-8\");\n}\n","/**\n * 自带背景色的轻量输入组件,替换 ink-text-input。\n *\n * Why:Ink 的 Box 不支持 backgroundColor 属性(只有 Text 支持),\n * 而 ink-text-input 输出的 Text 不暴露 bg 注入口。要实现\"整行高亮背景\"\n * 的输入条(对齐主流 TUI Agent 形态),最干净的方式是自己渲染。\n *\n * 实现:单个 Text 节点,padEnd 到 width 让 bg 填满整行。\n * 光标用 inverse 字符表示,超出 width 时做左侧 viewport 裁切常驻光标可见。\n *\n * 终端列宽口径:用 charWidth() 处理 CJK / 全角等 2 列字符,避免内容超 width\n * 时换行(换行让 Ink 渲染高度变化,引起上面内容被顶上去——非常显眼的 bug)。\n *\n * 不支持:多行、IME 复合输入、emoji 代理对的精确光标位置——v0.1 范围。\n */\n\nimport React, { useState, useEffect } from \"react\";\nimport { Text, useInput } from \"ink\";\nimport { grabClipboardImageBufferSync } from \"../clipboard/image.js\";\n\nexport interface BgTextInputProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n /** 主体内容可用宽度(\"› \" 这种前缀外),用于 padEnd 让 bg 填满整行。 */\n width: number;\n /** Tailwind 风 hex 或 Ink 颜色名。 */\n backgroundColor: string;\n /** 前景文字颜色;不传时用终端默认。 */\n color?: string;\n /** 是否启用键盘(弹模态时调用方传 false 让出键盘所有权)。 */\n isActive?: boolean;\n /**\n * 检测到一段疑似粘贴(含换行 或 > 200 字符)时回调;返回的字符串作为实际插入内容\n * 替换原始 chunk。调用方一般注册原文到 paste registry,返回 `[Pasted text #N ...]`\n * 占位符,避免 \\n 进入输入框造成多行渲染。\n */\n onPaste?: (chunk: string) => string;\n /**\n * paste 事件触发时,先**同步检测系统剪贴板是否含图片**;含图则跳过文本 paste\n * 路径,改调本回调:调用方一般把图保存到 image registry,返回 `[Image #N]` 占位符。\n *\n * 这是对齐业界 TUI Agent 的 Cmd+V 真粘图体验:用户复制图后按 Cmd+V,输入框直接出现\n * `[Image #N]`,无需 `/image` slash 命令。\n *\n * 仅 macOS / Linux 实装;Windows 返 null。\n */\n onPasteImage?: (data: Buffer, mediaType: \"image/png\") => string;\n /**\n * value 为空时显示的暗淡占位文本——典型场景:弹模态时 isActive=false,\n * 输入框仍可见但失焦,用 placeholder 透出 \"Chat about this\" 之类的提示。\n */\n placeholder?: string;\n}\n\nconst BLINK_MS = 530; // 标准终端 cursor 闪烁周期\nconst PASTE_CHAR_THRESHOLD = 200;\n\n// 光标前如果以下述占位符之一结尾,backspace/delete 一次性删整段。\n// 这两个占位符在 muse 里语义是\"原子附件单元\",字符级删除会留下 [Imag、[Pasted text #1 +3 这种半残的难看尾巴。\nconst PLACEHOLDER_TAIL_RE = /\\[Image #\\d+\\]$|\\[Pasted text #\\d+ \\+\\d+ lines\\]$/;\n\nfunction looksLikePaste(input: string): boolean {\n // \\r 也算:macOS Terminal / iTerm 粘贴多段文本时换行常为 \\r 而非 \\n,\n // 落进 value 后 \\r 会被终端解释为回车(光标回行首)→ 后文覆盖前文,看着像\"丢消息\"\n return input.includes(\"\\n\") || input.includes(\"\\r\") || input.length > PASTE_CHAR_THRESHOLD;\n}\n\n// bracketed paste 转义:部分终端把粘贴包成 \\x1b[200~...\\x1b[201~,Ink 不一定剥\nfunction stripBracketedPaste(s: string): string {\n return s.replace(/\\x1b\\[20[01]~/g, \"\");\n}\n\n// 统一换行:\\r\\n → \\n、裸 \\r → \\n\n// 用途:粘贴 chunk 在注册到 registry 前先规范化,避免 \\r 流进 value / 历史 / LLM\nfunction normalizeLineEndings(s: string): string {\n return s.replace(/\\r\\n?/g, \"\\n\");\n}\n\n// 拖文件到终端时:\n// - macOS Terminal.app 默认发 `/abs/path.png`(空格转义)\n// - iTerm2 默认 `'/abs/path.png'`(单引号)或开启 file://;\n// - 部分 linux 终端发 `file:///abs/path.png`\n// 输入若是上述独立单个 image path,自动 prepend `@` 并加空格,让 InputPipeline\n// 的 at-image stage 识别。仅识别 image 扩展名 — 非图片由用户显式 `@` 引用。\nconst IMAGE_EXT_RE = /\\.(?:png|jpg|jpeg|gif|webp)$/i;\nexport function maybeWrapImagePath(s: string): string {\n const t = s.trim().replace(/^['\"]|['\"]$/g, \"\");\n // 必须单一 token(无中间空白),且看起来像绝对路径或 file:// URL,且扩展名图片\n if (/\\s/.test(t)) return s;\n let path: string | null = null;\n const fileUrl = t.match(/^file:\\/\\/(\\/.+)$/i);\n if (fileUrl) path = decodeURI(fileUrl[1]);\n else if (t.startsWith(\"/\")) path = t;\n if (!path || !IMAGE_EXT_RE.test(path)) return s;\n return `@${path} `;\n}\n\nexport function BgTextInput({\n value,\n onChange,\n onSubmit,\n width,\n backgroundColor,\n color,\n isActive = true,\n onPaste,\n onPasteImage,\n placeholder,\n}: BgTextInputProps) {\n const [cursor, setCursor] = useState(value.length);\n const [blinkOn, setBlinkOn] = useState(true);\n\n useEffect(() => {\n // value 外部改变(commitInput / remount)时把光标移到末尾或夹在合法范围\n setCursor((c) => Math.min(c, value.length));\n }, [value]);\n\n // 光标闪烁:cursor / value 变化时重启 timer 让光标\"常亮\"过编辑动作;\n // isActive=false(模态弹起)时不闪也不显。\n // settings.env.MUSE_DISABLE_CURSOR_BLINK=1 → 不启动 interval,光标常亮。\n useEffect(() => {\n if (!isActive) return;\n setBlinkOn(true);\n if (process.env.MUSE_DISABLE_CURSOR_BLINK === \"1\") return; // 常亮\n const id = setInterval(() => setBlinkOn((b) => !b), BLINK_MS);\n return () => clearInterval(id);\n }, [isActive, cursor, value]);\n\n useInput(\n (input, key) => {\n if (key.return) {\n onSubmit?.(value);\n return;\n }\n if (key.backspace || key.delete) {\n if (cursor === 0) return;\n // 占位符整体删除:[Image #N] / [Pasted text #N +M lines] 视作一个不可拆原子单元\n const before = value.slice(0, cursor);\n const tail = before.match(PLACEHOLDER_TAIL_RE);\n const len = tail ? tail[0].length : 1;\n const next = value.slice(0, cursor - len) + value.slice(cursor);\n onChange(next);\n setCursor((c) => Math.max(0, c - len));\n return;\n }\n if (key.leftArrow) {\n setCursor((c) => Math.max(0, c - 1));\n return;\n }\n if (key.rightArrow) {\n setCursor((c) => Math.min(value.length, c + 1));\n return;\n }\n if (key.ctrl && input === \"a\") {\n setCursor(0);\n return;\n }\n if (key.ctrl && input === \"e\") {\n setCursor(value.length);\n return;\n }\n // Ctrl+V:从剪贴板读图片插入 [Image #N] 占位符。\n // 兼容 Ink 几种可能的 dispatch 形态(实测有差异):\n // - key.ctrl=true + input=\"v\"\n // - 裸 SYN 字符 \\x16 直接进 input(部分 ink 版本/raw mode)\n const isCtrlV =\n (key.ctrl && input === \"v\") || input === \"\\x16\" || input.startsWith(\"\\x16\");\n if (isCtrlV && onPasteImage) {\n const img = grabClipboardImageBufferSync();\n if (img) {\n const placeholder = onPasteImage(img.data, img.mediaType);\n const next = value.slice(0, cursor) + placeholder + value.slice(cursor);\n onChange(next);\n setCursor((c) => c + placeholder.length);\n }\n return;\n }\n // 不消费 Ctrl+C / Shift+Tab / ↑↓ / Tab / Esc / meta——交给 App 顶层 useInput\n if (key.ctrl || key.shift || key.tab || key.escape || key.upArrow || key.downArrow || key.meta) {\n return;\n }\n // 普通字符(含粘贴):在光标处插入\n if (input && !key.return) {\n // 先剥 bracketed paste 转义,再统一换行符——\\r 不处理会让后续渲染 / LLM 都吃坏\n let cleaned = normalizeLineEndings(stripBracketedPaste(input));\n if (!cleaned) return;\n // 拖图片到终端 → 自动 prepend @ 让 at-image stage 识别\n cleaned = maybeWrapImagePath(cleaned);\n // 检测疑似粘贴:交给调用方决定要不要替换成占位符\n // 避免 \\n 直接进 value 让 Text 渲染成多行,把输入框撑到看不见前文\n const insertion =\n onPaste && looksLikePaste(cleaned) ? onPaste(cleaned) : cleaned;\n const next = value.slice(0, cursor) + insertion + value.slice(cursor);\n onChange(next);\n setCursor((c) => c + insertion.length);\n }\n },\n { isActive },\n );\n\n // 光标渲染:active + blinkOn 时 inverse 高亮;blinkOff 或 inactive 时\n // 保持背景色不显光标,单元格宽度不变(避免布局抖动)\n const showCursor = isActive && blinkOn;\n\n // 空 value + 有 placeholder → 占位文本模式(暗淡显示,\"Chat about this\" 风格)\n if (value.length === 0 && placeholder) {\n // 留 1 列给光标位\n const maxW = Math.max(0, width - 1);\n let truncated = placeholder;\n while (stringWidth(truncated) > maxW && truncated.length > 0) {\n truncated = truncated.slice(0, -1);\n }\n const usedW = 1 + stringWidth(truncated);\n const padLen = Math.max(0, width - usedW);\n return (\n <Text backgroundColor={backgroundColor} color={color}>\n {showCursor ? (\n <Text backgroundColor=\"blue\" color={color} dimColor>\n {\" \"}\n </Text>\n ) : (\n <Text backgroundColor={backgroundColor} color={color}>\n {\" \"}\n </Text>\n )}\n <Text backgroundColor={backgroundColor} dimColor>\n {truncated}\n </Text>\n {\" \".repeat(padLen)}\n </Text>\n );\n }\n\n // 视口计算:保证整行可视宽度 == width,光标永远可见\n // 显示前把 \\n / \\r 换成 ↵(1 列宽可视符),避免 Ink Text 渲染成真换行 / 回车——\n // 换行会把输入框撑成多行;回车更糟,会让后文覆盖前文看着像\"消息丢了\"\n const displayValue = value.replace(/[\\n\\r]/g, \"↵\");\n const view = computeViewport(displayValue, cursor, width);\n const at = view.atChar;\n const padLen = Math.max(0, width - view.consumedWidth);\n\n return (\n <Text backgroundColor={backgroundColor} color={color}>\n {view.before}\n {showCursor ? (\n <Text backgroundColor=\"blue\" color={color} dimColor>\n {at}\n </Text>\n ) : (\n <Text backgroundColor={backgroundColor} color={color}>\n {at}\n </Text>\n )}\n {view.after}\n {\" \".repeat(padLen)}\n </Text>\n );\n}\n\n// ---------- helpers ----------\n\n/** 估计单字符在终端的列宽:CJK / 全角 = 2,控制符 = 0,其余 = 1。 */\nfunction charWidth(ch: string): number {\n const cp = ch.codePointAt(0);\n if (cp === undefined) return 0;\n if (cp < 0x20 || cp === 0x7f) return 0;\n if (\n (cp >= 0x1100 && cp <= 0x115f) || // Hangul Jamo\n (cp >= 0x2e80 && cp <= 0x303e) || // CJK Radicals\n (cp >= 0x3041 && cp <= 0x33ff) || // Hiragana / Katakana / CJK Symbols\n (cp >= 0x3400 && cp <= 0x4dbf) || // CJK Ext A\n (cp >= 0x4e00 && cp <= 0x9fff) || // CJK Unified\n (cp >= 0xa000 && cp <= 0xa4cf) || // Yi\n (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables\n (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compat\n (cp >= 0xfe30 && cp <= 0xfe4f) || // CJK Compat Forms\n (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth ASCII / Punctuation\n (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Sign\n (cp >= 0x20000 && cp <= 0x2fffd) // CJK Ext B–F\n ) {\n return 2;\n }\n return 1;\n}\n\nexport function stringWidth(s: string): number {\n let w = 0;\n for (const ch of s) w += charWidth(ch);\n return w;\n}\n\ninterface Viewport {\n before: string;\n atChar: string;\n after: string;\n consumedWidth: number;\n}\n\n/**\n * 计算视口:保证渲染宽度 == width,光标永远在可视范围内。\n * 溢出时从左侧裁掉字符让窗口右沿吃下光标。\n */\nfunction computeViewport(value: string, cursor: number, width: number): Viewport {\n const cursorAtEnd = cursor >= value.length;\n const atChar = cursorAtEnd ? \" \" : value[cursor] ?? \" \";\n const cursorCellW = charWidth(atChar);\n\n // 尝试用全量 [0, cursor) + cursor cell + (cursor+1, end] 渲染\n // 若总宽度 > width,从 before 左侧逐字符裁掉\n let beforeStart = 0;\n while (true) {\n const before = value.slice(beforeStart, cursor);\n const after = cursorAtEnd ? \"\" : value.slice(cursor + 1);\n const total = stringWidth(before) + cursorCellW + stringWidth(after);\n if (total <= width) {\n return { before, atChar, after, consumedWidth: total };\n }\n if (beforeStart >= cursor) {\n // before 已经全裁完仍超:再从 after 尾部裁\n // (cursor 后面有超长内容;少见,但 paste 一大段会触发)\n let after = cursorAtEnd ? \"\" : value.slice(cursor + 1);\n while (after.length > 0 && stringWidth(\"\") + cursorCellW + stringWidth(after) > width) {\n after = after.slice(0, -1);\n }\n return {\n before: \"\",\n atChar,\n after,\n consumedWidth: cursorCellW + stringWidth(after),\n };\n }\n beforeStart++;\n }\n}\n","/**\n * 从系统剪贴板抓图,落盘 `~/.muse/clipboard/<sha8>.png`。\n *\n * 平台支持:\n * - macOS: `pbpaste -Prefer png`(系统自带)\n * - Linux X11: `xclip -selection clipboard -t image/png -o`\n * - Linux Wayland: `wl-paste --type image/png`\n * - Windows: 尚未实现(欢迎 PR)\n *\n * 检测顺序:先看平台,再看 PATH 上有没有对应工具。\n */\n\nimport { execa, execaSync } from \"execa\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { existsSync, readFileSync, unlinkSync } from \"node:fs\";\nimport { homedir, platform, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { log } from \"../log/index.js\";\n\nexport interface ClipboardImageResult {\n /** 落盘的绝对路径。 */\n path: string;\n bytes: number;\n mediaType: \"image/png\";\n}\n\n/** 抓不到图(剪贴板里不是图片 / 工具不可用)返 null;真正错误抛 Error。 */\nexport async function grabClipboardImage(): Promise<ClipboardImageResult | null> {\n const buf = await readClipboardImageBytes();\n if (!buf || buf.byteLength === 0) return null;\n\n const dir = join(homedir(), \".muse\", \"clipboard\");\n await mkdir(dir, { recursive: true });\n const sha8 = createHash(\"sha256\").update(buf).digest(\"hex\").slice(0, 8);\n const path = join(dir, `${sha8}.png`);\n await writeFile(path, buf);\n return { path, bytes: buf.byteLength, mediaType: \"image/png\" };\n}\n\nasync function readClipboardImageBytes(): Promise<Buffer | null> {\n const plat = platform();\n if (plat === \"darwin\") {\n return runCaptureBuffer(\"pbpaste\", [\"-Prefer\", \"png\"]);\n }\n if (plat === \"linux\") {\n // 优先 wl-paste (Wayland),回退 xclip\n if (process.env.WAYLAND_DISPLAY) {\n const wl = await runCaptureBuffer(\"wl-paste\", [\"--type\", \"image/png\"]);\n if (wl && wl.byteLength > 0) return wl;\n }\n const x = await runCaptureBuffer(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"image/png\", \"-o\"]);\n if (x && x.byteLength > 0) return x;\n return null;\n }\n // Windows / 其他平台\n throw new Error(`Clipboard image read not supported on ${plat} yet.`);\n}\n\n/** 跑命令,把 stdout 拿成 Buffer;命令失败(找不到 / 非 0 退出 / 剪贴板没图)统一返 null。 */\nasync function runCaptureBuffer(cmd: string, args: string[]): Promise<Buffer | null> {\n try {\n const result = await execa(cmd, args, {\n reject: false,\n encoding: \"buffer\",\n timeout: 5_000,\n });\n if (result.failed) return null;\n const out = result.stdout;\n if (!out) return null;\n if (typeof out === \"string\") return Buffer.from(out, \"binary\");\n return Buffer.isBuffer(out) ? out : Buffer.from(out);\n } catch {\n return null;\n }\n}\n\n/**\n * **同步**抓剪贴板图。用于 Ink useInput 这种不能 await 的回调路径。\n *\n * 实测 macOS `pbpaste -Prefer png` 耗时 ~30-80ms,可接受;同步在主线程阻塞,\n * 但只在 paste 事件触发时跑(用户已经 Cmd+V),不影响日常打字。\n *\n * 返 null 表示剪贴板无图或工具不可用。\n */\nexport interface ClipboardImageBuffer {\n data: Buffer;\n mediaType: \"image/png\";\n}\n\nexport function grabClipboardImageBufferSync(): ClipboardImageBuffer | null {\n const plat = platform();\n if (plat === \"darwin\") return grabDarwinSync();\n if (plat === \"linux\") return grabLinuxSync();\n log.debug(\"clipboard image: unsupported platform\", { plat });\n return null;\n}\n\n/**\n * macOS 双路径:\n * 1. `pbpaste -Prefer png` — 剪贴板原生就是 PNG 时(浏览器右键复制图等)\n * 2. `osascript ... «class PNGf»` — macOS 截图复制(Cmd+Shift+Ctrl+4)时\n * 底层存的是 NSPasteboardType `public.tiff`,pbpaste 拿不到 PNG;走 osascript\n * 让 macOS 系统自己把任意图像类型转 PNG 落盘临时文件,我们读字节再删\n */\nfunction grabDarwinSync(): ClipboardImageBuffer | null {\n // 路径 1:pbpaste\n let buf = runCaptureBufferSync(\"pbpaste\", [\"-Prefer\", \"png\"]);\n if (buf && buf.byteLength > 0 && isPng(buf)) {\n log.debug(\"clipboard image: OK\", { source: \"pbpaste\", bytes: buf.byteLength });\n return { data: buf, mediaType: \"image/png\" };\n }\n // 路径 2:osascript\n const tmpPath = join(tmpdir(), `muse-clip-${process.pid}-${Date.now()}.png`);\n try {\n const result = execaSync(\n \"osascript\",\n [\n \"-e\", \"try\",\n \"-e\", `set p to POSIX file \"${tmpPath}\"`,\n \"-e\", \"set f to open for access p with write permission\",\n \"-e\", \"set eof f to 0\",\n \"-e\", \"write (the clipboard as «class PNGf») to f\",\n \"-e\", \"close access f\",\n \"-e\", `return \"ok\"`,\n \"-e\", \"on error errMsg\",\n \"-e\", `return \"err:\" & errMsg`,\n \"-e\", \"end try\",\n ],\n { reject: false, timeout: 5000 },\n );\n const out = typeof result.stdout === \"string\" ? result.stdout.trim() : \"\";\n if (!out.startsWith(\"ok\") || !existsSync(tmpPath)) {\n log.debug(\"clipboard image: osascript no PNG\", { osa: out, stderr: result.stderr });\n return null;\n }\n buf = readFileSync(tmpPath);\n } catch (err) {\n log.debug(\"clipboard image: osascript threw\", { msg: (err as Error).message });\n return null;\n } finally {\n if (existsSync(tmpPath)) {\n try { unlinkSync(tmpPath); } catch {}\n }\n }\n if (!buf || buf.byteLength === 0 || !isPng(buf)) {\n log.debug(\"clipboard image: osascript PNG bad\", {\n bytes: buf?.byteLength ?? 0,\n head8: buf ? buf.subarray(0, 8).toString(\"hex\") : \"\",\n });\n return null;\n }\n log.debug(\"clipboard image: OK\", { source: \"osascript\", bytes: buf.byteLength });\n return { data: buf, mediaType: \"image/png\" };\n}\n\nfunction grabLinuxSync(): ClipboardImageBuffer | null {\n let buf: Buffer | null = null;\n let source = \"\";\n if (process.env.WAYLAND_DISPLAY) {\n source = \"wl-paste --type image/png\";\n buf = runCaptureBufferSync(\"wl-paste\", [\"--type\", \"image/png\"]);\n }\n if (!buf || buf.byteLength === 0) {\n source = \"xclip -t image/png -o\";\n buf = runCaptureBufferSync(\"xclip\", [\"-selection\", \"clipboard\", \"-t\", \"image/png\", \"-o\"]);\n }\n if (!buf || buf.byteLength === 0) {\n log.debug(\"clipboard image: empty buffer\", { source, bytes: 0 });\n return null;\n }\n if (!isPng(buf)) {\n log.debug(\"clipboard image: not PNG\", { source, bytes: buf.byteLength });\n return null;\n }\n log.debug(\"clipboard image: OK\", { source, bytes: buf.byteLength });\n return { data: buf, mediaType: \"image/png\" };\n}\n\nfunction runCaptureBufferSync(cmd: string, args: string[]): Buffer | null {\n try {\n const result = execaSync(cmd, args, {\n reject: false,\n encoding: \"buffer\",\n timeout: 5_000,\n });\n if (result.failed) return null;\n const out = result.stdout;\n if (!out) return null;\n if (typeof out === \"string\") return Buffer.from(out, \"binary\");\n return Buffer.isBuffer(out) ? out : Buffer.from(out);\n } catch {\n return null;\n }\n}\n\n/** PNG magic: 89 50 4E 47 0D 0A 1A 0A。pbpaste 没图时返回的空 buffer 或文本 buffer 不会过这道。 */\nfunction isPng(buf: Buffer): boolean {\n if (buf.byteLength < 8) return false;\n return (\n buf[0] === 0x89 &&\n buf[1] === 0x50 &&\n buf[2] === 0x4e &&\n buf[3] === 0x47 &&\n buf[4] === 0x0d &&\n buf[5] === 0x0a &&\n buf[6] === 0x1a &&\n buf[7] === 0x0a\n );\n}\n","/**\n * Logger 包装。第一版用最朴素的 console + 文件追加;后期可替换 pino。\n * Why 不直接用 pino: 简化首版依赖图,等可观测性章节再上 pino。\n */\n\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVELS: Record<LogLevel, number> = {\n trace: 10,\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\ninterface LogEntry {\n time: string;\n level: LogLevel;\n msg: string;\n [key: string]: unknown;\n}\n\nclass Logger {\n private level: LogLevel = \"info\";\n private logPath: string;\n private fileEnabled = true;\n /**\n * 是否把 warn/error 同时打到 stderr。**默认 false**,因为 Ink TUI 会捕获 stderr\n * 渲染区,造成 \"[error] xxx\" 拼接到 PermissionModeBar / footer 等正常 UI 后面的\n * 视觉污染(B-19 修复)。需要 stderr 输出的场景(cli.tsx die / runOneShot)\n * 都已经在用 process.stderr.write 显式打,不依赖 logger。\n *\n * 单元测试 / 后台脚本可显式 setStderrEnabled(true) 开启。\n */\n private stderrEnabled = false;\n\n constructor() {\n const date = new Date().toISOString().slice(0, 10);\n this.logPath = join(homedir(), \".muse\", \"logs\", `${date}.jsonl`);\n try {\n mkdirSync(dirname(this.logPath), { recursive: true });\n } catch {\n this.fileEnabled = false;\n }\n }\n\n setLevel(level: LogLevel) {\n this.level = level;\n }\n\n setStderrEnabled(enabled: boolean) {\n this.stderrEnabled = enabled;\n }\n\n private write(level: LogLevel, msg: string, extra?: Record<string, unknown>) {\n if (LEVELS[level] < LEVELS[this.level]) return;\n const entry: LogEntry = {\n time: new Date().toISOString(),\n level,\n msg,\n ...extra,\n };\n if (this.fileEnabled) {\n try {\n appendFileSync(this.logPath, JSON.stringify(entry) + \"\\n\");\n } catch {\n // 落盘失败不阻断主流程\n }\n }\n // 默认不写 stderr,避免污染 Ink TUI 渲染区\n if (this.stderrEnabled && (level === \"warn\" || level === \"error\")) {\n const prefix = level === \"error\" ? \"[error]\" : \"[warn]\";\n process.stderr.write(`${prefix} ${msg}\\n`);\n }\n }\n\n trace(msg: string, extra?: Record<string, unknown>) { this.write(\"trace\", msg, extra); }\n debug(msg: string, extra?: Record<string, unknown>) { this.write(\"debug\", msg, extra); }\n info(msg: string, extra?: Record<string, unknown>) { this.write(\"info\", msg, extra); }\n warn(msg: string, extra?: Record<string, unknown>) { this.write(\"warn\", msg, extra); }\n error(msg: string, extra?: Record<string, unknown>) { this.write(\"error\", msg, extra); }\n}\n\nexport const log = new Logger();\n\n/** API key 脱敏:前 4 后 4,中间打码。 */\nexport function redactApiKey(key: string | undefined): string {\n if (!key) return \"<unset>\";\n if (key.length <= 12) return \"***\";\n return `${key.slice(0, 4)}...${key.slice(-4)}`;\n}\n","/**\n * 启动 banner:圆角灰框风格(对齐业界 CLI 横幅常见做法)。\n *\n * 布局:\n * ╭──────────────────────────────────────────────╮\n * │ >_ Muse (v0.1.3) │\n * │ │\n * │ model: <id> /model to change │\n * │ directory: <cwd> │\n * ╰─────────────────────────────────────────────╯\n *\n * 终端窄于 50 列退化为单行。alignSelf=flex-start 让框 shrink-to-content,\n * 不被 column 父容器的 stretch 默认值撑满整行。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nconst COLORS = {\n border: \"gray\",\n prompt: \"white\",\n app: \"white\",\n version: \"gray\",\n label: \"white\",\n value: \"#5EE3B5\",\n hint: \"gray\",\n} as const;\n\nconst LABEL_MODEL = \"model:\";\nconst LABEL_DIR = \"directory:\";\nconst LABEL_WIDTH = Math.max(LABEL_MODEL.length, LABEL_DIR.length); // 10\nconst LABEL_TO_VALUE_GAP = 1;\nconst VALUE_TO_HINT_GAP = 4;\n\nexport interface StartupBannerProps {\n version: string;\n model: string;\n cwd: string;\n}\n\nfunction padLabel(label: string): string {\n return label + \" \".repeat(LABEL_WIDTH - label.length + LABEL_TO_VALUE_GAP);\n}\n\nexport function StartupBanner({ version, model, cwd }: StartupBannerProps) {\n return (\n <Box flexDirection=\"column\" alignSelf=\"flex-start\" borderStyle=\"round\" borderColor={COLORS.border} paddingX={1}>\n <Box flexDirection=\"row\">\n <Text color={COLORS.prompt} bold>{\">_ \"}</Text>\n <Text color={COLORS.app} bold>Muse</Text>\n <Text color={COLORS.version}>{` (v${version})`}</Text>\n </Box>\n <Box height={1} />\n <Box flexDirection=\"row\">\n <Text color={COLORS.label}>{padLabel(LABEL_MODEL)}</Text>\n <Text color={COLORS.value}>{model}</Text>\n <Text color={COLORS.hint}>{\" \".repeat(VALUE_TO_HINT_GAP)}/model to change</Text>\n </Box>\n <Box flexDirection=\"row\">\n <Text color={COLORS.label}>{padLabel(LABEL_DIR)}</Text>\n <Text color={COLORS.value}>{cwd}</Text>\n </Box>\n </Box>\n );\n}\n\n/** 窄终端(< 50 列)单行兜底。 */\nexport function SingleLineBanner({ version, model }: Omit<StartupBannerProps, \"cwd\">) {\n return (\n <Text>\n <Text color={COLORS.app} bold>Muse </Text>\n <Text color={COLORS.version}>v{version}</Text>\n <Text color={COLORS.app}>{\" · \"}</Text>\n <Text color={COLORS.value}>{model}</Text>\n </Text>\n );\n}\n\nexport function pickBanner(width: number, props: StartupBannerProps): React.ReactElement {\n if (width >= 50) return <StartupBanner {...props} />;\n return <SingleLineBanner version={props.version} model={props.model} />;\n}\n","/**\n * 消息展示组件。区分 user / assistant / tool 三类。\n *\n * Assistant 文本走 marked + marked-terminal,把 markdown 渲染成 ANSI 字符串后交给 Ink Text。\n * 流式中(app.tsx 的 streamingText)保持纯文本,turn 结束后由 history 重渲染替换。\n */\n\nimport React, { useEffect, useMemo, useState } from \"react\";\nimport { Box, Text, useStdout } from \"ink\";\nimport chalk from \"chalk\";\nimport { parsePatch } from \"diff\";\nimport { highlight, supportsLanguage } from \"cli-highlight\";\nimport type { Message, ContentPart, ToolMessage, ToolUsePart } from \"../types/index.js\";\nimport type { TodoItem } from \"../tools/builtin/todo.js\";\nimport { stringWidth } from \"./BgTextInput.js\";\nimport { renderMarkdown } from \"../preprocess/render/index.js\";\nimport { FOCUS_COLOR, ACTIVE_TODO_COLOR } from \"../ui/theme.js\";\nimport { Shimmer } from \"./Shimmer.js\";\n\nexport function MessageView({\n message,\n resultsByCallId,\n latestTodoWritePartId,\n lastStartedToolId,\n}: {\n message: Message;\n /** 上层(app)按 toolUseId 索引的工具结果映射;AssistantMessage 据此把 result 内联到 call 下方。 */\n resultsByCallId?: Map<string, ToolMessage>;\n /** 全局最新一个 TodoWrite tool_use 的 part id。AssistantMessage 用它做 part 级去重——\n * 非最新的 TodoWrite part 不渲染,避免多个 → Todos 块刷屏(当 LLM 把 TodoWrite 跟其他\n * tool_use 放在同一条 message 里时,message 级去重逻辑无法覆盖,需要 part 级补)。 */\n latestTodoWritePartId?: string;\n /** 最近一次 onToolCallStart 的 tool_use id;BatchedToolBlock 据此 hold 上一个 active row。 */\n lastStartedToolId?: string | null;\n}) {\n switch (message.role) {\n case \"user\":\n return <UserMessage message={message} />;\n case \"assistant\":\n return (\n <AssistantMessage\n content={message.content}\n resultsByCallId={resultsByCallId}\n latestTodoWritePartId={latestTodoWritePartId}\n lastStartedToolId={lastStartedToolId}\n />\n );\n case \"tool\":\n // TodoWrite 的清单已在 tool_use 调用处渲染,结果行多余 → 不重复显示\n if (message.toolName === \"TodoWrite\") return null;\n // 兜底:当结果消息没有匹配的 tool_use(理论上不会发生)独立成一行\n return (\n <ToolResultTree result={message} standalone />\n );\n case \"system\":\n return null;\n }\n}\n\n/** 取 ContentPart[] 中所有 text part 拼成一段(给 UserMessage 主体渲染用)。 */\nfunction userTextOf(content: string | ContentPart[]): string {\n if (typeof content === \"string\") return content;\n return content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\\n\");\n}\n\n/** 取 ContentPart[] 中的 file/image attachments(给 UserMessage 子项渲染用)。 */\ninterface UserAttachmentRow {\n kind: \"file\" | \"image\";\n label: string;\n}\nfunction userAttachmentsOf(content: string | ContentPart[]): UserAttachmentRow[] {\n if (typeof content === \"string\") return [];\n const out: UserAttachmentRow[] = [];\n for (const p of content) {\n if (p.type === \"file\") out.push({ kind: \"file\", label: p.path });\n else if (p.type === \"image\") out.push({ kind: \"image\", label: p.path ?? `<image ${p.mediaType}>` });\n }\n return out;\n}\n\n/**\n * 行首圆点风格统一 ⏺,颜色按消息类型区分(对齐主流 TUI Agent 形态):\n * user → cyan(输入指示符 \"> \" 保留,不混入圆点风格)\n * assistant → cyan ⏺ 普通对话\n * tool_use → FOCUS_COLOR ⏺ 工具调用(淡紫,与选择器焦点色统一)\n * tool result → 树枝 └ 统一 dim,状态信息由上方 tool_use ⏺ 承担\n *\n * Batch 分组:同一 assistant turn 内的多个 tool_use 直接堆叠(无 marginTop),\n * 不同 turn 间靠 AssistantMessage 的 marginTop={1} 区隔。\n */\nexport const DOT = \"⏺\";\n\n/**\n * 用户消息:和输入框同款灰底条带(对齐主流 TUI Agent 形态)。\n * 多行内容每行都填满 bg,首行带 \"› \" 前缀,后续行用 3 空格缩进保持对齐。\n */\nconst USER_BG = \"#262626\";\n\nfunction UserMessage({ message }: { message: { content: string | ContentPart[] } }) {\n const { stdout } = useStdout();\n const termWidth = stdout?.columns ?? 80;\n const bandWidth = Math.max(1, termWidth - 1);\n const PREFIX = \" › \";\n const PREFIX_W = 3;\n\n const text = userTextOf(message.content);\n const attachments = userAttachmentsOf(message.content);\n\n // 先整体过 markdown,再按行切;不能先切行再过——会打断列表 / 代码块 / 表格等多行结构\n const rendered = useMemo(() => renderMarkdown(text), [text]);\n const lines = rendered.split(\"\\n\");\n const bg = chalk.bgHex(USER_BG);\n const prefixStyle = chalk.gray.bold;\n // 上下空白行:纯 bg,无文字。让消息条不至于紧贴顶/底文字行\n const padRow = bg(\" \".repeat(bandWidth));\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>{padRow}</Text>\n {lines.map((line, i) => {\n // marked-terminal 的输出含 ANSI 转义;填充宽度要按可见字符算,否则 padLen 偏大\n const visible = stringWidth(stripAnsi(line));\n const padLen = Math.max(0, bandWidth - PREFIX_W - visible);\n const prefix = i === 0 ? PREFIX : \" \";\n // 整行(prefix + content + padding)用 chalk.bgHex 包一层 ANSI bg。\n // 内嵌的 chalk.bold / fg-color 等 ANSI 只 reset fg / attr(\\x1b[22m / \\x1b[39m),\n // 不会 reset bg,所以灰底贯穿整行,不会有\"字体处没背景\"的断带。\n const fullLine = bg(prefixStyle(prefix) + line + \" \".repeat(padLen));\n return <Text key={i}>{fullLine}</Text>;\n })}\n <Text>{padRow}</Text>\n {/* 附件子项:用 `└ ` 树枝标识每个 file / image part */}\n {attachments.length > 0 && (\n <Box flexDirection=\"column\" marginLeft={2}>\n {attachments.map((att, i) => (\n <Box key={i} flexDirection=\"row\">\n <Text dimColor>{\"└ \"}</Text>\n <Text dimColor>{att.label}</Text>\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n}\n\nconst ANSI_RE = /\\x1b\\[[0-9;]*m/g;\nfunction stripAnsi(s: string): string {\n return s.replace(ANSI_RE, \"\");\n}\n\nfunction AssistantMessage({\n content,\n resultsByCallId,\n latestTodoWritePartId,\n lastStartedToolId,\n}: {\n content: ContentPart[];\n resultsByCallId?: Map<string, ToolMessage>;\n latestTodoWritePartId?: string;\n lastStartedToolId?: string | null;\n}) {\n // message 内 part 级聚合:连续 tool_use(非 TodoWrite) → BatchedToolBlock\n // 解决\"LLM 单条 message 含 text + 多个 tool_use\"散开渲染的问题:\n // 旧: ● Let me check / ● Read(a) └.. / ● Read(b) └.. / ● Read(c) └..\n // 新: ● Let me check / ● Reading 3 files… └ Read(a).. └ Read(b).. └ Read(c)..\n type RenderItem =\n | { kind: \"text\"; text: string; key: string }\n | { kind: \"todoWrite\"; todos: TodoItem[]; listTitle?: string; key: string }\n | { kind: \"askUserQuestion\"; result?: ToolMessage; key: string }\n | { kind: \"batch\"; uses: BatchedToolUse[]; key: string };\n const items: RenderItem[] = [];\n let batch: BatchedToolUse[] = [];\n let batchStart = 0;\n const flush = (curIdx: number) => {\n if (batch.length === 0) return;\n items.push({ kind: \"batch\", uses: batch, key: `b-${batchStart}-${curIdx}` });\n batch = [];\n };\n content.forEach((part, i) => {\n if (part.type === \"text\") {\n flush(i);\n items.push({ kind: \"text\", text: part.text, key: `t-${i}` });\n } else if (part.type === \"tool_use\") {\n if (part.name === \"TodoWrite\") {\n // TodoWrite 不再在历史区渲染,完全交给底部 sticky TodoList。\n // latestTodoWritePartId 字段保留兼容签名,本路径不再消费。\n return;\n } else if (part.name === \"AskUserQuestion\") {\n // AskUserQuestion 单独走特殊渲染(\"User answered\" 样式),\n // 不进 batch\n flush(i);\n items.push({ kind: \"askUserQuestion\", result: resultsByCallId?.get(part.id), key: `q-${i}` });\n } else if (BATCHABLE_TOOLS.has(part.name)) {\n // 纯读工具(Read/Glob/Grep/MemoryRead)进 batch 聚合\n if (batch.length === 0) batchStart = i;\n batch.push({ part, result: resultsByCallId?.get(part.id) });\n } else {\n // 有副作用 / 关键产物的工具(Edit/Write/Bash/WebFetch/MemoryWrite 等)单独显示。\n // 复用 length===1 → ToolCallBlock 的现有 fallback 路径:\n // header (Tool name + 参数核心) + result + diff(若有)\n flush(i);\n items.push({\n kind: \"batch\",\n uses: [{ part, result: resultsByCallId?.get(part.id) }],\n key: `single-${i}`,\n });\n }\n }\n });\n flush(content.length);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {items.map((item) => {\n if (item.kind === \"text\") return <AssistantTextPart key={item.key} text={item.text} />;\n if (item.kind === \"todoWrite\") return <TodoList key={item.key} todos={item.todos} listTitle={item.listTitle} />;\n if (item.kind === \"askUserQuestion\") return <AskUserQuestionResult key={item.key} result={item.result} />;\n // batch:length === 1 回退原 ToolCallBlock(避免无意义的 header)\n if (item.uses.length === 1) {\n const u = item.uses[0];\n return <ToolCallBlock key={item.key} name={u.part.name} args={u.part.args} result={u.result} />;\n }\n return <BatchedToolBlock key={item.key} uses={item.uses} lastStartedToolId={lastStartedToolId} />;\n })}\n </Box>\n );\n}\n\nfunction AssistantTextPart({ text }: { text: string }) {\n // 不再 collapse-long 折叠:muse 没有 TUI 展开键(可选用展开热键的 v0.3 再做),\n // 折叠 = 丢内容。终端 scrollback 足够展示长输出。\n // collapseLong helper 留着供 ResultPipeline 折叠工具结果(那里有 summary 可恢复),\n // 但 assistant 文本直接渲染全文。\n const rendered = useMemo(() => renderMarkdown(text), [text]);\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\">{DOT} </Text>\n <Box flexDirection=\"column\" flexGrow={1}>\n <Text>{rendered}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction ToolCallLine({ name, args }: { name: string; args: unknown }) {\n // 单工具与 batch 子项共用 innerArg 抽参数核心,header 这里加 Tool name() 包装:\n // ● Bash(ls -la ~/Git) ← 不再是 Bash(command=\"ls -la ~/Git\")\n // ● Read(src/app.tsx)\n // ● Grep(useState)\n const inner = innerArg(name, args);\n return (\n <Box flexDirection=\"row\">\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Text color={FOCUS_COLOR} bold>{name}</Text>\n <Box flexGrow={1} minWidth={0}>\n <Text dimColor wrap=\"truncate-end\">({inner})</Text>\n </Box>\n </Box>\n );\n}\n\nexport function extractTodos(args: unknown): TodoItem[] {\n if (typeof args !== \"object\" || args === null) return [];\n const todos = (args as { todos?: unknown }).todos;\n return Array.isArray(todos) ? (todos as TodoItem[]) : [];\n}\n\n/** TodoWrite args.listTitle 提取(可选):LLM 给整批 todo 起的标题。 */\nexport function extractListTitle(args: unknown): string | undefined {\n if (typeof args !== \"object\" || args === null) return undefined;\n const t = (args as { listTitle?: unknown }).listTitle;\n return typeof t === \"string\" && t.trim() ? t.trim() : undefined;\n}\n\n/** 首条 todo 的 content 截断作为兜底标题(B 方案);省略号 + 最大 40 字。 */\nfunction fallbackTitleFromTodos(todos: TodoItem[]): string {\n const first = todos[0]?.content?.trim();\n if (!first) return \"Todos\";\n return first.length > 40 ? first.slice(0, 40) + \"…\" : first;\n}\n\n// Todos 渲染:\n// - in_progress 时顶层升级为 active 状态行(Shimmer 扫光 activeForm + 计时)\n// - 否则顶层用 LLM 起的 listTitle(A 方案);LLM 没给 → 首条 content 截断兜底(B 方案)\n// - 完成态用绿色 ✓(不再 strikethrough,对齐业界 TUI Agent 形态)\nexport function TodoList({ todos, listTitle }: { todos: TodoItem[]; listTitle?: string }) {\n const inProgress = todos.find((t) => t.status === \"in_progress\");\n // 用 content 作为身份键(activeForm 可能省略,content 是稳定的)\n const inProgressKey = inProgress?.content ?? null;\n // 该 in_progress 项首次出现的时刻;切到别的 todo 时重置\n const startRef = React.useRef<{ key: string; at: number } | null>(null);\n if (inProgressKey) {\n if (!startRef.current || startRef.current.key !== inProgressKey) {\n startRef.current = { key: inProgressKey, at: Date.now() };\n }\n } else {\n startRef.current = null;\n }\n // 500ms tick 让 (Xs) 计时刷新\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n if (!inProgressKey) return;\n const t = setInterval(() => setNow(Date.now()), 500);\n return () => clearInterval(t);\n }, [inProgressKey]);\n\n // 静态 header 标题:LLM listTitle 优先,否则首条 content 截断,最后 fallback \"Todos\"\n const staticTitle = listTitle ?? fallbackTitleFromTodos(todos);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {inProgress && startRef.current ? (\n <TodoActiveHeader todo={inProgress} elapsedSec={Math.max(0, Math.floor((now - startRef.current.at) / 1000))} />\n ) : (\n <Box flexDirection=\"row\">\n <Text color={FOCUS_COLOR}>{\"→ \"}</Text>\n <Text color={FOCUS_COLOR} bold>{staticTitle}</Text>\n </Box>\n )}\n {todos.map((todo, i) => (\n <TodoRow key={i} todo={todo} />\n ))}\n </Box>\n );\n}\n\n/** 顶层 active header:`● <activeForm>… (Xs)`,activeForm 文字走 Shimmer 扫光。 */\nfunction TodoActiveHeader({ todo, elapsedSec }: { todo: TodoItem; elapsedSec: number }) {\n const label = todo.activeForm ?? todo.content;\n return (\n <Box flexDirection=\"row\">\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Shimmer text={label} />\n <Text dimColor>{`… (${elapsedSec}s)`}</Text>\n </Box>\n );\n}\n\nfunction TodoRow({ todo }: { todo: TodoItem }) {\n const label = todo.status === \"in_progress\" && todo.activeForm ? todo.activeForm : todo.content;\n switch (todo.status) {\n case \"completed\":\n // 完成态:绿勾 + 灰字 + 删除线\n return (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color=\"green\">{\"✓ \"}</Text>\n <Text dimColor strikethrough>{label}</Text>\n </Box>\n );\n case \"in_progress\":\n // 进行中:橙色实心方块 ■ + 白字加粗(方块橙、文字白)\n return (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text color={ACTIVE_TODO_COLOR}>{\"■ \"}</Text>\n <Text bold>{label}</Text>\n </Box>\n );\n default:\n // 未完成:灰色空心方框 □ + 灰字\n return (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text dimColor>{\"□ \"}</Text>\n <Text dimColor>{label}</Text>\n </Box>\n );\n }\n}\n\n/**\n * AskUserQuestion 工具结果的特殊渲染(\"User answered\" 样式):\n * ● User answered:\n * └ · <Question> → <Answer>\n * Notes: <user notes>\n * content 来自 ask-user-question.ts execute() 的 Q/A/Notes 文本拼装,这里反向解析。\n */\nfunction AskUserQuestionResult({ result }: { result?: ToolMessage }) {\n if (!result) {\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Text color={FOCUS_COLOR} bold>Waiting for user's answers…</Text>\n </Box>\n );\n }\n const content = result.content ?? \"\";\n // 取消 / 失败两种特殊态\n if (content.startsWith(\"User cancelled\")) {\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box flexDirection=\"row\">\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Text color={FOCUS_COLOR} bold>User answered:</Text>\n </Box>\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text dimColor>{\"└ \"}</Text>\n <Text dimColor>(cancelled)</Text>\n </Box>\n </Box>\n );\n }\n if (result.isError) {\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Text color=\"red\">{content || \"AskUserQuestion failed\"}</Text>\n </Box>\n );\n }\n // 解析 \"Q: ... / A: ... / Notes: ...\" 块,块之间用 \\n\\n 分隔\n const blocks = content.split(\"\\n\\n\");\n const qas: Array<{ q: string; a: string; notes: string }> = [];\n for (const b of blocks) {\n let q = \"\", a = \"\", notes = \"\";\n for (const line of b.split(\"\\n\")) {\n if (line.startsWith(\"Q: \")) q = line.slice(3);\n else if (line.startsWith(\"A: \")) a = line.slice(3);\n else if (line.startsWith(\"Notes: \")) notes = line.slice(7);\n }\n if (q) qas.push({ q, a, notes });\n }\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box flexDirection=\"row\">\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Text color={FOCUS_COLOR} bold>User answered:</Text>\n </Box>\n <Box flexDirection=\"column\" marginLeft={2}>\n {qas.map((qa, i) => (\n <Box key={i} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text dimColor>{\"└ · \"}</Text>\n <Box flexGrow={1} minWidth={0}>\n <Text wrap=\"truncate-end\" dimColor>\n {qa.q}{\" → \"}{qa.a}\n </Text>\n </Box>\n </Box>\n {qa.notes && (\n <Box flexDirection=\"row\" marginLeft={4}>\n <Text dimColor wrap=\"truncate-end\">Notes: {qa.notes}</Text>\n </Box>\n )}\n </Box>\n ))}\n </Box>\n </Box>\n );\n}\n\n/**\n * 单个工具的\"调用 + 结果\"块(●Tool(...) + └ result 树形展示)。\n * 结果 region 缩进 2 空格,首行用 └ 树枝角标,颜色按状态。\n *\n * Edit/Write 且 result 含 diff 时,header 之下额外加一行 `└ Added N lines, removed M lines`\n * (从 unified diff 字符串数 +/- 行得出)。\n */\nfunction ToolCallBlock({\n name,\n args,\n result,\n}: {\n name: string;\n args: unknown;\n result?: ToolMessage;\n}) {\n const diffStats = useMemo(\n () => (result?.diff ? countDiffStats(result.diff) : null),\n [result?.diff],\n );\n // 从 Edit/Write args 提 file_path 透传给 DiffBlock,用于 syntax highlight 语言推断\n const filePath =\n typeof args === \"object\" && args !== null\n ? (args as { file_path?: unknown }).file_path\n : undefined;\n const filePathStr = typeof filePath === \"string\" ? filePath : undefined;\n return (\n <Box flexDirection=\"column\">\n <ToolCallLine name={name} args={args} />\n {diffStats && (\n <Box flexDirection=\"row\" marginLeft={2}>\n <Text dimColor>{\"└ \"}</Text>\n <Text dimColor>{formatDiffStats(diffStats)}</Text>\n </Box>\n )}\n {result && <ToolResultTree result={result} suppressContent={!!diffStats} filePath={filePathStr} />}\n </Box>\n );\n}\n\n/** 数 unified diff 字符串里的 + / - 行(跳过 hunk header `+++` / `---`)。 */\nfunction countDiffStats(diff: string): { added: number; removed: number } {\n let added = 0;\n let removed = 0;\n for (const line of diff.split(\"\\n\")) {\n if (line.startsWith(\"+++\") || line.startsWith(\"---\")) continue;\n if (line.startsWith(\"+\")) added++;\n else if (line.startsWith(\"-\")) removed++;\n }\n return { added, removed };\n}\n\nfunction formatDiffStats(s: { added: number; removed: number }): string {\n const parts: string[] = [];\n if (s.added > 0) parts.push(`Added ${s.added} line${s.added === 1 ? \"\" : \"s\"}`);\n if (s.removed > 0) parts.push(`removed ${s.removed} line${s.removed === 1 ? \"\" : \"s\"}`);\n if (parts.length === 0) return \"No changes\";\n return parts.join(\", \");\n}\n\nconst MAX_RESULT_LINES = 5;\n\n/**\n * 工具结果的树形展示:\n * - 有 summary → 一行 summary(带 \"+N lines\" 暗示更多内容)\n * - 无 summary 且 content 短 → 全展开(每行一条)\n * - 无 summary 且 content 长 → 头 MAX_RESULT_LINES 行 + \"(+M more lines)\"\n *\n * standalone 标志:用于兜底(独立成块)的情况——通常不会触发。\n */\nfunction ToolResultTree({\n result,\n standalone = false,\n suppressContent = false,\n filePath,\n}: {\n result: ToolMessage;\n standalone?: boolean;\n /** Edit/Write 等已经在上层用 `Added N, removed M` 表达了 content 摘要时,跳过这里再渲染一遍 content。\n * diff 仍然由 DiffBlock 单独渲染。 */\n suppressContent?: boolean;\n /** Edit/Write 的 file_path,透给 DiffBlock 推断 syntax language。 */\n filePath?: string;\n}) {\n // bash 等工具会把 stdout/stderr 包在 <stdout>...</stdout> 里给 LLM 区分通道;\n // UI 里把这种独立行的标签剥掉,让用户直接看到 stdout 内容\n const cleaned = stripWrapperTags(result.content);\n const rawLines = cleaned.split(\"\\n\");\n // 去尾部空行(XML 标签剥离后常剩一行空)\n while (rawLines.length > 0 && rawLines[rawLines.length - 1].trim() === \"\") rawLines.pop();\n // 去头部空行\n while (rawLines.length > 0 && rawLines[0].trim() === \"\") rawLines.shift();\n\n let displayLines: string[];\n let omitted = 0;\n\n if (result.summary) {\n const extra = rawLines.length > 1 ? ` (+${rawLines.length - 1} lines)` : \"\";\n displayLines = [result.summary + extra];\n } else if (rawLines.length === 0) {\n displayLines = [\"(no output)\"];\n } else if (rawLines.length <= MAX_RESULT_LINES) {\n displayLines = rawLines;\n } else {\n displayLines = rawLines.slice(0, MAX_RESULT_LINES);\n omitted = rawLines.length - MAX_RESULT_LINES;\n }\n\n return (\n <Box flexDirection=\"column\" marginLeft={2} marginTop={standalone ? 1 : 0}>\n {!suppressContent &&\n displayLines.map((line, i) => (\n <Box key={i} flexDirection=\"row\">\n {/* └ 统一灰色:状态信息已由上方 ● 的 dotColor 传达,树枝不再叠色,避免视觉杂乱 */}\n <Text dimColor>{i === 0 ? \"└ \" : \" \"}</Text>\n <Box flexGrow={1} minWidth={0}>\n <Text dimColor wrap=\"truncate-end\">{line || \" \"}</Text>\n </Box>\n </Box>\n ))}\n {!suppressContent && omitted > 0 && (\n <Box marginLeft={2}>\n <Text dimColor>{`(+${omitted} more lines)`}</Text>\n </Box>\n )}\n {result.diff && <DiffBlock diff={result.diff} filePath={filePath} />}\n </Box>\n );\n}\n\n/** bash 工具内容里独立成行的 <stdout>/<stderr>/<timeout>/<exit_code> 包装标签,UI 不展示。 */\nfunction stripWrapperTags(content: string): string {\n return content\n .split(\"\\n\")\n .filter((l) => !/^<\\/?(stdout|stderr|timeout|exit_code)>\\s*$/.test(l.trim()))\n .join(\"\\n\");\n}\n\n/**\n * Diff 渲染:绝对行号 + 整行 bg 高亮(延伸到 EOL)。\n *\n * 数据流:工具(edit/write)生成的 unified diff 字符串 → jsdiff::parsePatch\n * → hunks 数组(每个 hunk 有 oldStart/newStart + lines[`+/-/space` 前缀])\n * → 按 hunks 渲染:行号列(右对齐) + `+/-/space` 列 + 内容\n *\n * **bg 延伸到 EOL** 用 ANSI `\\x1b[K`(Erase in Line)+ 当前 bg 色:VT100 标准,\n * 终端自动用当前 bg 把行末空白填满,**不需要**算 termWidth 做 padEnd。这避免了\n * 之前 padEnd 算宽度边界跟 Ink Box 实际可用宽度不一致导致的 wrap → 行间空白。\n *\n * 颜色用 ANSI 标准 8 色(bgGreen / bgRed),终端主题决定具体色调\n * (Solarized / Dracula / 默认 各自映射不同绿/红)。\n */\n// 用 truecolor RGB(\\x1b[48;2;R;G;Bm)做暗绿/暗红,对齐 GitHub / VSCode 暗主题\n// diff 风格,不依赖终端主题映射(避免 \\x1b[42m 在不同主题下出现刺眼亮绿)。\n// 配色参考 GitHub dark + 略提亮(确保中文也能读清)。\nconst ANSI_BG_ADD = \"\\x1b[48;2;28;56;33m\"; // #1c3821 暗叶绿\nconst ANSI_BG_REMOVE = \"\\x1b[48;2;80;30;30m\"; // #501e1e 暗酒红\nconst ANSI_FG = \"\\x1b[38;2;220;220;220m\"; // #dcdcdc 浅灰白(bg 上默认文字)\nconst ANSI_EL = \"\\x1b[K\"; // Erase in Line:用当前 bg 把行末填到 EOL\nconst ANSI_RESET = \"\\x1b[0m\";\nconst ANSI_FG_RESET = \"\\x1b[39m\"; // 只 reset fg(保留 bg)\n\n/** 文件扩展名 → highlight.js 语言名映射。未列出的返 undefined,DiffLine 跳过 highlight。 */\nfunction inferLanguage(filePath?: string): string | undefined {\n if (!filePath) return undefined;\n const ext = filePath.toLowerCase().match(/\\.([a-z0-9]+)$/)?.[1];\n if (!ext) return undefined;\n const map: Record<string, string> = {\n ts: \"typescript\",\n tsx: \"typescript\",\n js: \"javascript\",\n jsx: \"javascript\",\n mjs: \"javascript\",\n cjs: \"javascript\",\n py: \"python\",\n rs: \"rust\",\n go: \"go\",\n java: \"java\",\n kt: \"kotlin\",\n swift: \"swift\",\n rb: \"ruby\",\n php: \"php\",\n c: \"c\",\n h: \"c\",\n cpp: \"cpp\",\n hpp: \"cpp\",\n cs: \"csharp\",\n sh: \"bash\",\n bash: \"bash\",\n zsh: \"bash\",\n md: \"markdown\",\n markdown: \"markdown\",\n json: \"json\",\n yaml: \"yaml\",\n yml: \"yaml\",\n toml: \"ini\",\n xml: \"xml\",\n html: \"xml\",\n css: \"css\",\n scss: \"scss\",\n sql: \"sql\",\n vue: \"html\",\n svelte: \"html\",\n };\n const lang = map[ext];\n if (!lang) return undefined;\n // cli-highlight 装载语言要靠 highlight.js;有的语言可能未注册\n try {\n return supportsLanguage(lang) ? lang : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** 对单行做 syntax highlight;language 推断失败或 highlight 抛错都退回原文。\n * 关键:把 cli-highlight 输出里的 `\\x1b[39m`(fg reset 到终端默认)替换成\n * 我们设定的 ANSI_FG(#dcdcdc),保持外层 fg 不被中断 → bg 上的文字色一致。 */\nfunction highlightLine(text: string, lang?: string): string {\n if (!lang || !text) return text;\n try {\n const out = highlight(text, { language: lang, ignoreIllegals: true });\n // syntax token 内部 reset 用 \\x1b[39m → 替回我们的 #dcdcdc,避免恢复终端默认 fg\n return out.replace(/\\x1b\\[39m/g, ANSI_FG);\n } catch {\n return text;\n }\n}\n\nfunction DiffBlock({ diff, filePath }: { diff: string; filePath?: string }) {\n const { stdout } = useStdout();\n const termWidth = stdout?.columns ?? 80;\n\n const hunks = useMemo(() => {\n try {\n const patches = parsePatch(diff);\n return patches[0]?.hunks ?? [];\n } catch {\n return [];\n }\n }, [diff]);\n\n const lang = useMemo(() => inferLanguage(filePath), [filePath]);\n\n if (hunks.length === 0) return null;\n\n const maxLineNum = Math.max(\n ...hunks.map((h) => Math.max(h.oldStart + h.oldLines, h.newStart + h.newLines)),\n );\n const lineNumWidth = String(maxLineNum).length;\n // contentWidth = 终端宽 - 左 margin(2) - 行号列(lineNumWidth) - prefix(空格 + mark + 空格 = 3)\n // -1 留 safety,避免边界情况触发 wrap\n const contentWidth = Math.max(10, termWidth - 2 - lineNumWidth - 3 - 1);\n\n return (\n <Box flexDirection=\"column\" marginLeft={2} marginTop={1}>\n {hunks.map((hunk, hi) => (\n <HunkRows\n key={hi}\n oldStart={hunk.oldStart}\n newStart={hunk.newStart}\n lines={hunk.lines}\n lineNumWidth={lineNumWidth}\n contentWidth={contentWidth}\n lang={lang}\n />\n ))}\n </Box>\n );\n}\n\nfunction HunkRows({\n oldStart,\n newStart,\n lines,\n lineNumWidth,\n contentWidth,\n lang,\n}: {\n oldStart: number;\n newStart: number;\n lines: string[];\n lineNumWidth: number;\n contentWidth: number;\n lang?: string;\n}) {\n let oldCur = oldStart;\n let newCur = newStart;\n const rendered: Array<{ kind: \"add\" | \"remove\" | \"context\"; lineNum: number; text: string }> = [];\n for (const raw of lines) {\n if (raw.startsWith(\"\\\\\")) continue;\n const ch = raw[0] ?? \" \";\n const text = raw.slice(1);\n if (ch === \"+\") {\n rendered.push({ kind: \"add\", lineNum: newCur, text });\n newCur++;\n } else if (ch === \"-\") {\n rendered.push({ kind: \"remove\", lineNum: oldCur, text });\n oldCur++;\n } else {\n rendered.push({ kind: \"context\", lineNum: newCur, text });\n oldCur++;\n newCur++;\n }\n }\n return (\n <>\n {rendered.map((r, i) => (\n <DiffLine\n key={i}\n kind={r.kind}\n lineNum={r.lineNum}\n text={r.text}\n lineNumWidth={lineNumWidth}\n contentWidth={contentWidth}\n lang={lang}\n />\n ))}\n </>\n );\n}\n\nfunction DiffLine({\n kind,\n lineNum,\n text,\n lineNumWidth,\n contentWidth,\n lang,\n}: {\n kind: \"add\" | \"remove\" | \"context\";\n lineNum: number;\n text: string;\n lineNumWidth: number;\n contentWidth: number;\n lang?: string;\n}) {\n const numStr = String(lineNum).padStart(lineNumWidth, \" \");\n const mark = kind === \"add\" ? \"+\" : kind === \"remove\" ? \"-\" : \" \";\n // 先做 syntax highlight 再 padEnd:padEnd 用 visible width(stringWidth,忽略 ANSI)\n // 确保整行 bg 延伸到 contentWidth + prefix,所有 +/- 行宽度一致,不随内容长度抖动。\n const highlighted = lang ? highlightLine(text, lang) : text;\n const visible = stringWidth(stripAnsi(highlighted));\n // 截断或 padding:长内容截断到 contentWidth;短内容用空格补到 contentWidth(空格也吃 bg 色)\n const padded =\n visible > contentWidth ? truncateVisible(highlighted, contentWidth) : highlighted + \" \".repeat(contentWidth - visible);\n const inner = ` ${mark} ${padded}`;\n let styled: string;\n if (kind === \"add\") {\n styled = `${ANSI_BG_ADD}${ANSI_FG}${inner}${ANSI_RESET}`;\n } else if (kind === \"remove\") {\n styled = `${ANSI_BG_REMOVE}${ANSI_FG}${inner}${ANSI_RESET}`;\n } else {\n // context 行不染 bg;高亮后 dim 一层让它柔和\n styled = chalk.dim(inner);\n }\n return (\n <Box flexDirection=\"row\">\n <Text dimColor>{numStr}</Text>\n <Text>{styled}</Text>\n </Box>\n );\n}\n\n/** 把带 ANSI 的字符串按 visible width 截断到 maxWidth;粗略实现:\n * 按 visible 字符逐个累加,不破坏 ANSI 序列。截断后补一个 reset(若有未闭合 ANSI 上下文)。 */\nfunction truncateVisible(text: string, maxWidth: number): string {\n let visibleCount = 0;\n let i = 0;\n let out = \"\";\n while (i < text.length && visibleCount < maxWidth) {\n const ch = text.charCodeAt(i);\n if (ch === 0x1b && text[i + 1] === \"[\") {\n // ANSI escape:`ESC [ ... letter`,整段照搬,不算 visible\n const end = text.indexOf(\"m\", i + 2);\n if (end < 0) {\n out += text.slice(i);\n break;\n }\n out += text.slice(i, end + 1);\n i = end + 1;\n } else {\n const c = text[i];\n const w = stringWidth(c);\n if (visibleCount + w > maxWidth) break;\n out += c;\n visibleCount += w;\n i++;\n }\n }\n return out;\n}\n\nfunction formatArgs(args: unknown): string {\n if (typeof args !== \"object\" || args === null) return String(args);\n const entries = Object.entries(args as Record<string, unknown>);\n if (entries.length === 0) return \"\";\n const parts: string[] = [];\n for (const [k, v] of entries) {\n if (typeof v === \"string\") {\n const truncated = v.length > 40 ? v.slice(0, 40) + \"...\" : v;\n parts.push(`${k}=\"${truncated}\"`);\n } else {\n parts.push(`${k}=${JSON.stringify(v).slice(0, 40)}`);\n }\n }\n return parts.join(\", \");\n}\n\n/**\n * 可 batch 聚合的工具白名单:探索/查询类工具进 batch。\n *\n * 完成态不再\"完全隐藏子项\",改为常驻显示前 MAX_DONE_ROWS 行 + `(+N more)` 折叠,\n * 让用户能扫一眼跑过什么命令;长 stdout 详情可走 scrollback 回看。\n *\n * **不**进 batch:Edit / Write(diff 必看) / TodoWrite(独立 sticky) /\n * AskUserQuestion(独立 Q&A 渲染) / MemoryWrite(写动作)\n */\nexport const BATCHABLE_TOOLS: ReadonlySet<string> = new Set([\n \"Read\",\n \"Glob\",\n \"Grep\",\n \"MemoryRead\",\n \"Bash\",\n \"WebFetch\",\n]);\n\n// ============== Batched tool rendering ==============\n// muse 的 agent ReAct 是串行 tool loop:每跑 1 个工具就单独成一条 assistant message。\n// 散开显示在多次连续 tool 调用时观感差(垂直占用大、节奏被切碎),改用业界常见的\n// \"batch 聚合\"——把连续的只含 tool_use 的 assistant message 合并为一个虚拟块,\n// header 用复数形式,子项一行一条。\n\nexport interface BatchedToolUse {\n part: ToolUsePart;\n result?: ToolMessage;\n}\n\n/** 按工具名生成 batch header:\n * - 单一类型 → 复数模板,如 \"Running 4 shell commands…\" (展开子项)\n * - 混合类型 → 动名词摘要句,如 \"Searched for 2 patterns, read 1 file, ran 1 shell command\" (不展子项) */\nfunction batchHeader(uses: BatchedToolUse[]): string {\n const counts = new Map<string, number>();\n for (const u of uses) counts.set(u.part.name, (counts.get(u.part.name) ?? 0) + 1);\n if (counts.size === 1) {\n const [name, n] = [...counts.entries()][0];\n return labelForN(name, n);\n }\n // 混合:按工具名排序拼动名词短语,首字母大写,. 结尾的语感更克制 → 不加句号\n const phrases = [...counts.entries()]\n .sort((a, b) => a[0].localeCompare(b[0]))\n .map(([name, n]) => actionPhrase(name, n));\n const sentence = phrases.join(\", \");\n return sentence.charAt(0).toUpperCase() + sentence.slice(1);\n}\n\n/** 单一类型场景:工具名 + 复数 label;有省略号表示\"正在/已经处理多个\" 的现在进行感。 */\nfunction labelForN(toolName: string, n: number): string {\n const s = n > 1 ? \"s\" : \"\";\n switch (toolName) {\n case \"Bash\": return `Running ${n} shell command${s}…`;\n case \"Read\": return `Reading ${n} file${s}…`;\n case \"Grep\": return `Searched ${n} pattern${s}`;\n case \"Glob\": return `Searched ${n} glob${s}`;\n case \"WebFetch\": return `Fetched ${n} URL${s}`;\n case \"Edit\": return `Editing ${n} file${s}…`;\n case \"Write\": return `Writing ${n} file${s}…`;\n case \"AskUserQuestion\": return `Asking ${n} question${s}`;\n case \"MemoryRead\": return `Reading ${n} memor${n > 1 ? \"ies\" : \"y\"}…`;\n case \"MemoryWrite\": return `Writing ${n} memor${n > 1 ? \"ies\" : \"y\"}…`;\n default: return `${toolName} ×${n}`;\n }\n}\n\n/** 混合 batch 场景:工具名 + 动名词短语 (lowercase,被 join 拼成英文句子)。 */\nfunction actionPhrase(toolName: string, n: number): string {\n const s = n > 1 ? \"s\" : \"\";\n switch (toolName) {\n case \"Bash\": return `ran ${n} shell command${s}`;\n case \"Read\": return `read ${n} file${s}`;\n case \"Grep\": return `searched for ${n} pattern${s}`;\n case \"Glob\": return `searched ${n} glob${s}`;\n case \"WebFetch\": return `fetched ${n} URL${s}`;\n case \"Edit\": return `edited ${n} file${s}`;\n case \"Write\": return `wrote ${n} file${s}`;\n case \"AskUserQuestion\": return `asked ${n} question${s}`;\n case \"MemoryRead\": return `read ${n} memor${n > 1 ? \"ies\" : \"y\"}`;\n case \"MemoryWrite\": return `wrote ${n} memor${n > 1 ? \"ies\" : \"y\"}`;\n default: return `used ${n} ${toolName}${s}`;\n }\n}\n\n/** active row 切换最小停留时间(ms):让快命令(本地 ls/cat 几十 ms)的 active row 也能被看见。\n * 渲染层加 sticky delay,实际 tool 执行速度不变(业界常见手法)。 */\nconst ACTIVE_ROW_STICKY_MS = 500;\n\n/** 全展开子项时最多渲染几行,余下用 `(+N more)` 折叠,避免 50+ 项的 batch 把屏幕占满。 */\nconst MAX_EXPANDED_ROWS = 5;\n/** 完成态(allDone)默认显示前 N 行 + (+M more) 折叠 — 不再完全隐藏:\n * 既视觉紧凑,又能扫一眼看到 agent 跑过什么(尤其 Bash/WebFetch 这种命令)。 */\nconst MAX_DONE_ROWS = 3;\n\nexport function BatchedToolBlock({\n uses,\n lastStartedToolId,\n}: {\n uses: BatchedToolUse[];\n /** 最近一次 onToolCallStart 的 tool_use id;用于 \"hold 上一个直到下一个真的开始\" 语义。\n * 未提供时回退到 firstPending(下一个没 result 的)。 */\n lastStartedToolId?: string | null;\n}) {\n // Transient 渲染:\n // - 全部完成 → 显示前 MAX_DONE_ROWS 行 + `(+N more)` 折叠提示(\n // 既视觉紧凑,又能扫一眼看到 agent 跑过什么命令/读了什么文件)\n // - 执行中 → 用灰色 `└` 显示 active row;**hold 上一个直到下一个真的开始**:\n // target 优先匹配 lastStartedToolId(最近一次 onToolCallStart 的 id),避免\n // firstPending 立刻跳到 LLM 还在思考 / 等权限的下一个 tool。未拿到 id 时\n // (初始 / Static 包的历史 batch)回退 firstPending。\n // - **abort 中断**(Esc)→ 整批展开 MAX_EXPANDED_ROWS 行 + 折叠,让用户看清楚\n // muse 当时干到哪一步被打断,避免\"消失感\"\n const allDone = uses.every((u) => u.result);\n let targetIdx = -1;\n if (!allDone) {\n if (lastStartedToolId) {\n targetIdx = uses.findIndex((u) => u.part.id === lastStartedToolId);\n }\n if (targetIdx < 0) {\n // 没匹配上 → 回退到 firstPending 给个初始显示\n targetIdx = uses.findIndex((u) => !u.result);\n }\n }\n // sticky displayIdx:targetIdx 切换后延迟 ACTIVE_ROW_STICKY_MS 再生效,\n // 保证每个 active row 至少可见这么长时间(连续快切时旧 timeout 被 clear,直接跳终值)。\n const [displayIdx, setDisplayIdx] = useState(targetIdx);\n useEffect(() => {\n if (targetIdx === displayIdx) return;\n const t = setTimeout(() => setDisplayIdx(targetIdx), ACTIVE_ROW_STICKY_MS);\n return () => clearTimeout(t);\n }, [targetIdx, displayIdx]);\n const activeIdx = displayIdx >= 0 && displayIdx < uses.length ? displayIdx : -1;\n const wasInterrupted = uses.some(\n (u) => u.result?.content?.includes(\"Interrupted by user (Esc)\"),\n );\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box flexDirection=\"row\">\n <Text color={FOCUS_COLOR}>{DOT} </Text>\n <Text color={FOCUS_COLOR} bold>{batchHeader(uses)}</Text>\n </Box>\n {wasInterrupted ? (\n <Box flexDirection=\"column\" marginLeft={2}>\n {uses.slice(0, MAX_EXPANDED_ROWS).map((u, i) => (\n <BatchedToolRow key={i} use={u} />\n ))}\n {uses.length > MAX_EXPANDED_ROWS && (\n <Box flexDirection=\"row\">\n <Text dimColor>{\" \"}</Text>\n <Text dimColor>{`(+${uses.length - MAX_EXPANDED_ROWS} more)`}</Text>\n </Box>\n )}\n </Box>\n ) : activeIdx >= 0 ? (\n <Box flexDirection=\"column\" marginLeft={2}>\n <BatchedToolRow use={uses[activeIdx]} />\n </Box>\n ) : (\n // 完成态:显示前 MAX_DONE_ROWS 行 + `(+N more)` 折叠\n <Box flexDirection=\"column\" marginLeft={2}>\n {uses.slice(0, MAX_DONE_ROWS).map((u, i) => (\n <BatchedToolRow key={i} use={u} />\n ))}\n {uses.length > MAX_DONE_ROWS && (\n <Box flexDirection=\"row\">\n <Text dimColor>{\" \"}</Text>\n <Text dimColor>{`(+${uses.length - MAX_DONE_ROWS} more)`}</Text>\n </Box>\n )}\n </Box>\n )}\n </Box>\n );\n}\n\nfunction BatchedToolRow({ use }: { use: BatchedToolUse }) {\n // 按工具类型展示参数核心,不再用 Tool(args=...) 代码风格:\n // Read/Edit/Write → 文件路径\n // Bash → $ <command>\n // Grep/Glob → pattern\n // WebFetch → URL\n // 其他 → fallback 到 Tool(args)\n const summary = formatToolUseSummary(use.part);\n return (\n <Box flexDirection=\"row\">\n <Text dimColor>{\"└ \"}</Text>\n <Box flexGrow={1} minWidth={0}>\n <Text dimColor wrap=\"truncate-end\">{summary}</Text>\n </Box>\n </Box>\n );\n}\n\n/** 工具参数核心(去 key=value 包装),单工具 header 与 batch 子项共用。 */\nfunction innerArg(name: string, args: unknown): string {\n const a = (args ?? {}) as Record<string, unknown>;\n const str = (k: string): string => (typeof a[k] === \"string\" ? (a[k] as string) : \"\");\n switch (name) {\n case \"Bash\":\n return str(\"command\");\n case \"Read\":\n case \"Edit\":\n case \"Write\":\n return str(\"file_path\");\n case \"Grep\":\n return str(\"pattern\");\n case \"Glob\":\n return str(\"pattern\");\n case \"WebFetch\":\n return str(\"url\");\n case \"MemoryRead\":\n case \"MemoryWrite\":\n return str(\"path\");\n case \"AskUserQuestion\": {\n const qs = a.questions;\n const n = Array.isArray(qs) ? qs.length : 0;\n return `${n} question${n === 1 ? \"\" : \"s\"}`;\n }\n default:\n return formatArgs(args);\n }\n}\n\n/** Batch 子项的\"无 header 独立行\"展示:Bash 加 `$` 前缀提示 shell 命令,其他直接用核心参数。 */\nfunction formatToolUseSummary(part: ToolUsePart): string {\n const inner = innerArg(part.name, part.args);\n return part.name === \"Bash\" ? `$ ${inner}` : inner;\n}\n","const ANSI_BACKGROUND_OFFSET = 10;\n\nconst wrapAnsi16 = (offset = 0) => code => `\\u001B[${code + offset}m`;\n\nconst wrapAnsi256 = (offset = 0) => code => `\\u001B[${38 + offset};5;${code}m`;\n\nconst wrapAnsi16m = (offset = 0) => (red, green, blue) => `\\u001B[${38 + offset};2;${red};${green};${blue}m`;\n\nconst styles = {\n\tmodifier: {\n\t\treset: [0, 0],\n\t\t// 21 isn't widely supported and 22 does the same thing\n\t\tbold: [1, 22],\n\t\tdim: [2, 22],\n\t\titalic: [3, 23],\n\t\tunderline: [4, 24],\n\t\toverline: [53, 55],\n\t\tinverse: [7, 27],\n\t\thidden: [8, 28],\n\t\tstrikethrough: [9, 29],\n\t},\n\tcolor: {\n\t\tblack: [30, 39],\n\t\tred: [31, 39],\n\t\tgreen: [32, 39],\n\t\tyellow: [33, 39],\n\t\tblue: [34, 39],\n\t\tmagenta: [35, 39],\n\t\tcyan: [36, 39],\n\t\twhite: [37, 39],\n\n\t\t// Bright color\n\t\tblackBright: [90, 39],\n\t\tgray: [90, 39], // Alias of `blackBright`\n\t\tgrey: [90, 39], // Alias of `blackBright`\n\t\tredBright: [91, 39],\n\t\tgreenBright: [92, 39],\n\t\tyellowBright: [93, 39],\n\t\tblueBright: [94, 39],\n\t\tmagentaBright: [95, 39],\n\t\tcyanBright: [96, 39],\n\t\twhiteBright: [97, 39],\n\t},\n\tbgColor: {\n\t\tbgBlack: [40, 49],\n\t\tbgRed: [41, 49],\n\t\tbgGreen: [42, 49],\n\t\tbgYellow: [43, 49],\n\t\tbgBlue: [44, 49],\n\t\tbgMagenta: [45, 49],\n\t\tbgCyan: [46, 49],\n\t\tbgWhite: [47, 49],\n\n\t\t// Bright color\n\t\tbgBlackBright: [100, 49],\n\t\tbgGray: [100, 49], // Alias of `bgBlackBright`\n\t\tbgGrey: [100, 49], // Alias of `bgBlackBright`\n\t\tbgRedBright: [101, 49],\n\t\tbgGreenBright: [102, 49],\n\t\tbgYellowBright: [103, 49],\n\t\tbgBlueBright: [104, 49],\n\t\tbgMagentaBright: [105, 49],\n\t\tbgCyanBright: [106, 49],\n\t\tbgWhiteBright: [107, 49],\n\t},\n};\n\nexport const modifierNames = Object.keys(styles.modifier);\nexport const foregroundColorNames = Object.keys(styles.color);\nexport const backgroundColorNames = Object.keys(styles.bgColor);\nexport const colorNames = [...foregroundColorNames, ...backgroundColorNames];\n\nfunction assembleStyles() {\n\tconst codes = new Map();\n\n\tfor (const [groupName, group] of Object.entries(styles)) {\n\t\tfor (const [styleName, style] of Object.entries(group)) {\n\t\t\tstyles[styleName] = {\n\t\t\t\topen: `\\u001B[${style[0]}m`,\n\t\t\t\tclose: `\\u001B[${style[1]}m`,\n\t\t\t};\n\n\t\t\tgroup[styleName] = styles[styleName];\n\n\t\t\tcodes.set(style[0], style[1]);\n\t\t}\n\n\t\tObject.defineProperty(styles, groupName, {\n\t\t\tvalue: group,\n\t\t\tenumerable: false,\n\t\t});\n\t}\n\n\tObject.defineProperty(styles, 'codes', {\n\t\tvalue: codes,\n\t\tenumerable: false,\n\t});\n\n\tstyles.color.close = '\\u001B[39m';\n\tstyles.bgColor.close = '\\u001B[49m';\n\n\tstyles.color.ansi = wrapAnsi16();\n\tstyles.color.ansi256 = wrapAnsi256();\n\tstyles.color.ansi16m = wrapAnsi16m();\n\tstyles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);\n\tstyles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);\n\n\t// From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js\n\tObject.defineProperties(styles, {\n\t\trgbToAnsi256: {\n\t\t\tvalue(red, green, blue) {\n\t\t\t\t// We use the extended greyscale palette here, with the exception of\n\t\t\t\t// black and white. normal palette only has 4 greyscale shades.\n\t\t\t\tif (red === green && green === blue) {\n\t\t\t\t\tif (red < 8) {\n\t\t\t\t\t\treturn 16;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (red > 248) {\n\t\t\t\t\t\treturn 231;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn Math.round(((red - 8) / 247) * 24) + 232;\n\t\t\t\t}\n\n\t\t\t\treturn 16\n\t\t\t\t\t+ (36 * Math.round(red / 255 * 5))\n\t\t\t\t\t+ (6 * Math.round(green / 255 * 5))\n\t\t\t\t\t+ Math.round(blue / 255 * 5);\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToRgb: {\n\t\t\tvalue(hex) {\n\t\t\t\tconst matches = /[a-f\\d]{6}|[a-f\\d]{3}/i.exec(hex.toString(16));\n\t\t\t\tif (!matches) {\n\t\t\t\t\treturn [0, 0, 0];\n\t\t\t\t}\n\n\t\t\t\tlet [colorString] = matches;\n\n\t\t\t\tif (colorString.length === 3) {\n\t\t\t\t\tcolorString = [...colorString].map(character => character + character).join('');\n\t\t\t\t}\n\n\t\t\t\tconst integer = Number.parseInt(colorString, 16);\n\n\t\t\t\treturn [\n\t\t\t\t\t/* eslint-disable no-bitwise */\n\t\t\t\t\t(integer >> 16) & 0xFF,\n\t\t\t\t\t(integer >> 8) & 0xFF,\n\t\t\t\t\tinteger & 0xFF,\n\t\t\t\t\t/* eslint-enable no-bitwise */\n\t\t\t\t];\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi256: {\n\t\t\tvalue: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t\tansi256ToAnsi: {\n\t\t\tvalue(code) {\n\t\t\t\tif (code < 8) {\n\t\t\t\t\treturn 30 + code;\n\t\t\t\t}\n\n\t\t\t\tif (code < 16) {\n\t\t\t\t\treturn 90 + (code - 8);\n\t\t\t\t}\n\n\t\t\t\tlet red;\n\t\t\t\tlet green;\n\t\t\t\tlet blue;\n\n\t\t\t\tif (code >= 232) {\n\t\t\t\t\tred = (((code - 232) * 10) + 8) / 255;\n\t\t\t\t\tgreen = red;\n\t\t\t\t\tblue = red;\n\t\t\t\t} else {\n\t\t\t\t\tcode -= 16;\n\n\t\t\t\t\tconst remainder = code % 36;\n\n\t\t\t\t\tred = Math.floor(code / 36) / 5;\n\t\t\t\t\tgreen = Math.floor(remainder / 6) / 5;\n\t\t\t\t\tblue = (remainder % 6) / 5;\n\t\t\t\t}\n\n\t\t\t\tconst value = Math.max(red, green, blue) * 2;\n\n\t\t\t\tif (value === 0) {\n\t\t\t\t\treturn 30;\n\t\t\t\t}\n\n\t\t\t\t// eslint-disable-next-line no-bitwise\n\t\t\t\tlet result = 30 + ((Math.round(blue) << 2) | (Math.round(green) << 1) | Math.round(red));\n\n\t\t\t\tif (value === 2) {\n\t\t\t\t\tresult += 60;\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t},\n\t\t\tenumerable: false,\n\t\t},\n\t\trgbToAnsi: {\n\t\t\tvalue: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),\n\t\t\tenumerable: false,\n\t\t},\n\t\thexToAnsi: {\n\t\t\tvalue: hex => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),\n\t\t\tenumerable: false,\n\t\t},\n\t});\n\n\treturn styles;\n}\n\nconst ansiStyles = assembleStyles();\n\nexport default ansiStyles;\n","import process from 'node:process';\nimport os from 'node:os';\nimport tty from 'node:tty';\n\n// From: https://github.com/sindresorhus/has-flag/blob/main/index.js\n/// function hasFlag(flag, argv = globalThis.Deno?.args ?? process.argv) {\nfunction hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {\n\tconst prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');\n\tconst position = argv.indexOf(prefix + flag);\n\tconst terminatorPosition = argv.indexOf('--');\n\treturn position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);\n}\n\nconst {env} = process;\n\nlet flagForceColor;\nif (\n\thasFlag('no-color')\n\t|| hasFlag('no-colors')\n\t|| hasFlag('color=false')\n\t|| hasFlag('color=never')\n) {\n\tflagForceColor = 0;\n} else if (\n\thasFlag('color')\n\t|| hasFlag('colors')\n\t|| hasFlag('color=true')\n\t|| hasFlag('color=always')\n) {\n\tflagForceColor = 1;\n}\n\nfunction envForceColor() {\n\tif ('FORCE_COLOR' in env) {\n\t\tif (env.FORCE_COLOR === 'true') {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (env.FORCE_COLOR === 'false') {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);\n\t}\n}\n\nfunction translateLevel(level) {\n\tif (level === 0) {\n\t\treturn false;\n\t}\n\n\treturn {\n\t\tlevel,\n\t\thasBasic: true,\n\t\thas256: level >= 2,\n\t\thas16m: level >= 3,\n\t};\n}\n\nfunction _supportsColor(haveStream, {streamIsTTY, sniffFlags = true} = {}) {\n\tconst noFlagForceColor = envForceColor();\n\tif (noFlagForceColor !== undefined) {\n\t\tflagForceColor = noFlagForceColor;\n\t}\n\n\tconst forceColor = sniffFlags ? flagForceColor : noFlagForceColor;\n\n\tif (forceColor === 0) {\n\t\treturn 0;\n\t}\n\n\tif (sniffFlags) {\n\t\tif (hasFlag('color=16m')\n\t\t\t|| hasFlag('color=full')\n\t\t\t|| hasFlag('color=truecolor')) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (hasFlag('color=256')) {\n\t\t\treturn 2;\n\t\t}\n\t}\n\n\t// Check for Azure DevOps pipelines.\n\t// Has to be above the `!streamIsTTY` check.\n\tif ('TF_BUILD' in env && 'AGENT_NAME' in env) {\n\t\treturn 1;\n\t}\n\n\tif (haveStream && !streamIsTTY && forceColor === undefined) {\n\t\treturn 0;\n\t}\n\n\tconst min = forceColor || 0;\n\n\tif (env.TERM === 'dumb') {\n\t\treturn min;\n\t}\n\n\tif (process.platform === 'win32') {\n\t\t// Windows 10 build 10586 is the first Windows release that supports 256 colors.\n\t\t// Windows 10 build 14931 is the first release that supports 16m/TrueColor.\n\t\tconst osRelease = os.release().split('.');\n\t\tif (\n\t\t\tNumber(osRelease[0]) >= 10\n\t\t\t&& Number(osRelease[2]) >= 10_586\n\t\t) {\n\t\t\treturn Number(osRelease[2]) >= 14_931 ? 3 : 2;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\tif ('CI' in env) {\n\t\tif (['GITHUB_ACTIONS', 'GITEA_ACTIONS', 'CIRCLECI'].some(key => key in env)) {\n\t\t\treturn 3;\n\t\t}\n\n\t\tif (['TRAVIS', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn min;\n\t}\n\n\tif ('TEAMCITY_VERSION' in env) {\n\t\treturn /^(9\\.(0*[1-9]\\d*)\\.|\\d{2,}\\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;\n\t}\n\n\tif (env.COLORTERM === 'truecolor') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-kitty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'xterm-ghostty') {\n\t\treturn 3;\n\t}\n\n\tif (env.TERM === 'wezterm') {\n\t\treturn 3;\n\t}\n\n\tif ('TERM_PROGRAM' in env) {\n\t\tconst version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);\n\n\t\tswitch (env.TERM_PROGRAM) {\n\t\t\tcase 'iTerm.app': {\n\t\t\t\treturn version >= 3 ? 3 : 2;\n\t\t\t}\n\n\t\t\tcase 'Apple_Terminal': {\n\t\t\t\treturn 2;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (/-256(color)?$/i.test(env.TERM)) {\n\t\treturn 2;\n\t}\n\n\tif (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {\n\t\treturn 1;\n\t}\n\n\tif ('COLORTERM' in env) {\n\t\treturn 1;\n\t}\n\n\treturn min;\n}\n\nexport function createSupportsColor(stream, options = {}) {\n\tconst level = _supportsColor(stream, {\n\t\tstreamIsTTY: stream && stream.isTTY,\n\t\t...options,\n\t});\n\n\treturn translateLevel(level);\n}\n\nconst supportsColor = {\n\tstdout: createSupportsColor({isTTY: tty.isatty(1)}),\n\tstderr: createSupportsColor({isTTY: tty.isatty(2)}),\n};\n\nexport default supportsColor;\n","// TODO: When targeting Node.js 16, use `String.prototype.replaceAll`.\nexport function stringReplaceAll(string, substring, replacer) {\n\tlet index = string.indexOf(substring);\n\tif (index === -1) {\n\t\treturn string;\n\t}\n\n\tconst substringLength = substring.length;\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\treturnValue += string.slice(endIndex, index) + substring + replacer;\n\t\tendIndex = index + substringLength;\n\t\tindex = string.indexOf(substring, endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n\nexport function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {\n\tlet endIndex = 0;\n\tlet returnValue = '';\n\tdo {\n\t\tconst gotCR = string[index - 1] === '\\r';\n\t\treturnValue += string.slice(endIndex, (gotCR ? index - 1 : index)) + prefix + (gotCR ? '\\r\\n' : '\\n') + postfix;\n\t\tendIndex = index + 1;\n\t\tindex = string.indexOf('\\n', endIndex);\n\t} while (index !== -1);\n\n\treturnValue += string.slice(endIndex);\n\treturn returnValue;\n}\n","import ansiStyles from '#ansi-styles';\nimport supportsColor from '#supports-color';\nimport { // eslint-disable-line import/order\n\tstringReplaceAll,\n\tstringEncaseCRLFWithFirstIndex,\n} from './utilities.js';\n\nconst {stdout: stdoutColor, stderr: stderrColor} = supportsColor;\n\nconst GENERATOR = Symbol('GENERATOR');\nconst STYLER = Symbol('STYLER');\nconst IS_EMPTY = Symbol('IS_EMPTY');\n\n// `supportsColor.level` → `ansiStyles.color[name]` mapping\nconst levelMapping = [\n\t'ansi',\n\t'ansi',\n\t'ansi256',\n\t'ansi16m',\n];\n\nconst styles = Object.create(null);\n\nconst applyOptions = (object, options = {}) => {\n\tif (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {\n\t\tthrow new Error('The `level` option should be an integer from 0 to 3');\n\t}\n\n\t// Detect level if not set manually\n\tconst colorLevel = stdoutColor ? stdoutColor.level : 0;\n\tobject.level = options.level === undefined ? colorLevel : options.level;\n};\n\nexport class Chalk {\n\tconstructor(options) {\n\t\t// eslint-disable-next-line no-constructor-return\n\t\treturn chalkFactory(options);\n\t}\n}\n\nconst chalkFactory = options => {\n\tconst chalk = (...strings) => strings.join(' ');\n\tapplyOptions(chalk, options);\n\n\tObject.setPrototypeOf(chalk, createChalk.prototype);\n\n\treturn chalk;\n};\n\nfunction createChalk(options) {\n\treturn chalkFactory(options);\n}\n\nObject.setPrototypeOf(createChalk.prototype, Function.prototype);\n\nfor (const [styleName, style] of Object.entries(ansiStyles)) {\n\tstyles[styleName] = {\n\t\tget() {\n\t\t\tconst builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);\n\t\t\tObject.defineProperty(this, styleName, {value: builder});\n\t\t\treturn builder;\n\t\t},\n\t};\n}\n\nstyles.visible = {\n\tget() {\n\t\tconst builder = createBuilder(this, this[STYLER], true);\n\t\tObject.defineProperty(this, 'visible', {value: builder});\n\t\treturn builder;\n\t},\n};\n\nconst getModelAnsi = (model, level, type, ...arguments_) => {\n\tif (model === 'rgb') {\n\t\tif (level === 'ansi16m') {\n\t\t\treturn ansiStyles[type].ansi16m(...arguments_);\n\t\t}\n\n\t\tif (level === 'ansi256') {\n\t\t\treturn ansiStyles[type].ansi256(ansiStyles.rgbToAnsi256(...arguments_));\n\t\t}\n\n\t\treturn ansiStyles[type].ansi(ansiStyles.rgbToAnsi(...arguments_));\n\t}\n\n\tif (model === 'hex') {\n\t\treturn getModelAnsi('rgb', level, type, ...ansiStyles.hexToRgb(...arguments_));\n\t}\n\n\treturn ansiStyles[type][model](...arguments_);\n};\n\nconst usedModels = ['rgb', 'hex', 'ansi256'];\n\nfor (const model of usedModels) {\n\tstyles[model] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'color', ...arguments_), ansiStyles.color.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n\n\tconst bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);\n\tstyles[bgModel] = {\n\t\tget() {\n\t\t\tconst {level} = this;\n\t\t\treturn function (...arguments_) {\n\t\t\t\tconst styler = createStyler(getModelAnsi(model, levelMapping[level], 'bgColor', ...arguments_), ansiStyles.bgColor.close, this[STYLER]);\n\t\t\t\treturn createBuilder(this, styler, this[IS_EMPTY]);\n\t\t\t};\n\t\t},\n\t};\n}\n\nconst proto = Object.defineProperties(() => {}, {\n\t...styles,\n\tlevel: {\n\t\tenumerable: true,\n\t\tget() {\n\t\t\treturn this[GENERATOR].level;\n\t\t},\n\t\tset(level) {\n\t\t\tthis[GENERATOR].level = level;\n\t\t},\n\t},\n});\n\nconst createStyler = (open, close, parent) => {\n\tlet openAll;\n\tlet closeAll;\n\tif (parent === undefined) {\n\t\topenAll = open;\n\t\tcloseAll = close;\n\t} else {\n\t\topenAll = parent.openAll + open;\n\t\tcloseAll = close + parent.closeAll;\n\t}\n\n\treturn {\n\t\topen,\n\t\tclose,\n\t\topenAll,\n\t\tcloseAll,\n\t\tparent,\n\t};\n};\n\nconst createBuilder = (self, _styler, _isEmpty) => {\n\t// Single argument is hot path, implicit coercion is faster than anything\n\t// eslint-disable-next-line no-implicit-coercion\n\tconst builder = (...arguments_) => applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));\n\n\t// We alter the prototype because we must return a function, but there is\n\t// no way to create a function with a different prototype\n\tObject.setPrototypeOf(builder, proto);\n\n\tbuilder[GENERATOR] = self;\n\tbuilder[STYLER] = _styler;\n\tbuilder[IS_EMPTY] = _isEmpty;\n\n\treturn builder;\n};\n\nconst applyStyle = (self, string) => {\n\tif (self.level <= 0 || !string) {\n\t\treturn self[IS_EMPTY] ? '' : string;\n\t}\n\n\tlet styler = self[STYLER];\n\n\tif (styler === undefined) {\n\t\treturn string;\n\t}\n\n\tconst {openAll, closeAll} = styler;\n\tif (string.includes('\\u001B')) {\n\t\twhile (styler !== undefined) {\n\t\t\t// Replace any instances already present with a re-opening code\n\t\t\t// otherwise only the part of the string until said closing code\n\t\t\t// will be colored, and the rest will simply be 'plain'.\n\t\t\tstring = stringReplaceAll(string, styler.close, styler.open);\n\n\t\t\tstyler = styler.parent;\n\t\t}\n\t}\n\n\t// We can move both next actions out of loop, because remaining actions in loop won't have\n\t// any/visible effect on parts we add here. Close the styling before a linebreak and reopen\n\t// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92\n\tconst lfIndex = string.indexOf('\\n');\n\tif (lfIndex !== -1) {\n\t\tstring = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);\n\t}\n\n\treturn openAll + string + closeAll;\n};\n\nObject.defineProperties(createChalk.prototype, styles);\n\nconst chalk = createChalk();\nexport const chalkStderr = createChalk({level: stderrColor ? stderrColor.level : 0});\n\nexport {\n\tmodifierNames,\n\tforegroundColorNames,\n\tbackgroundColorNames,\n\tcolorNames,\n\n\t// TODO: Remove these aliases in the next major version\n\tmodifierNames as modifiers,\n\tforegroundColorNames as foregroundColors,\n\tbackgroundColorNames as backgroundColors,\n\tcolorNames as colors,\n} from './vendor/ansi-styles/index.js';\n\nexport {\n\tstdoutColor as supportsColor,\n\tstderrColor as supportsColorStderr,\n};\n\nexport default chalk;\n","/**\n * Assistant / user 消息的 markdown → ANSI 渲染入口。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.4。\n *\n * 之前散在 `src/components/MessageView.tsx` 内的 marked 初始化与 renderMarkdown\n * 函数集中到这里,作为 RenderPipeline 模块的对外 helper。UI 只 import 这一个入口。\n *\n * marked-terminal 7.x 默认配置 `showSectionPrefix: true`,会在 heading 文本前\n * 显式拼回 `## `,渲染出 `[bold green]## 标题[/]` 的效果 — 即使 heading 颜色生效,\n * 用户视觉上也会看到原始的 `## ` 标记。这里强制关掉。\n */\n\nimport chalk from \"chalk\";\nimport { marked } from \"marked\";\n// @ts-expect-error marked-terminal 7.x 无内置 .d.ts;运行时正常\nimport { markedTerminal } from \"marked-terminal\";\n\n// chalk 在 module load 时可能基于 stdout 探测把 level 锁成 0(非 TTY、CI 等场景),\n// 这会让 markedTerminal 的 chalk.bold/italic 全部返回纯文本。Ink 渲染到的目标是 TTY,\n// 强制至少 256 色,让 ANSI 码进得了 Text 节点。\nif (chalk.level === 0) chalk.level = 3;\n\nlet registered = false;\nfunction ensureRegistered(): void {\n if (registered) return;\n marked.use(\n markedTerminal({\n // 关键:不要在 heading 文本前拼回 `## `。\n showSectionPrefix: false,\n // 默认 4 空格缩进 list / blockquote,看起来过深 — 跟 Codex 风格对齐:\n // 圆点 + 空格作左边界,续行起点 = 首行文字起点,list 不再额外缩进 4 空格,\n // 用 2 空格只够区分嵌套层级。\n tab: \" \",\n }) as Parameters<typeof marked.use>[0],\n );\n registered = true;\n}\n\n/** Markdown → ANSI 字符串。流到一半的 ```code 等会让 parse 抛错,退化到纯文本。 */\nexport function renderMarkdown(text: string): string {\n ensureRegistered();\n try {\n let out = marked.parse(text) as string;\n out = out.replace(/\\n+$/, \"\"); // 末尾换行去掉,免得 Ink Box 多一行空白\n\n // 修 marked-terminal 在 list item 等场景里把 **bold** / *italic* 当文本吐出来:\n // 自己用正则补一刀(在 reset 处理之前做,否则 \\x1b[0m 会把 \\x1b[1m 切断)\n out = out.replace(/\\*\\*([^\\n*]+?)\\*\\*/g, (_, body) => `\\x1b[1m${body}\\x1b[22m`);\n out = out.replace(/(?<![*\\\\\\x1b])\\*([^\\n*]+?)\\*(?!\\*)/g, (_, body) => `\\x1b[3m${body}\\x1b[23m`);\n\n // marked-terminal 在每个 block 前后塞 \\x1b[0m 全 reset——这会把外层的\n // chalk.bgHex(用户消息条带)一并清掉,渲染出\"字体处没背景\"的断带。\n // 整体剥掉,让样式 close 各自的 \\x1b[22m / \\x1b[23m / \\x1b[39m 收尾即可。\n out = out.replace(/\\x1b\\[0m/g, \"\");\n\n // 兜底:LLM 自己写的 markdown 可能用 4-空格缩进表达\"代码块\"/\"突出段落\",\n // 即使 marked 不把它解析为 code(语义边界没满足),前导空白仍残留。\n // 把每行前导空白以 4 为单位减半成 2,既保留嵌套层级,又防\"过深\"。\n out = out.replace(/^( {4,})/gm, (m) => \" \".repeat(Math.floor(m.length / 2)));\n\n return out;\n } catch {\n return text;\n }\n}\n","/**\n * RenderPipeline 模块占位 + 渲染 helper。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.4。\n *\n * **MVP 偏离说明(ADR)**:\n * React 组件本身是声明式渲染,把 `fold-tool-use` / `highlight-diff` 强行 stage 化\n * 会引入额外抽象层(组件 ↔ stage ctx 互相转换),收益反而是负的。\n * 因此本期 RenderPipeline 仅暴露 **纯函数 helper**,供 MessageView 继续以组件方式调用;\n * 真正 stage 化推到 v0.2.x(若 stream-markdown / collapse-long / linkify 真正需要时再做)。\n *\n * 不影响整体框架——其它三段 pipeline 已统一在 Pipeline<Ctx> 之下。\n */\n\nexport { renderMarkdown } from \"./markdown.js\";\n\n/** bash 工具内容里独立成行的 <stdout>/<stderr>/<timeout>/<exit_code> 包装标签剥除。 */\nexport function stripWrapperTags(content: string): string {\n return content\n .split(\"\\n\")\n .filter((l) => !/^<\\/?(stdout|stderr|timeout|exit_code)>\\s*$/.test(l.trim()))\n .join(\"\\n\");\n}\n\n/** 工具结果折叠展示:长输出取头 N 行 + \"+M more lines\" 提示。 */\nexport interface FoldedResult {\n lines: string[];\n omittedLines: number;\n}\n\nexport function foldToolResult(content: string, maxLines: number): FoldedResult {\n const all = content.split(\"\\n\");\n while (all.length > 0 && all[all.length - 1].trim() === \"\") all.pop();\n while (all.length > 0 && all[0].trim() === \"\") all.shift();\n if (all.length <= maxLines) return { lines: all, omittedLines: 0 };\n return { lines: all.slice(0, maxLines), omittedLines: all.length - maxLines };\n}\n\n/**\n * 单条 assistant 消息内容过长(> maxLines)时折叠成 head + omitted 标记 + tail 三段。\n * 设计文档:模块设计/消息预处理工程/设计.md §4.4.2(`collapse-long`)。\n *\n * 折叠原则:\n * - 默认 200 行触发(只盖\"小说级\"长输出,日常对话不受影响)\n * - 头 5 行 + 尾 5 行 + 中间 omittedLines 计数;让用户既看到意图,又看到结论\n * - **仅在历史回看触发** — 流式中由 StreamingMarkdown 独立渲染,不调本 helper\n * - 完整内容仍在 session JSONL,需要时 /resume 重新加载\n *\n * 不支持展开:Ink TUI 里\"按某键展开第 K 条 message\"需引入 view state + 键盘路由,\n * 增加复杂度但价值低(完整内容已在 JSONL)。等真有需求再加。\n */\nexport interface CollapsedLong {\n head: string[];\n tail: string[];\n omittedLines: number;\n collapsed: boolean;\n}\n\nexport function collapseLong(\n content: string,\n opts: { maxLines?: number; headLines?: number; tailLines?: number } = {},\n): CollapsedLong {\n const maxLines = opts.maxLines ?? 200;\n const headLines = opts.headLines ?? 5;\n const tailLines = opts.tailLines ?? 5;\n const all = content.split(\"\\n\");\n if (all.length <= maxLines) {\n return { head: all, tail: [], omittedLines: 0, collapsed: false };\n }\n // 退化兜底:head + tail 比 maxLines 还大(opts 配错) → 按比例缩\n const room = Math.max(2, Math.min(maxLines - 1, headLines + tailLines));\n const safeHead = Math.max(1, Math.floor(room * (headLines / (headLines + tailLines))));\n const safeTail = Math.max(1, room - safeHead);\n return {\n head: all.slice(0, safeHead),\n tail: all.slice(-safeTail),\n omittedLines: all.length - safeHead - safeTail,\n collapsed: true,\n };\n}\n\n/** Unified diff 头几行(Index / === / --- / +++)裁掉,只保留 @@ hunks。 */\nexport function diffHunksOnly(diff: string): string[] {\n const lines = diff.split(\"\\n\");\n const start = lines.findIndex((l) => l.startsWith(\"@@\"));\n return start >= 0 ? lines.slice(start) : lines;\n}\n","/**\n * Muse UI 统一色板。\n *\n * 焦点系:所有选择器(Selector / QuestionPicker / SessionSelector / ModelSelector /\n * PermissionPrompt)与补全 overlay(SlashAutocomplete / AtFileAutocomplete)的「焦点行」\n * 共用同色,避免散落硬编码。\n *\n * 后续若做 light / dark 主题切换,改这一文件即可;未来 plugin / mcp 等新选择器\n * 直接 import FOCUS_COLOR,无需再造常量。\n */\n\n/** 焦点行 / 焦点项的整体高亮色 — 命令名 / 文件名 / 选项 label / 边框 ▎。\n * 淡紫色(Tailwind violet-300),对齐主流 TUI Agent 的 Todos 配色风格。 */\nexport const FOCUS_COLOR = \"#C4B5FD\";\n\n/** 焦点指针装饰符 `›` 的色 — 默认与 FOCUS_COLOR 同色,留分化空间。 */\nexport const POINTER_COLOR = FOCUS_COLOR;\n\n/** Todos in_progress 当前进行中任务的高亮色 — 橙色(Tailwind orange-500),\n * 对齐主流 TUI Agent 形态;与 FOCUS_COLOR 分语义:选择器焦点 vs 活跃任务 是两类色。 */\nexport const ACTIVE_TODO_COLOR = \"#F97316\";\n","/**\n * 字面闪烁动画:一个明亮窗口从左往右扫过文字,到尾巴后有短暂间隔再从头来。\n *\n * 渲染方式:把 text 拆成单字符 <Text>,按到当前 phase 的距离上色——\n * distance 0 → bright white + bold\n * distance 1 → white\n * 其他 → dim gray\n * 一个 setInterval 推进 phase。\n *\n * 视觉效果:像扫光带掠过 \"Working\" 字样,无 spinner 字符。\n */\n\nimport React, { useEffect, useState } from \"react\";\nimport { Text } from \"ink\";\n\nconst FRAME_MS = 100;\nconst TRAIL = 4; // 扫完最后一个字符后再走几帧再绕回起点,给眼睛留间隔\n\nexport interface ShimmerProps {\n text: string;\n bold?: boolean;\n}\n\nexport function Shimmer({ text, bold = true }: ShimmerProps) {\n const chars = Array.from(text);\n const cycle = chars.length + TRAIL;\n\n const [phase, setPhase] = useState(0);\n useEffect(() => {\n const id = setInterval(() => {\n setPhase((p) => (p + 1) % cycle);\n }, FRAME_MS);\n return () => clearInterval(id);\n }, [cycle]);\n\n return (\n <Text>\n {chars.map((ch, i) => {\n const d = Math.abs(i - phase);\n if (d === 0) {\n return (\n <Text key={i} color=\"white\" bold={bold}>\n {ch}\n </Text>\n );\n }\n if (d === 1) {\n return (\n <Text key={i} color=\"white\">\n {ch}\n </Text>\n );\n }\n return (\n <Text key={i} color=\"gray\" dimColor>\n {ch}\n </Text>\n );\n })}\n </Text>\n );\n}\n","/**\n * 工具调用的权限确认 prompt(v2 picker)。\n *\n * ↑/↓ 选择 + Enter 确认;快捷键 y/s/n 与 1/2/3 直接落子;Esc 等价于 no。\n *\n * 三选项:\n * 1. Yes — 本次允许\n * 2. Yes, allow <Tool> for session — 后续该 toolName 在 session 内全部 allow\n * 3. No — 拒绝\n */\n\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { PermissionDecision } from \"../permission/index.js\";\nimport { FOCUS_COLOR } from \"../ui/theme.js\";\n\nexport interface PermissionRequest {\n toolName: string;\n args: unknown;\n summary: string;\n resolve: (decision: PermissionDecision) => void;\n}\n\nconst OPTIONS: { decision: PermissionDecision; labelKey: \"yes\" | \"session\" | \"no\"; shortcut: string }[] = [\n { decision: \"yes\", labelKey: \"yes\", shortcut: \"y\" },\n { decision: \"session_allow\", labelKey: \"session\", shortcut: \"s\" },\n { decision: \"no\", labelKey: \"no\", shortcut: \"n\" },\n];\n\nexport function PermissionPrompt({ request }: { request: PermissionRequest }) {\n const [index, setIndex] = useState(0);\n\n useInput((input, key) => {\n if (key.upArrow) {\n setIndex((i) => (i - 1 + OPTIONS.length) % OPTIONS.length);\n return;\n }\n if (key.downArrow) {\n setIndex((i) => (i + 1) % OPTIONS.length);\n return;\n }\n if (key.return) {\n request.resolve(OPTIONS[index].decision);\n return;\n }\n if (key.escape) {\n request.resolve(\"no\");\n return;\n }\n const lower = input?.toLowerCase?.();\n for (let i = 0; i < OPTIONS.length; i++) {\n const o = OPTIONS[i];\n if (lower === o.shortcut || input === String(i + 1)) {\n request.resolve(o.decision);\n return;\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginY={1} borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text color=\"yellow\" bold>\n ⏵ Approve {request.toolName}?\n </Text>\n <Text dimColor>{request.summary}</Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {OPTIONS.map((o, i) => {\n const focused = i === index;\n const label = labelFor(o.labelKey, request.toolName);\n return (\n <Text key={o.decision} color={focused ? FOCUS_COLOR : undefined} bold={focused}>\n {focused ? \"› \" : \" \"}\n {i + 1}. {label}{\" \"}\n <Text dimColor>({o.shortcut})</Text>\n </Text>\n );\n })}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>↑↓ select · Enter confirm · y/s/n shortcut · Esc=no</Text>\n </Box>\n </Box>\n );\n}\n\nfunction labelFor(key: \"yes\" | \"session\" | \"no\", toolName: string): string {\n switch (key) {\n case \"yes\":\n return \"Yes\";\n case \"session\":\n return `Yes, allow ${toolName} for the rest of this session`;\n case \"no\":\n return \"No\";\n }\n}\n","/**\n * 模型选择器:用 Selector 骨架实现,提供 model entry 专用行渲染。\n *\n * 由 /model 命令通过 ctx.actions.pickModel(...) 拉起。\n * 接口(ModelPickerRequest)保持稳定,便于 app.tsx 不动 actions.pickModel 调用方。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { Selector } from \"./Selector.js\";\nimport type { ModelEntry } from \"../config/models.js\";\n\nexport interface ModelPickerRequest {\n items: ModelEntry[];\n currentId?: string;\n resolve: (picked: ModelEntry | null) => void;\n}\n\nexport function ModelSelector({ request }: { request: ModelPickerRequest }) {\n const { items, currentId, resolve } = request;\n const initialIndex = Math.max(\n 0,\n items.findIndex((m) => m.id === currentId),\n );\n const labelWidth = Math.max(...items.map((m) => (m.name ?? m.id).length));\n\n return (\n <Selector\n items={items}\n initialIndex={initialIndex}\n title=\"Select model\"\n hint=\"↑↓ navigate · Enter confirm · Esc cancel\"\n onSubmit={(m) => resolve(m)}\n onCancel={() => resolve(null)}\n renderRow={(m, _focused) => (\n <ModelRow model={m} active={m.id === currentId} labelWidth={labelWidth} />\n )}\n />\n );\n}\n\nfunction ModelRow({\n model,\n active,\n labelWidth,\n}: {\n model: ModelEntry;\n active: boolean;\n labelWidth: number;\n}) {\n const dot = active ? \"●\" : \" \";\n const label = (model.name ?? model.id).padEnd(labelWidth);\n const vendor = model.vendor ? `[${model.vendor}]` : \"\";\n const caps = formatCaps(model);\n\n return (\n <Box flexDirection=\"row\">\n <Text color={active ? \"green\" : undefined}>{dot} </Text>\n <Text>{label}</Text>\n <Text dimColor>{\" \"}{vendor}</Text>\n {caps && <Text dimColor>{\" \"}{caps}</Text>}\n </Box>\n );\n}\n\nfunction formatCaps(m: ModelEntry): string {\n const flags: string[] = [];\n if (m.supportsToolCall === false) flags.push(\"no-tools\");\n if (m.supportsImages) flags.push(\"vision\");\n return flags.length ? flags.join(\" · \") : \"\";\n}\n","/**\n * 通用键盘 selector 骨架:↑↓ 导航 + Enter 确认 + Esc 取消。\n *\n * 行渲染由 renderRow 回调提供;本组件只负责:\n * - 键盘事件\n * - 焦点状态 + 滑动窗口(保证 focused 始终可见)\n * - 紫色 `›` 焦点指针(色见 `src/ui/theme.ts::POINTER_COLOR`)\n * - 标题 + 提示\n *\n * 当前调用方:ModelSelector / SessionSelector。\n * 第三处再考虑把外层 borderStyle 等做成 prop;暂时硬编码。\n */\n\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport { POINTER_COLOR } from \"../ui/theme.js\";\n\nexport interface SelectorProps<T> {\n items: T[];\n initialIndex?: number;\n title?: string;\n hint?: string;\n maxVisible?: number;\n renderRow: (item: T, focused: boolean) => React.ReactNode;\n onSubmit: (item: T) => void;\n onCancel: () => void;\n}\n\nexport function Selector<T>({\n items,\n initialIndex = 0,\n title,\n hint,\n maxVisible,\n renderRow,\n onSubmit,\n onCancel,\n}: SelectorProps<T>) {\n const safeInitial = Math.max(0, Math.min(initialIndex, items.length - 1));\n const [index, setIndex] = useState(safeInitial);\n\n useInput((_, key) => {\n if (key.upArrow) {\n setIndex((i) => Math.max(0, i - 1));\n } else if (key.downArrow) {\n setIndex((i) => Math.min(items.length - 1, i + 1));\n } else if (key.return) {\n onSubmit(items[index]);\n } else if (key.escape) {\n onCancel();\n }\n });\n\n const len = items.length;\n const window = maxVisible && maxVisible < len ? maxVisible : len;\n const start = Math.max(0, Math.min(index - Math.floor(window / 2), len - window));\n const end = Math.min(len, start + window);\n const visible = items.slice(start, end);\n\n return (\n <Box\n flexDirection=\"column\"\n marginTop={1}\n paddingX={1}\n borderStyle=\"round\"\n borderColor=\"cyan\"\n >\n {(title || hint) && (\n <Box marginBottom={1}>\n {title && <Text bold>{title}</Text>}\n {title && hint && <Text dimColor>{\" \"}</Text>}\n {hint && <Text dimColor>{hint}</Text>}\n </Box>\n )}\n {visible.map((item, i) => {\n const realIndex = start + i;\n const focused = realIndex === index;\n return (\n <Box key={realIndex} flexDirection=\"row\">\n <Text color={POINTER_COLOR} bold>\n {focused ? \"› \" : \" \"}\n </Text>\n {renderRow(item, focused)}\n </Box>\n );\n })}\n {window < len && (\n <Box marginTop={1}>\n <Text dimColor>\n ({start + 1}-{end} / {len})\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * Session 选择器:列出当前 cwd 下的历史会话,键盘选中加载。\n *\n * 由 /resume 命令通过 ctx.actions.pickSession(...) 拉起。\n * 行布局对齐 /resume display 文本版(id8 · time · [N msgs] · preview),\n * 视觉差异:紫色 `›` 箭头 + 边框 + 选中态。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { Selector } from \"./Selector.js\";\nimport type { SessionSummary } from \"../session/jsonl.js\";\n\nexport interface SessionPickerRequest {\n items: SessionSummary[];\n currentId?: string;\n resolve: (picked: SessionSummary | null) => void;\n}\n\nexport function SessionSelector({ request }: { request: SessionPickerRequest }) {\n const { items, currentId, resolve } = request;\n const initialIndex = Math.max(\n 0,\n items.findIndex((s) => s.id === currentId),\n );\n\n return (\n <Selector\n items={items}\n initialIndex={initialIndex}\n maxVisible={12}\n title=\"Resume session\"\n hint=\"↑↓ navigate · Enter load · Esc cancel\"\n onSubmit={(s) => resolve(s)}\n onCancel={() => resolve(null)}\n renderRow={(s) => <SessionRow session={s} active={s.id === currentId} />}\n />\n );\n}\n\nfunction SessionRow({ session, active }: { session: SessionSummary; active: boolean }) {\n const id8 = session.id.slice(0, 8);\n const time = formatTime(session.createdAt);\n const count = `[${String(session.messageCount).padStart(2)} msgs]`;\n const preview = session.preview ?? \"(empty)\";\n\n return (\n <Box flexDirection=\"row\">\n <Text color={active ? \"green\" : undefined}>{active ? \"● \" : \" \"}</Text>\n <Text>{id8}</Text>\n <Text dimColor>{\" \"}{time}</Text>\n <Text dimColor>{\" \"}{count}</Text>\n <Text>{\" \"}{preview}</Text>\n </Box>\n );\n}\n\nfunction formatTime(iso: string): string {\n const d = new Date(iso);\n if (isNaN(d.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n","/**\n * AskUserQuestion UI——对齐业界 Coding Agent 的链式选择器形态。\n *\n * 布局:\n *\n * ─────────────────────────────────────────────────────────────────\n * ← □ Header1 □ Header2 □ Header3 ✔ Submit →\n *\n * Question text?\n *\n * 1. Option A ┌──────────────────────────────┐\n * description │ preview content for the │\n * 2. Option B │ focused option │\n * description │ (multi-line allowed) │\n * └──────────────────────────────┘\n *\n * Notes: press n to add notes\n * ─────────────────────────────────────────────────────────────────\n * Enter to select · ↑/↓ to navigate · n to add notes · Tab to switch questions · Esc to cancel\n *\n * 状态:\n * - 每题独立 optionIndex / selected / notes\n * - notesEditing 切换内联文本编辑器(Enter 保存 / Esc 退出回 picker,不取消整批)\n *\n * 键位:\n * ↑↓ 选项移动\n * ←→ / Tab 题间切换(含 Submit chip)\n * Enter option 上:单选 → 选定 + 跳下一题;多选 → toggle\n * Submit 上 → 提交\n * Space 多选 toggle\n * n 进入 notes 编辑(Enter 保存 / Esc 退出)\n * Esc picker 取消\n *\n * Tab chip 标记:\n * 单选未答 □ / 答了 ✔\n * 多选未选 □ / 选了 N 个 [N]\n * 聚焦 chip 走 FOCUS_BG 背景高亮\n *\n * 单题特化:\n * 单题不渲染 tab bar / Submit chip——单选 Enter 直提交;多选 Submit 行放选项末尾\n */\n\nimport React, { useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { AskQuestion, AskQuestionResponse } from \"../tools/builtin/ask-user-question.js\";\nimport { POINTER_COLOR } from \"../ui/theme.js\";\n\nconst FOCUS_BG = \"#5B5598\"; // 聚焦 chip 背景(柔和淡紫)\nconst FOCUS_FG = \"white\";\nconst SUBMIT_COLOR = \"green\";\nconst NOTES_LABEL_COLOR = \"yellow\";\nconst PREVIEW_BORDER = \"gray\";\nconst TAB_GAP = 3;\nconst PREVIEW_MIN_WIDTH = 28;\n\nexport interface QuestionPickerRequest {\n questions: AskQuestion[];\n resolve: (responses: AskQuestionResponse[]) => void;\n}\n\ninterface QState {\n optionIndex: number;\n selected: Set<number>;\n notes: string;\n notesEditing: boolean;\n /** notes 编辑中的草稿——Enter 保存到 notes / Esc 丢弃。 */\n notesDraft: string;\n}\n\nexport function QuestionPicker({ request }: { request: QuestionPickerRequest }) {\n const { questions } = request;\n const N = questions.length;\n const hasTabs = N > 1;\n const submitTabIndex = N;\n\n const [tabIndex, setTabIndex] = useState(0);\n const [states, setStates] = useState<QState[]>(() =>\n questions.map(() => ({\n optionIndex: 0,\n selected: new Set<number>(),\n notes: \"\",\n notesEditing: false,\n notesDraft: \"\",\n })),\n );\n\n const currentQ = tabIndex < N ? questions[tabIndex] : null;\n const isMulti = currentQ?.multiSelect === true;\n const onSubmitChip = hasTabs && tabIndex === submitTabIndex;\n\n // 任意 option 提供了 preview?整个题就走双栏,焦点项的 preview 渲染到右侧\n const anyPreview = !!currentQ?.options.some((o) => o.preview);\n const focusedOpt = currentQ?.options[states[tabIndex]?.optionIndex ?? 0];\n const focusedPreview = anyPreview ? focusedOpt?.preview ?? \"\" : \"\";\n\n const buildResponses = (cancelled: boolean): AskQuestionResponse[] => {\n if (cancelled) return questions.map(() => ({ cancelled: true, selections: [] }));\n return questions.map((q, qi) => ({\n cancelled: false,\n selections: Array.from(states[qi].selected)\n .sort((a, b) => a - b)\n .map((i) => q.options[i].label),\n notes: states[qi].notes,\n }));\n };\n\n const submit = () => request.resolve(buildResponses(false));\n const cancel = () => request.resolve(buildResponses(true));\n\n const updateState = (qi: number, mut: (s: QState) => QState) => {\n setStates((prev) => {\n const next = [...prev];\n next[qi] = mut(prev[qi]);\n return next;\n });\n };\n\n const toggleOption = (qi: number, oi: number) => {\n updateState(qi, (s) => {\n const sel = new Set(s.selected);\n if (sel.has(oi)) sel.delete(oi);\n else sel.add(oi);\n return { ...s, selected: sel };\n });\n };\n\n const selectSingleOption = (qi: number, oi: number) => {\n updateState(qi, (s) => ({ ...s, selected: new Set([oi]) }));\n if (!hasTabs) {\n request.resolve([\n {\n cancelled: false,\n selections: [questions[0].options[oi].label],\n notes: states[0].notes,\n },\n ]);\n return;\n }\n if (qi < N - 1) setTabIndex(qi + 1);\n else setTabIndex(submitTabIndex);\n };\n\n // 单题多选用的 Submit 行(=options.length,options 末尾)\n const singleQMultiSubmitRowIndex = !hasTabs && isMulti ? currentQ!.options.length : -1;\n const optionRowCount =\n !hasTabs && isMulti ? currentQ!.options.length + 1 : currentQ?.options.length ?? 0;\n\n const currentNotesEditing =\n tabIndex < N ? states[tabIndex].notesEditing : false;\n\n useInput((input, key) => {\n // ---------- notes 编辑模式 ----------\n if (currentNotesEditing) {\n if (key.escape) {\n updateState(tabIndex, (s) => ({ ...s, notesEditing: false, notesDraft: \"\" }));\n return;\n }\n if (key.return) {\n updateState(tabIndex, (s) => ({\n ...s,\n notesEditing: false,\n notes: s.notesDraft,\n notesDraft: \"\",\n }));\n return;\n }\n if (key.backspace || key.delete) {\n updateState(tabIndex, (s) => ({\n ...s,\n notesDraft: s.notesDraft.slice(0, -1),\n }));\n return;\n }\n if (key.ctrl || key.tab || key.upArrow || key.downArrow || key.leftArrow || key.rightArrow || key.meta) {\n return;\n }\n if (input) {\n updateState(tabIndex, (s) => ({ ...s, notesDraft: s.notesDraft + input }));\n }\n return;\n }\n\n // ---------- picker 主模式 ----------\n if (key.escape) {\n cancel();\n return;\n }\n\n if (hasTabs && (key.tab || key.leftArrow || key.rightArrow)) {\n if (key.leftArrow || (key.shift && key.tab)) {\n setTabIndex((t) => Math.max(0, t - 1));\n } else {\n setTabIndex((t) => Math.min(submitTabIndex, t + 1));\n }\n return;\n }\n\n if (onSubmitChip) {\n if (key.return) submit();\n return;\n }\n\n const qi = tabIndex;\n const s = states[qi];\n\n if (key.upArrow) {\n updateState(qi, (st) => ({ ...st, optionIndex: Math.max(0, st.optionIndex - 1) }));\n return;\n }\n if (key.downArrow) {\n updateState(qi, (st) => ({\n ...st,\n optionIndex: Math.min(optionRowCount - 1, st.optionIndex + 1),\n }));\n return;\n }\n // n —— 进入 notes 编辑(任何 picker 题都允许)\n if (input === \"n\" && !key.ctrl && !key.meta) {\n updateState(qi, (st) => ({\n ...st,\n notesEditing: true,\n notesDraft: st.notes,\n }));\n return;\n }\n if (key.return) {\n if (!hasTabs && isMulti && s.optionIndex === singleQMultiSubmitRowIndex) {\n submit();\n return;\n }\n if (isMulti) toggleOption(qi, s.optionIndex);\n else selectSingleOption(qi, s.optionIndex);\n return;\n }\n if (isMulti && input === \" \" && s.optionIndex !== singleQMultiSubmitRowIndex) {\n toggleOption(qi, s.optionIndex);\n }\n });\n\n // ---------- render ----------\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Divider />\n {hasTabs && (\n <Box marginTop={0}>\n <TabBar questions={questions} states={states} tabIndex={tabIndex} />\n </Box>\n )}\n\n {tabIndex < N && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>{questions[tabIndex].question}</Text>\n <Box flexDirection=\"row\" marginTop={1}>\n <Box flexDirection=\"column\" flexGrow={anyPreview ? 0 : 1} flexShrink={0} marginRight={anyPreview ? 2 : 0}>\n <OptionsList\n options={questions[tabIndex].options}\n focusedIndex={states[tabIndex].optionIndex}\n selected={states[tabIndex].selected}\n isMulti={isMulti}\n submitRowIndex={singleQMultiSubmitRowIndex}\n />\n </Box>\n {anyPreview && (\n <Box flexGrow={1} minWidth={PREVIEW_MIN_WIDTH}>\n <PreviewPanel content={focusedPreview} />\n </Box>\n )}\n </Box>\n <NotesLine\n notes={states[tabIndex].notes}\n editing={states[tabIndex].notesEditing}\n draft={states[tabIndex].notesDraft}\n />\n </Box>\n )}\n\n {onSubmitChip && (\n <Box flexDirection=\"column\" marginTop={1}>\n <SubmitPreview questions={questions} states={states} />\n </Box>\n )}\n\n <Divider />\n <Box>\n <Text dimColor>{hintLine(hasTabs, isMulti, currentNotesEditing)}</Text>\n </Box>\n </Box>\n );\n}\n\n// ---------- subcomponents ----------\n\nfunction Divider() {\n // 占满终端宽度的水平细线——用 box 的 borderTop 模拟最简单\n return (\n <Box borderStyle=\"single\" borderTop borderBottom={false} borderLeft={false} borderRight={false} borderColor=\"gray\" />\n );\n}\n\nfunction TabBar({\n questions,\n states,\n tabIndex,\n}: {\n questions: AskQuestion[];\n states: QState[];\n tabIndex: number;\n}) {\n const submitIndex = questions.length;\n const canLeft = tabIndex > 0;\n const canRight = tabIndex < submitIndex;\n return (\n <Box flexDirection=\"row\" flexWrap=\"wrap\">\n <Box marginRight={1}>\n <Text dimColor={!canLeft}>{\"←\"}</Text>\n </Box>\n {questions.map((q, i) => {\n const focused = i === tabIndex;\n const isMulti = q.multiSelect === true;\n const count = states[i].selected.size;\n const answered = count > 0;\n const mark = answered ? (isMulti ? `[${count}]` : \"✔\") : \"□\";\n return (\n <Box key={i} marginRight={TAB_GAP}>\n <Text\n backgroundColor={focused ? FOCUS_BG : undefined}\n color={focused ? FOCUS_FG : undefined}\n bold={focused}\n dimColor={!focused}\n >\n {` ${mark} ${q.header} `}\n </Text>\n </Box>\n );\n })}\n <Box marginRight={1}>\n <Text\n backgroundColor={tabIndex === submitIndex ? FOCUS_BG : undefined}\n color={tabIndex === submitIndex ? FOCUS_FG : SUBMIT_COLOR}\n bold={tabIndex === submitIndex}\n dimColor={tabIndex !== submitIndex}\n >\n {\" ✔ Submit \"}\n </Text>\n </Box>\n <Text dimColor={!canRight}>{\"→\"}</Text>\n </Box>\n );\n}\n\nfunction OptionsList({\n options,\n focusedIndex,\n selected,\n isMulti,\n submitRowIndex,\n}: {\n options: AskQuestion[\"options\"];\n focusedIndex: number;\n selected: Set<number>;\n isMulti: boolean;\n submitRowIndex: number;\n}) {\n return (\n <Box flexDirection=\"column\">\n {options.map((opt, i) => {\n const focused = i === focusedIndex;\n const checked = selected.has(i);\n return (\n <Box key={i} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text color={POINTER_COLOR} bold>\n {focused ? \"› \" : \" \"}\n </Text>\n {isMulti && (\n <Text color={checked ? \"green\" : undefined}>{checked ? \"[x] \" : \"[ ] \"}</Text>\n )}\n <Text dimColor>{`${i + 1}. `}</Text>\n <Text color={focused ? POINTER_COLOR : undefined} bold={focused}>\n {opt.label}\n </Text>\n </Box>\n {opt.description && (\n <Box marginLeft={isMulti ? 6 : 5}>\n <Text dimColor wrap=\"truncate-end\">\n {opt.description}\n </Text>\n </Box>\n )}\n </Box>\n );\n })}\n {submitRowIndex >= 0 && (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color={POINTER_COLOR} bold>\n {focusedIndex === submitRowIndex ? \"› \" : \" \"}\n </Text>\n <Text\n color={focusedIndex === submitRowIndex ? SUBMIT_COLOR : undefined}\n bold={focusedIndex === submitRowIndex}\n dimColor={focusedIndex !== submitRowIndex}\n >\n {`── Submit (${selected.size} selected)`}\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction PreviewPanel({ content }: { content: string }) {\n const lines = content ? content.split(\"\\n\") : [\"(no preview)\"];\n return (\n <Box\n borderStyle=\"round\"\n borderColor={PREVIEW_BORDER}\n flexDirection=\"column\"\n paddingX={1}\n flexGrow={1}\n >\n {lines.map((line, i) => (\n <Text key={i} wrap=\"truncate-end\" dimColor={!content}>\n {line || \" \"}\n </Text>\n ))}\n </Box>\n );\n}\n\nfunction NotesLine({\n notes,\n editing,\n draft,\n}: {\n notes: string;\n editing: boolean;\n draft: string;\n}) {\n if (editing) {\n return (\n <Box marginTop={1} flexDirection=\"row\">\n <Text color={NOTES_LABEL_COLOR} bold>\n {\"Notes: \"}\n </Text>\n <Text>{draft}</Text>\n <Text color={POINTER_COLOR}>{\"▎\"}</Text>\n <Box flexGrow={1} marginLeft={2}>\n <Text dimColor>{\"(Enter to save · Esc to discard)\"}</Text>\n </Box>\n </Box>\n );\n }\n return (\n <Box marginTop={1} flexDirection=\"row\" justifyContent=\"center\">\n <Text color={NOTES_LABEL_COLOR} bold>\n {\"Notes: \"}\n </Text>\n {notes ? (\n <Text>{notes}</Text>\n ) : (\n <Text dimColor>{\"press n to add notes\"}</Text>\n )}\n </Box>\n );\n}\n\nfunction SubmitPreview({\n questions,\n states,\n}: {\n questions: AskQuestion[];\n states: QState[];\n}) {\n return (\n <Box flexDirection=\"column\">\n <Text bold>Review</Text>\n {questions.map((q, qi) => {\n const sel = Array.from(states[qi].selected)\n .sort((a, b) => a - b)\n .map((i) => q.options[i].label);\n const notes = states[qi].notes.trim();\n return (\n <Box key={qi} flexDirection=\"column\" marginLeft={2}>\n <Box flexDirection=\"row\">\n <Text color=\"yellow\">{`${q.header}: `}</Text>\n <Text dimColor={sel.length === 0}>\n {sel.length > 0 ? sel.join(\", \") : \"(no answer)\"}\n </Text>\n </Box>\n {notes && (\n <Box marginLeft={2} flexDirection=\"row\">\n <Text color={NOTES_LABEL_COLOR}>{\"notes: \"}</Text>\n <Text dimColor>{notes}</Text>\n </Box>\n )}\n </Box>\n );\n })}\n </Box>\n );\n}\n\nfunction hintLine(hasTabs: boolean, isMulti: boolean, editingNotes: boolean): string {\n if (editingNotes) {\n return \"Enter to save · Esc to discard · backspace to delete\";\n }\n const parts: string[] = [\"Enter to select\", \"↑/↓ to navigate\", \"n to add notes\"];\n if (hasTabs) parts.push(\"Tab to switch questions\");\n if (isMulti) parts.push(\"Space to toggle\");\n parts.push(\"Esc to cancel\");\n return parts.join(\" · \");\n}\n","/**\n * /btw 旁白浮层。\n *\n * 用当前对话作上下文跑一次无工具 LLM 流,答案 stream 到浮层;Q & A 都不进 messages。\n * 关闭键:Enter / Esc / Space(与 Claude Code /btw 对齐)。\n *\n * v0.1 留 TODO:\n * - 浮层内 ↑↓ 滚动(当前依赖终端 reflow)\n * - `f` 分支为新会话\n * - `x` 清除早先 /btw 交换列表(当前同时只能有一个 /btw)\n * - 并发于主 turn 运行(当前 slash 调度对 status !== idle 一律拒绝)\n */\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { Box, Text, useInput } from \"ink\";\nimport type { LLMClient } from \"../llm/types.js\";\nimport type { Message } from \"../types/index.js\";\n\nexport interface BtwRequest {\n question: string;\n history: Message[];\n resolve: () => void;\n}\n\nconst BTW_SYSTEM_PROMPT =\n `You are answering a side question from the user. Your reply is shown in a transient ` +\n `popup overlay and will NOT be saved to the conversation history. You have NO tools — ` +\n `answer directly from the conversation context above and your own knowledge. Be concise.`;\n\nexport function BtwOverlay({ request, llm }: { request: BtwRequest; llm: LLMClient }) {\n const [text, setText] = useState(\"\");\n const [status, setStatus] = useState<\"streaming\" | \"done\" | \"error\">(\"streaming\");\n const [errMsg, setErrMsg] = useState(\"\");\n const abortRef = useRef(new AbortController());\n\n useEffect(() => {\n const controller = abortRef.current;\n let cancelled = false;\n (async () => {\n try {\n const stream = llm.stream({\n messages: [...request.history, { role: \"user\", content: request.question }],\n systemPrompt: BTW_SYSTEM_PROMPT,\n abortSignal: controller.signal,\n });\n for await (const ev of stream) {\n if (cancelled) break;\n if (ev.type === \"text\") {\n setText((t) => t + ev.delta);\n } else if (ev.type === \"error\") {\n throw ev.error;\n }\n }\n if (!cancelled) setStatus(\"done\");\n } catch (err) {\n if (cancelled) return;\n setErrMsg(err instanceof Error ? err.message : String(err));\n setStatus(\"error\");\n }\n })();\n return () => {\n cancelled = true;\n controller.abort();\n };\n // request 每次拉起都是新对象——deps 用 request 本身即可,question/history 跟着变\n }, [llm, request]);\n\n useInput((input, key) => {\n if (key.return || key.escape || input === \" \") {\n abortRef.current.abort();\n request.resolve();\n }\n });\n\n return (\n <Box flexDirection=\"column\" marginY={1} borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Box>\n <Text color=\"cyan\" bold>/btw </Text>\n <Text dimColor>side question · not saved to history</Text>\n </Box>\n <Box marginTop={1} flexDirection=\"row\">\n <Text color=\"gray\">{\"› \"}</Text>\n <Text bold>{request.question}</Text>\n </Box>\n <Box flexDirection=\"column\" marginTop={1}>\n {text ? <Text>{text}</Text> : null}\n {status === \"streaming\" && !text && <Text dimColor>answering…</Text>}\n {status === \"error\" && <Text color=\"red\">[error] {errMsg}</Text>}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Enter / Esc / Space close</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Slash 命令自动补全 overlay。\n *\n * 触发条件:input.startsWith(\"/\") && !input.includes(\" \")(用户在输入命令名阶段)\n * 进入参数阶段(空格之后)→ overlay 关闭,让用户安静地输入参数\n *\n * 显示:默认色 / + name + dim description\n * focused 行整条命令名变浅青 + bold(不用 inverse 背景条)\n * 超过 maxVisible 行折叠尾部\n *\n * 渲染由 App 控制,本组件是纯展示。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { SlashCommand } from \"../slash/index.js\";\nimport { FOCUS_COLOR } from \"../ui/theme.js\";\n\nexport interface SlashAutocompleteProps {\n matches: SlashCommand[];\n index: number;\n maxVisible?: number;\n}\n\nconst DEFAULT_MAX = 10;\n\nexport function SlashAutocomplete({ matches, index, maxVisible = DEFAULT_MAX }: SlashAutocompleteProps) {\n if (matches.length === 0) return null;\n\n // 窗口:保证 focused 始终可见\n const start = Math.max(0, Math.min(index - Math.floor(maxVisible / 2), matches.length - maxVisible));\n const end = Math.min(matches.length, start + maxVisible);\n const visible = matches.slice(start, end);\n\n const nameWidth = Math.max(...matches.map((c) => c.name.length));\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.map((cmd, i) => {\n const realIndex = start + i;\n return (\n <Row key={cmd.name} cmd={cmd} focused={realIndex === index} nameWidth={nameWidth} />\n );\n })}\n {matches.length > visible.length && (\n <Box marginLeft={2}>\n <Text dimColor>\n ↑↓ select · Tab/Enter accept · Esc cancel ({matches.length - visible.length} more)\n </Text>\n </Box>\n )}\n {matches.length <= visible.length && (\n <Box marginLeft={2}>\n <Text dimColor>↑↓ select · Tab/Enter accept · Esc cancel</Text>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction Row({ cmd, focused, nameWidth }: { cmd: SlashCommand; focused: boolean; nameWidth: number }) {\n const padded = cmd.name.padEnd(nameWidth);\n // focused 整条命令名变浅青 + bold;非 focused 用默认色\n return (\n <Box flexDirection=\"row\">\n <Text color={focused ? FOCUS_COLOR : undefined} bold={focused}>\n {\"/\"}{padded}\n </Text>\n <Text>{\" \"}</Text>\n <Text dimColor>{cmd.description}</Text>\n </Box>\n );\n}\n","/**\n * @ 引用自动补全 overlay。\n *\n * 触发条件:input 在光标位置含有 `@xxx` 段(`@` 后到下一个空白前)。\n * 进入空白后 overlay 关闭。\n *\n * 显示:\n * - 目录: `› dirname/` 紫色(后续可展开)\n * - 文件: `+ filename` 默认色\n * - focused 行整条变紫色 + bold\n * - 超过 maxVisible 行窗口截取,顶部 / 底部箭头提示\n *\n * @ 引用补全风格:文件 `+ name`,目录 `+ dirname/`。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { AtCandidate } from \"../preprocess/input/at-source.js\";\nimport { FOCUS_COLOR } from \"../ui/theme.js\";\n\nexport interface AtFileAutocompleteProps {\n matches: AtCandidate[];\n index: number;\n maxVisible?: number;\n}\n\nconst DEFAULT_MAX = 10;\n\nexport function AtFileAutocomplete({ matches, index, maxVisible = DEFAULT_MAX }: AtFileAutocompleteProps) {\n if (matches.length === 0) return null;\n\n // 窗口:保证 focused 始终可见\n const start = Math.max(0, Math.min(index - Math.floor(maxVisible / 2), matches.length - maxVisible));\n const end = Math.min(matches.length, start + maxVisible);\n const visible = matches.slice(start, end);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n {visible.map((cand, i) => {\n const realIndex = start + i;\n return <Row key={cand.rel} cand={cand} focused={realIndex === index} />;\n })}\n <Box marginLeft={2}>\n <Text dimColor>\n {`↑↓ select · Tab/Enter accept · Esc cancel${\n matches.length > visible.length ? ` (${matches.length - visible.length} more)` : \"\"\n }`}\n </Text>\n </Box>\n </Box>\n );\n}\n\nfunction Row({ cand, focused }: { cand: AtCandidate; focused: boolean }) {\n // 显示文本:dir 加 `/` 后缀\n const display = cand.isDir ? `${cand.rel}/` : cand.rel;\n return (\n <Box flexDirection=\"row\">\n <Text color={focused ? FOCUS_COLOR : undefined} bold={focused}>\n {\"+ \"}{display}\n </Text>\n </Box>\n );\n}\n","/**\n * @ 引用的 fuzzy 候选源。\n *\n * 设计:\n * - 无 `/` 在 query 里:fast-glob 扫 cwd 全树(默认排除 node_modules / .git),\n * 按 fuzzy score 排序;限 1000 条候选,picker UI 再窗口截取\n * - 含 `/`:解析出目录前缀 + 子查询,只列该目录下子项(逐级展开,大目录友好)\n * - LRU 缓存:同一 cwd 的全树扫描结果缓存 5 秒,避免每次按键重扫\n *\n * 性能考量:键盘事件每次按键都会重 query;扫盘放 async + cache 即可,Ink render\n * 拿到 promise resolve 后更新候选列表。\n */\n\nimport { readdir, stat } from \"node:fs/promises\";\nimport { basename, dirname, join, relative, resolve } from \"node:path\";\nimport fg from \"fast-glob\";\n\nexport interface AtCandidate {\n /** 相对 cwd 的路径,UI 直接显示。 */\n rel: string;\n /** 是否为目录。目录后缀加 `/` 视觉提示 + 选中后继续展开。 */\n isDir: boolean;\n}\n\n/** 全树扫描默认排除模式。 */\nconst DEFAULT_IGNORE = [\n \"**/node_modules/**\",\n \"**/.git/**\",\n \"**/.next/**\",\n \"**/.turbo/**\",\n \"**/.cache/**\",\n \"**/.muse/**\",\n];\n\nconst MAX_RESULTS = 1000;\nconst CACHE_TTL_MS = 5_000;\n\ninterface CacheEntry {\n cwd: string;\n at: number;\n files: AtCandidate[];\n}\n\nlet cache: CacheEntry | null = null;\n\n/** 清缓存(测试用)。 */\nexport function _clearAtCache(): void {\n cache = null;\n}\n\nasync function loadAllFiles(cwd: string): Promise<AtCandidate[]> {\n const now = Date.now();\n if (cache && cache.cwd === cwd && now - cache.at < CACHE_TTL_MS) {\n return cache.files;\n }\n const entries = await fg(\"**/*\", {\n cwd,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n ignore: DEFAULT_IGNORE,\n suppressErrors: true,\n });\n const files: AtCandidate[] = entries.slice(0, MAX_RESULTS * 5).map((e) => ({\n rel: e.endsWith(\"/\") ? e.slice(0, -1) : e,\n isDir: e.endsWith(\"/\"),\n }));\n cache = { cwd, at: now, files };\n return files;\n}\n\n/**\n * 查找候选。\n *\n * @param cwd 工作目录\n * @param query @ 之后的字符串,可能含 `/` 表示逐级展开\n */\nexport async function queryAtCandidates(cwd: string, query: string): Promise<AtCandidate[]> {\n // 模式 1:query 含 `/` → 按目录展开\n if (query.includes(\"/\")) {\n return listDir(cwd, query);\n }\n // 模式 2:扁平 fuzzy 全树\n const all = await loadAllFiles(cwd);\n return fuzzyFilter(all, query).slice(0, MAX_RESULTS);\n}\n\nasync function listDir(cwd: string, query: string): Promise<AtCandidate[]> {\n // 拆 dir prefix + leaf query\n const lastSlash = query.lastIndexOf(\"/\");\n const dirPart = query.slice(0, lastSlash);\n const leafQuery = query.slice(lastSlash + 1).toLowerCase();\n // dirPart 可能是 \"\" (`/` 开头 → cwd 根)或 \"src/preprocess\" 等\n const absDir = dirPart === \"\" || dirPart === \".\"\n ? cwd\n : resolve(cwd, dirPart.replace(/^\\.\\//, \"\"));\n let entries: string[];\n try {\n entries = await readdir(absDir);\n } catch {\n return [];\n }\n const out: AtCandidate[] = [];\n for (const name of entries) {\n if (leafQuery && !name.toLowerCase().includes(leafQuery)) continue;\n if (name === \"node_modules\" || name === \".git\") continue;\n try {\n const info = await stat(join(absDir, name));\n const rel = dirPart === \"\" || dirPart === \".\" ? name : `${dirPart}/${name}`;\n out.push({ rel, isDir: info.isDirectory() });\n } catch {\n // skip\n }\n }\n // 排序:目录优先,然后字典序\n out.sort((a, b) => {\n if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;\n return a.rel.localeCompare(b.rel);\n });\n return out.slice(0, MAX_RESULTS);\n}\n\n/**\n * 简单 fuzzy 匹配:子序列存在即命中,score 越小越好。\n * score = 首匹配位置 + 字符跨度;字典序作为 tie-breaker。\n */\nfunction fuzzyFilter(all: AtCandidate[], query: string): AtCandidate[] {\n if (!query) {\n // 无 query → 返浅层目录优先(rel 中 `/` 越少越前),\n // 让用户敲 @ 就看到 cwd 顶层,符合常见的 @ 引用补全行为\n return all\n .slice()\n .sort((a, b) => {\n const depthDiff = depthOf(a.rel) - depthOf(b.rel);\n if (depthDiff !== 0) return depthDiff;\n if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;\n return a.rel.localeCompare(b.rel);\n });\n }\n const q = query.toLowerCase();\n const scored: Array<{ c: AtCandidate; score: number }> = [];\n for (const c of all) {\n const base = basename(c.rel).toLowerCase();\n const full = c.rel.toLowerCase();\n // 基础名 starts-with 优先\n if (base.startsWith(q)) {\n scored.push({ c, score: 0 });\n continue;\n }\n if (base.includes(q)) {\n scored.push({ c, score: 10 + base.indexOf(q) });\n continue;\n }\n if (full.includes(q)) {\n scored.push({ c, score: 100 + full.indexOf(q) });\n continue;\n }\n // 子序列模糊\n const sub = subsequenceScore(full, q);\n if (sub >= 0) scored.push({ c, score: 1000 + sub });\n }\n scored.sort((a, b) => {\n if (a.score !== b.score) return a.score - b.score;\n if (a.c.isDir !== b.c.isDir) return a.c.isDir ? -1 : 1;\n return a.c.rel.localeCompare(b.c.rel);\n });\n return scored.map((s) => s.c);\n}\n\nfunction depthOf(rel: string): number {\n let n = 0;\n for (const ch of rel) if (ch === \"/\") n++;\n return n;\n}\n\nfunction subsequenceScore(haystack: string, needle: string): number {\n let i = 0;\n let score = 0;\n for (const ch of haystack) {\n if (ch === needle[i]) {\n score += i; // 散度越大分越高\n i++;\n if (i === needle.length) return score;\n }\n }\n return -1;\n}\n","/**\n * 权限模式状态栏。固定在 TUI 输入框下方。\n *\n * 设计:见文档库 permission-modes.md §四 状态栏 UI。\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport { MODE_LABEL, MODE_COLOR, type PermissionMode } from \"../permission/index.js\";\n\nexport function PermissionModeBar({ mode, compact }: { mode: PermissionMode; compact?: boolean }) {\n const color = MODE_COLOR[mode];\n const label = MODE_LABEL[mode];\n const isBypass = mode === \"bypassPermissions\";\n\n if (compact) {\n const short: Record<PermissionMode, string> = {\n default: \"[default]\",\n acceptEdits: \"[edits]\",\n plan: \"[plan]\",\n bypassPermissions: \"[bypass]\",\n };\n return (\n <Box flexDirection=\"row\">\n <Text color={color} bold={isBypass}>{short[mode]}</Text>\n <Text dimColor>{\" shift+tab\"}</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"row\">\n <Text color={color} bold={isBypass}>{\"▸▸ \"}{label}</Text>\n <Text dimColor>{\" (shift+tab to cycle)\"}</Text>\n </Box>\n );\n}\n","/**\n * 权限模型:三态 allow / ask / deny,叠加 4 档 PermissionMode。\n *\n * 模式匹配(pattern):\n * - \"ToolName\" 精确匹配\n * - \"Bash(<prefix>)\" 匹配 Bash 工具 + 命令前缀\n * - \"Bash(<prefix>:*)\" 通配\n *\n * PermissionMode(详见文档库 permission-modes.md):\n * - default:完全走 settings.permissions 规则\n * - acceptEdits:Edit/Write 自动 allow,其他走 default\n * - plan:只允许 read 类工具,其他全 deny\n * - bypassPermissions:除显式 deny 与 Bash 硬 deny 外全 allow\n *\n * 危险操作(rm -rf / sudo 等)由 Bash 工具内部 HARD_DENY_PATTERNS 兜底,所有模式都不可绕过。\n */\n\nimport type { Permissions } from \"../config/types.js\";\nimport type { PermissionLevel } from \"../tools/types.js\";\n\nexport type Decision = \"allow\" | \"ask\" | \"deny\";\n\n/** 用户对 PermissionPrompt 三档选择。 */\nexport type PermissionDecision = \"yes\" | \"session_allow\" | \"no\";\n\nexport type PermissionMode = \"default\" | \"acceptEdits\" | \"plan\" | \"bypassPermissions\";\n\nexport const MODE_CYCLE: readonly PermissionMode[] = [\n \"default\",\n \"acceptEdits\",\n \"plan\",\n \"bypassPermissions\",\n] as const;\n\nexport const MODE_LABEL: Record<PermissionMode, string> = {\n default: \"default permissions on\",\n acceptEdits: \"accept edits on\",\n plan: \"plan mode on\",\n bypassPermissions: \"bypass permissions on\",\n};\n\nexport const MODE_COLOR: Record<PermissionMode, string> = {\n default: \"gray\",\n acceptEdits: \"#EAB308\",\n plan: \"#06B6D4\",\n bypassPermissions: \"#EF4444\",\n};\n\nexport interface PermissionInput {\n toolName: string;\n args: unknown;\n /** Tool 的权限级别;由 Agent loop 从 ToolRegistry 注入。Plan 模式用此区分 read/write。 */\n permission?: PermissionLevel;\n}\n\nexport class PermissionGate {\n private rules: Required<Permissions>;\n private mode: PermissionMode = \"default\";\n /** Session 级 allow:用户在 PermissionPrompt 选 \"yes, for session\" 后填充。 */\n private sessionAllow = new Set<string>();\n\n constructor(rules: Permissions = {}) {\n this.rules = {\n allow: rules.allow ?? [],\n ask: rules.ask ?? [],\n deny: rules.deny ?? [],\n defaultMode: rules.defaultMode ?? \"ask\",\n };\n }\n\n setMode(mode: PermissionMode): void {\n this.mode = mode;\n }\n\n getMode(): PermissionMode {\n return this.mode;\n }\n\n cycleMode(): PermissionMode {\n const i = MODE_CYCLE.indexOf(this.mode);\n this.mode = MODE_CYCLE[(i + 1) % MODE_CYCLE.length];\n return this.mode;\n }\n\n /** 用户在 PermissionPrompt 选 \"yes, allow for session\" 时记下。 */\n allowForSession(toolName: string): void {\n this.sessionAllow.add(toolName);\n }\n\n isSessionAllowed(toolName: string): boolean {\n return this.sessionAllow.has(toolName);\n }\n\n decide(input: PermissionInput): Decision {\n // 用户显式 deny 永远生效,所有模式不可绕过\n if (this.matches(this.rules.deny, input)) return \"deny\";\n // session 级 allow 在 deny 之后、mode 分支之前生效\n if (this.sessionAllow.has(input.toolName)) return \"allow\";\n\n switch (this.mode) {\n case \"bypassPermissions\":\n return \"allow\";\n\n case \"plan\":\n // 只允许只读工具;写/执行/网络类直接 deny\n return input.permission === \"read\" ? \"allow\" : \"deny\";\n\n case \"acceptEdits\":\n if (input.toolName === \"Edit\" || input.toolName === \"Write\") return \"allow\";\n return this.defaultDecide(input);\n\n case \"default\":\n default:\n return this.defaultDecide(input);\n }\n }\n\n private defaultDecide(input: PermissionInput): Decision {\n if (this.matches(this.rules.allow, input)) return \"allow\";\n if (this.matches(this.rules.ask, input)) return \"ask\";\n switch (this.rules.defaultMode) {\n case \"strict\":\n return \"ask\";\n case \"relaxed\":\n return \"allow\";\n case \"ask\":\n default:\n return \"ask\";\n }\n }\n\n private matches(patterns: string[], input: PermissionInput): boolean {\n for (const pattern of patterns) {\n if (this.matchOne(pattern, input)) return true;\n }\n return false;\n }\n\n private matchOne(pattern: string, input: PermissionInput): boolean {\n // \"ToolName\" 精确匹配\n if (!pattern.includes(\"(\")) {\n return pattern === input.toolName;\n }\n // \"Bash(<prefix>:*)\" 形式\n const m = pattern.match(/^([A-Za-z_][A-Za-z0-9_]*)\\(([^)]*)\\)$/);\n if (!m) return false;\n const [, toolName, sub] = m;\n if (toolName !== input.toolName) return false;\n if (input.toolName === \"Bash\" && typeof input.args === \"object\" && input.args !== null) {\n const cmd = (input.args as { command?: string }).command ?? \"\";\n if (sub.endsWith(\":*\")) {\n const prefix = sub.slice(0, -2);\n return cmd.startsWith(prefix);\n }\n return cmd === sub || cmd.startsWith(sub + \" \");\n }\n return false;\n }\n}\n","/**\n * 输入框下方的状态尾栏(对齐主流 TUI Agent 形态)。\n *\n * 信息(从左到右):\n * @<sid8> 当前 session 短 id(首 8 字符;resume 后亦同)\n * <model> 当前模型 id\n * ctx: ████░ NN% 上下文窗口填充率(基于最近一轮 input tokens / maxContextWindow)\n * <in>/<max> 绝对值,便于核对\n * ↑<in> ↓<out> 本会话累计 token(自 app 启动后;/resume 不回灌)\n *\n * 配色:\n * session id → cyan bold (区分 session 标识色,与 model 对比)\n * model → magenta (粉品红,显眼但不抢主视觉)\n * \"ctx:\" → 默认白 (label 不 dim,醒目)\n * 填充进度条 → 主题色:<70% green / 70–89% yellow / ≥90% red(\"快爆\"警告)\n * 百分比 / in/max → dim gray (次要信息)\n * \"│\" → dim gray (分隔符弱化)\n * ↑ 累计 in → green\n * ↓ 累计 out → blueBright\n *\n * 宽度策略:\n * termWidth >= 100 完整版(含累计 token)\n * 60 ≤ width < 100 精简版(去掉 ↑↓ 累计、去掉 in/max)\n * width < 60 极简版(只剩 sid · model · 进度条 NN%)\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nconst BAR_TOTAL_WIDE = 10;\nconst BAR_TOTAL_COMPACT = 6;\n\nexport interface FooterStatusProps {\n /** 当前 session id(取首 8 字符显示)。 */\n sessionId: string;\n /** 当前模型 id(如 \"deepseek-chat\")。 */\n model: string;\n /** 模型上下文窗口大小;0/未知时隐藏 ctx 字段。 */\n contextWindow: number;\n /** 最近一轮 input tokens;约等于本轮 prompt 实际占用的上下文。 */\n lastInputTokens: number;\n /** 本会话累计 input tokens。 */\n sessionInputTokens: number;\n /** 本会话累计 output tokens。 */\n sessionOutputTokens: number;\n /** 终端宽度,用于布局降级。 */\n termWidth: number;\n}\n\nexport function FooterStatus({\n sessionId,\n model,\n contextWindow,\n lastInputTokens,\n sessionInputTokens,\n sessionOutputTokens,\n termWidth,\n}: FooterStatusProps) {\n const sid = sessionId.slice(0, 8);\n const hasCtx = contextWindow > 0;\n const pct = hasCtx ? Math.min(100, Math.round((lastInputTokens / contextWindow) * 100)) : 0;\n const ctxColor: \"green\" | \"yellow\" | \"red\" = pct >= 90 ? \"red\" : pct >= 70 ? \"yellow\" : \"green\";\n\n const SEP = <Text dimColor>{\" │ \"}</Text>;\n const SEP_DOT = <Text dimColor>{\" · \"}</Text>;\n\n // 已填部分按阈值上色,未填部分恒 dim gray;0% 时整条灰\n const renderBar = (barW: number): React.ReactNode => {\n const filled = Math.round((pct / 100) * barW);\n const empty = barW - filled;\n return (\n <>\n {filled > 0 && <Text color={ctxColor}>{\"█\".repeat(filled)}</Text>}\n {empty > 0 && <Text dimColor>{\"░\".repeat(empty)}</Text>}\n </>\n );\n };\n\n // <60: 极简\n if (termWidth < 60) {\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\" bold>{sid}</Text>\n {SEP_DOT}\n <Text color=\"magenta\">{model}</Text>\n {hasCtx && (\n <>\n {SEP_DOT}\n {renderBar(BAR_TOTAL_COMPACT)}\n <Text dimColor>{` ${pct}%`}</Text>\n </>\n )}\n </Box>\n );\n }\n\n // 60–100: 精简(无累计 token、无 in/max 绝对值)\n if (termWidth < 100) {\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\" bold>{`@${sid}`}</Text>\n {SEP}\n <Text color=\"magenta\">{model}</Text>\n {hasCtx && (\n <>\n {SEP}\n <Text>{\"ctx: \"}</Text>\n {renderBar(BAR_TOTAL_COMPACT)}\n <Text dimColor>{` ${pct}%`}</Text>\n </>\n )}\n </Box>\n );\n }\n\n // ≥100: 完整\n return (\n <Box flexDirection=\"row\">\n <Text color=\"cyan\" bold>{`@${sid}`}</Text>\n {SEP}\n <Text color=\"magenta\">{model}</Text>\n {hasCtx && (\n <>\n {SEP}\n <Text>{\"ctx: \"}</Text>\n {renderBar(BAR_TOTAL_WIDE)}\n <Text dimColor>{` ${pct}%`}</Text>\n </>\n )}\n {SEP}\n <Text>{\"tok: \"}</Text>\n <Text color=\"green\">{`↑${formatTokens(sessionInputTokens)}`}</Text>\n <Text> </Text>\n <Text color=\"blueBright\">{`↓${formatTokens(sessionOutputTokens)}`}</Text>\n </Box>\n );\n}\n\nfunction formatTokens(n: number): string {\n if (n < 1000) return String(n);\n if (n < 10000) return (n / 1000).toFixed(1).replace(/\\.0$/, \"\") + \"k\";\n if (n < 1000000) return Math.round(n / 1000) + \"k\";\n return (n / 1000000).toFixed(1).replace(/\\.0$/, \"\") + \"M\";\n}\n","/**\n * 通用进度横幅:cyan 标签 + 经过秒数 + 进度条 + 旋转 tip。\n *\n * 由 SlashActions.showProgress/hideProgress 控制;目前 /compact 是首个使用者。\n *\n * 视觉形态(参照业界 CLI Agent 的 /compact 风格):\n * ✦ <Title>... (Ns)\n * ▰▰▰▰▰▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱▱ 24%\n * └ Tip: <rotating>\n */\n\nimport React, { useEffect, useState } from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface ProgressState {\n title: string;\n tips: string[];\n /** 0-100;ProgressBanner 自行 clamp 与 floor。 */\n getPercent: () => number;\n startTime: number;\n}\n\nconst BAR_WIDTH = 42;\nconst TICK_MS = 400;\nconst TIP_ROTATE_SEC = 5;\n\nexport function ProgressBanner({ state }: { state: ProgressState }) {\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n const t = setInterval(() => setNow(Date.now()), TICK_MS);\n return () => clearInterval(t);\n }, []);\n\n const elapsedSec = Math.max(0, Math.floor((now - state.startTime) / 1000));\n const percent = Math.max(0, Math.min(99, Math.floor(state.getPercent())));\n const filled = Math.floor((percent / 100) * BAR_WIDTH);\n const empty = BAR_WIDTH - filled;\n const bar = \"▰\".repeat(filled) + \"▱\".repeat(empty);\n const tip = state.tips.length\n ? state.tips[Math.floor(elapsedSec / TIP_ROTATE_SEC) % state.tips.length]\n : \"\";\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Box>\n <Text color=\"cyan\" bold>✦ </Text>\n <Text color=\"cyan\">{state.title}...</Text>\n <Text dimColor>{` (${elapsedSec}s)`}</Text>\n </Box>\n <Box marginLeft={2}>\n <Text color=\"cyan\">{bar}</Text>\n <Text dimColor>{` ${percent}%`}</Text>\n </Box>\n {tip && (\n <Box marginLeft={2}>\n <Text dimColor>{`└ Tip: ${tip}`}</Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * 处理中的状态行(流式 / 工具执行期间常驻底部)。\n *\n * 单行设计:\n * ● Thinking… ✨闪烁 (12s · ↑ 1.2k tokens · thought for 4s)\n *\n * 主标签按 phase 三态切换:\n * - thinking: 请求已发,还没收到 LLM 首字\n * - streaming: 已收到 text-delta,LLM 在出字\n * - working: 工具执行中(runningTool ≠ null)\n *\n * 不再显示 \"↳ ToolName\" 子行——active tool 由其所属 BatchedToolBlock / ToolCallBlock\n * 承担,在历史区呈现具体参数;状态行只表达当前 phase + 计时 + token,不再分裂信息。\n *\n * 不接收 status 字段——调用方根据 status !== \"idle\" 决定是否挂载本组件。\n */\n\nimport React, { useEffect, useState } from \"react\";\nimport { Box, Text } from \"ink\";\nimport { Shimmer } from \"./Shimmer.js\";\n\nconst TICK_MS = 400;\n\nexport interface StatusLineProps {\n /** 本轮开始时间(user_submit 触发时 Date.now())。 */\n startTime: number;\n /** 首次 text-delta 时间(\"thought for\" 用);null 表示尚未流出任何 text。 */\n firstTextTime: number | null;\n /** 本轮已累计的 input tokens(usage 事件累加,>0 才显示)。 */\n inputTokens: number;\n /** 工具运行中时的工具名,null 表示不在跑工具。仅用于推导 phase,不再渲染子行。 */\n runningTool: string | null;\n /** UI 语言:影响标签文案。 */\n lang: \"en\" | \"zh-CN\";\n}\n\nconst PHASE_LABELS = {\n en: { thinking: \"Thinking\", streaming: \"Streaming\", working: \"Working\" },\n \"zh-CN\": { thinking: \"思考中\", streaming: \"输出中\", working: \"工作中\" },\n} as const;\n\nexport function StatusLine({ startTime, firstTextTime, inputTokens, runningTool, lang }: StatusLineProps) {\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n const t = setInterval(() => setNow(Date.now()), TICK_MS);\n return () => clearInterval(t);\n }, []);\n\n const elapsedSec = Math.max(0, Math.floor((now - startTime) / 1000));\n // phase 推导:工具执行优先级最高,其次\"已开始流字\"=streaming,最初是 thinking\n const phase: \"thinking\" | \"streaming\" | \"working\" =\n runningTool ? \"working\" : firstTextTime !== null ? \"streaming\" : \"thinking\";\n const mainLabel = PHASE_LABELS[lang][phase];\n\n const parts: string[] = [formatDuration(elapsedSec)];\n if (inputTokens > 0) {\n parts.push(`↑ ${formatTokens(inputTokens)} tokens`);\n }\n if (firstTextTime !== null) {\n const thinkSec = Math.max(0, Math.floor((firstTextTime - startTime) / 1000));\n parts.push(\n lang === \"zh-CN\" ? `思考 ${formatDuration(thinkSec)}` : `thought for ${formatDuration(thinkSec)}`,\n );\n }\n\n return (\n <Box flexDirection=\"row\" marginTop={1}>\n <Text color=\"gray\">● </Text>\n <Shimmer text={mainLabel} />\n <Text dimColor>{` (${parts.join(\" · \")})`}</Text>\n </Box>\n );\n}\n\nfunction formatTokens(n: number): string {\n if (n < 1000) return String(n);\n if (n < 10000) return (n / 1000).toFixed(1).replace(/\\.0$/, \"\") + \"k\";\n if (n < 1000000) return Math.round(n / 1000) + \"k\";\n return (n / 1000000).toFixed(1).replace(/\\.0$/, \"\") + \"M\";\n}\n\nfunction formatDuration(sec: number): string {\n if (sec < 60) return `${sec}s`;\n const m = Math.floor(sec / 60);\n const s = sec % 60;\n return s === 0 ? `${m}m` : `${m}m${s}s`;\n}\n","/**\n * 流式 markdown 渲染:实时渲染已闭合段落,未闭合段保留纯文本。\n *\n * 设计:\n * 1. 节流 16ms / 32 字符,降低 setState 频率\n * 2. splitStableUnstable 切 stable + unstable\n * 3. **关键优化**:marked.lexer 把 stable 进一步切成 block tokens(段/代码块/list 等);\n * 每个 block 是独立 React.memo + useMemo 组件,内容不变 → 不重 parse / 不重渲染\n * 4. unstable 直接纯文本(短,parse 没意义)\n *\n * 闪屏根因 + 修法:\n * - 之前每次 stable 增长都把整段 stable 重 parse + 重 reconcile → 长输出累积时\n * CPU + Ink 重画整段动态区 → 视觉闪屏\n * - 现在按 block 切分缓存,只有新闭合 block 触发 parse,旧 block 走 cache\n * - React.memo 阻止旧 block 的 re-render,Ink 看到 child 没变也会减少 erase\n *\n * 段切分用 marked.lexer 而非简单 \\n\\n split:\n * - fence 代码块内空行会被 \\n\\n 误切;lexer 把 fence 当一个 token,边界正确\n * - lexer 1-3ms,只在 stable 变化时跑一次,可接受\n */\n\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Box, Text } from \"ink\";\nimport { marked } from \"marked\";\nimport { renderMarkdown } from \"../preprocess/render/markdown.js\";\nimport { splitStableUnstable } from \"../preprocess/render/stream-markdown.js\";\n\nconst FLUSH_INTERVAL_MS = 16;\nconst TOKEN_THRESHOLD = 32;\n\nexport interface StreamingMarkdownProps {\n text: string;\n}\n\nexport function StreamingMarkdown({ text }: StreamingMarkdownProps) {\n // 节流 setState,避免每 delta 都触发 re-render\n const [flushed, setFlushed] = useState(text);\n const lastFlushAtRef = useRef<number>(0);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n const now = Date.now();\n const elapsed = now - lastFlushAtRef.current;\n const delta = text.length - flushed.length;\n if (elapsed >= FLUSH_INTERVAL_MS || delta >= TOKEN_THRESHOLD) {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n setFlushed(text);\n lastFlushAtRef.current = now;\n return;\n }\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n setFlushed(text);\n lastFlushAtRef.current = Date.now();\n }, FLUSH_INTERVAL_MS - elapsed);\n }, [text, flushed]);\n\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, []);\n\n // 切 stable + unstable;再用 marked.lexer 把 stable 切成 block tokens\n const { stableBlocks, unstable } = useMemo(() => {\n const { stable, unstable } = splitStableUnstable(flushed);\n if (!stable) return { stableBlocks: [] as string[], unstable };\n let blocks: string[];\n try {\n const tokens = marked.lexer(stable);\n blocks = tokens\n .map((t) => ((t as { raw?: string }).raw ?? \"\").replace(/\\n+$/, \"\"))\n .filter((s) => s.trim().length > 0);\n } catch {\n // lexer 出错退化到 \\n\\n 切分(fence 内空行可能误切,可接受)\n blocks = stable.split(/\\n{2,}/).filter((s) => s.trim().length > 0);\n }\n return { stableBlocks: blocks, unstable };\n }, [flushed]);\n\n if (stableBlocks.length === 0 && !unstable) return null;\n\n return (\n <Box flexDirection=\"column\">\n {stableBlocks.map((block, i) => (\n <StableBlock key={i} text={block} />\n ))}\n {unstable && <Text>{unstable}</Text>}\n </Box>\n );\n}\n\n/** 单个已闭合 markdown block:text 不变 → useMemo 命中 + React.memo 阻止 re-render。 */\nconst StableBlock = React.memo(function StableBlock({ text }: { text: string }) {\n const rendered = useMemo(() => renderMarkdown(text), [text]);\n return <Text>{rendered}</Text>;\n});\n","/**\n * 流式 markdown 拆分:把累计的 streaming text 切成 \"stable\"(可渲染)+ \"unstable\"(保留纯文本)。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.4.3。\n *\n * 启发式(不真跑 marked.lexer,因为我们关心的是「断点」而非「token tree」):\n * 1. 找最后一个段落边界 `\\n\\n`(markdown 里所有 block 都以此分隔)。\n * - 之前 → stable\n * - 之后 → unstable(可能是个未完成的段落 / list item / heading)\n * 2. 校验 stable 内 fence(```)行首匹配数为偶数;奇数说明 stable 误切到了未闭合 fence\n * 内部 → 把\"最后一个未配对 fence\"以及之后整段降级到 unstable\n * 3. inline 标记(**bold** / *italic* / `code`)不做特殊处理;`renderMarkdown` 出错时\n * 已经 try/catch 退回纯文本,代价可接受\n *\n * Why 不用 marked.lexer:\n * - lexer 单次 ~1-3ms,流式每 16ms 跑一次累积量已大,N 次重复 parse 浪费\n * - lexer 对未闭合 token 的处理依版本而异,不如硬规则可控\n * - 我们的目标是「LLM 输出的 prose / list / fence / heading 大概对」,不追求 spec 完美\n */\n\n/** 段落边界正则 — 用懒匹配最后一个 \\n\\n */\nconst PARA_BOUNDARY = \"\\n\\n\";\n/** 行首 fence(三反引号),用作 stable 区域内\"奇偶校验\"的锚点 */\nconst FENCE_RE = /^```/gm;\n\nexport interface SplitResult {\n /** 已闭合段落,可放心走 renderMarkdown */\n stable: string;\n /** 最后一段未闭合的内容,保留纯文本 */\n unstable: string;\n}\n\nexport function splitStableUnstable(text: string): SplitResult {\n if (!text) return { stable: \"\", unstable: \"\" };\n\n const lastDoubleNL = text.lastIndexOf(PARA_BOUNDARY);\n if (lastDoubleNL === -1) {\n // 整段还没出现段落边界 → 全是 unstable\n return { stable: \"\", unstable: text };\n }\n\n let stable = text.slice(0, lastDoubleNL + PARA_BOUNDARY.length);\n let unstable = text.slice(lastDoubleNL + PARA_BOUNDARY.length);\n\n // fence 校验:stable 中行首 ``` 个数为奇数时,最后一个 fence 是 open 未 close\n // → 把它之后(含)的整段转给 unstable,等 close 出现再升 stable\n const fences = [...stable.matchAll(FENCE_RE)];\n if (fences.length % 2 === 1) {\n const openIdx = fences[fences.length - 1].index ?? -1;\n if (openIdx >= 0) {\n unstable = stable.slice(openIdx) + unstable;\n stable = stable.slice(0, openIdx);\n }\n }\n\n return { stable, unstable };\n}\n","/**\n * 终端标题栏控制(OSC 0/1/2 转义序列)。\n *\n * 用途:在 OS-level tab/window 标题里放一个旋转动画 + 当前状态,\n * 让用户切到别的窗口也能从 dock / taskbar 看出 muse 还在跑(vs 卡死 / 已完成)。\n *\n * 协议:`ESC ] 0 ; <text> BEL` 同时设置 icon name 和 window title——所有主流\n * 终端都认(Terminal.app / iTerm2 / Alacritty / kitty / WezTerm / Windows Terminal)。\n *\n * 安全:非 TTY(管道、CI)和 MUSE_NO_TITLE=1 时静默;title 文本 strip 控制字符\n * 防止注入。\n */\n\nconst ENABLED = (() => {\n if (!process.stdout.isTTY) return false;\n if (process.env.MUSE_NO_TITLE === \"1\") return false;\n return true;\n})();\n\nlet lastTitle = \"\";\n\nfunction sanitize(s: string): string {\n // 删 NUL / BEL / ESC / 其它 C0 控制符——防止用户 cwd 包含恶意字节注入 title\n return s.replace(/[\\x00-\\x1f\\x7f]/g, \"\");\n}\n\n/** 设标题;与上次完全相同时跳过(减少 stdout 写流量)。 */\nexport function setTerminalTitle(title: string): void {\n if (!ENABLED) return;\n const clean = sanitize(title);\n if (clean === lastTitle) return;\n lastTitle = clean;\n process.stdout.write(`\\x1b]0;${clean}\\x07`);\n}\n\n/** 清空标题(让终端用默认值)。在进程退出前调一次。 */\nexport function resetTerminalTitle(): void {\n if (!ENABLED) return;\n lastTitle = \"\";\n process.stdout.write(`\\x1b]0;\\x07`);\n}\n","/**\n * OpenAI 兼容协议 provider。\n * 覆盖:OpenAI 官方、DeepSeek、Qwen、Moonshot (Kimi)、智谱、OpenRouter、Ollama (其 /v1 endpoint)、自建 vLLM/LocalAI 等。\n *\n * Why 自己包一层而不是直接用 @ai-sdk/openai-compatible:\n * - 抹平 stream 事件差异,统一为本仓库的 LLMEvent 类型\n * - 在 stream 中拼装 tool_call.arguments(OpenAI 流式 tool_call 是分片增量的 JSON 字符串)\n * - 留口子未来插入降级、重试、token 计数估算\n */\n\nimport { createOpenAICompatible } from \"@ai-sdk/openai-compatible\";\nimport { streamText, jsonSchema, tool, type CoreMessage, type ToolSet } from \"ai\";\nimport type {\n LLMClient,\n LLMEvent,\n ModelCapabilities,\n ProviderConfig,\n StreamOptions,\n} from \"../types.js\";\nimport type { Message, AssistantMessage, ToolDefinition, ContentPart } from \"../../types/index.js\";\nimport { log, redactApiKey } from \"../../log/index.js\";\n\ninterface OpenAICompatibleProviderOpts {\n providerName: string;\n baseUrl: string;\n apiKey: string;\n model: string;\n capabilities?: Partial<ModelCapabilities>;\n}\n\nconst DEFAULT_CAPABILITIES: ModelCapabilities = {\n toolCalling: true,\n parallelToolCalls: true,\n vision: false,\n jsonMode: true,\n // 没在 models.local.json 显式声明 contextWindow 时的兜底值。\n // 200k 是 2026 年主流 LLM(GPT-4.1 / Claude / DeepSeek-v3 / Qwen-Plus / GLM-4 等)的\n // 常见容量,比 32k 兜底更接近真实,避免 ctx% 大幅虚高 / auto-compact 过早触发。\n // 仍建议在每条 entry 显式写 contextWindow,避免依赖默认值。\n maxContextWindow: 200_000,\n};\n\nexport class OpenAICompatibleClient implements LLMClient {\n readonly providerName: string;\n readonly model: string;\n readonly capabilities: ModelCapabilities;\n private modelProvider: ReturnType<ReturnType<typeof createOpenAICompatible>>;\n\n constructor(opts: OpenAICompatibleProviderOpts) {\n this.providerName = opts.providerName;\n this.model = opts.model;\n this.capabilities = { ...DEFAULT_CAPABILITIES, ...opts.capabilities };\n\n const provider = createOpenAICompatible({\n name: opts.providerName,\n baseURL: opts.baseUrl,\n apiKey: opts.apiKey,\n });\n this.modelProvider = provider(opts.model);\n\n log.debug(\"LLM provider initialized\", {\n provider: opts.providerName,\n model: opts.model,\n baseUrl: opts.baseUrl,\n apiKey: redactApiKey(opts.apiKey),\n });\n }\n\n async *stream(opts: StreamOptions): AsyncIterable<LLMEvent> {\n const { messages, tools, systemPrompt, temperature, maxTokens, abortSignal } = opts;\n\n const aiMessages = convertMessages(messages, systemPrompt);\n const aiTools = tools ? convertTools(tools) : undefined;\n\n // 重试:仅在还没收到任何 chunk 时(连接级错误)退避重试,最多 3 次\n let attempt = 0;\n const maxAttempts = 3;\n let result: ReturnType<typeof streamText> | undefined;\n while (true) {\n try {\n result = streamText({\n model: this.modelProvider,\n messages: aiMessages,\n tools: aiTools,\n temperature,\n maxTokens,\n abortSignal,\n });\n break;\n } catch (err) {\n if (abortSignal?.aborted) {\n yield { type: \"error\", error: err instanceof Error ? err : new Error(String(err)) };\n return;\n }\n if (!isRetryable(err) || attempt >= maxAttempts - 1) {\n yield { type: \"error\", error: err instanceof Error ? err : new Error(String(err)) };\n return;\n }\n const delay = 1000 * Math.pow(2, attempt);\n log.warn(`LLM connect failed (attempt ${attempt + 1}/${maxAttempts}); retrying in ${delay}ms`, {\n msg: err instanceof Error ? err.message : String(err),\n });\n await sleep(delay, abortSignal);\n attempt += 1;\n }\n }\n\n if (!result) {\n yield { type: \"error\", error: new Error(\"Internal: stream result is undefined after retry loop.\") };\n return;\n }\n const stream = result.fullStream;\n\n try {\n const seenToolCalls = new Set<string>();\n\n for await (const part of stream) {\n switch (part.type) {\n case \"text-delta\":\n yield { type: \"text\", delta: part.textDelta };\n break;\n\n case \"tool-call\":\n if (!seenToolCalls.has(part.toolCallId)) {\n seenToolCalls.add(part.toolCallId);\n yield { type: \"tool_call_start\", id: part.toolCallId, name: part.toolName };\n }\n yield {\n type: \"tool_call_complete\",\n id: part.toolCallId,\n name: part.toolName,\n args: part.args,\n };\n break;\n\n case \"finish\":\n yield {\n type: \"finish\",\n reason: mapFinishReason(part.finishReason),\n usage: part.usage\n ? {\n inputTokens: part.usage.promptTokens ?? 0,\n outputTokens: part.usage.completionTokens ?? 0,\n totalTokens: part.usage.totalTokens ?? 0,\n }\n : undefined,\n };\n break;\n\n case \"error\":\n yield { type: \"error\", error: part.error instanceof Error ? part.error : new Error(String(part.error)) };\n break;\n\n default:\n // 忽略其它(如 step-start / step-finish / tool-call-streaming-start 等)\n break;\n }\n }\n } catch (err) {\n yield { type: \"error\", error: err instanceof Error ? err : new Error(String(err)) };\n }\n }\n}\n\n// ---------- helpers ----------\n\nfunction convertMessages(messages: Message[], systemPrompt?: string): CoreMessage[] {\n const result: CoreMessage[] = [];\n if (systemPrompt) {\n result.push({ role: \"system\", content: systemPrompt });\n }\n for (const msg of messages) {\n switch (msg.role) {\n case \"system\":\n result.push({ role: \"system\", content: msg.content });\n break;\n case \"user\":\n if (typeof msg.content === \"string\") {\n result.push({ role: \"user\", content: msg.content });\n } else {\n result.push({ role: \"user\", content: convertUserParts(msg.content) });\n }\n break;\n case \"assistant\":\n result.push({ role: \"assistant\", content: convertAssistantContent(msg) });\n break;\n case \"tool\":\n result.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: msg.toolUseId,\n toolName: \"_tool\",\n result: msg.content,\n isError: msg.isError ?? false,\n },\n ],\n });\n break;\n }\n }\n return result;\n}\n\ntype UserContent = Extract<CoreMessage, { role: \"user\" }>[\"content\"];\ntype UserPart = Exclude<UserContent, string>[number];\n\n/**\n * 把 muse 的 user ContentPart[] 转 Vercel AI SDK UserContent。\n *\n * 策略:\n * - text 直通\n * - image → SDK ImagePart(SDK 内部按 provider 翻译为 image_url 等)\n * - file → **降级为 text part 用 XML wrap**。原因:OpenAI Chat Completions 协议\n * 与多数兼容 provider 不支持 file part(只有 Assistants API 才有);把文本文件\n * 直接 wrap 进 text 在所有 provider 上都能工作,不依赖能力探测。\n * - tool_use / tool_result 在 user role 不出现,跳过\n */\n// 仅为测试导出 — 业务代码通过 convertMessages 间接调用\nexport function convertUserParts(parts: ContentPart[]): UserContent {\n const out: UserPart[] = [];\n for (const part of parts) {\n if (part.type === \"text\") {\n out.push({ type: \"text\", text: part.text });\n } else if (part.type === \"image\") {\n out.push({\n type: \"image\",\n // SDK 接受 base64 字符串作为 DataContent\n image: part.data,\n mimeType: part.mediaType,\n });\n } else if (part.type === \"file\") {\n // 退化为 text wrap\n out.push({\n type: \"text\",\n text: `<file path=\"${part.path}\"${part.mimeType ? ` mimeType=\"${part.mimeType}\"` : \"\"}>\\n${part.text}\\n</file>`,\n });\n }\n // tool_use / tool_result 在 user role 不应该出现,丢\n }\n if (out.length === 0) return \"\";\n // 全 text 时 join 成 string 更紧凑,行为也与 string-content 用户消息等同\n if (out.every((p) => p.type === \"text\")) {\n return (out as Array<{ type: \"text\"; text: string }>).map((p) => p.text).join(\"\\n\\n\");\n }\n return out;\n}\n\ntype AssistantContent = Extract<CoreMessage, { role: \"assistant\" }>[\"content\"];\n\nfunction convertAssistantContent(msg: AssistantMessage): AssistantContent {\n const parts: Array<\n { type: \"text\"; text: string } | { type: \"tool-call\"; toolCallId: string; toolName: string; args: unknown }\n > = [];\n for (const part of msg.content) {\n if (part.type === \"text\") {\n parts.push({ type: \"text\", text: part.text });\n } else if (part.type === \"tool_use\") {\n parts.push({\n type: \"tool-call\",\n toolCallId: part.id,\n toolName: part.name,\n args: part.args,\n });\n }\n }\n // 至少要有一个内容;空数组 SDK 会报错\n if (parts.length === 0) return \"\";\n return parts as AssistantContent;\n}\n\nfunction convertTools(tools: ToolDefinition[]): ToolSet {\n const result: ToolSet = {};\n for (const t of tools) {\n result[t.name] = tool({\n description: t.description,\n parameters: jsonSchema(t.parameters as Parameters<typeof jsonSchema>[0]),\n });\n }\n return result;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const msg = err.message.toLowerCase();\n const code = (err as Error & { code?: string }).code ?? \"\";\n if (\n code === \"ECONNRESET\" ||\n code === \"ETIMEDOUT\" ||\n code === \"ENOTFOUND\" ||\n code === \"ECONNREFUSED\" ||\n code === \"EAI_AGAIN\"\n ) {\n return true;\n }\n if (\n msg.includes(\"fetch failed\") ||\n msg.includes(\"network\") ||\n msg.includes(\"socket hang up\") ||\n msg.includes(\"under maintenance\") ||\n msg.includes(\"rate limit\") ||\n msg.includes(\"429\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\")\n ) {\n return true;\n }\n return false;\n}\n\nasync function sleep(ms: number, abortSignal?: AbortSignal): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n if (abortSignal?.aborted) return reject(new Error(\"aborted\"));\n const t = setTimeout(() => {\n abortSignal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(t);\n abortSignal?.removeEventListener(\"abort\", onAbort);\n reject(new Error(\"aborted\"));\n };\n abortSignal?.addEventListener(\"abort\", onAbort);\n });\n}\n\nfunction mapFinishReason(reason: string | undefined): \"stop\" | \"tool_calls\" | \"length\" | \"content_filter\" | \"error\" | \"unknown\" {\n switch (reason) {\n case \"stop\":\n case \"stop-sequence\":\n return \"stop\";\n case \"tool-calls\":\n case \"tool_calls\":\n return \"tool_calls\";\n case \"length\":\n return \"length\";\n case \"content-filter\":\n case \"content_filter\":\n return \"content_filter\";\n case \"error\":\n return \"error\";\n default:\n return \"unknown\";\n }\n}\n\n// ---------- 预设 provider 工厂 ----------\n\nexport interface PresetConfig {\n baseUrl: string;\n defaultModel: string;\n capabilities?: Partial<ModelCapabilities>;\n}\n\nexport const PRESETS: Record<string, PresetConfig> = {\n openai: {\n baseUrl: \"https://api.openai.com/v1\",\n defaultModel: \"gpt-4o-mini\",\n },\n deepseek: {\n baseUrl: \"https://api.deepseek.com/v1\",\n defaultModel: \"deepseek-chat\",\n capabilities: { maxContextWindow: 128_000 },\n },\n qwen: {\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n defaultModel: \"qwen-plus\",\n capabilities: { maxContextWindow: 128_000 },\n },\n moonshot: {\n baseUrl: \"https://api.moonshot.cn/v1\",\n defaultModel: \"moonshot-v1-32k\",\n capabilities: { maxContextWindow: 32_000 },\n },\n zhipu: {\n baseUrl: \"https://open.bigmodel.cn/api/paas/v4\",\n defaultModel: \"glm-4-flash\",\n capabilities: { maxContextWindow: 128_000 },\n },\n ollama: {\n baseUrl: \"http://localhost:11434/v1\",\n defaultModel: \"llama3.1\",\n capabilities: { maxContextWindow: 8_000 },\n },\n openrouter: {\n baseUrl: \"https://openrouter.ai/api/v1\",\n defaultModel: \"openai/gpt-4o-mini\",\n },\n};\n\nexport function createPresetClient(\n providerName: string,\n config: ProviderConfig,\n model?: string,\n): OpenAICompatibleClient {\n const preset = PRESETS[providerName];\n if (!preset) {\n throw new Error(`Unknown provider preset: ${providerName}. Available: ${Object.keys(PRESETS).join(\", \")}`);\n }\n return new OpenAICompatibleClient({\n providerName,\n baseUrl: (config.baseUrl as string | undefined) ?? preset.baseUrl,\n apiKey: (config.apiKey as string | undefined) ?? \"\",\n model: model ?? preset.defaultModel,\n capabilities: preset.capabilities,\n });\n}\n","/**\n * 全局共享类型。其它模块按需 re-export 子集。\n * Why 集中:避免类型循环依赖。\n */\n\n// ---------- 消息(与 LLM 交互的最小单元)----------\n\nexport type MessageRole = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\nexport interface TextPart {\n type: \"text\";\n text: string;\n}\n\n/**\n * 通过 @file 引用进来的纯文本文件附件。\n *\n * 设计:作为独立 part 而不是 wrap XML 拼进 text,目的让 PDF / audio / video 等\n * 后续多模态 part 进来时不动协议层(模块设计/消息预处理工程/设计.md 等讨论 §1)。\n *\n * 下游 LLM client 视 provider 能力序列化:\n * - 支持 file part 的 provider → 原生 file part\n * - 不支持的 provider → 退化为 text wrap `<file path=\"...\">…</file>`\n */\nexport interface FilePart {\n type: \"file\";\n path: string;\n /** RFC 6838 mime type;text/x-typescript / text/markdown 等;不强约束,信息性。 */\n mimeType?: string;\n /** 文本内容(utf-8)。 */\n text: string;\n}\n\n/**\n * 图片附件(@image.png 或拖拽 / 粘贴)。\n *\n * 用 base64 data URI 模式存,序列化为 OpenAI 兼容协议的 image_url part。\n */\nexport interface ImagePart {\n type: \"image\";\n /** image/png / image/jpeg / image/webp / image/gif。 */\n mediaType: string;\n /** base64 编码的图片字节。 */\n data: string;\n /** 来源路径(若有),用于 UI 展示与 LLM 上下文。 */\n path?: string;\n}\n\nexport interface ToolUsePart {\n type: \"tool_use\";\n id: string;\n name: string;\n args: unknown;\n}\n\nexport interface ToolResultPart {\n type: \"tool_result\";\n toolUseId: string;\n content: string;\n isError?: boolean;\n}\n\nexport type ContentPart = TextPart | FilePart | ImagePart | ToolUsePart | ToolResultPart;\n\nexport interface SystemMessage {\n role: \"system\";\n content: string;\n}\n\nexport interface UserMessage {\n role: \"user\";\n content: string | ContentPart[];\n}\n\nexport interface AssistantMessage {\n role: \"assistant\";\n content: ContentPart[];\n}\n\nexport interface ToolMessage {\n role: \"tool\";\n toolUseId: string;\n content: string;\n isError?: boolean;\n /** Unified diff for UI display only (Write/Edit). Not sent to LLM. */\n diff?: string;\n /** UI-only one-line summary; if absent, UI falls back to content first line. */\n summary?: string;\n /** UI-only status dot color: success(green) / error(red) / warn(yellow). Default derived from isError. */\n kind?: \"success\" | \"error\" | \"warn\";\n /** 产生该结果的工具名;UI 据此做工具专属渲染(如 TodoWrite 隐藏结果行)。 */\n toolName?: string;\n}\n\nexport type Message = SystemMessage | UserMessage | AssistantMessage | ToolMessage;\n\n// ---------- LLM 工具定义(暴露给模型)----------\n\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: Record<string, unknown>; // JSON Schema\n}\n\n// ---------- Token 用量 ----------\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n}\n\nexport type FinishReason = \"stop\" | \"tool_calls\" | \"length\" | \"content_filter\" | \"error\" | \"unknown\";\n\n// ---------- 错误 ----------\n\nexport class MuseError extends Error {\n constructor(message: string, public readonly code?: string, public readonly cause?: unknown) {\n super(message);\n this.name = \"MuseError\";\n }\n}\n\nexport class ToolError extends MuseError {\n constructor(message: string, public readonly toolName: string, cause?: unknown) {\n super(message, \"TOOL_ERROR\", cause);\n this.name = \"ToolError\";\n }\n}\n\nexport class PermissionDeniedError extends MuseError {\n constructor(public readonly toolName: string, public readonly reason: string) {\n super(`Permission denied for ${toolName}: ${reason}`, \"PERMISSION_DENIED\");\n this.name = \"PermissionDeniedError\";\n }\n}\n","/**\n * LLMClient 工厂:根据配置创建对应 provider 的客户端。\n *\n * 当前只实现 openai-compatible 协议族(覆盖 95% 国产模型 + OpenAI 本身)。\n * Anthropic 走自己的协议,留待 v0.3 加。\n */\n\nimport { createPresetClient, PRESETS, OpenAICompatibleClient } from \"./providers/index.js\";\nimport type { LLMClient, ModelCapabilities, ProviderConfig } from \"./types.js\";\nimport { MuseError } from \"../types/index.js\";\nimport type { ModelEntry } from \"../config/models.js\";\n\nexport interface CreateClientOpts {\n provider: string;\n model: string;\n providers: Record<string, ProviderConfig>;\n}\n\n/**\n * 当前 active model 的 apiKey 注入到此进程 env 字段下。\n *\n * 业务代码(LLM client)只看到 env name,不直接持有 key 副本。\n * /model 切换或启动加载时由 setActiveModelEnv() 写入;从这里读出来给 client。\n */\nexport const ACTIVE_API_KEY_ENV = \"MUSE_ACTIVE_API_KEY\";\n\n/** 把 entry 的 apiKey 注入 process.env,供 createLLMClientFromModelEntry 读取。 */\nexport function setActiveModelEnv(entry: ModelEntry): void {\n if (entry.apiKey) {\n process.env[ACTIVE_API_KEY_ENV] = entry.apiKey;\n } else {\n delete process.env[ACTIVE_API_KEY_ENV];\n }\n}\n\n/**\n * 从用户在 models.local.json 里定义的 ModelEntry 构造 LLMClient。\n *\n * apiKey 不直接传值——而是从 process.env[ACTIVE_API_KEY_ENV] 读,调用前必须先\n * setActiveModelEnv(entry) 写入。这样业务代码只看到 env name,不直接持有 key。\n *\n * vendor 字段仅用于显示(providerName 显示在 banner / /status)。\n * 当前所有 entry 走 openai-compatible 协议;未来引入其他协议时按 entry.protocol 分流。\n */\nexport function createLLMClientFromModelEntry(entry: ModelEntry): LLMClient {\n const apiKey = process.env[ACTIVE_API_KEY_ENV] ?? \"\";\n if (!apiKey && !entry.baseUrl.includes(\"localhost\")) {\n throw new MuseError(buildMissingKeyMessage(entry), \"MISSING_API_KEY\");\n }\n const capabilities: Partial<ModelCapabilities> = {};\n if (entry.supportsToolCall !== undefined) capabilities.toolCalling = entry.supportsToolCall;\n if (entry.supportsImages !== undefined) capabilities.vision = entry.supportsImages;\n if (entry.contextWindow !== undefined) capabilities.maxContextWindow = entry.contextWindow;\n\n return new OpenAICompatibleClient({\n providerName: entry.vendor ?? \"custom\",\n baseUrl: entry.baseUrl,\n apiKey,\n model: entry.id,\n capabilities,\n });\n}\n\n/**\n * 用户向报错:当 apiKey 是 ${VAR} 占位符但 VAR 没设时,告诉用户具体缺哪个 env var\n * 和三种修复方式;不是占位符 / 直接缺字段时退化为通用提示。\n */\nfunction buildMissingKeyMessage(entry: ModelEntry): string {\n const envVars = ((entry as { _apiKeyEnvVars?: string[] })._apiKeyEnvVars ?? []).filter(\n (v) => !process.env[v],\n );\n const head = `Model \"${entry.id}\" needs an API key but none was found.`;\n\n if (envVars.length > 0) {\n const list = envVars.map((v) => `$${v}`).join(\", \");\n const fixVar = envVars[0];\n return [\n head,\n ``,\n `Cause: ~/.muse/models.local.json sets apiKey to a placeholder referencing ${list},`,\n ` but the shell environment does not have ${envVars.length > 1 ? \"those variables\" : \"that variable\"} set.`,\n ``,\n `Fix (pick one):`,\n ` 1. Replace the \\${${fixVar}} placeholder in ~/.muse/models.local.json with the literal key`,\n ` (recommended — the file is local-only and never enters git).`,\n ` 2. Export the variable in your shell:`,\n ` export ${fixVar}=<your-key>`,\n ].join(\"\\n\");\n }\n\n return [\n head,\n ``,\n `Edit ~/.muse/models.local.json and set \"apiKey\" on the \"${entry.id}\" entry`,\n `(plain text is fine — the file stays local-only).`,\n ].join(\"\\n\");\n}\n\nexport function createLLMClient(opts: CreateClientOpts): LLMClient {\n const { provider, model, providers } = opts;\n const config = providers[provider];\n\n if (!config) {\n throw new MuseError(\n `Provider \"${provider}\" is not configured. Add a \"providers.${provider}\" entry to your settings.json.`,\n \"PROVIDER_NOT_CONFIGURED\",\n );\n }\n\n // 预设 provider(含国产模型)\n if (PRESETS[provider]) {\n if (!config.apiKey && provider !== \"ollama\") {\n throw new MuseError(\n `Provider \"${provider}\" requires apiKey. Set it in settings.json or via the corresponding env var.`,\n \"MISSING_API_KEY\",\n );\n }\n return createPresetClient(provider, config, model);\n }\n\n // 自定义 openai-compatible 端点\n if (config.baseUrl) {\n return new OpenAICompatibleClient({\n providerName: provider,\n baseUrl: config.baseUrl as string,\n apiKey: (config.apiKey as string | undefined) ?? \"\",\n model,\n });\n }\n\n throw new MuseError(\n `Unknown provider \"${provider}\". Either use a preset (${Object.keys(PRESETS).join(\", \")}) or set \"baseUrl\" in providers.${provider}.`,\n \"UNKNOWN_PROVIDER\",\n );\n}\n","/**\n * Session 内 Todo 清单。\n *\n * 仅存活于单次 muse 进程内,不入 JSONL 持久化(任务清单是 ephemeral 调度状态,\n * 不是对话内容;下次进程恢复 session 时 LLM 应基于历史重建清单)。\n *\n * 工具 TodoWrite 通过 ToolContext.todos 写入;buildSystemPrompt 读出注入下一轮 LLM 的视野。\n */\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\";\n\nexport interface Todo {\n content: string;\n status: TodoStatus;\n /** 进行中状态的现在分词式描述,UI 可用作 spinner 文案。 */\n activeForm?: string;\n}\n\nexport class TodoStore {\n private items: Todo[] = [];\n\n list(): Todo[] {\n return this.items.slice();\n }\n\n set(items: Todo[]): void {\n this.items = items.slice();\n }\n\n clear(): void {\n this.items = [];\n }\n\n /** 把当前清单格式化为 system prompt 段落;无任务时返回空串。 */\n toPromptSection(): string {\n if (this.items.length === 0) return \"\";\n const lines = this.items.map((t, i) => {\n const marker = t.status === \"completed\" ? \"[x]\" : t.status === \"in_progress\" ? \"[~]\" : \"[ ]\";\n return ` ${i + 1}. ${marker} ${t.content}`;\n });\n return `# Current todos\\n${lines.join(\"\\n\")}\\n\\nUpdate via TodoWrite as you make progress. Keep exactly one item in_progress at a time.`;\n }\n}\n","/**\n * 4 段预处理管线共享类型。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §3.3。\n */\n\n/** stage 执行结果(用于日志/metrics)。 */\nexport type StageStatus = \"ok\" | \"skip\" | \"error\" | \"timeout\";\n\nexport interface StageReport {\n pipeline: string;\n stage: string;\n durationMs: number;\n status: StageStatus;\n error?: string;\n}\n\nexport interface PreprocessLogger {\n stage(report: StageReport): void;\n warn(stage: string, msg: string, meta?: Record<string, unknown>): void;\n}\n\n/** noop logger:测试与默认接入时不传 logger 也能跑。 */\nexport const NOOP_LOGGER: PreprocessLogger = {\n stage() {},\n warn() {},\n};\n\nexport interface PreprocessTelemetry {\n /** stage 累计耗时(毫秒)。 */\n stageDurations: Map<string, number>;\n /** stage 执行次数。 */\n stageInvocations: Map<string, number>;\n}\n\nexport function createTelemetry(): PreprocessTelemetry {\n return {\n stageDurations: new Map(),\n stageInvocations: new Map(),\n };\n}\n","/**\n * 统一 Pipeline 抽象。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §2.1。\n *\n * 4 段管线(Input/Request/Result/Render)共享同一套框架。\n * stage 顺序执行 + 可变 ctx;单 stage 失败可配 throw / skip 容忍。\n */\n\nimport { NOOP_LOGGER, type PreprocessLogger, type StageStatus, type StageReport } from \"./types.js\";\n\n/** Pipeline 短路信号:抛出后 pipeline 立即停止,剩余 stage 跳过。 */\nexport class PipelineShortCircuit extends Error {\n constructor(public readonly reason: string) {\n super(`pipeline short-circuit: ${reason}`);\n this.name = \"PipelineShortCircuit\";\n }\n}\n\n/** Hook 阻断信号:用户配置的 hook 命令返回 block 时,pipeline 应转换为此错误向上抛。 */\nexport class PipelineBlockedError extends Error {\n constructor(public readonly point: string, public readonly reason: string) {\n super(`blocked at ${point}: ${reason}`);\n this.name = \"PipelineBlockedError\";\n }\n}\n\nexport interface PipelineStage<Ctx> {\n /** stage 名,唯一,kebab-case;用于日志、disable 列表。 */\n readonly name: string;\n /** 入参与出参共享同一个可变 ctx;返回 Promise<void> 表示就地修改。 */\n run(ctx: Ctx): Promise<void> | void;\n /** 可选:跳过条件;返回 true 时本 stage 不执行。 */\n skip?(ctx: Ctx): boolean;\n}\n\nexport interface PipelineRunOptions {\n /** 全局执行超时(毫秒);超时后剩余 stage 跳过并标 timeout。 */\n timeoutMs?: number;\n /** 单 stage 出错策略:\"throw\"(默认)| \"skip\"(记日志后跳过)。 */\n onStageError?: \"throw\" | \"skip\";\n /** 已禁用的 stage name 列表;来自 settings.preprocess.disable。 */\n disable?: ReadonlyArray<string>;\n /** 结构化日志器。 */\n logger?: PreprocessLogger;\n /** Pipeline 名,用于日志归类(如 \"input\" / \"request\")。 */\n pipelineName?: string;\n}\n\nexport class Pipeline<Ctx> {\n constructor(\n private readonly stages: ReadonlyArray<PipelineStage<Ctx>>,\n private readonly opts: PipelineRunOptions = {},\n ) {}\n\n /** 按声明顺序执行 stages,逐个写日志。 */\n async run(ctx: Ctx): Promise<void> {\n const logger = this.opts.logger ?? NOOP_LOGGER;\n const pipelineName = this.opts.pipelineName ?? \"pipeline\";\n const disable = new Set(this.opts.disable ?? []);\n const onStageError = this.opts.onStageError ?? \"throw\";\n const startWall = Date.now();\n const timeoutMs = this.opts.timeoutMs;\n\n for (const stage of this.stages) {\n if (timeoutMs != null && Date.now() - startWall >= timeoutMs) {\n report(logger, pipelineName, stage.name, 0, \"timeout\");\n continue;\n }\n if (disable.has(stage.name)) {\n report(logger, pipelineName, stage.name, 0, \"skip\");\n continue;\n }\n if (stage.skip?.(ctx)) {\n report(logger, pipelineName, stage.name, 0, \"skip\");\n continue;\n }\n\n const t0 = Date.now();\n try {\n await stage.run(ctx);\n report(logger, pipelineName, stage.name, Date.now() - t0, \"ok\");\n } catch (err) {\n if (err instanceof PipelineShortCircuit) {\n report(logger, pipelineName, stage.name, Date.now() - t0, \"ok\");\n return;\n }\n if (err instanceof PipelineBlockedError) {\n report(logger, pipelineName, stage.name, Date.now() - t0, \"error\", err.message);\n throw err;\n }\n const msg = err instanceof Error ? err.message : String(err);\n report(logger, pipelineName, stage.name, Date.now() - t0, \"error\", msg);\n if (onStageError === \"throw\") throw err;\n }\n }\n }\n}\n\nfunction report(\n logger: PreprocessLogger,\n pipeline: string,\n stage: string,\n durationMs: number,\n status: StageStatus,\n error?: string,\n): void {\n const r: StageReport = { pipeline, stage, durationMs, status, ...(error ? { error } : {}) };\n logger.stage(r);\n}\n","/**\n * System prompt 构造。\n *\n * 简短、命令式:把可用工具与运行时约束直接摆出来给 LLM。\n * 中文输出由 ui.lang 控制;英文为默认。\n */\n\nimport { homedir } from \"node:os\";\n\nexport interface SystemPromptOpts {\n cwd: string;\n model: string;\n provider: string;\n lang?: \"en\" | \"zh-CN\";\n toolNames: string[];\n /** MEMORY.md index 内容(loadMemoryIndex 加载后传入);空串视为无 memory。 */\n memoryIndex?: string;\n}\n\nexport function buildSystemPrompt(opts: SystemPromptOpts): string {\n const { cwd, model, provider, lang, toolNames, memoryIndex } = opts;\n const home = homedir();\n const displayCwd = cwd.startsWith(home) ? cwd.replace(home, \"~\") : cwd;\n\n const sections: string[] = [];\n\n sections.push(`You are Muse, a CLI coding assistant. You are running on the user's local machine via a terminal interface.`);\n\n sections.push(\n `# Environment\\n` +\n `- Working directory: ${displayCwd}\\n` +\n `- LLM backend: ${provider} (${model})\\n` +\n `- Date: ${new Date().toISOString().slice(0, 10)}`,\n );\n\n sections.push(\n `# Available tools\\n` +\n toolNames.map((n) => `- ${n}`).join(\"\\n\") +\n `\\n\\nPrefer the dedicated tool over Bash when one fits (Read for file reading, Edit for partial updates, Write for new files / full rewrites, Grep for content search, Glob for file lookup).`,\n );\n\n sections.push(\n `# Behavior\\n` +\n `- Be concise. State results, not your thinking. Don't narrate every step.\\n` +\n `- Before editing a file you have not seen, Read it first.\\n` +\n `- For Write/Edit/Bash the user may need to approve — proceed normally; the host will gate dangerous calls.\\n` +\n `- If a command may be destructive (rm -rf, force push, drop table, etc.), warn first and let the user run it manually.\\n` +\n `- When the user asks a question that does not need tools, just answer.`,\n );\n\n if (toolNames.includes(\"TodoWrite\")) {\n sections.push(\n `# Task management\\n` +\n `- For non-trivial, multi-step work, use TodoWrite to plan and track progress.\\n` +\n `- Keep exactly one task in_progress; mark a task completed immediately when done.\\n` +\n `- Skip it for trivial single-step requests.`,\n );\n }\n\n if (lang === \"zh-CN\") {\n sections.push(`# Output language\\nReply in Chinese (简体中文) unless the user writes in English.`);\n }\n\n if (memoryIndex && memoryIndex.trim()) {\n sections.push(\n `# Memory (long-term)\\n` +\n `Below is MEMORY.md — your index of persistent facts about the user, project, and prior feedback. ` +\n `Each line points at a file you can MemoryRead. Use MemoryWrite to record new durable knowledge ` +\n `(user role/preferences, validated decisions, project facts, external references). Do NOT save things ` +\n `derivable from the repo or git history.\\n\\n` +\n memoryIndex,\n );\n }\n\n return sections.join(\"\\n\\n\");\n}\n","/**\n * 项目级配置文件 hierarchy 加载(MUSE.md + AGENTS.md)。\n *\n * 设计文档:模块设计/Agent 记忆系统/设计.md §4.1。\n *\n * 5 层(低到高优先级):\n * 1. managed /etc/muse/MUSE.md 企业 IT 部署(本期占位,只读不写)\n * 2. user ~/.muse/MUSE.md 跨项目偏好\n * 3. project <root>/MUSE.md 或 AGENTS.md 团队共享(入 git);两者并存时 overlay(MUSE.md 优先)\n * 4. local <root>/.muse/MUSE.local.md 个人本地(不入 git)\n * 5. subdir <root>/<subdir>/MUSE.md 子目录上下文(惰性加载,下一阶段实装)\n *\n * 注入点:RequestPipeline.build-system-prompt 把前 4 层拼到 systemPrompt 头部。\n * 子目录(第 5 层)在 Agent loop 检测到文件路径触及未加载子目录时主动注入到 tool result prefix。\n *\n * projectRoot 识别:从 cwd 向上找 `.git` 或 `.muse`;找不到则用 cwd 本身。\n * 与 config loader(只用 cwd)略有差异,因为 hierarchy 文件通常落项目根,\n * 子目录跑 muse 也应能找到。\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport type HierarchyLevel = \"managed\" | \"user\" | \"project\" | \"local\" | \"subdir\";\nexport type HierarchySource = \"MUSE.md\" | \"AGENTS.md\";\n\nexport interface HierarchyLayer {\n level: HierarchyLevel;\n path: string;\n content: string;\n source: HierarchySource;\n /** hierarchy 来源永远 trusted(对齐设计 §4.4)。 */\n trust: \"trusted\";\n}\n\nexport interface LoadHierarchyOpts {\n /** 启用 managed 层(读 /etc/muse/MUSE.md)。默认 false(本期占位)。 */\n enableManaged?: boolean;\n /** Managed 层路径覆盖(便于测试 / 自定义部署)。默认 /etc/muse/MUSE.md。 */\n managedPath?: string;\n /** 忽略 AGENTS.md(只读 MUSE.md)。默认 false。 */\n ignoreAgentsMd?: boolean;\n}\n\nconst DEFAULT_MANAGED_PATH = \"/etc/muse/MUSE.md\";\n\n/**\n * 从 cwd 向上找到第一个含 `.git` 或 `.muse` 的目录作为 project root。找不到则用 cwd。\n *\n * 用于 hierarchy 查找的项目层根目录,与 memory/projects/<hash>/ 的 cwd 隔离逻辑无关\n * (后者保留按 cwd 隔离,避免动既有 session/memory 数据)。\n */\nexport function findProjectRoot(cwd: string): string {\n let cur = resolve(cwd);\n while (true) {\n if (existsSync(join(cur, \".git\")) || existsSync(join(cur, \".muse\"))) {\n return cur;\n }\n const parent = dirname(cur);\n if (parent === cur) return resolve(cwd); // 到根没找到 — 回退 cwd\n cur = parent;\n }\n}\n\n/**\n * 加载前 4 层 hierarchy。子目录(第 5 层)由独立函数 loadSubdirMemory 在 Agent loop 触发。\n *\n * 行为:\n * - 每一层文件不存在 → skip(无副作用)\n * - project 层 MUSE.md + AGENTS.md 并存 → 两条 layer(MUSE.md 在前)\n * - 读取失败 → skip 该 layer,不抛错\n */\nexport async function loadHierarchy(cwd: string, opts: LoadHierarchyOpts = {}): Promise<HierarchyLayer[]> {\n const layers: HierarchyLayer[] = [];\n const ignoreAgents = opts.ignoreAgentsMd === true;\n\n // 1. managed(占位 — 默认 false)\n if (opts.enableManaged === true) {\n const path = opts.managedPath ?? DEFAULT_MANAGED_PATH;\n const layer = await tryLoadLayer(\"managed\", path, \"MUSE.md\");\n if (layer) layers.push(layer);\n }\n\n // 2. user\n const userPath = join(homedir(), \".muse\", \"MUSE.md\");\n const userLayer = await tryLoadLayer(\"user\", userPath, \"MUSE.md\");\n if (userLayer) layers.push(userLayer);\n\n // 3. project — MUSE.md 优先,AGENTS.md 备份;两者并存时各推一条\n const root = findProjectRoot(cwd);\n const projectMuse = await tryLoadLayer(\"project\", join(root, \"MUSE.md\"), \"MUSE.md\");\n if (projectMuse) layers.push(projectMuse);\n if (!ignoreAgents) {\n const projectAgents = await tryLoadLayer(\"project\", join(root, \"AGENTS.md\"), \"AGENTS.md\");\n if (projectAgents) layers.push(projectAgents);\n }\n\n // 4. local\n const localPath = join(root, \".muse\", \"MUSE.local.md\");\n const localLayer = await tryLoadLayer(\"local\", localPath, \"MUSE.md\");\n if (localLayer) layers.push(localLayer);\n\n return layers;\n}\n\nasync function tryLoadLayer(\n level: HierarchyLevel,\n path: string,\n source: HierarchySource,\n): Promise<HierarchyLayer | null> {\n if (!existsSync(path)) return null;\n try {\n const content = (await readFile(path, \"utf-8\")).trim();\n if (!content) return null;\n return { level, path, content, source, trust: \"trusted\" };\n } catch {\n return null;\n }\n}\n\n/**\n * 把多个 layer 拼成 system prompt 的 hierarchy 段。各层之间用 `---` 分隔,标注来源。\n *\n * 输出格式:\n * # Project guidance (hierarchy)\n *\n * [user: ~/.muse/MUSE.md]\n * ...\n *\n * ---\n *\n * [project: ./MUSE.md]\n * ...\n */\nexport function formatHierarchyForPrompt(layers: HierarchyLayer[]): string {\n if (layers.length === 0) return \"\";\n const sections = layers.map((l) => `[${l.level}: ${prettyPath(l.path)}]\\n${l.content}`);\n return `# Project guidance (hierarchy)\\n\\n${sections.join(\"\\n\\n---\\n\\n\")}`;\n}\n\n/**\n * 子目录惰性加载入口。给 Agent loop 用:每跑完一个工具,检测工具操作的路径是否进入了\n * 未加载过的子目录;若该子目录含 MUSE.md / AGENTS.md → 返回内容附加到 tool result prefix。\n *\n * 单次调用只读一个子目录;去重逻辑由调用方维护(用绝对路径 Set)。\n */\nexport async function loadSubdirMemory(\n absSubdir: string,\n opts: { ignoreAgentsMd?: boolean; sizeCapBytes?: number } = {},\n): Promise<{ content: string; source: HierarchySource; truncated: boolean } | null> {\n const sizeCap = opts.sizeCapBytes ?? 5120;\n // MUSE.md 优先,AGENTS.md 备份\n const candidates: { path: string; source: HierarchySource }[] = [\n { path: join(absSubdir, \"MUSE.md\"), source: \"MUSE.md\" },\n ];\n if (opts.ignoreAgentsMd !== true) {\n candidates.push({ path: join(absSubdir, \"AGENTS.md\"), source: \"AGENTS.md\" });\n }\n for (const { path, source } of candidates) {\n if (!existsSync(path)) continue;\n try {\n let raw = (await readFile(path, \"utf-8\")).trim();\n if (!raw) continue;\n const truncated = raw.length > sizeCap;\n if (truncated) {\n raw = raw.slice(0, sizeCap) + `\\n\\n[... truncated (over ${sizeCap}B; use Read tool to view full file)]`;\n }\n return { content: raw, source, truncated };\n } catch {\n // 单文件失败 → 试下一个 candidate\n }\n }\n return null;\n}\n\nfunction prettyPath(p: string): string {\n const home = homedir();\n if (p.startsWith(home)) return \"~\" + p.slice(home.length);\n return p;\n}\n\n/** 加载日志辅助:供 --debug 输出 hierarchy 加载情况。 */\nexport function describeLayers(layers: HierarchyLayer[]): string {\n if (layers.length === 0) return \"(no hierarchy files found)\";\n return layers\n .map((l) => {\n let size = 0;\n try {\n size = statSync(l.path).size;\n } catch {}\n return `[${l.level}] ${prettyPath(l.path)} (${size}B, ${l.source})`;\n })\n .join(\"\\n\");\n}\n","/**\n * build-system-prompt:复用 src/loop/system-prompt.ts 的 builder 拼装基线 system prompt。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.2;模块设计/Agent 记忆系统/设计.md §4.1。\n *\n * 顺序:基础 prompt → hierarchy(MUSE.md / AGENTS.md)→ extraSystemPrompt(SessionStart hook)\n * 后续 stage(inject-memory / inject-todos)继续追加。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { buildSystemPrompt } from \"../../loop/system-prompt.js\";\nimport { formatHierarchyForPrompt } from \"../../loop/hierarchy.js\";\nimport type { RequestCtx } from \"./ctx.js\";\n\nexport class BuildSystemPromptStage implements PipelineStage<RequestCtx> {\n readonly name = \"build-system-prompt\";\n\n run(ctx: RequestCtx): void {\n // memoryIndex 留给 inject-memory stage 单独注入,这里不重复拼。\n // toolNames 取全集(plan 模式过滤推迟到 apply-mode-filter,system prompt 文案\n // 里展示工具仍按全集 — 让 LLM 在 plan 模式也知道有哪些工具可\"将来\"用)。\n ctx.systemPrompt = buildSystemPrompt({\n cwd: ctx.cwd,\n model: ctx.modelId,\n provider: ctx.services.provider,\n lang: ctx.services.lang,\n toolNames: ctx.services.toolRegistry.list().map((t) => t.name),\n });\n // II-1:hierarchy(MUSE.md / AGENTS.md / local / managed)拼进稳定 prefix 段\n const hierarchyText = formatHierarchyForPrompt(ctx.services.hierarchy ?? []);\n if (hierarchyText) {\n ctx.systemPrompt = `${ctx.systemPrompt}\\n\\n${hierarchyText}`;\n }\n // SessionStart hook 注入的额外 system prompt(若有)。\n if (ctx.services.extraSystemPrompt) {\n ctx.systemPrompt = `${ctx.systemPrompt}\\n\\n${ctx.services.extraSystemPrompt}`;\n }\n }\n}\n","/**\n * Memory 向量索引(II-5)。\n *\n * 设计文档:模块设计/Agent 记忆系统/设计.md §4.5。\n *\n * 持久化:每个 scope 一份 .index.json(自家 JSON;ADR D8-rev 拍板,不用 LanceDB):\n * - `~/.muse/projects/<hash>/memory/.index.json`(项目层)\n * - `~/.muse/memory/.index.json`(全局层)\n *\n * 数据结构(每份):\n * PersistentIndex = { providerId, dim, entries: { [name]: { mtime, vector, ... } } }\n *\n * 启动 / 增量行为(每个 scope 独立):\n * 1. 读 .index.json,如果 providerId 一致 → entries 复用\n * 2. 列 memory/*.md,逐条对照 mtime;一致复用 vector,不一致重 embed\n * 3. .index.json 中 name 不在当前 memory 目录 → 删除该 entry\n * 4. providerId 切换 → 全量重 embed,文件覆盖\n *\n * 召回(R1 + R3):\n * - **embed 输入只用 `name + description`**(短而精,语义聚焦;body 留作召回后注入素材)\n * - query → embed → 余弦相似度 × 双重加权(trustW × scopeW)\n * - trustW:trusted ×1.5 / verified ×1.2 / auto ×1.0\n * - scopeW:project ×1.2 / user ×1.0\n *\n * 冷启动保护:memoryCount < minMemoryCount(默认 3,2026-06-07 修订;原 10 过激)\n * → 退化到全注入。\n */\n\nimport { readFile, writeFile, mkdir, unlink } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n listMemories,\n readMemory,\n memoryDir,\n globalMemoryDir,\n scopeDir,\n type MemoryFile,\n type MemoryType,\n type TrustLevel,\n type Scope,\n SCOPES,\n trustRank,\n} from \"./memory.js\";\nimport {\n createEmbeddingProvider,\n createAndProbeProvider,\n cosineSimilarity,\n type EmbeddingProvider,\n type EmbeddingConfig,\n type ExtendedEmbeddingConfig,\n} from \"./embedding/index.js\";\n\nexport interface MemoryIndexEntry {\n name: string;\n type: MemoryType;\n trust: TrustLevel;\n scope: Scope;\n description: string;\n /** 用于注入 prompt 的\"行格式\"片段:`[trust] - [name](name.md) — description`。 */\n rawIndexLine: string;\n /** 完整 frontmatter + body(给召回结果详情展示用)。 */\n bodySnippet: string;\n /** 完整 body(注入分级用:trusted 完整 / verified 摘要 / auto 不用)。 */\n fullBody: string;\n vector: number[];\n}\n\nexport interface MemoryIndex {\n provider: EmbeddingProvider;\n entries: MemoryIndexEntry[];\n /** 索引构建时刻 ISO。 */\n builtAt: string;\n /** cwd(用于增量 upsert / remove 操作时找文件)。 */\n cwd: string;\n}\n\n/** 落盘格式(.index.json):name → 持久化条目 + provider 元数据 + dim。 */\ninterface PersistentIndex {\n providerId: string;\n dim: number;\n schemaVersion: 1;\n entries: { [name: string]: PersistentEntry };\n}\n\ninterface PersistentEntry {\n mtime: string;\n type: MemoryType;\n trust: TrustLevel;\n description: string;\n bodySnippet: string;\n fullBody: string;\n vector: number[];\n}\n\nexport interface BuildIndexOpts {\n config?: ExtendedEmbeddingConfig;\n /** 自定义 provider(测试用);提供时覆盖 config。 */\n provider?: EmbeddingProvider;\n /** 是否禁用磁盘持久化(测试 / 临时场景)。默认 false。 */\n noPersist?: boolean;\n /** 是否跳过 probe 校验(测试 / hash-bag 场景默认跳过)。默认 false(自动按 provider id 判断)。 */\n skipProbe?: boolean;\n}\n\nfunction indexPath(cwd: string, scope: Scope): string {\n return join(scopeDir(cwd, scope), \".index.json\");\n}\n\nasync function readPersistent(cwd: string, scope: Scope): Promise<PersistentIndex | null> {\n const path = indexPath(cwd, scope);\n if (!existsSync(path)) return null;\n try {\n const raw = await readFile(path, \"utf-8\");\n const parsed = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n if (parsed.schemaVersion !== 1) return null;\n return parsed as PersistentIndex;\n } catch {\n return null;\n }\n}\n\nasync function writePersistent(cwd: string, scope: Scope, persistent: PersistentIndex): Promise<void> {\n const dir = scopeDir(cwd, scope);\n await mkdir(dir, { recursive: true });\n await writeFile(indexPath(cwd, scope), JSON.stringify(persistent), \"utf-8\");\n}\n\nfunction snippet(body: string): string {\n return body.length > 400 ? body.slice(0, 400) + \"\\n... [truncated]\" : body;\n}\n\n/** R1:embed 输入只用 `name + description`(短而精,语义聚焦)。 */\nfunction embedInputText(f: MemoryFile): string {\n return `${f.frontmatter.name}: ${f.frontmatter.description}`;\n}\n\nasync function embedMemoryFile(provider: EmbeddingProvider, f: MemoryFile): Promise<PersistentEntry> {\n const fm = f.frontmatter;\n const vector = await provider.embed(embedInputText(f));\n return {\n mtime: fm.updated_at,\n type: fm.type,\n trust: fm.trust,\n description: fm.description,\n bodySnippet: snippet(f.body),\n fullBody: f.body,\n vector,\n };\n}\n\nfunction makeEntry(name: string, scope: Scope, p: PersistentEntry): MemoryIndexEntry {\n return {\n name,\n type: p.type,\n trust: p.trust,\n scope,\n description: p.description,\n rawIndexLine: `[${p.trust}] - [${name}](${name}.md) — ${p.description}`,\n bodySnippet: p.bodySnippet,\n fullBody: p.fullBody,\n vector: p.vector,\n };\n}\n\n/**\n * 从 cwd 下所有 memory 文件构建向量索引(同时遍历 project + user 两 scope)。\n *\n * 行为(2026-06-07 D8-rev + scope 双层):\n * 每个 scope 独立处理:\n * 1. 读 .index.json\n * 2. 如果 providerId 不匹配 → 整库 invalidate,全部重 embed\n * 3. 否则按 mtime 增量:一致复用,不一致重 embed,删除多余\n * 4. 写回 .index.json\n *\n * 输出合并的 entries(每条带 scope 字段),按 scope 顺序 project → user。\n */\nexport async function buildMemoryIndex(cwd: string, opts: BuildIndexOpts = {}): Promise<MemoryIndex> {\n // 优先用 caller 注入的 provider;否则按配置创建并(默认)做 probe 校验\n let provider: EmbeddingProvider;\n if (opts.provider) {\n provider = opts.provider;\n } else if (opts.skipProbe) {\n provider = createEmbeddingProvider(opts.config);\n } else {\n provider = await createAndProbeProvider(opts.config ?? {});\n }\n const allEntries: MemoryIndexEntry[] = [];\n\n for (const scope of SCOPES) {\n const files = await listMemories(cwd, { scope });\n if (files.length === 0) continue;\n\n const persistent = opts.noPersist ? null : await readPersistent(cwd, scope);\n const sameProvider = persistent?.providerId === provider.id && persistent?.dim === provider.dim;\n const oldEntries = sameProvider ? persistent!.entries : {};\n\n const newEntries: { [name: string]: PersistentEntry } = {};\n for (const f of files) {\n const name = f.frontmatter.name;\n const old = oldEntries[name];\n if (old && old.mtime === f.frontmatter.updated_at) {\n newEntries[name] = {\n ...old,\n type: f.frontmatter.type,\n trust: f.frontmatter.trust,\n description: f.frontmatter.description,\n bodySnippet: snippet(f.body),\n fullBody: f.body,\n };\n } else {\n newEntries[name] = await embedMemoryFile(provider, f);\n }\n }\n\n if (!opts.noPersist) {\n await writePersistent(cwd, scope, {\n providerId: provider.id,\n dim: provider.dim,\n schemaVersion: 1,\n entries: newEntries,\n });\n }\n\n for (const [name, p] of Object.entries(newEntries)) {\n allEntries.push(makeEntry(name, scope, p));\n }\n }\n\n return { provider, entries: allEntries, builtAt: new Date().toISOString(), cwd };\n}\n\n/**\n * 增量 upsert:MemoryWrite 后调用,把单条 memory 加入或更新到已有索引。\n * scope 不指定时按 readMemory 规则自动定位(project 优先 fallback user)。\n */\nexport async function upsertMemoryEntry(index: MemoryIndex, name: string, scope?: Scope): Promise<void> {\n let f: MemoryFile;\n try {\n f = await readMemory(index.cwd, name, scope);\n } catch {\n return;\n }\n const p = await embedMemoryFile(index.provider, f);\n\n // in-memory 数组 upsert\n const idx = index.entries.findIndex((e) => e.name === name && e.scope === f.scope);\n const newEntry = makeEntry(name, f.scope, p);\n if (idx >= 0) index.entries[idx] = newEntry;\n else index.entries.push(newEntry);\n\n // 落盘(该 scope 的 .index.json)\n const persistent = (await readPersistent(index.cwd, f.scope)) ?? {\n providerId: index.provider.id,\n dim: index.provider.dim,\n schemaVersion: 1 as const,\n entries: {},\n };\n persistent.entries[name] = p;\n await writePersistent(index.cwd, f.scope, persistent);\n}\n\n/**\n * 移除单条 entry:deleteMemory 后调用。\n * scope 指定时只删该层;不指定时项目 + 全局都尝试删(无害,name 不存在不抛错)。\n */\nexport async function removeMemoryEntry(index: MemoryIndex, name: string, scope?: Scope): Promise<void> {\n const targets: Scope[] = scope ? [scope] : [\"project\", \"user\"];\n for (const s of targets) {\n // in-memory\n const idx = index.entries.findIndex((e) => e.name === name && e.scope === s);\n if (idx >= 0) index.entries.splice(idx, 1);\n // 落盘\n const persistent = await readPersistent(index.cwd, s);\n if (persistent && persistent.entries[name]) {\n delete persistent.entries[name];\n await writePersistent(index.cwd, s, persistent);\n }\n }\n}\n\n/** 强制 invalidate 某 scope 的索引文件,下次 buildMemoryIndex 全量重 embed。 */\nexport async function clearPersistedIndex(cwd: string, scope?: Scope): Promise<void> {\n const targets: Scope[] = scope ? [scope] : [\"project\", \"user\"];\n for (const s of targets) {\n const path = indexPath(cwd, s);\n if (!existsSync(path)) continue;\n try {\n await unlink(path);\n } catch {\n // ignore\n }\n }\n}\n\n// ============================== 查询 / 召回 ==============================\n\nexport interface QueryOpts {\n /** top-K(默认 5)。 */\n topK?: number;\n /** 最低相似度阈值(默认 0;降低阈值召回更多但噪音多)。 */\n minScore?: number;\n}\n\nexport interface QueryResult {\n entry: MemoryIndexEntry;\n /** 余弦相似度(0-1)。 */\n score: number;\n /** trust × scope 双重加权后的最终排序分。 */\n weighted: number;\n}\n\n/**\n * 召回:embed query → 双重加权(trust × scope) → top-K。\n *\n * 加权公式(R3 拍板):\n * weighted = cosine × trustW × scopeW\n *\n * trustW:trusted ×1.5 / verified ×1.2 / auto ×1.0\n * scopeW:project ×1.2 / user ×1.0\n */\nexport async function queryMemoryIndex(\n index: MemoryIndex,\n queryText: string,\n opts: QueryOpts = {},\n): Promise<QueryResult[]> {\n if (index.entries.length === 0) return [];\n const topK = opts.topK ?? 5;\n const minScore = opts.minScore ?? 0;\n const queryVec = await index.provider.embed(queryText);\n const scored = index.entries\n .map((entry) => {\n const score = cosineSimilarity(queryVec, entry.vector);\n const weighted = score * trustWeight(entry.trust) * scopeWeight(entry.scope);\n return { entry, score, weighted };\n })\n .filter((r) => r.score > minScore)\n .sort((a, b) => b.weighted - a.weighted);\n return scored.slice(0, topK);\n}\n\n/** trust 加权:trusted ×1.5,verified ×1.2,auto ×1.0(R3 设计 §4.5)。 */\nfunction trustWeight(t: TrustLevel): number {\n switch (t) {\n case \"trusted\":\n return 1.5;\n case \"verified\":\n return 1.2;\n case \"auto\":\n return 1.0;\n }\n}\n\n/** scope 加权:project ×1.2,user ×1.0(R3 — 项目优先 > 全局)。 */\nfunction scopeWeight(s: Scope): number {\n return s === \"project\" ? 1.2 : 1.0;\n}\n\n/** 把召回结果格式化为可注入 system prompt 的索引段(替代 loadMemoryIndex)。\n * 本函数只输出索引行;trust 分级 body 注入由 inject-memory stage 完成。 */\nexport function formatRetrievedAsIndex(results: QueryResult[]): string {\n if (results.length === 0) return \"\";\n return results.map((r) => r.entry.rawIndexLine).join(\"\\n\");\n}\n\nexport { trustRank, trustWeight, scopeWeight };\n","/**\n * 长期 Memory:跨 session 持久化的小段知识。\n *\n * 两层 scope(2026-06-07 设计扩展):\n * - project:`~/.muse/projects/<projectHash>/memory/`(已有)\n * - user:`~/.muse/memory/`(新增 — 跨项目用户级)\n *\n * 用户级 memory 对当前项目也生效,优先级低于项目级(召回时 project ×1.2)。\n *\n * 文件结构(每个 scope 内):\n * - MEMORY.md index(每行 `[trust] - [name](name.md) — one-line hook`)\n * - <name>.md 具体记忆,带 frontmatter(含 trust + source + timestamps)\n *\n * trust 三级(模块设计/Agent 记忆系统/设计.md §4.4):\n * - trusted hierarchy 层(MUSE.md / AGENTS.md / managed)\n * - verified 用户编辑过 / 显式 promote\n * - auto LLM 通过 MemoryWrite 自动写入,未审核(可被覆盖)\n *\n * source 来源:user-edit / user-remember / compact-promote / manual-write / imported / promote-scope。\n *\n * 类型:user / feedback / project / reference。\n */\n\nimport { mkdir, readFile, writeFile, unlink, readdir } from \"node:fs/promises\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { createHash } from \"node:crypto\";\n\nexport type MemoryType = \"user\" | \"feedback\" | \"project\" | \"reference\";\nexport type TrustLevel = \"trusted\" | \"verified\" | \"auto\";\nexport type Scope = \"project\" | \"user\";\nexport type MemorySource =\n | \"user-edit\"\n | \"user-remember\"\n | \"compact-promote\"\n | \"manual-write\"\n | \"imported\"\n | \"promote-scope\";\n\nexport const TRUST_LEVELS: readonly TrustLevel[] = [\"trusted\", \"verified\", \"auto\"];\nexport const SCOPES: readonly Scope[] = [\"project\", \"user\"];\n\n/**\n * trust 排序:trusted > verified > auto。\n * II-5 向量召回的加权 / II-3 list 排序 用此函数比较。\n */\nexport function trustRank(t: TrustLevel): number {\n switch (t) {\n case \"trusted\":\n return 2;\n case \"verified\":\n return 1;\n case \"auto\":\n return 0;\n }\n}\n\nexport interface MemoryFrontmatter {\n name: string;\n description: string;\n type: MemoryType;\n trust: TrustLevel;\n source: string;\n created_at: string;\n updated_at: string;\n}\n\nexport interface MemoryFile {\n frontmatter: MemoryFrontmatter;\n body: string;\n filePath: string;\n scope: Scope;\n}\n\nfunction projectHash(cwd: string): string {\n return createHash(\"sha256\").update(cwd).digest(\"hex\").slice(0, 16);\n}\n\n// ============================== 路径 helpers ==============================\n\nexport function memoryDir(cwd: string): string {\n return join(homedir(), \".muse\", \"projects\", projectHash(cwd), \"memory\");\n}\n\nexport function globalMemoryDir(): string {\n return join(homedir(), \".muse\", \"memory\");\n}\n\nexport function scopeDir(cwd: string, scope: Scope): string {\n return scope === \"user\" ? globalMemoryDir() : memoryDir(cwd);\n}\n\nexport function memoryIndexPath(cwd: string, scope: Scope = \"project\"): string {\n return join(scopeDir(cwd, scope), \"MEMORY.md\");\n}\n\nexport function memoryFilePath(cwd: string, name: string, scope: Scope = \"project\"): string {\n return join(scopeDir(cwd, scope), `${name}.md`);\n}\n\n// ============================== 加载 / 读取 ==============================\n\n/** 加载 MEMORY.md 前 N 行供 system prompt 注入。\n * 默认合并两层:project 在前 + user 在后(用 `---` 分隔)。 */\nexport async function loadMemoryIndex(cwd: string, maxLines = 200): Promise<string> {\n const parts: string[] = [];\n for (const scope of SCOPES) {\n const path = memoryIndexPath(cwd, scope);\n if (!existsSync(path)) continue;\n try {\n const raw = await readFile(path, \"utf-8\");\n const trimmed = raw.trim();\n if (!trimmed) continue;\n const tag = scope === \"project\" ? \"# project memory\" : \"# user (global) memory\";\n parts.push(`${tag}\\n${trimmed}`);\n } catch {\n // skip\n }\n }\n if (parts.length === 0) return \"\";\n const full = parts.join(\"\\n\\n---\\n\\n\");\n const lines = full.split(\"\\n\");\n if (lines.length <= maxLines) return full;\n return lines.slice(0, maxLines).join(\"\\n\") + `\\n... [truncated; ${lines.length - maxLines} more lines]`;\n}\n\n/**\n * 读取单条 memory:scope 未指定时**先 project,fallback user**;name 在两层都存在\n * 时 scope 显式可消歧。\n *\n * 旧文件无 trust/source/timestamps 时**懒填**(基于 file mtime),不写回磁盘。\n */\nexport async function readMemory(cwd: string, name: string, scope?: Scope): Promise<MemoryFile> {\n const candidates: Scope[] = scope ? [scope] : [\"project\", \"user\"];\n for (const s of candidates) {\n const filePath = memoryFilePath(cwd, name, s);\n if (!existsSync(filePath)) continue;\n const raw = await readFile(filePath, \"utf-8\");\n const { frontmatter, body } = parseMemoryFile(raw, name, filePath);\n return { frontmatter, body, filePath, scope: s };\n }\n const where = scope ? `${scope} scope` : `project or user scope`;\n throw new Error(`Memory \"${name}\" does not exist in ${where}.`);\n}\n\n/** 仅返回文件原文(含 frontmatter)。MemoryRead 工具用此让 LLM 看到 trust + scope。 */\nexport async function readMemoryFile(cwd: string, name: string, scope?: Scope): Promise<string> {\n const file = await readMemory(cwd, name, scope);\n return readFile(file.filePath, \"utf-8\");\n}\n\n// ============================== 写入 ==============================\n\nexport interface WriteMemoryOpts {\n name: string;\n description: string;\n type: MemoryType;\n body: string;\n /** 默认 \"auto\"。 */\n trust?: TrustLevel;\n /** 默认 \"manual-write\"。 */\n source?: MemorySource;\n /** 默认 \"project\"。LLM 自行判断 / /remember 命令显式覆盖。 */\n scope?: Scope;\n}\n\nexport interface WriteMemoryResult {\n filePath: string;\n indexUpdated: boolean;\n /** 新建文件 = true;更新已有 = false。 */\n created: boolean;\n /** 写入的实际 scope(便于 caller 提示)。 */\n scope: Scope;\n}\n\n/**\n * 写一条 memory + 更新对应 scope 的 MEMORY.md 索引。\n *\n * 行为:\n * - 新建:落 frontmatter + body,created_at = updated_at = now\n * - 已存在(同 scope):**保留**原 created_at,刷新 updated_at;trust 走升级语义\n * (不能从 verified 自动降回 auto;trusted 永久不变)\n * - 跨 scope 同名:两层独立存储,各自独立 frontmatter\n * - 索引:替换或追加 `[trust] - [name](name.md) — description` 行\n */\nexport async function writeMemory(cwd: string, opts: WriteMemoryOpts): Promise<WriteMemoryResult> {\n const scope = opts.scope ?? \"project\";\n const dir = scopeDir(cwd, scope);\n await mkdir(dir, { recursive: true });\n\n const filePath = memoryFilePath(cwd, opts.name, scope);\n const now = new Date().toISOString();\n const reqTrust: TrustLevel = opts.trust ?? \"auto\";\n const reqSource = opts.source ?? \"manual-write\";\n\n let createdAt = now;\n let finalTrust: TrustLevel = reqTrust;\n let finalSource: string = reqSource;\n const isCreating = !existsSync(filePath);\n\n if (!isCreating) {\n try {\n const raw = await readFile(filePath, \"utf-8\");\n const existing = parseMemoryFile(raw, opts.name, filePath).frontmatter;\n createdAt = existing.created_at;\n if (trustRank(existing.trust) > trustRank(reqTrust)) {\n finalTrust = existing.trust;\n finalSource = existing.source;\n }\n } catch {\n createdAt = now;\n }\n }\n\n const fm: MemoryFrontmatter = {\n name: opts.name,\n description: opts.description.replace(/\\n/g, \" \").trim(),\n type: opts.type,\n trust: finalTrust,\n source: finalSource,\n created_at: createdAt,\n updated_at: now,\n };\n\n const content = serializeMemoryFile(fm, opts.body);\n await writeFile(filePath, content, \"utf-8\");\n\n const indexUpdated = await upsertIndexLine(cwd, scope, fm);\n return { filePath, indexUpdated, created: isCreating, scope };\n}\n\n/**\n * 改 trust 但不动 body / description(同 scope 内)。用于:\n * - /memory edit 退出后自动升 verified\n * - /memory promote(auto → verified)\n * - /memory trust <verified|auto> 显式改\n *\n * 只升不降语义:trustRank(new) >= trustRank(old);否则报错。\n * scope 未指定 → 走 readMemory 自动定位规则。\n */\nexport async function setMemoryTrust(\n cwd: string,\n name: string,\n trust: TrustLevel,\n source: MemorySource = \"user-edit\",\n scope?: Scope,\n): Promise<void> {\n const file = await readMemory(cwd, name, scope);\n if (trustRank(trust) < trustRank(file.frontmatter.trust)) {\n throw new Error(\n `Cannot lower trust: \"${name}\" is currently ${file.frontmatter.trust}; ${trust} would be a downgrade.`,\n );\n }\n if (trust === file.frontmatter.trust && source === file.frontmatter.source) {\n return; // no-op\n }\n const fm: MemoryFrontmatter = {\n ...file.frontmatter,\n trust,\n source,\n updated_at: new Date().toISOString(),\n };\n const content = serializeMemoryFile(fm, file.body);\n await writeFile(file.filePath, content, \"utf-8\");\n await upsertIndexLine(cwd, file.scope, fm);\n}\n\n/** 删除单条 memory + 从对应 scope 索引移除。scope 未指定 → 自动定位。 */\nexport async function deleteMemory(cwd: string, name: string, scope?: Scope): Promise<Scope> {\n // 先确定 actual scope\n let actualScope: Scope | undefined = scope;\n if (!actualScope) {\n for (const s of SCOPES) {\n if (existsSync(memoryFilePath(cwd, name, s))) {\n actualScope = s;\n break;\n }\n }\n }\n if (!actualScope) {\n throw new Error(`Memory \"${name}\" does not exist in any scope.`);\n }\n const filePath = memoryFilePath(cwd, name, actualScope);\n if (existsSync(filePath)) await unlink(filePath);\n await removeIndexLine(cwd, actualScope, name);\n return actualScope;\n}\n\n/**\n * 把 project scope 的 memory 提升到 user scope(II-3 promote-scope)。\n * 行为:\n * 1. 从 project 读 → 写入 user(保留 created_at;source 改 promote-scope)\n * 2. 删除 project 下的原文件 + 索引行\n * 3. 失败任一步骤抛错(原子性:写 user 失败时不删 project)\n *\n * 已在 user scope:noop 返回 false。\n */\nexport async function promoteScopeToUser(cwd: string, name: string): Promise<boolean> {\n const projectPath = memoryFilePath(cwd, name, \"project\");\n const userPath = memoryFilePath(cwd, name, \"user\");\n if (!existsSync(projectPath)) {\n if (existsSync(userPath)) return false; // 已经在 user scope\n throw new Error(`Memory \"${name}\" does not exist in project scope.`);\n }\n if (existsSync(userPath)) {\n throw new Error(`Memory \"${name}\" already exists in user scope. Delete one of them first.`);\n }\n const file = await readMemory(cwd, name, \"project\");\n await writeMemory(cwd, {\n name: file.frontmatter.name,\n description: file.frontmatter.description,\n type: file.frontmatter.type,\n body: file.body,\n trust: file.frontmatter.trust,\n source: \"promote-scope\",\n scope: \"user\",\n });\n await deleteMemory(cwd, name, \"project\");\n return true;\n}\n\n// ============================== 列表 ==============================\n\nexport interface ListMemoriesOpts {\n /** \"project\" | \"user\" | \"all\"(默认)。 */\n scope?: Scope | \"all\";\n}\n\n/** 列出 memory(按 trust → updated_at 降序;all 时合并两层)。 */\nexport async function listMemories(cwd: string, opts: ListMemoriesOpts = {}): Promise<MemoryFile[]> {\n const scope = opts.scope ?? \"all\";\n const targets: Scope[] = scope === \"all\" ? [\"project\", \"user\"] : [scope];\n const files: MemoryFile[] = [];\n for (const s of targets) {\n const dir = scopeDir(cwd, s);\n if (!existsSync(dir)) continue;\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (!entry.endsWith(\".md\")) continue;\n if (entry === \"MEMORY.md\") continue;\n const name = entry.replace(/\\.md$/, \"\");\n try {\n files.push(await readMemory(cwd, name, s));\n } catch {\n // skip 损坏文件\n }\n }\n }\n files.sort((a, b) => {\n // 优先 trust,再 updated_at,scope 仅做最后 tie-break(project 在前)\n const t = trustRank(b.frontmatter.trust) - trustRank(a.frontmatter.trust);\n if (t !== 0) return t;\n const u = b.frontmatter.updated_at.localeCompare(a.frontmatter.updated_at);\n if (u !== 0) return u;\n if (a.scope === b.scope) return 0;\n return a.scope === \"project\" ? -1 : 1;\n });\n return files;\n}\n\n// ============================== frontmatter 内部实现 ==============================\n\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n?/;\n\n/**\n * 极简 frontmatter 解析。仅识别:\n * name / description 顶层 key: value\n * metadata: 嵌套块,缩进的 key: value\n *\n * 缺失字段懒填:trust=auto, source=manual-write, created_at = file.mtime,\n * updated_at = created_at, type = \"user\"(兜底)。\n */\nfunction parseMemoryFile(\n raw: string,\n fallbackName: string,\n filePath: string,\n): { frontmatter: MemoryFrontmatter; body: string } {\n const m = raw.match(FRONTMATTER_RE);\n if (!m) {\n return {\n frontmatter: lazyDefaults(fallbackName, \"\", filePath),\n body: raw.trim(),\n };\n }\n const fmText = m[1];\n const body = raw.slice(m[0].length).trim();\n\n const lines = fmText.split(\"\\n\");\n let name = fallbackName;\n let description = \"\";\n let type: MemoryType = \"user\";\n let trust: TrustLevel = \"auto\";\n let source = \"manual-write\";\n let createdAt = \"\";\n let updatedAt = \"\";\n let inMetadata = false;\n\n for (const line of lines) {\n if (line.match(/^metadata:\\s*$/)) {\n inMetadata = true;\n continue;\n }\n if (!inMetadata) {\n const kv = parseKV(line);\n if (!kv) continue;\n if (kv.key === \"name\") name = kv.value;\n else if (kv.key === \"description\") description = kv.value;\n } else {\n if (!line.match(/^\\s+\\S/)) {\n inMetadata = false;\n continue;\n }\n const kv = parseKV(line);\n if (!kv) continue;\n switch (kv.key) {\n case \"type\":\n if (isMemoryType(kv.value)) type = kv.value;\n break;\n case \"trust\":\n if (isTrustLevel(kv.value)) trust = kv.value;\n break;\n case \"source\":\n source = kv.value;\n break;\n case \"created_at\":\n createdAt = kv.value;\n break;\n case \"updated_at\":\n updatedAt = kv.value;\n break;\n }\n }\n }\n\n if (!createdAt || !updatedAt) {\n const mtimeIso = safeFileMtime(filePath);\n if (!createdAt) createdAt = mtimeIso;\n if (!updatedAt) updatedAt = createdAt;\n }\n\n return {\n frontmatter: { name, description, type, trust, source, created_at: createdAt, updated_at: updatedAt },\n body,\n };\n}\n\nfunction parseKV(line: string): { key: string; value: string } | null {\n const m = line.match(/^\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*:\\s*(.*?)\\s*$/);\n if (!m) return null;\n const key = m[1];\n let value = m[2];\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n value = value.slice(1, -1);\n }\n return { key, value };\n}\n\nfunction isMemoryType(v: string): v is MemoryType {\n return v === \"user\" || v === \"feedback\" || v === \"project\" || v === \"reference\";\n}\n\nfunction isTrustLevel(v: string): v is TrustLevel {\n return v === \"trusted\" || v === \"verified\" || v === \"auto\";\n}\n\nfunction safeFileMtime(filePath: string): string {\n try {\n return statSync(filePath).mtime.toISOString();\n } catch {\n return new Date().toISOString();\n }\n}\n\nfunction lazyDefaults(name: string, description: string, filePath: string): MemoryFrontmatter {\n const mtimeIso = safeFileMtime(filePath);\n return {\n name,\n description,\n type: \"user\",\n trust: \"auto\",\n source: \"manual-write\",\n created_at: mtimeIso,\n updated_at: mtimeIso,\n };\n}\n\nfunction serializeMemoryFile(fm: MemoryFrontmatter, body: string): string {\n const lines = [\n \"---\",\n `name: ${fm.name}`,\n `description: ${escapeYamlValue(fm.description)}`,\n \"metadata:\",\n ` type: ${fm.type}`,\n ` trust: ${fm.trust}`,\n ` source: ${fm.source}`,\n ` created_at: ${fm.created_at}`,\n ` updated_at: ${fm.updated_at}`,\n \"---\",\n \"\",\n body.trim(),\n \"\",\n ];\n return lines.join(\"\\n\");\n}\n\nfunction escapeYamlValue(v: string): string {\n if (/[:#&*?{}[\\]|>!%@`]/.test(v) || v.startsWith(\" \") || v.endsWith(\" \")) {\n return `\"${v.replace(/\"/g, '\\\\\"')}\"`;\n }\n return v;\n}\n\n// ============================== MEMORY.md 索引 ==============================\n\nconst INDEX_LINE_RE = /^\\[(trusted|verified|auto)\\]\\s+-\\s+\\[([a-zA-Z0-9-_]+)\\]\\(([^)]+)\\)\\s+—\\s+(.*)$/;\n\nfunction formatIndexLine(fm: MemoryFrontmatter): string {\n return `[${fm.trust}] - [${fm.name}](${fm.name}.md) — ${fm.description}`;\n}\n\nasync function upsertIndexLine(cwd: string, scope: Scope, fm: MemoryFrontmatter): Promise<boolean> {\n const indexPath = memoryIndexPath(cwd, scope);\n let index = existsSync(indexPath) ? await readFile(indexPath, \"utf-8\") : \"\";\n const lines = index ? index.split(\"\\n\") : [];\n const newLine = formatIndexLine(fm);\n\n const existingIdx = lines.findIndex((l) => {\n const m = l.match(INDEX_LINE_RE);\n if (m) return m[2] === fm.name;\n return l.startsWith(`- [${fm.name}](${fm.name}.md)`);\n });\n\n let changed = false;\n if (existingIdx >= 0) {\n if (lines[existingIdx] !== newLine) {\n lines[existingIdx] = newLine;\n changed = true;\n }\n } else {\n lines.push(newLine);\n changed = true;\n }\n if (changed) {\n const out = lines.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trimEnd() + \"\\n\";\n await mkdir(scopeDir(cwd, scope), { recursive: true });\n await writeFile(indexPath, out, \"utf-8\");\n }\n return changed;\n}\n\nasync function removeIndexLine(cwd: string, scope: Scope, name: string): Promise<void> {\n const indexPath = memoryIndexPath(cwd, scope);\n if (!existsSync(indexPath)) return;\n const raw = await readFile(indexPath, \"utf-8\");\n const lines = raw.split(\"\\n\");\n const next = lines.filter((l) => {\n const m = l.match(INDEX_LINE_RE);\n if (m) return m[2] !== name;\n return !l.startsWith(`- [${name}](${name}.md)`);\n });\n if (next.length !== lines.length) {\n const out = next.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\").trimEnd() + \"\\n\";\n await writeFile(indexPath, out, \"utf-8\");\n }\n}\n","/**\n * Hash-bag embedding(本期默认 provider,零依赖)。\n *\n * 算法:\n * 1. 文本 → 小写 + 词边界 tokenize(英文 + 中文混合按 unicode 字符切)\n * 2. 每个 token 哈希到 dim 维向量的一个 bucket,+1\n * 3. L2 归一化\n *\n * 优劣:\n * ✓ 跨平台、零 native binding、跨语言可用(中英混合)\n * ✓ 余弦相似度对\"含相同关键词\"的文本得分高 → 替代精确 grep 一定程度上有效\n * ✗ 不懂语义(\"user prefers tabs\" 与 \"缩进风格\" 不会匹配)\n *\n * 适用场景:memory 文件少(< 100)+ 用户搜索习惯走关键词时;真 embedding 模型在\n * 模糊语义检索上明显更优,通过同接口扩展。\n */\n\nimport type { EmbeddingProvider } from \"./types.js\";\n\nconst DEFAULT_DIM = 128;\n\nexport class HashBagEmbeddingProvider implements EmbeddingProvider {\n readonly id: string;\n readonly dim: number;\n\n constructor(dim: number = DEFAULT_DIM) {\n this.dim = dim;\n this.id = `hash-bag-${dim}`;\n }\n\n async embed(text: string): Promise<number[]> {\n return embedSync(text, this.dim);\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n return texts.map((t) => embedSync(t, this.dim));\n }\n}\n\n/** 同步版本(本 provider 无 I/O,实际就是 CPU)。 */\nfunction embedSync(text: string, dim: number): number[] {\n const tokens = tokenize(text);\n const vector = new Array<number>(dim).fill(0);\n for (const token of tokens) {\n const idx = djb2Hash(token) % dim;\n vector[idx] += 1;\n }\n // L2 归一化\n let normSq = 0;\n for (const v of vector) normSq += v * v;\n const norm = Math.sqrt(normSq);\n if (norm === 0) return vector;\n for (let i = 0; i < dim; i++) vector[i] /= norm;\n return vector;\n}\n\n/**\n * Tokenize:\n * - 英文按 \\b\\w+\\b(单词)\n * - 中文按单字(unicode CJK 范围)\n * - 数字按词\n * - 标点 / 空白丢\n *\n * 这样 \"用 pnpm 不 npm\" 切成 [\"用\", \"pnpm\", \"不\", \"npm\"] —— 中英混合都覆盖。\n */\nexport function tokenize(text: string): string[] {\n const out: string[] = [];\n const lower = text.toLowerCase();\n // 用 unicode 属性切:字母 / 数字 / CJK\n const re = /[\\p{L}\\p{N}]+/gu;\n let m: RegExpExecArray | null;\n while ((m = re.exec(lower)) !== null) {\n const chunk = m[0];\n // CJK 字符单独切;其他作为单词\n if (/[一-鿿]/.test(chunk)) {\n for (const ch of chunk) {\n if (/[一-鿿]/.test(ch)) out.push(ch);\n else out.push(ch);\n }\n } else {\n out.push(chunk);\n }\n }\n return out;\n}\n\n/** DJB2 字符串哈希,简单稳定无碰撞偏差。 */\nfunction djb2Hash(s: string): number {\n let h = 5381;\n for (let i = 0; i < s.length; i++) h = ((h << 5) + h + s.charCodeAt(i)) | 0;\n // 32-bit 无符号\n return h >>> 0;\n}\n\n/** 余弦相似度(已归一化向量 → dot product)。 */\nexport function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) return 0;\n let sum = 0;\n for (let i = 0; i < a.length; i++) sum += a[i] * b[i];\n return sum;\n}\n","/**\n * OpenAI-compatible HTTP embedding provider(纯 fetch,无 npm 依赖)。\n *\n * 覆盖:\n * - OpenAI(api.openai.com)\n * - 阿里 DashScope(国内直连)\n * - 智谱 BigModel(国内直连)\n * - Ollama 本地(localhost,无需 apiKey)\n * - 任何 OpenAI 协议的自托管端点(vLLM / TEI / 等)\n *\n * 协议:POST `{baseUrl}/embeddings`\n * body: { model, input, dimensions? }\n * response: { data: [{ embedding: number[] }, ...] }\n *\n * `dimensions` 参数(MRL truncation)只在 sendDimensions=true 时带 — 用户显式覆盖 dim 时启用。\n * preset 默认 dim 不带 dimensions,走模型默认维度。\n */\n\nimport type { EmbeddingProvider } from \"./types.js\";\n\nexport interface OpenAICompatibleConfig {\n baseUrl: string;\n model: string;\n /** 可选;Ollama 等本地端点不需要。 */\n apiKey?: string;\n /** 必填(由 preset 默认 / 用户覆盖)。 */\n dim: number;\n /** 是否在 HTTP body 中带 dimensions 参数(MRL truncation)。默认 false。 */\n sendDimensions?: boolean;\n /** 默认 30000ms。 */\n timeoutMs?: number;\n}\n\nexport class OpenAICompatibleEmbeddingProvider implements EmbeddingProvider {\n readonly id: string;\n readonly dim: number;\n private readonly url: string;\n\n constructor(private config: OpenAICompatibleConfig) {\n const baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n this.url = `${baseUrl}/embeddings`;\n this.dim = config.dim;\n // id 包含 model 和 dim;切换模型 / 维度时索引会被自动 invalidate 重建\n this.id = `openai-compat:${config.model}:${config.dim}`;\n }\n\n async embed(text: string): Promise<number[]> {\n const out = await this.embedBatch([text]);\n return out[0];\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n const body: Record<string, unknown> = {\n model: this.config.model,\n input: texts.length === 1 ? texts[0] : texts,\n };\n if (this.config.sendDimensions) {\n body.dimensions = this.dim;\n }\n\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.config.apiKey) {\n headers.Authorization = `Bearer ${this.config.apiKey}`;\n }\n\n const ctrl = new AbortController();\n const timeoutMs = this.config.timeoutMs ?? 30_000;\n const timer = setTimeout(() => ctrl.abort(), timeoutMs);\n\n let res: Response;\n try {\n res = await fetch(this.url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: ctrl.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new Error(`embedding request timeout after ${timeoutMs}ms: ${this.url}`);\n }\n throw new Error(`embedding network error (${this.url}): ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw new Error(\n `embedding HTTP ${res.status} ${res.statusText} (${this.url}): ${text.slice(0, 200) || \"(no body)\"}`,\n );\n }\n\n let data: { data?: Array<{ embedding?: unknown }> };\n try {\n data = (await res.json()) as { data?: Array<{ embedding?: unknown }> };\n } catch (err) {\n throw new Error(`embedding response is not JSON (${this.url}): ${(err as Error).message}`);\n }\n\n if (!Array.isArray(data.data)) {\n throw new Error(`embedding response missing \"data\" array (${this.url})`);\n }\n\n const vectors: number[][] = [];\n for (const item of data.data) {\n if (!Array.isArray(item.embedding)) {\n throw new Error(`embedding response item missing \"embedding\" array (${this.url})`);\n }\n // 容错:确保每个元素是 number(部分 provider 可能返回 string)\n const vec = (item.embedding as unknown[]).map((v) => {\n const n = typeof v === \"number\" ? v : Number(v);\n if (!Number.isFinite(n)) {\n throw new Error(`embedding contains non-numeric value (${this.url})`);\n }\n return n;\n });\n vectors.push(vec);\n }\n return vectors;\n }\n}\n","/**\n * Local embedding provider 基于 `@huggingface/transformers`(原 Xenova/transformers)。\n *\n * 部署要求(用户启用 local-* preset 时手动安装):\n * npm i -g @huggingface/transformers # 或在项目内 npm i @huggingface/transformers\n *\n * 行为:\n * - lazy 加载模型(首次 embed 时):走 ONNX runtime 跨平台跑\n * - 模型缓存到 ~/.cache/huggingface/hub/(transformers 自管)\n * - 实例级单例 pipeline:同 provider 实例多次 embed 复用 pipeline,不重复加载\n * - 错误处理:模块未装 → 抛清晰错(含 npm i 命令);其他错误抛原始消息\n *\n * macOS 测试 OK 后,其他平台(Linux x86 / Linux ARM / Windows)需另测 ONNX runtime 兼容性。\n *\n * 当前推荐模型(参考 Xenova 命名空间 ONNX 转换版):\n * - Xenova/bge-small-zh-v1.5 512-dim 中文优化\n * - Xenova/bge-small-en-v1.5 384-dim 英文优化\n * - Xenova/all-MiniLM-L6-v2 384-dim 通用多语言\n * - Xenova/bge-m3 1024-dim 多语言强项\n */\n\nimport type { EmbeddingProvider } from \"./types.js\";\n\nexport interface LocalTransformersConfig {\n /** HuggingFace 模型 ID(必填;通常 Xenova/... 命名空间的 ONNX 版本)。 */\n model: string;\n /** 维度(用户根据模型官方说明 / preset 默认填)。 */\n dim: number;\n}\n\n/**\n * 全局 pipeline 缓存:同模型在 muse 整个进程内只加载一次。\n * key = model name;value = pipeline 函数(`@huggingface/transformers` 的 feature-extraction pipeline)。\n */\nconst PIPELINE_CACHE = new Map<string, unknown>();\n\n/** 标记 import 失败时缓存 — 避免每次 embed 都重试导入(失败一次就稳定降级)。 */\nlet importFailed = false;\nlet cachedImportError: string | undefined;\n\nexport class LocalTransformersEmbeddingProvider implements EmbeddingProvider {\n readonly id: string;\n readonly dim: number;\n\n constructor(private readonly config: LocalTransformersConfig) {\n this.dim = config.dim;\n this.id = `local-transformers:${config.model}:${config.dim}`;\n }\n\n async embed(text: string): Promise<number[]> {\n const pipe = await this.getPipeline();\n // pipe(text, { pooling: \"mean\", normalize: true }) → output.data 是 Float32Array\n const output = await (pipe as (text: string, opts: object) => Promise<{ data: Float32Array | number[] }>)(text, {\n pooling: \"mean\",\n normalize: true,\n });\n return Array.from(output.data);\n }\n\n async embedBatch(texts: string[]): Promise<number[][]> {\n // transformers.js 的 pipeline 支持 batch input,但内部仍是串行处理(单 ONNX session)\n // 为简洁与可重入,本期直接 for 串行;后续可优化\n const out: number[][] = [];\n for (const text of texts) {\n out.push(await this.embed(text));\n }\n return out;\n }\n\n private async getPipeline(): Promise<unknown> {\n const cached = PIPELINE_CACHE.get(this.config.model);\n if (cached) return cached;\n\n if (importFailed) {\n throw new Error(\n cachedImportError ??\n `@huggingface/transformers not installed. Run: npm i -g @huggingface/transformers`,\n );\n }\n\n let transformers: { pipeline: (task: string, model: string) => Promise<unknown> };\n try {\n // 动态 import — 未装时抛 ERR_MODULE_NOT_FOUND\n transformers = (await import(\n /* @vite-ignore */ \"@huggingface/transformers\" as string\n )) as { pipeline: (task: string, model: string) => Promise<unknown> };\n } catch (err) {\n importFailed = true;\n const msg = err instanceof Error ? err.message : String(err);\n // 友好提示\n if (msg.includes(\"Cannot find module\") || msg.includes(\"ERR_MODULE_NOT_FOUND\") || msg.includes(\"not installed\")) {\n cachedImportError =\n `Provider local-* requires @huggingface/transformers. Run:\\n` +\n ` npm i -g @huggingface/transformers\\n` +\n `(first-run will download the ONNX model ~24MB to ~/.cache/huggingface/hub/)`;\n } else {\n cachedImportError = `Failed to load @huggingface/transformers: ${msg}`;\n }\n throw new Error(cachedImportError);\n }\n\n if (typeof transformers.pipeline !== \"function\") {\n throw new Error(`@huggingface/transformers loaded but pipeline export is missing`);\n }\n\n const pipe = await transformers.pipeline(\"feature-extraction\", this.config.model);\n PIPELINE_CACHE.set(this.config.model, pipe);\n return pipe;\n }\n}\n\n/** 测试用:清缓存 + 重置 import 失败状态。 */\nexport function _resetLocalTransformersCache(): void {\n PIPELINE_CACHE.clear();\n importFailed = false;\n cachedImportError = undefined;\n}\n","/**\n * Embedding preset 表 — 内置主流厂商的推荐配置(2026-06-07)。\n *\n * 设计:\n * - preset 给\"推荐默认\"(baseUrl + model + dim + requiresKey)\n * - 用户可通过 settings.memory.embedding.{model, dim, baseUrl} 覆盖任一字段\n * - dim 是关键:用户根据模型官方说明可调,muse 启动期 probe 校验实际是否匹配\n *\n * 选 preset 的指导:\n * - 国内用户 + 中文场景:dashscope-v3(便宜 + 直连)\n * - 海外 + 跨语言强:openai-3-small / openai-3-large(需梯子)\n * - 完全本地零成本:ollama-nomic / ollama-bge-m3(需先 ollama pull)\n * - 完全自托管(vLLM / TEI):用 provider=\"openai-compatible\" + 手填 baseUrl/model/dim/apiKey\n */\n\nexport interface EmbeddingPreset {\n baseUrl: string;\n model: string;\n /** 推荐默认维度;用户可通过 settings.dim 覆盖。 */\n dim: number;\n /** 是否必须 apiKey(本地端点为 false)。 */\n requiresKey: boolean;\n /** 显示用的人类可读描述(诊断输出 + 操作手册引用)。 */\n description: string;\n}\n\nexport const EMBEDDING_PRESETS: Record<string, EmbeddingPreset> = {\n // === 国内直连 ===\n \"dashscope-v3\": {\n baseUrl: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n model: \"text-embedding-v3\",\n dim: 1024,\n requiresKey: true,\n description: \"Alibaba DashScope text-embedding-v3 — 中文优化, MRL 降维支持(64/128/256/512/768/1024)\",\n },\n \"zhipu-3\": {\n baseUrl: \"https://open.bigmodel.cn/api/paas/v4\",\n model: \"embedding-3\",\n dim: 2048,\n requiresKey: true,\n description: \"Zhipu BigModel embedding-3\",\n },\n\n // === OpenAI(需梯子)===\n \"openai-3-small\": {\n baseUrl: \"https://api.openai.com/v1\",\n model: \"text-embedding-3-small\",\n dim: 1536,\n requiresKey: true,\n description: \"OpenAI text-embedding-3-small — MRL 降维支持(任意 ≤ 1536)\",\n },\n \"openai-3-large\": {\n baseUrl: \"https://api.openai.com/v1\",\n model: \"text-embedding-3-large\",\n dim: 3072,\n requiresKey: true,\n description: \"OpenAI text-embedding-3-large — MRL 降维支持(任意 ≤ 3072)\",\n },\n\n // === Ollama 本地(零成本)===\n \"ollama-nomic\": {\n baseUrl: \"http://localhost:11434/v1\",\n model: \"nomic-embed-text\",\n dim: 768,\n requiresKey: false,\n description: \"Ollama nomic-embed-text — 本地,先 `ollama pull nomic-embed-text`\",\n },\n \"ollama-bge-m3\": {\n baseUrl: \"http://localhost:11434/v1\",\n model: \"bge-m3\",\n dim: 1024,\n requiresKey: false,\n description: \"Ollama bge-m3 — 多语言本地,先 `ollama pull bge-m3`\",\n },\n\n // === local-transformers(@huggingface/transformers,纯本地无 HTTP)===\n // baseUrl 字段不用,但保留以满足 EmbeddingPreset 类型;factory 通过 preset name 路由\n \"local-bge-zh\": {\n baseUrl: \"\",\n model: \"Xenova/bge-small-zh-v1.5\",\n dim: 512,\n requiresKey: false,\n description: \"Local @huggingface/transformers bge-small-zh-v1.5 — 中文,先 `npm i -g @huggingface/transformers`\",\n },\n \"local-bge-en\": {\n baseUrl: \"\",\n model: \"Xenova/bge-small-en-v1.5\",\n dim: 384,\n requiresKey: false,\n description: \"Local @huggingface/transformers bge-small-en-v1.5 — 英文,先 `npm i -g @huggingface/transformers`\",\n },\n \"local-minilm\": {\n baseUrl: \"\",\n model: \"Xenova/all-MiniLM-L6-v2\",\n dim: 384,\n requiresKey: false,\n description: \"Local @huggingface/transformers all-MiniLM-L6-v2 — 通用多语言,先 `npm i -g @huggingface/transformers`\",\n },\n \"local-bge-m3\": {\n baseUrl: \"\",\n model: \"Xenova/bge-m3\",\n dim: 1024,\n requiresKey: false,\n description: \"Local @huggingface/transformers bge-m3 — 多语言强项(大),先 `npm i -g @huggingface/transformers`\",\n },\n};\n\n/** 是 local-transformers 类 preset(name 以 local- 开头)。 */\nexport function isLocalTransformersPreset(name: string): boolean {\n return name.startsWith(\"local-\");\n}\n\nexport function getPreset(name: string): EmbeddingPreset | null {\n return EMBEDDING_PRESETS[name] ?? null;\n}\n\nexport function listPresetNames(): string[] {\n return Object.keys(EMBEDDING_PRESETS);\n}\n","/**\n * Embedding Provider factory + 配置解析 + probe 校验。\n *\n * 配置层级(用户视角):\n * - settings.memory.embedding.enabled=false(默认)→ 走 hash-bag(零依赖)\n * - enabled=true + preset=\"...\" → 用 preset 默认,用户可覆盖 model/dim\n * - enabled=true + provider=\"openai-compatible\" + 手填 baseUrl/model/dim/apiKey → 完全自定义\n *\n * preset / provider / modelId 三选一(modelId 路径在 cli/app 解析时翻译成 provider 参数)。\n *\n * probe 行为(createAndProbeProvider):\n * - 创建 provider 后发一个 embed(\"muse-embedding-test\") 探针\n * - 校验返回向量长度 === provider.dim\n * - 不一致 → 抛 EmbeddingDimMismatchError(caller 降级 + 提示用户修正)\n * - hash-bag 不做 probe(代码内决定,稳定)\n */\n\nimport type { EmbeddingConfig, EmbeddingProvider } from \"./types.js\";\nimport { HashBagEmbeddingProvider } from \"./hash-bag.js\";\nimport { OpenAICompatibleEmbeddingProvider } from \"./openai-compatible.js\";\nimport { LocalTransformersEmbeddingProvider } from \"./local-transformers.js\";\nimport { getPreset, listPresetNames, isLocalTransformersPreset, EMBEDDING_PRESETS, type EmbeddingPreset } from \"./presets.js\";\n\nexport * from \"./types.js\";\nexport { HashBagEmbeddingProvider, tokenize, cosineSimilarity } from \"./hash-bag.js\";\nexport { OpenAICompatibleEmbeddingProvider } from \"./openai-compatible.js\";\nexport { LocalTransformersEmbeddingProvider } from \"./local-transformers.js\";\nexport { EMBEDDING_PRESETS, getPreset, listPresetNames, isLocalTransformersPreset, type EmbeddingPreset } from \"./presets.js\";\n\n/** preset/provider 默认维度跟实际返回维度不匹配。 */\nexport class EmbeddingDimMismatchError extends Error {\n constructor(\n public readonly configured: number,\n public readonly actual: number,\n public readonly model: string,\n ) {\n super(\n `Embedding dimension mismatch: configured=${configured} but model returned ${actual} ` +\n `(model: ${model}). Fix by setting settings.memory.embedding.dim to ${actual}.`,\n );\n this.name = \"EmbeddingDimMismatchError\";\n }\n}\n\n/** 扩展的 embedding 配置(对 settings 解析后的标准化形态)。 */\nexport interface ExtendedEmbeddingConfig extends EmbeddingConfig {\n preset?: string;\n baseUrl?: string;\n dim?: number;\n}\n\n/**\n * 创建 provider(不做 probe)。\n * probe 由 createAndProbeProvider 包装,cli/app 启动期使用 probe 版本。\n */\nexport function createEmbeddingProvider(config: ExtendedEmbeddingConfig = {}): EmbeddingProvider {\n // 默认 / 显式 hash-bag(零依赖)\n if (!config.provider && !config.preset) {\n return new HashBagEmbeddingProvider();\n }\n if (config.provider === \"hash-bag\") {\n return new HashBagEmbeddingProvider();\n }\n\n // preset 解析(填默认值)\n let baseUrl = config.baseUrl;\n let model = config.model;\n let dim = config.dim;\n let preset: EmbeddingPreset | null = null;\n\n if (config.preset) {\n preset = getPreset(config.preset);\n if (!preset) {\n throw new Error(\n `Unknown embedding preset \"${config.preset}\". Available: ${listPresetNames().join(\", \")}`,\n );\n }\n baseUrl ??= preset.baseUrl;\n model ??= preset.model;\n dim ??= preset.dim;\n }\n\n // local-transformers(@huggingface/transformers):优先识别 preset 前缀\n if (config.preset && isLocalTransformersPreset(config.preset)) {\n if (!model) throw new Error(`local-transformers config missing model`);\n if (!dim) throw new Error(`local-transformers config missing dim`);\n return new LocalTransformersEmbeddingProvider({ model, dim });\n }\n\n // 显式 provider=\"local-minilm\"(兼容);需用户填 model + dim,或转推 preset\n if (config.provider === \"local-minilm\") {\n if (!model || !dim) {\n throw new Error(\n `Provider \"local-minilm\" requires model + dim. Use preset \"local-bge-zh\" / \"local-bge-en\" / \"local-minilm\" / \"local-bge-m3\" instead, or set model + dim explicitly.`,\n );\n }\n return new LocalTransformersEmbeddingProvider({ model, dim });\n }\n\n // openai-compatible(显式 / 通过 preset)\n if (config.provider === \"openai-compatible\" || config.preset) {\n if (!baseUrl) throw new Error(`embedding config missing baseUrl (set via preset or explicitly)`);\n if (!model) throw new Error(`embedding config missing model`);\n if (!dim) throw new Error(`embedding config missing dim`);\n\n // apiKey 必填校验(preset 标了 requiresKey 的)\n if (preset && preset.requiresKey && !config.apiKey) {\n throw new Error(\n `preset \"${config.preset}\" requires apiKey. ` +\n `Set settings.memory.embedding.apiKey (\\${ENV_VAR} supported, e.g. \\${DASHSCOPE_API_KEY}).`,\n );\n }\n\n return new OpenAICompatibleEmbeddingProvider({\n baseUrl,\n model,\n apiKey: config.apiKey,\n dim,\n // 用户显式覆盖 dim 时,HTTP 请求带 dimensions 参数(MRL truncation)\n sendDimensions: config.dim !== undefined,\n });\n }\n\n // 兼容旧 provider 名\n if (config.provider === \"openai\") {\n const p = EMBEDDING_PRESETS[\"openai-3-small\"];\n if (!config.apiKey) throw new Error(`provider \"openai\" requires apiKey`);\n return new OpenAICompatibleEmbeddingProvider({\n baseUrl: p.baseUrl,\n model: config.model ?? p.model,\n apiKey: config.apiKey,\n dim: config.dim ?? p.dim,\n sendDimensions: config.dim !== undefined,\n });\n }\n\n if (config.provider === \"local-minilm\") {\n throw new Error(\n `Provider \"local-minilm\" requires @huggingface/transformers (not yet supported in this version). ` +\n `Use preset \"ollama-nomic\" / \"ollama-bge-m3\" for local, or preset \"dashscope-v3\" / \"openai-3-small\" for cloud.`,\n );\n }\n\n throw new Error(`Unknown embedding provider: ${config.provider}`);\n}\n\n/**\n * createAndProbeProvider:创建 provider + 探针校验 dim。\n *\n * - hash-bag 不 probe(稳定,无 HTTP)\n * - 其他 provider:发 embed(\"muse-embedding-test\") 一次,校验向量长度\n * - 不一致 → 抛 EmbeddingDimMismatchError\n * - 网络 / 401 等其他失败 → 抛原始错误(包含 baseUrl + status,便于用户定位)\n *\n * cli/app 在启动期 catch 任何错误 → 降级 hash-bag(完全不阻塞 muse 启动)。\n */\nexport async function createAndProbeProvider(config: ExtendedEmbeddingConfig): Promise<EmbeddingProvider> {\n const provider = createEmbeddingProvider(config);\n if (provider.id.startsWith(\"hash-bag\")) return provider;\n\n const probe = await provider.embed(\"muse-embedding-test\");\n if (probe.length !== provider.dim) {\n throw new EmbeddingDimMismatchError(provider.dim, probe.length, config.model ?? \"(unknown)\");\n }\n return provider;\n}\n","/**\n * Token 计数:基于 js-tiktoken(纯 JS,无 WASM 依赖)。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.3 trim-history / §4.2.4 budget-guard\n * ADR:暂用 cl100k_base 作为跨 provider 通用编码。OpenAI / DeepSeek / Qwen / Kimi\n * 系实际编码各异,但 trim/budget 的 0.8/0.95 阈值已留出 ~20% safety margin,\n * 不同 provider 真实 token 数偏差通常在 ±20% 内可吸收。后续需要 provider-aware\n * 时只改 getEncoder() 一处。\n *\n * 单例 encoder:getEncoding 内部已经做了缓存,但模块级 once 更明确。\n */\n\nimport { getEncoding, type Tiktoken } from \"js-tiktoken\";\nimport type { Message, ToolDefinition } from \"../types/index.js\";\n\nlet _enc: Tiktoken | undefined;\nfunction enc(): Tiktoken {\n if (!_enc) _enc = getEncoding(\"cl100k_base\");\n return _enc;\n}\n\n/** 计单段文本的 token 数。空字符串返 0。 */\nexport function countText(text: string): number {\n if (!text) return 0;\n return enc().encode(text).length;\n}\n\n/**\n * 计一组 messages + 可选 systemPrompt + 可选 tools 的总 prompt token 数。\n *\n * - text part 直接 encode\n * - tool_use part:name + JSON.stringify(args)\n * - tool result(role=\"tool\"):content 字符串\n * - file / image part:占位文本(图像真实 token 由 vision 模型另计,这里无法预知)\n * - tools 定义:JSON.stringify 后 encode\n *\n * 这是上层 RequestPipeline / Agent estimateInputTokens 的统一入口。\n */\nexport function countMessages(\n messages: Message[],\n systemPrompt?: string,\n tools?: ToolDefinition[],\n): number {\n let total = 0;\n if (systemPrompt) total += countText(systemPrompt);\n\n for (const m of messages) {\n if (m.role === \"tool\") {\n total += countText(m.content);\n continue;\n }\n const content = m.content;\n if (typeof content === \"string\") {\n total += countText(content);\n } else if (Array.isArray(content)) {\n for (const p of content) {\n if (p.type === \"text\") total += countText(p.text ?? \"\");\n else if (p.type === \"tool_use\") {\n total += countText(p.name) + countText(JSON.stringify(p.args ?? {}));\n } else if (p.type === \"file\") {\n // file part 在 client 序列化时 wrap 为 <file path=\"...\">...</file> 送 LLM;\n // 估算时把 path + text 全算上,避免 file 附件 token 数被漏估\n total += countText(p.path) + countText(p.text);\n } else if (p.type === \"image\") {\n // vision token 由模型方按 tile/resolution 计费,prompt 侧用占位估算\n total += countText(`[image: ${p.path ?? p.mediaType}]`);\n }\n }\n }\n }\n\n if (tools && tools.length > 0) {\n // tools 整段 JSON 序列化 — 与发给 LLM 的 schema 形态最接近的近似\n for (const t of tools) total += countText(JSON.stringify(t));\n }\n\n return total;\n}\n\n/**\n * 单条 message 的 token 数(trim-history 逐条估算用)。\n */\nexport function countMessage(m: Message): number {\n return countMessages([m]);\n}\n","/**\n * inject-memory:把 MEMORY.md 索引内容拼到 system prompt 末尾。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.2;模块设计/Agent 记忆系统/设计.md §4.4 + §4.5。\n *\n * 两种模式(由 caller 通过 services 字段切换):\n *\n * 1. 全文模式(默认):services.memoryIndex 提供两层 MEMORY.md(已合并 project + user),直接注入\n * 2. 向量模式(II-5):services.memoryEmbeddingIndex 提供已构建的向量索引;\n * 取最近 N 条 user 消息作 query → 召回 top-K → 按 trust 分级注入 body/snippet/索引行\n *\n * R1-R6 改进(2026-06-07):\n * - R2:query 用最近 3 条 user 消息拼接;短 query(<5 字符)fallback 拼接最近 assistant 上下文\n * - R3:cosine × trust × scope 双重加权(memory-index 内实装)\n * - R4:--debug 召回日志\n * - R5:minCount 降到 3(原 10 过激);按 trust 分级注入 body / snippet / 行索引\n * - R6:maxInjectTokens 预算 1500;超出按 trust 优先级保留(trusted 永不丢)\n *\n * 退化规则(向量模式 → 全文模式):\n * - 索引为空 / 索引 entry 数 < minMemoryCount(默认 3)→ 退化\n * - 提不到 user query → 退化\n * - 召回 0 条 → 退化\n * - 召回失败(provider error / abort)→ 退化\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { RequestCtx } from \"./ctx.js\";\nimport type { Message } from \"../../types/index.js\";\nimport { queryMemoryIndex, type QueryResult } from \"../../loop/memory-index.js\";\nimport { countText } from \"../tokenize.js\";\nimport { log } from \"../../log/index.js\";\n\nconst DEFAULT_TOP_K = 5;\nconst DEFAULT_MIN_COUNT = 3;\nconst DEFAULT_MAX_INJECT_TOKENS = 1500;\nconst QUERY_RECENT_USER_N = 3;\nconst SHORT_QUERY_THRESHOLD = 5;\n\nexport class InjectMemoryStage implements PipelineStage<RequestCtx> {\n readonly name = \"inject-memory\";\n\n async run(ctx: RequestCtx): Promise<void> {\n // 1. 向量模式优先(若启用且不退化)\n const embIndex = ctx.services.memoryEmbeddingIndex;\n const minCount = ctx.services.memoryEmbeddingMinCount ?? DEFAULT_MIN_COUNT;\n const maxTokens = ctx.services.memoryEmbeddingMaxInjectTokens ?? DEFAULT_MAX_INJECT_TOKENS;\n\n if (embIndex && embIndex.entries.length >= minCount) {\n const queryText = buildQuery(ctx.messages);\n if (queryText) {\n try {\n const topK = ctx.services.memoryEmbeddingTopK ?? DEFAULT_TOP_K;\n const results = await queryMemoryIndex(embIndex, queryText, { topK });\n if (results.length > 0) {\n log.debug(\"[memory recall]\", {\n query: queryText.slice(0, 100),\n hits: results.map((r) => ({\n name: r.entry.name,\n scope: r.entry.scope,\n trust: r.entry.trust,\n score: Number(r.score.toFixed(3)),\n weighted: Number(r.weighted.toFixed(3)),\n })),\n });\n const injection = formatRetrievedInjection(results, maxTokens);\n if (injection) {\n ctx.systemPrompt = appendMemorySection(ctx.systemPrompt, injection, \"embedding\", results.length);\n return;\n }\n }\n } catch (err) {\n log.warn(\"[memory recall] query failed; falling back to full-text\", { msg: (err as Error).message });\n }\n }\n }\n\n // 2. 全文模式(默认 / 退化)\n const fullIndex = ctx.services.memoryIndex?.trim();\n if (!fullIndex) return;\n ctx.systemPrompt = appendMemorySection(ctx.systemPrompt, fullIndex, \"full\");\n }\n}\n\n/**\n * R2:构造召回 query。\n * - 取最近 N(=3)条 user 消息(跳过 trim marker / compaction summary 等系统插入)\n * - 用 \\n--- 分隔拼起来\n * - 短 query(<5 字符)fallback 加入最近一条 assistant 文本(代表当前任务上下文)\n * - 全空 → 返回 null\n */\nfunction buildQuery(messages: Message[]): string | null {\n const userTexts: string[] = [];\n let lastAssistantText = \"\";\n for (let i = messages.length - 1; i >= 0 && userTexts.length < QUERY_RECENT_USER_N; i--) {\n const m = messages[i];\n if (m.role === \"user\") {\n const text = extractUserText(m);\n if (text) userTexts.push(text);\n } else if (m.role === \"assistant\" && !lastAssistantText) {\n lastAssistantText = extractAssistantText(m);\n }\n }\n if (userTexts.length === 0) return null;\n let query = userTexts.reverse().join(\"\\n---\\n\");\n // 短 query fallback\n if (query.length < SHORT_QUERY_THRESHOLD && lastAssistantText) {\n query = `${lastAssistantText.slice(0, 200)}\\n---\\n${query}`;\n }\n return query;\n}\n\nfunction extractUserText(m: Message & { role: \"user\" }): string | null {\n if (typeof m.content === \"string\") {\n const t = m.content.trim();\n if (!t) return null;\n // 跳过 trim marker / compaction summary 等系统插入(以 [ 开头多半是 marker)\n if (t.startsWith(\"[\")) return null;\n return t;\n }\n const parts: string[] = [];\n for (const p of m.content) {\n if (p.type === \"text\" && p.text.trim()) parts.push(p.text);\n }\n return parts.length > 0 ? parts.join(\"\\n\") : null;\n}\n\nfunction extractAssistantText(m: Message & { role: \"assistant\" }): string {\n const parts: string[] = [];\n for (const p of m.content) {\n if (p.type === \"text\" && p.text.trim()) parts.push(p.text);\n }\n return parts.join(\"\\n\").trim();\n}\n\n/**\n * R5-R6:按 trust 分级注入 body / snippet / 索引行,并守 maxInjectTokens 预算。\n *\n * 注入形态:\n * - trusted:完整 body(硬约束,绝不省 — 即使 token 超也保留)\n * - verified:description + body snippet(前 ~400 字)\n * - auto:rawIndexLine(索引行同传统模式)\n *\n * 预算策略:按相关性排序遍历,累计 token;超 maxTokens 时:\n * - 已塞入的 trusted 全留\n * - 已塞入的 verified / auto 从尾部回退\n * - 还能塞进 token 预算内的 trusted 优先塞\n */\nfunction formatRetrievedInjection(results: QueryResult[], maxTokens: number): string {\n // 先按\"原排序\"产出每条的注入文本 + token 估算\n const items = results.map((r) => {\n const text = renderEntry(r);\n return { text, tokens: countText(text), trust: r.entry.trust };\n });\n\n // 第一遍:按相关性顺序塞入,守预算\n const kept: typeof items = [];\n let usedTokens = 0;\n for (const item of items) {\n if (usedTokens + item.tokens <= maxTokens) {\n kept.push(item);\n usedTokens += item.tokens;\n continue;\n }\n // 超预算 — 如果是 trusted,把 verified/auto 尾部回退给它腾位置\n if (item.trust === \"trusted\") {\n while (kept.length > 0 && usedTokens + item.tokens > maxTokens) {\n const tail = kept[kept.length - 1];\n if (tail.trust === \"trusted\") break; // 不踢已存在的 trusted\n kept.pop();\n usedTokens -= tail.tokens;\n }\n if (usedTokens + item.tokens <= maxTokens) {\n kept.push(item);\n usedTokens += item.tokens;\n }\n // 仍放不下:跳过(超大单条 trusted,极端情况)\n }\n // 非 trusted 超预算 → 直接丢\n }\n\n return kept.map((k) => k.text).join(\"\\n\\n\");\n}\n\n/** R5:按 trust 分级渲染单条 memory 注入文本。 */\nfunction renderEntry(r: QueryResult): string {\n const e = r.entry;\n const tag = `[${e.trust}] [${e.scope}] [${e.type}]`;\n if (e.trust === \"trusted\") {\n return `## ${e.name} ${tag}\\n${e.description}\\n\\n${e.fullBody}`;\n }\n if (e.trust === \"verified\") {\n return `## ${e.name} ${tag}\\n${e.description}\\n\\n${e.bodySnippet}`;\n }\n // auto:索引行 + 一句 description(信息密度更高过单纯 rawIndexLine)\n return `${e.rawIndexLine}`;\n}\n\nfunction appendMemorySection(\n systemPrompt: string,\n body: string,\n mode: \"embedding\" | \"full\",\n count?: number,\n): string {\n const modeNote =\n mode === \"embedding\"\n ? `Below are the ${count ?? \"top\"} most relevant memories for the current request, ` +\n `retrieved by vector similarity from your project + user (global) memory pool. ` +\n `Higher-trust entries (trusted > verified > auto) and project-scoped entries (project > user) ` +\n `appear first; trusted memories show full body, verified show a snippet, auto show only the index line. ` +\n `Use MemoryRead to view a specific name in full.`\n : `Below is MEMORY.md — your index of persistent facts about the user, project, and prior feedback. ` +\n `Two scopes are merged: # project memory (current project) and # user (global) memory (cross-project). ` +\n `Each line points to a file you can MemoryRead.`;\n\n const section =\n `# Memory (long-term)\\n` +\n `${modeNote} Each line is tagged with a trust level:\\n` +\n ` [trusted] — from MUSE.md / AGENTS.md / managed config; treat as hard constraint.\\n` +\n ` [verified] — user-edited or explicitly promoted; treat as confirmed knowledge.\\n` +\n ` [auto] — LLM-written, unreviewed; treat as a hint that newer evidence may override.\\n\\n` +\n `Use MemoryWrite to record new durable knowledge ` +\n `(scope=project for project facts; scope=user for cross-project user preferences — read the tool's scope arg description carefully). ` +\n `Do NOT save things derivable from the repo or git history. New memories you write are ` +\n `automatically tagged [auto] — the user can promote them later.\\n\\n` +\n body;\n return systemPrompt ? `${systemPrompt}\\n\\n${section}` : section;\n}\n","/**\n * inject-todos:把当前 todos 拼到 system prompt 末尾。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.2。\n *\n * 原逻辑在 agent.ts L82-85,搬到 stage,行为不变。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { RequestCtx } from \"./ctx.js\";\n\nexport class InjectTodosStage implements PipelineStage<RequestCtx> {\n readonly name = \"inject-todos\";\n\n run(ctx: RequestCtx): void {\n const section = ctx.services.todos.toPromptSection();\n if (!section) return;\n ctx.systemPrompt = ctx.systemPrompt\n ? `${ctx.systemPrompt}\\n\\n${section}`\n : section;\n }\n}\n","/**\n * apply-mode-filter:plan 模式过滤工具列表为 read-only,并把 mode 提示拼入 system prompt。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.2。\n *\n * 原逻辑在 agent.ts L77-80,搬到 stage,行为不变。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { RequestCtx } from \"./ctx.js\";\n\nexport class ApplyModeFilterStage implements PipelineStage<RequestCtx> {\n readonly name = \"apply-mode-filter\";\n\n run(ctx: RequestCtx): void {\n // I-5:Memory 工具永远可见(plan 模式下也保留)— Anthropic cookbook 强制\n // exclude_tools:[\"memory\"] 反义,对齐\"压缩时不丢记忆\"原则;memory 写入不算\"执行性写代码\",\n // 不违反 plan 模式语义。\n const MEMORY_WHITELIST = new Set([\"MemoryRead\", \"MemoryWrite\"]);\n const filter =\n ctx.mode === \"plan\"\n ? (t: { name: string; permission: string }) =>\n t.permission === \"read\" || MEMORY_WHITELIST.has(t.name)\n : undefined;\n ctx.tools = ctx.services.toolRegistry.toLLMDefinitions(filter);\n\n if (ctx.mode === \"plan\") {\n // 显式列出可用工具名 + 明令\"忽略历史里 write tool 的例子\"。\n // 没有 enumeration 时 mimo / qwen 等国内模型容易因为历史里有 Edit/Bash 调用而\n // 模仿,触发 provider server 端 \"unavailable tool\" 拒绝(用户看到一条无关\n // 的 server error,体验差)。把白名单 inline 写死能显著降低这种 false call。\n const allowedNames = ctx.tools.map((t) => t.name).join(\", \");\n const note =\n `# Plan mode (active)\\n` +\n `You are in PLAN mode. Read and analyze, then propose changes in your text answer — do not execute them.\\n\\n` +\n `Allowed tools this turn: **${allowedNames}**.\\n\\n` +\n `⚠ HARD RULES:\\n` +\n `1. Do NOT call any tool not in the allowed list (e.g. Edit, Write, Bash, MemoryWrite, WebFetch).\\n` +\n `2. Earlier turns may contain successful write-tool calls (Edit / Write / Bash etc.) — those examples DO NOT apply now. Ignore them.\\n` +\n `3. If the user's request requires writing, reply with a plan and ask them to switch out of plan mode to apply it.`;\n ctx.systemPrompt = ctx.systemPrompt\n ? `${ctx.systemPrompt}\\n\\n${note}`\n : note;\n }\n }\n}\n","/**\n * clear-stale-tool-results stage:折叠\"可重新获取\"的旧 tool result。\n *\n * 设计文档:模块设计/上下文管理工程/设计.md §4.3。\n *\n * 思路:\n * - Read / Grep / Glob 类工具是\"可重新获取\"的 — 同一文件 / 同一查询出现多次时,\n * 只保留最新一次的结果原文,旧的折叠成 placeholder\n * - Bash / Edit / Write / MemoryWrite / WebFetch 等有副作用或不可重获,绝不清\n *\n * 安全保护:\n * 1. 最近 K 轮(默认 3)不清:刚跑完的可能正被 assistant 引用\n * 2. 一条 Read 后若有同文件 Edit/Write,该 Read 保留(Edit 依赖\"必须先 Read\")\n * 3. 配对完整性:只改 tool result.content,不删 message,保 tool_use ↔ tool_result 关系\n * 4. 保留 summary 字段(ResultPipeline.summarize 生成),只清原文 content\n *\n * 不污染 agent.messages:就地修改 ctx.messages 数组里的 tool message content,\n * 不替换 message 引用(因为 message 在 Agent 持有的 messages 数组里共享 — 改 content\n * 会让 Agent 看到清理后的版本)。\n *\n * 实际上:为了真正不污染 Agent 真值,这里创建**新的 ToolMessage 对象**(浅 copy + content 覆盖),\n * 替换 ctx.messages 数组里的引用。Agent 通过 services.compact 之外的路径不会污染。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { RequestCtx } from \"./ctx.js\";\nimport type { Message, ToolMessage, AssistantMessage } from \"../../types/index.js\";\n\nconst DEFAULT_CLEAR_TOOLS: readonly string[] = [\"Read\", \"Grep\", \"Glob\"];\nconst DEFAULT_KEEP_RECENT_TURNS = 3;\n\nexport interface ClearStaleToolResultsSettings {\n enabled?: boolean;\n keepRecentTurns?: number;\n clearTools?: string[];\n}\n\nexport class ClearStaleToolResultsStage implements PipelineStage<RequestCtx> {\n readonly name = \"clear-stale-tool-results\";\n\n skip(ctx: RequestCtx): boolean {\n return ctx.settings.clearStaleToolResults?.enabled === false;\n }\n\n run(ctx: RequestCtx): void {\n const settings = ctx.settings.clearStaleToolResults;\n const keepRecent = settings?.keepRecentTurns ?? DEFAULT_KEEP_RECENT_TURNS;\n const clearTools = new Set(settings?.clearTools ?? DEFAULT_CLEAR_TOOLS);\n ctx.messages = clearStaleResults(ctx.messages, keepRecent, clearTools);\n }\n}\n\n/**\n * 核心算法(导出便于测试):\n * 1. 扫描 messages 数组,建立 toolUseId → ToolUsePart 映射 + recordIdx 索引\n * 2. 对每条 tool message,按 (name, normalizedArgs) 分组\n * 3. 同组中保留 lastOccurrence(最大 idx);其他 occurrences 标记 stale\n * 4. 同时检测\"被该 Read 之后是否有同文件的 Edit/Write\"→ 是则该 Read 不清\n * 5. 最近 keepRecentTurns 条 tool message 不清(无论是否 stale)\n * 6. 替换 stale 的 tool message content 为 placeholder,保留 summary\n */\nexport function clearStaleResults(\n messages: Message[],\n keepRecentTurns: number,\n clearTools: Set<string>,\n): Message[] {\n // 1. 建索引:toolUseId → { name, args, msgIdx }\n const toolUseIndex = new Map<string, { name: string; args: unknown; assistantIdx: number }>();\n messages.forEach((m, i) => {\n if (m.role === \"assistant\") {\n const am = m as AssistantMessage;\n for (const p of am.content) {\n if (p.type === \"tool_use\") {\n toolUseIndex.set(p.id, { name: p.name, args: p.args, assistantIdx: i });\n }\n }\n }\n });\n\n // 2. 收集 tool messages 的位置 + 关联 tool_use 信息\n interface ToolEntry {\n msgIdx: number;\n toolUseId: string;\n name: string;\n args: unknown;\n key: string;\n }\n const toolEntries: ToolEntry[] = [];\n messages.forEach((m, i) => {\n if (m.role === \"tool\") {\n const tm = m as ToolMessage;\n const info = toolUseIndex.get(tm.toolUseId);\n if (!info) return; // 悬挂 tool;不动它(理论上不应该出现)\n if (!clearTools.has(info.name)) return; // 不在可清白名单\n const key = `${info.name}::${normalizeArgs(info.args)}`;\n toolEntries.push({ msgIdx: i, toolUseId: tm.toolUseId, name: info.name, args: info.args, key });\n }\n });\n\n if (toolEntries.length === 0) return messages;\n\n // 3. 按 key 分组,留 lastOccurrence\n const lastOccByKey = new Map<string, number>(); // key → msgIdx\n for (const e of toolEntries) {\n const prev = lastOccByKey.get(e.key) ?? -1;\n if (e.msgIdx > prev) lastOccByKey.set(e.key, e.msgIdx);\n }\n\n // 4. 检测被保护的 Read(后续有 Edit/Write 同文件)\n // 提 path 的逻辑只对 Read 类适用(args.file_path);Grep/Glob 没有\"修改\"概念,跳过保护检查\n const protectedReads = new Set<number>(); // msgIdx 集合\n for (const e of toolEntries) {\n if (e.name !== \"Read\") continue;\n const readPath = extractPath(e.args);\n if (!readPath) continue;\n // 在 e.msgIdx 之后找 Edit/Write 操作同路径\n for (let i = e.msgIdx + 1; i < messages.length; i++) {\n const m = messages[i];\n if (m.role !== \"assistant\") continue;\n const am = m as AssistantMessage;\n for (const p of am.content) {\n if (p.type === \"tool_use\" && (p.name === \"Edit\" || p.name === \"Write\")) {\n const editPath = extractPath(p.args);\n if (editPath === readPath) {\n protectedReads.add(e.msgIdx);\n break;\n }\n }\n }\n if (protectedReads.has(e.msgIdx)) break;\n }\n }\n\n // 5. 最近 K 条 tool message 全保(无论 stale)\n const allToolIndices = toolEntries.map((e) => e.msgIdx);\n const recentCutoff =\n allToolIndices.length > keepRecentTurns\n ? allToolIndices[allToolIndices.length - keepRecentTurns]\n : -1;\n\n // 6. 决定哪些 stale 要清\n const indicesToClear = new Set<number>();\n for (const e of toolEntries) {\n // 不在最新一次 → stale\n if (lastOccByKey.get(e.key) === e.msgIdx) continue;\n // 在最近 K 轮内 → 保\n if (e.msgIdx >= recentCutoff) continue;\n // 被 Edit/Write 保护 → 保\n if (protectedReads.has(e.msgIdx)) continue;\n indicesToClear.add(e.msgIdx);\n }\n\n if (indicesToClear.size === 0) return messages;\n\n // 7. 构造新数组,替换 stale tool message 的 content\n const newMessages: Message[] = messages.map((m, i) => {\n if (!indicesToClear.has(i)) return m;\n const entry = toolEntries.find((e) => e.msgIdx === i)!;\n const latestIdx = lastOccByKey.get(entry.key)!;\n const original = m as ToolMessage;\n const originalSize = original.content?.length ?? 0;\n const cleared: ToolMessage = {\n ...original,\n content:\n `[tool result cleared — ${entry.name}(${formatArgPreview(entry.args)}) was re-run later;` +\n ` see message at index ${latestIdx} for latest result. Original size: ${originalSize}B]`,\n };\n return cleared;\n });\n return newMessages;\n}\n\n/** 规范化参数用作分组 key。简单 JSON.stringify + key 排序。 */\nfunction normalizeArgs(args: unknown): string {\n if (args === null || typeof args !== \"object\") return JSON.stringify(args);\n const sortedEntries = Object.entries(args as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => a.localeCompare(b));\n return JSON.stringify(Object.fromEntries(sortedEntries));\n}\n\n/** Edit / Write / Read 的 args 取 file_path;Grep/Glob 等无对应概念则返 null。 */\nfunction extractPath(args: unknown): string | null {\n if (args === null || typeof args !== \"object\") return null;\n const fp = (args as { file_path?: unknown }).file_path;\n return typeof fp === \"string\" ? fp : null;\n}\n\nfunction formatArgPreview(args: unknown): string {\n if (args === null || typeof args !== \"object\") return String(args);\n const fp = (args as { file_path?: unknown }).file_path;\n if (typeof fp === \"string\") return fp;\n const pattern = (args as { pattern?: unknown }).pattern;\n if (typeof pattern === \"string\") return pattern;\n const s = JSON.stringify(args);\n return s.length > 50 ? s.slice(0, 50) + \"…\" : s;\n}\n","/**\n * Hook 加载与执行。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §六。\n *\n * Hook 协议:外部 shell 命令 + stdin JSON / stdout JSON。\n * Hook 点位(MVP 只接 PreToolUse / PostToolUse,其余 schema 保留但不调用):\n * SessionStart / SessionEnd / UserPromptSubmit /\n * PreLLMRequest / PostLLMResponse /\n * PreToolUse / PostToolUse /\n * PreCompact / PostCompact\n */\n\nimport { execa } from \"execa\";\nimport { NOOP_LOGGER, type PreprocessLogger } from \"./types.js\";\nimport { PipelineBlockedError } from \"./pipeline.js\";\n\nexport type HookPoint =\n | \"SessionStart\"\n | \"SessionEnd\"\n | \"UserPromptSubmit\"\n | \"PreLLMRequest\"\n | \"PostLLMResponse\"\n | \"PreToolUse\"\n | \"PostToolUse\"\n | \"PreCompact\"\n | \"PostCompact\"\n | \"MemoryPromote\";\n\nexport interface HookSpec {\n /** 工具名 / 路径前缀的正则匹配字符串(不含 /);\"\" 或缺省视为全匹配 .* 。 */\n matcher?: string;\n /** 绝对路径或 PATH 可解析命令;**禁用 shell 元字符**。 */\n command: string;\n /** 毫秒,默认 30000,上限 60000。 */\n timeout?: number;\n /** \"skip\"(默认)记 warn 后继续 / \"throw\" 命中即 abort 当前 turn。 */\n onError?: \"skip\" | \"throw\";\n}\n\nexport interface HooksConfig {\n SessionStart?: HookSpec[];\n SessionEnd?: HookSpec[];\n UserPromptSubmit?: HookSpec[];\n PreLLMRequest?: HookSpec[];\n PostLLMResponse?: HookSpec[];\n PreToolUse?: HookSpec[];\n PostToolUse?: HookSpec[];\n PreCompact?: HookSpec[];\n PostCompact?: HookSpec[];\n /** I-5:compactMessages 在 promote 每条 fact 到 memory 之前调用;可 block 该条。 */\n MemoryPromote?: HookSpec[];\n}\n\nexport interface HookOutput {\n /** 由 hook 返回的字段,会与原 input merge(具体字段由点位定义)。 */\n [k: string]: unknown;\n block?: { reason: string };\n}\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst MAX_TIMEOUT = 60_000;\nconst SHELL_META = /[;|&><`$()]/;\n\n/**\n * 跑同点位的全部 hooks(串行链式)。返回最终 merged 输出。\n *\n * - 任一 hook 返回 block → 立即抛 PipelineBlockedError\n * - hook 进程非 0 退出 / 超时 / stdout 非 JSON → 按 onError 处理\n *\n * MVP 期间只在 PreToolUse / PostToolUse 调用;其它点位 schema 保留,不接代码。\n */\nexport async function runHooks(\n point: HookPoint,\n input: Record<string, unknown>,\n hooks: HooksConfig | undefined,\n logger: PreprocessLogger = NOOP_LOGGER,\n): Promise<HookOutput> {\n const specs = hooks?.[point];\n if (!specs || specs.length === 0) return {};\n\n let merged: HookOutput = {};\n let payload: Record<string, unknown> = { ...input };\n\n const matcherKey = pickMatcherKey(input);\n\n for (const spec of specs) {\n if (!matchesMatcher(spec.matcher, payload, matcherKey)) continue;\n if (SHELL_META.test(spec.command)) {\n logger.warn(`hook:${point}`, `command rejected: contains shell metachar`, { command: spec.command });\n continue;\n }\n const timeout = Math.min(spec.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);\n try {\n const result = await execa(spec.command, [], {\n input: JSON.stringify(payload),\n timeout,\n reject: false,\n env: hookEnv(),\n });\n if (result.failed) {\n const reason = `exit ${result.exitCode ?? \"?\"} / signal ${result.signal ?? \"\"}`;\n handleHookError(point, spec, reason, logger);\n continue;\n }\n const text = (result.stdout ?? \"\").trim();\n if (!text) continue;\n let out: HookOutput;\n try {\n out = JSON.parse(text) as HookOutput;\n } catch (err) {\n handleHookError(point, spec, `stdout not JSON: ${(err as Error).message}`, logger);\n continue;\n }\n if (out?.block && typeof out.block === \"object\" && typeof out.block.reason === \"string\") {\n throw new PipelineBlockedError(point, out.block.reason);\n }\n merged = { ...merged, ...out };\n // 链式:下一 hook 看见上一个 hook 改写后的值\n payload = { ...payload, ...out };\n } catch (err) {\n if (err instanceof PipelineBlockedError) throw err;\n handleHookError(point, spec, (err as Error).message, logger);\n }\n }\n return merged;\n}\n\nfunction handleHookError(point: HookPoint, spec: HookSpec, reason: string, logger: PreprocessLogger): void {\n const onError = spec.onError ?? \"skip\";\n logger.warn(`hook:${point}`, reason, { command: spec.command, onError });\n if (onError === \"throw\") {\n throw new Error(`hook ${point} failed: ${reason}`);\n }\n}\n\n/** 输入哪个字段作 matcher 比较:PreToolUse/PostToolUse 用 toolName,其余按 stage 自身约定。 */\nfunction pickMatcherKey(input: Record<string, unknown>): string | undefined {\n if (typeof input.toolName === \"string\") return \"toolName\";\n if (typeof input.path === \"string\") return \"path\";\n return undefined;\n}\n\nfunction matchesMatcher(matcher: string | undefined, payload: Record<string, unknown>, key: string | undefined): boolean {\n if (!matcher || matcher === \".*\") return true;\n if (!key) return true;\n const value = payload[key];\n if (typeof value !== \"string\") return true;\n try {\n return new RegExp(matcher).test(value);\n } catch {\n return false;\n }\n}\n\n/** Hook 子进程的环境变量白名单(避免泄露 MUSE_ACTIVE_API_KEY 等密钥)。 */\nfunction hookEnv(): NodeJS.ProcessEnv {\n const allow = [\"PATH\", \"HOME\", \"LANG\", \"LC_ALL\", \"TERM\", \"USER\", \"SHELL\"];\n const out: NodeJS.ProcessEnv = {};\n for (const key of allow) {\n const v = process.env[key];\n if (v) out[key] = v;\n }\n return out;\n}\n","/**\n * Compaction 摘要 prompt 模板。\n *\n * 设计文档:模块设计/上下文管理工程/设计.md §4.2(I-2)。\n *\n * 主 schema:9 节结构化(对齐业界共识),要求 LLM 完整列出所有 user 消息原文。\n * 降级 schema:6 节(合并较松散的小节),供未明实测稳定性的 provider 用。\n *\n * 摘要后附加 facts_to_promote JSON(I-5 联动):提取跨 session 价值事实供\n * compactMessages 自动写入长期 memory。LLM 强约束\"宁可少不可多\",防误存。\n */\n\nexport type SummarySchema = \"9-section\" | \"6-section\";\n\nconst FACTS_BLOCK = `\n\n---\n\n# Extracted Facts for Long-term Memory (optional)\n\nIf — and only if — the conversation revealed durable facts worth keeping across future sessions,\noutput one JSON code block in this format:\n\n\\`\\`\\`json\n{\n \"facts\": [\n {\n \"name\": \"kebab-case-slug\",\n \"type\": \"user\" | \"feedback\" | \"project\" | \"reference\",\n \"description\": \"one-line summary used as memory index hook\",\n \"body\": \"markdown content of the fact\"\n }\n ]\n}\n\\`\\`\\`\n\nStrict constraints (read carefully — over-eager extraction breaks user trust):\n- Only include facts with **cross-session value**: user role / preference, project hard rule, validated approach\n- Do NOT include: code visible in the repo, git history facts, transient task state, errors already fixed\n- Do NOT save chitchat, model-internal reasoning, or speculation\n- If nothing meets the bar, output \\`{\"facts\": []}\\` — empty is better than noise\n- Each fact \\`name\\` must be a unique slug (kebab- or snake-case alphanumeric)\n- For \\`feedback\\` / \\`project\\` types, body should lead with the rule, then \"Why:\" and \"How to apply:\" lines`;\n\nexport function buildSummaryPrompt(transcript: string, schema: SummarySchema): string {\n if (schema === \"9-section\") {\n return SECTION_9_TEMPLATE.replace(\"{TRANSCRIPT}\", transcript) + FACTS_BLOCK;\n }\n return SECTION_6_TEMPLATE.replace(\"{TRANSCRIPT}\", transcript) + FACTS_BLOCK;\n}\n\nconst SECTION_9_TEMPLATE = `Summarize the following conversation. Use **exactly these 9 sections in this order**. If a section has no content, write \"(none)\" — do not skip section numbers.\n\n# Conversation Summary\n\n1. **Primary Request and Intent**\n — Quote the user's original request verbatim (use > markdown quotes). Do not paraphrase.\n\n2. **Key Technical Concepts**\n — Bullet list of frameworks, languages, libraries, patterns relevant to the conversation.\n\n3. **Files and Code Sections**\n — File path + function / class name + what was read or changed. Be concrete.\n\n4. **Errors and fixes**\n — Each error message (or class of error) + the specific fix taken. Future you will repeat these mistakes if this section is sloppy.\n\n5. **Problem Solving**\n — Key reasoning steps and trade-offs considered. \"I chose A over B because X.\"\n\n6. **All user messages**\n — **List every user message verbatim**, separated by \\`---\\`. Sacred section: NEVER omit, paraphrase, or merge user messages.\n\n7. **Pending Tasks**\n — TODOs the user explicitly stated and items the assistant identified as not-yet-done.\n\n8. **Current Work**\n — What was actively being done at the moment of summarization. One paragraph.\n\n9. **Optional Next Step**\n — Recommended next action, anchored in quote(s) from the user's recent messages. If unclear, write \"(awaiting user direction)\".\n\n--- BEGIN CONVERSATION ---\n{TRANSCRIPT}\n--- END CONVERSATION ---`;\n\nconst SECTION_6_TEMPLATE = `Summarize the following conversation. Use these 6 sections in order. Do not skip section numbers; write \"(none)\" for empty sections.\n\n# Conversation Summary\n\n1. **Primary Request and Intent** — Quote the user's original request verbatim.\n\n2. **Concepts, Decisions, and Reasoning** — Frameworks involved + key trade-offs.\n\n3. **Files and Changes** — File paths + what was modified.\n\n4. **Errors and fixes** — Error messages + specific fixes.\n\n5. **All user messages** — List every user message verbatim, separated by \\`---\\`. Sacred: never omit.\n\n6. **Current Work + Next Step** — What was being done + recommended next action (anchored in user quotes).\n\n--- BEGIN CONVERSATION ---\n{TRANSCRIPT}\n--- END CONVERSATION ---`;\n\n/**\n * 从 LLM 输出中提取 facts JSON 块。\n *\n * 解析策略:\n * 1. 找 ```json ... ``` 代码块,解析内容\n * 2. 容错:含 facts 字段且为数组才返;否则返 null\n * 3. 单条 fact 字段缺失 / 非 string → 跳过该条\n * 4. 重复 name → 后写覆盖前(无报错)\n */\nexport interface ExtractedFact {\n name: string;\n type: \"user\" | \"feedback\" | \"project\" | \"reference\";\n description: string;\n body: string;\n}\n\nexport function extractFacts(summaryText: string): ExtractedFact[] {\n const jsonBlock = summaryText.match(/```(?:json)?\\s*\\n([\\s\\S]*?)\\n```/);\n if (!jsonBlock) return [];\n let parsed: unknown;\n try {\n parsed = JSON.parse(jsonBlock[1].trim());\n } catch {\n return [];\n }\n if (typeof parsed !== \"object\" || parsed === null) return [];\n const facts = (parsed as { facts?: unknown }).facts;\n if (!Array.isArray(facts)) return [];\n\n const out = new Map<string, ExtractedFact>();\n for (const raw of facts) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const r = raw as Record<string, unknown>;\n const name = typeof r.name === \"string\" ? r.name : \"\";\n const type = r.type;\n const description = typeof r.description === \"string\" ? r.description : \"\";\n const body = typeof r.body === \"string\" ? r.body : \"\";\n if (!name || !description || !body) continue;\n if (!/^[a-z0-9][a-z0-9-_]*$/i.test(name)) continue;\n if (type !== \"user\" && type !== \"feedback\" && type !== \"project\" && type !== \"reference\") continue;\n out.set(name, { name, type, description, body });\n }\n return [...out.values()];\n}\n\n/**\n * 把摘要文本里的 facts JSON 代码块剥掉,只留人类可读的摘要主体。\n * compactMessages 用此把\"干净摘要\"放回 messages,facts JSON 不污染对话。\n */\nexport function stripFactsBlock(summaryText: string): string {\n return summaryText\n .replace(/---\\s*\\n\\s*#?\\s*Extracted Facts[\\s\\S]*?```(?:json)?[\\s\\S]*?```/i, \"\")\n .replace(/```(?:json)?\\s*\\n[\\s\\S]*?\\n```/g, (match) => {\n // 仅剥 JSON 含 \"facts\" 的块,其他 code block 保留\n if (/\"facts\"\\s*:/.test(match)) return \"\";\n return match;\n })\n .trim();\n}\n","/**\n * 上下文管理:手动 / 自动压缩对话历史。\n *\n * 设计文档:muse-design.md §5.3 / 模块设计/上下文管理工程/设计.md §4.2 + §4.5。\n *\n * 算法:\n * 1. 找一个安全切割点 cutoff:cutoff 之前是 \"older\",之后是 \"recent\"\n * 2. 安全 = 不破坏 assistant 的 tool_use ↔ 紧随的 tool 消息 配对\n * (在 tool_use 之后但 tool result 之前切,会让 LLM 看到悬挂的 tool_use)\n * 3. older 拼成转录,调 LLM 摘要(I-2:9 节结构化 schema,带 facts JSON)\n * 4. 摘要剥 facts JSON 后包成一条 user message(\"[Previous conversation summary] ...\"),\n * 作为新历史的开头,后接 recent\n * 5. I-5:facts 经 MemoryPromote hook 后 writeMemory(trust=auto, source=compact-promote)\n *\n * Why user 角色而非 system:\n * - 系统提示 muse 已在 systemPrompt 单独管理;不污染它\n * - 用 user role 让 LLM 自然把它当成\"任务上下文\"继续推理\n */\n\nimport type { LLMClient } from \"../llm/types.js\";\nimport type { Message, AssistantMessage, ContentPart } from \"../types/index.js\";\nimport type { HooksConfig } from \"../preprocess/hooks.js\";\nimport { runHooks } from \"../preprocess/hooks.js\";\nimport { PipelineBlockedError } from \"../preprocess/pipeline.js\";\nimport {\n buildSummaryPrompt,\n extractFacts,\n stripFactsBlock,\n type ExtractedFact,\n type SummarySchema,\n} from \"./prompts/summarize.js\";\nimport { writeMemory } from \"./memory.js\";\n\nexport interface CompactOptions {\n llm: LLMClient;\n /** 保留最近 N 条原始消息不压缩。默认 4。 */\n keepRecent?: number;\n abortSignal?: AbortSignal;\n /** LLM 摘要流式过程中的字符进度回调(每个 text-delta 触发,传累计字符数)。 */\n onProgress?: (charsReceived: number) => void;\n /** PreCompact / PostCompact / MemoryPromote hooks 配置。 */\n hooks?: HooksConfig;\n /** I-2 schema 选择;默认 \"9-section\"。 */\n schema?: SummarySchema;\n /** I-5 联动:本次 compact 触发的 cwd,用于 writeMemory 写到正确项目下。\n * 未提供时跳过 facts 提取(纯摘要模式)。 */\n cwd?: string;\n /** I-5:是否自动把 facts 写入 memory(默认 true)。 */\n promoteFactsToMemory?: boolean;\n}\n\nexport class CompactBlockedError extends Error {\n constructor(public readonly reason: string) {\n super(`compact blocked by PreCompact hook: ${reason}`);\n this.name = \"CompactBlockedError\";\n }\n}\n\nexport interface CompactResult {\n newMessages: Message[];\n summary: string;\n originalCount: number;\n newCount: number;\n /** 没有可压缩内容时为 true,messages 原样返回。 */\n noop: boolean;\n /** I-5:被提取并尝试写入 memory 的 facts(可能被 hook block 部分)。 */\n promotedFacts?: PromotedFact[];\n}\n\nexport interface PromotedFact {\n name: string;\n type: ExtractedFact[\"type\"];\n description: string;\n /** 写入结果:\"saved\" / \"blocked\"(MemoryPromote hook 拒绝)/ \"failed\"(writeMemory 错)。 */\n status: \"saved\" | \"blocked\" | \"failed\";\n reason?: string;\n}\n\nexport async function compactMessages(\n messages: Message[],\n opts: CompactOptions,\n): Promise<CompactResult> {\n const keepRecent = opts.keepRecent ?? 4;\n const cutoff = findSafeCutoff(messages, keepRecent);\n\n if (cutoff <= 0) {\n return {\n newMessages: messages,\n summary: \"\",\n originalCount: messages.length,\n newCount: messages.length,\n noop: true,\n };\n }\n\n // PreCompact hook(可 block / 用于审计)\n try {\n await runHooks(\n \"PreCompact\",\n { messageCount: messages.length, cutoff, keepRecent },\n opts.hooks,\n );\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n throw new CompactBlockedError(err.reason);\n }\n throw err;\n }\n\n const older = messages.slice(0, cutoff);\n const recent = messages.slice(cutoff);\n const schema: SummarySchema = opts.schema ?? \"9-section\";\n const rawSummary = await summarizeConversation(\n older,\n opts.llm,\n schema,\n opts.abortSignal,\n opts.onProgress,\n );\n\n // I-2:剥 facts JSON 块,留人类可读摘要主体\n const summary = stripFactsBlock(rawSummary);\n const facts = opts.cwd ? extractFacts(rawSummary) : [];\n\n const summaryMessage: Message = {\n role: \"user\",\n content:\n `[Previous conversation summary]\\n\\n${summary}\\n\\n` +\n `[End of summary. The conversation continues below.]`,\n };\n\n const newMessages: Message[] = [summaryMessage, ...recent];\n\n // PostCompact hook(不阻断)\n try {\n await runHooks(\n \"PostCompact\",\n { before: messages.length, after: newMessages.length, summary, factCount: facts.length },\n opts.hooks,\n );\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n // PostCompact 不允许 block;降级为 no-op\n } else {\n throw err;\n }\n }\n\n // I-5:把 facts 写入 memory(每条走 MemoryPromote hook 审核;失败不阻塞 compact)\n let promotedFacts: PromotedFact[] | undefined;\n const shouldPromote = opts.promoteFactsToMemory !== false && opts.cwd && facts.length > 0;\n if (shouldPromote) {\n promotedFacts = await promoteFactsToMemory(facts, opts.cwd!, opts.hooks);\n }\n\n return {\n newMessages,\n summary,\n originalCount: messages.length,\n newCount: newMessages.length,\n noop: false,\n promotedFacts,\n };\n}\n\n/**\n * I-5:把 ExtractedFact 列表写入 long-term memory。\n *\n * 行为:\n * - 每条独立处理(失败不影响下一条)\n * - MemoryPromote hook 可 block:该条标记 status=blocked + reason\n * - writeMemory 异常:status=failed + reason\n * - 成功:status=saved,trust=auto + source=compact-promote\n */\nasync function promoteFactsToMemory(\n facts: ExtractedFact[],\n cwd: string,\n hooks: HooksConfig | undefined,\n): Promise<PromotedFact[]> {\n const results: PromotedFact[] = [];\n for (const fact of facts) {\n try {\n await runHooks(\n \"MemoryPromote\",\n { name: fact.name, type: fact.type, description: fact.description, body: fact.body, source: \"compact-promote\" },\n hooks,\n );\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n results.push({\n name: fact.name,\n type: fact.type,\n description: fact.description,\n status: \"blocked\",\n reason: err.reason,\n });\n continue;\n }\n results.push({\n name: fact.name,\n type: fact.type,\n description: fact.description,\n status: \"failed\",\n reason: err instanceof Error ? err.message : String(err),\n });\n continue;\n }\n try {\n await writeMemory(cwd, {\n name: fact.name,\n description: fact.description,\n type: fact.type,\n body: fact.body,\n trust: \"auto\",\n source: \"compact-promote\",\n });\n results.push({ name: fact.name, type: fact.type, description: fact.description, status: \"saved\" });\n } catch (err) {\n results.push({\n name: fact.name,\n type: fact.type,\n description: fact.description,\n status: \"failed\",\n reason: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return results;\n}\n\n/**\n * 从理想切点(messages.length - keepRecent)向前找最近的安全边界。\n * 安全边界 = user 消息(自然 turn 起点),且其之前不存在悬挂的 tool_use。\n *\n * 退化策略:找不到合法切点 → 返回 0(不压缩)。\n */\nexport function findSafeCutoff(messages: Message[], keepRecent: number): number {\n if (messages.length <= keepRecent) return 0;\n const ideal = Math.max(0, messages.length - keepRecent);\n\n for (let i = ideal; i > 0; i--) {\n if (messages[i].role !== \"user\") continue;\n if (hasUnresolvedToolUse(messages.slice(0, i))) continue;\n return i;\n }\n return 0;\n}\n\n/** older 段是否有 assistant.tool_use 但缺对应 tool 消息。 */\nfunction hasUnresolvedToolUse(older: Message[]): boolean {\n const seenToolUseIds = new Set<string>();\n const seenToolResultIds = new Set<string>();\n for (const msg of older) {\n if (msg.role === \"assistant\") {\n for (const part of msg.content) {\n if (part.type === \"tool_use\") seenToolUseIds.add(part.id);\n }\n } else if (msg.role === \"tool\") {\n seenToolResultIds.add(msg.toolUseId);\n }\n }\n for (const id of seenToolUseIds) {\n if (!seenToolResultIds.has(id)) return true;\n }\n return false;\n}\n\nasync function summarizeConversation(\n older: Message[],\n llm: LLMClient,\n schema: SummarySchema,\n abortSignal?: AbortSignal,\n onProgress?: (chars: number) => void,\n): Promise<string> {\n const transcript = renderTranscript(older);\n const prompt: Message[] = [\n {\n role: \"user\",\n content: buildSummaryPrompt(transcript, schema),\n },\n ];\n\n let text = \"\";\n for await (const ev of llm.stream({ messages: prompt, abortSignal })) {\n if (ev.type === \"text\") {\n text += ev.delta;\n onProgress?.(text.length);\n } else if (ev.type === \"error\") throw ev.error;\n }\n return text.trim() || \"(empty summary)\";\n}\n\nfunction renderTranscript(messages: Message[]): string {\n const lines: string[] = [];\n for (const msg of messages) {\n switch (msg.role) {\n case \"system\":\n lines.push(`[system]\\n${msg.content}\\n`);\n break;\n case \"user\":\n lines.push(`[user]\\n${typeof msg.content === \"string\" ? msg.content : flattenContent(msg.content)}\\n`);\n break;\n case \"assistant\":\n lines.push(`[assistant]\\n${renderAssistant(msg)}\\n`);\n break;\n case \"tool\":\n lines.push(`[tool result${msg.isError ? \" ERROR\" : \"\"}]\\n${msg.content}\\n`);\n break;\n }\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderAssistant(msg: AssistantMessage): string {\n const parts: string[] = [];\n for (const part of msg.content) {\n if (part.type === \"text\") parts.push(part.text);\n else if (part.type === \"tool_use\") {\n parts.push(`<tool_call name=\"${part.name}\" args=${JSON.stringify(part.args)} />`);\n }\n }\n return parts.join(\"\\n\");\n}\n\nfunction flattenContent(parts: ContentPart[]): string {\n const out: string[] = [];\n for (const p of parts) {\n if (p.type === \"text\") out.push(p.text);\n else if (p.type === \"file\") out.push(`[file: ${p.path}]`);\n else if (p.type === \"image\") out.push(`[image: ${p.path ?? p.mediaType}]`);\n }\n return out.join(\"\\n\");\n}\n","/**\n * trim-history stage:基于 token 预算的滑动窗口/优先级裁剪。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.3;模块设计/上下文管理工程/设计.md §4.1。\n * ADR #3:触发阈值 budget × 0.8,裁剪到 budget × 0.6 以下停手(2026-06-07 拍板)。\n *\n * 策略:\n * 1. 估算总 prompt token(systemPrompt + messages + tools)\n * 2. 未超阈值 → 写 estimatedTokens 后 no-op\n * 3. 超阈值:\n * - 保第一条 user(initial task,通常是用户原始诉求)\n * - 找一个安全切点 keepStart 使得 [0] + [keepStart..end] 落入 0.6 budget\n * - 安全切点 = 不破坏 tool_use ↔ tool_result 配对(复用 findSafeCutoff)\n * - **保护 user 消息原文**(2026-06-07 I-1 修):被 cutoff 段内的所有 user 消息\n * 提取出来按原顺序排在 messages[0] 之后,只把 assistant + tool result 压成一条\n * marker。理由:对齐业界共识\"用户消息不可丢\"(详见调研报告 §3.1.2)\n *\n * 不污染 agent.messages:替换 ctx.messages 整体引用,不就地 splice/mutate。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { RequestCtx } from \"./ctx.js\";\nimport type { Message } from \"../../types/index.js\";\nimport { countMessages } from \"../tokenize.js\";\nimport { findSafeCutoff } from \"../../loop/context.js\";\n\nconst DEFAULT_TRIM_RATIO = 0.8;\nconst TARGET_RATIO = 0.6;\nconst MIN_KEEP_RECENT = 4;\nconst MAX_KEEP_RECENT = 24;\n\nexport class TrimHistoryStage implements PipelineStage<RequestCtx> {\n readonly name = \"trim-history\";\n\n skip(ctx: RequestCtx): boolean {\n if (ctx.settings.trimHistory?.enabled === false) return true;\n // 没有 contextWindow 信息无法计算预算,直接跳过(默认是 200k,但只用于\n // 显式配置时才裁;不配则视作\"模型方自己处理\"不动)\n if (!ctx.services.contextWindow) return true;\n return false;\n }\n\n run(ctx: RequestCtx): void {\n const budget = ctx.services.contextWindow!;\n const trimRatio = ctx.settings.trimHistory?.budgetRatio ?? DEFAULT_TRIM_RATIO;\n const triggerAt = budget * trimRatio;\n const targetAt = budget * TARGET_RATIO;\n\n const initial = countMessages(ctx.messages, ctx.systemPrompt, ctx.tools);\n ctx.estimatedTokens = initial;\n if (initial <= triggerAt) return;\n\n const trimmed = trimMessages(ctx.messages, targetAt, ctx.systemPrompt, ctx.tools);\n if (trimmed === ctx.messages) return;\n\n ctx.messages = trimmed;\n ctx.estimatedTokens = countMessages(trimmed, ctx.systemPrompt, ctx.tools);\n }\n}\n\n/**\n * 从小 keepRecent 起步(裁得激进),命中 target 后返回。\n *\n * 为什么不从大 keepRecent 起手:大 keepRecent 对应 cutoff 很小(甚至 cutoff=1),\n * 此时 [messages[0], marker, ...slice(1)] 反而比原 messages 多 1 条 marker —\n * 没起到裁剪作用还增加 token。\n *\n * MIN_TRIM_COUNT 保底:cutoff 必须 >= 2(至少裁掉 2 条原 message),否则视作没裁。\n *\n * 返回新数组(不就地 mutate);裁不下来时返原数组。\n */\nconst MIN_TRIM_COUNT = 2;\n\nexport function trimMessages(\n messages: Message[],\n targetTokens: number,\n systemPrompt: string,\n tools: import(\"../../types/index.js\").ToolDefinition[],\n): Message[] {\n if (messages.length <= MIN_KEEP_RECENT + 2) return messages;\n\n let bestTrimmed: Message[] | undefined;\n\n // 从激进(小 keepRecent)往保守(大 keepRecent)走;命中 target 立刻 return\n for (let keepRecent = MIN_KEEP_RECENT; keepRecent <= MAX_KEEP_RECENT; keepRecent++) {\n if (keepRecent >= messages.length - 1) break;\n const cutoff = findSafeCutoff(messages, keepRecent);\n if (cutoff < MIN_TRIM_COUNT) continue;\n\n const trimmed = buildTrimmedWithUserProtection(messages, cutoff);\n const tokens = countMessages(trimmed, systemPrompt, tools);\n if (tokens <= targetTokens) return trimmed;\n // 没命中但记下最激进的尝试,作为兜底\n if (!bestTrimmed) bestTrimmed = trimmed;\n }\n\n // 所有 keepRecent 都裁不到 target 以下 — 返回最激进的那次(已是最大努力)\n return bestTrimmed ?? messages;\n}\n\n/**\n * 构造 trim 后的 messages 数组,保护 user 消息原文。\n *\n * 输入:原始 messages + 安全切点 cutoff(messages[0..cutoff-1] 被压缩,\n * messages[cutoff..] 原样保留)\n * 输出:[messages[0], ...被压段内所有 user 消息原文, marker, ...messages[cutoff..]]\n *\n * marker 说明被吃掉了多少 assistant turn + tool result,让 LLM 知道有上下文丢失但\n * 用户消息全保。\n */\nfunction buildTrimmedWithUserProtection(messages: Message[], cutoff: number): Message[] {\n const middle = messages.slice(1, cutoff);\n const preservedUsers: Message[] = [];\n let assistantTurns = 0;\n let toolResults = 0;\n for (const m of middle) {\n if (m.role === \"user\") preservedUsers.push(m);\n else if (m.role === \"assistant\") assistantTurns++;\n else if (m.role === \"tool\") toolResults++;\n }\n\n const parts: string[] = [];\n if (assistantTurns > 0) parts.push(`${assistantTurns} assistant turn${assistantTurns === 1 ? \"\" : \"s\"}`);\n if (toolResults > 0) parts.push(`${toolResults} tool result${toolResults === 1 ? \"\" : \"s\"}`);\n const userNote =\n preservedUsers.length > 0\n ? ` The ${preservedUsers.length} user message${preservedUsers.length === 1 ? \"\" : \"s\"} from that range ${preservedUsers.length === 1 ? \"is\" : \"are\"} preserved above for context.`\n : \"\";\n const markerText =\n parts.length > 0\n ? `[System note: ${parts.join(\" and \")} from earlier in this conversation were trimmed to fit the context window.${userNote}]`\n : `[System note: earlier conversation trimmed to fit context window.${userNote}]`;\n const marker: Message = { role: \"user\", content: markerText };\n\n return [messages[0], ...preservedUsers, marker, ...messages.slice(cutoff)];\n}\n","/**\n * budget-guard stage:trim-history 后兜底。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.4。\n * 触发阈值:budget × 0.95(trim 后仍超 → 调 compact;原设计默认值)。\n *\n * 顺序约束:必须排在 trim-history 之后。trim-history 已经裁掉一波又写好了\n * ctx.estimatedTokens,本 stage 只做最后的兜底。\n *\n * 失败处理:\n * - 未配 services.compact 而又超阈值 → 抛 BudgetExceededError\n * - compact 调用抛错 → 包成 BudgetExceededError\n * - compact 成功但还超阈值 → 也抛 BudgetExceededError(意味着光 compact 也救不回来,\n * 需要用户介入)\n * Agent 捕获 BudgetExceededError → onError 报告给用户,turn 结束。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { RequestCtx } from \"./ctx.js\";\nimport { countMessages } from \"../tokenize.js\";\n\nconst DEFAULT_GUARD_RATIO = 0.95;\n\nexport class BudgetExceededError extends Error {\n constructor(\n public readonly estimated: number,\n public readonly budget: number,\n public readonly reason: string,\n ) {\n super(`context budget exceeded: estimated ${estimated} > budget ${budget} (${reason})`);\n this.name = \"BudgetExceededError\";\n }\n}\n\nexport class BudgetGuardStage implements PipelineStage<RequestCtx> {\n readonly name = \"budget-guard\";\n\n skip(ctx: RequestCtx): boolean {\n if (ctx.settings.budgetGuard?.enabled === false) return true;\n if (!ctx.services.contextWindow) return true;\n return false;\n }\n\n async run(ctx: RequestCtx): Promise<void> {\n const budget = ctx.services.contextWindow!;\n const guardRatio = ctx.settings.budgetGuard?.budgetRatio ?? DEFAULT_GUARD_RATIO;\n const triggerAt = budget * guardRatio;\n\n // trim-history 已经写了 estimatedTokens;若未写则现场算一次\n let estimated = ctx.estimatedTokens ?? countMessages(ctx.messages, ctx.systemPrompt, ctx.tools);\n ctx.estimatedTokens = estimated;\n if (estimated <= triggerAt) return;\n\n if (!ctx.services.compact) {\n throw new BudgetExceededError(estimated, budget, \"no compact available and over 0.95 budget\");\n }\n\n let compacted: import(\"../../types/index.js\").Message[];\n try {\n compacted = await ctx.services.compact(ctx.services.abortSignal);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new BudgetExceededError(estimated, budget, `compact failed: ${msg}`);\n }\n\n ctx.messages = compacted;\n estimated = countMessages(compacted, ctx.systemPrompt, ctx.tools);\n ctx.estimatedTokens = estimated;\n if (estimated > triggerAt) {\n throw new BudgetExceededError(\n estimated,\n budget,\n \"still over 0.95 budget after compact — context unrecoverable\",\n );\n }\n }\n}\n","/**\n * RequestPipeline 上下文。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2.1。\n */\n\nimport type { Message, ToolDefinition } from \"../../types/index.js\";\nimport type { PermissionMode } from \"../../permission/index.js\";\nimport type { TodoStore } from \"../../loop/todos.js\";\nimport type { ToolRegistry } from \"../../tools/registry.js\";\nimport type { HierarchyLayer } from \"../../loop/hierarchy.js\";\nimport type { MemoryIndex } from \"../../loop/memory-index.js\";\n\nexport interface RequestPreprocessSettings {\n trimHistory?: { enabled?: boolean; budgetRatio?: number };\n budgetGuard?: { enabled?: boolean; budgetRatio?: number };\n redact?: { enabled?: boolean };\n /** I-3 stale tool result clearing。默认开,keepRecentTurns=3,clearTools=[Read/Grep/Glob]。 */\n clearStaleToolResults?: {\n enabled?: boolean;\n keepRecentTurns?: number;\n clearTools?: string[];\n };\n}\n\nexport interface RequestServices {\n todos: TodoStore;\n /** 已加载的 MEMORY.md 索引(由 app/cli 在 turn 前刷新一次后注入)。 */\n memoryIndex: string;\n /** 已加载的 hierarchy(MUSE.md / AGENTS.md 5 层)。II-1 引入。 */\n hierarchy?: HierarchyLayer[];\n /** 已构建的 memory 向量索引(II-5,settings.memory.embedding.enabled=true 时由 caller 注入)。 */\n memoryEmbeddingIndex?: MemoryIndex;\n /** memory.embedding.topK 配置;默认 5。 */\n memoryEmbeddingTopK?: number;\n /** memory.embedding.minMemoryCount;少于此值退化到全注入。默认 3(2026-06-07 R5 修订)。 */\n memoryEmbeddingMinCount?: number;\n /** memory.embedding.maxInjectTokens;注入预算上限,超出按 trust 优先级保留。默认 1500。 */\n memoryEmbeddingMaxInjectTokens?: number;\n /** 工具注册中心,用于 toLLMDefinitions + tool 元数据。 */\n toolRegistry: ToolRegistry;\n /** 输出语言。 */\n lang?: \"en\" | \"zh-CN\";\n /** Provider 名(用于 system prompt 拼装)。 */\n provider: string;\n /** SessionStart hook 返回的额外 system prompt 片段(append 到 base 末尾)。 */\n extraSystemPrompt?: string;\n /** 当前模型可见上下文窗口(token 数);trim-history / budget-guard 用。\n * 未提供时这两个 stage 自动 skip。 */\n contextWindow?: number;\n /** 主动触发上下文压缩(budget-guard 用)。\n * 返回压缩后的新 messages。Agent 注入时会同步更新 agent.messages。\n * 抛错 = 压缩失败(LLM 调用失败 / hook block / 无可压缩内容等)。 */\n compact?: (abortSignal?: AbortSignal) => Promise<import(\"../../types/index.js\").Message[]>;\n /** 本轮 abortSignal,透给 compact 用。 */\n abortSignal?: AbortSignal;\n}\n\nexport interface RequestCtx {\n /** 当前 messages 数组(可变;stage 直接修改)。 */\n messages: Message[];\n /** 当前系统提示(stage 内累积拼装)。 */\n systemPrompt: string;\n /** 当前可见工具列表(plan 模式过滤后)。 */\n tools: ToolDefinition[];\n /** 模型 ID。 */\n modelId: string;\n /** 当前 PermissionMode。 */\n mode: PermissionMode;\n /** 估算的 prompt token 数;BudgetGuard 写入,后续 stage 可读。 */\n estimatedTokens?: number;\n /** settings.preprocess.request 配置。 */\n settings: RequestPreprocessSettings;\n /** 关联 services。 */\n services: RequestServices;\n /** 工作目录。 */\n cwd: string;\n}\n\nexport function createRequestCtx(init: {\n messages: Message[];\n modelId: string;\n mode: PermissionMode;\n cwd: string;\n services: RequestServices;\n settings?: RequestPreprocessSettings;\n}): RequestCtx {\n return {\n messages: init.messages,\n systemPrompt: \"\",\n tools: [],\n modelId: init.modelId,\n mode: init.mode,\n cwd: init.cwd,\n services: init.services,\n settings: init.settings ?? {},\n };\n}\n","/**\n * RequestPipeline 装配。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2。\n *\n * Stage 顺序:\n * build-system-prompt → inject-memory → inject-todos → apply-mode-filter\n * → trim-history → budget-guard\n *\n * trim-history / budget-guard 排最末:前面所有 stage 注入的内容(memory/todos/\n * tools schema)都参与 token 估算后再决定是否裁/压缩。\n *\n * redact 留 v0.2.x(P2,设计文档 §八)。\n */\n\nimport { Pipeline, type PipelineRunOptions } from \"../pipeline.js\";\nimport { BuildSystemPromptStage } from \"./build-system-prompt.js\";\nimport { InjectMemoryStage } from \"./inject-memory.js\";\nimport { InjectTodosStage } from \"./inject-todos.js\";\nimport { ApplyModeFilterStage } from \"./apply-mode-filter.js\";\nimport { ClearStaleToolResultsStage } from \"./clear-stale-tool-results.js\";\nimport { TrimHistoryStage } from \"./trim-history.js\";\nimport { BudgetGuardStage } from \"./budget-guard.js\";\nimport type { RequestCtx } from \"./ctx.js\";\n\nexport type { RequestCtx, RequestServices, RequestPreprocessSettings } from \"./ctx.js\";\nexport { createRequestCtx } from \"./ctx.js\";\nexport { BudgetExceededError } from \"./budget-guard.js\";\n\nexport function RequestPipeline(opts: PipelineRunOptions = {}): Pipeline<RequestCtx> {\n return new Pipeline<RequestCtx>(\n [\n new BuildSystemPromptStage(),\n new InjectMemoryStage(),\n new ClearStaleToolResultsStage(), // I-3:折叠可重获取的旧 tool result(在 trim/budget 之前)\n new InjectTodosStage(),\n new ApplyModeFilterStage(),\n new TrimHistoryStage(),\n new BudgetGuardStage(),\n ],\n { ...opts, pipelineName: \"request\" },\n );\n}\n","/**\n * Agent loop:单循环 ReAct。\n *\n * loop:\n * RequestPipeline.run(ctx) — 拼装 systemPrompt + tools(stage 化预处理)\n * llm.stream(messages, tools)\n * → emit text → 累计 assistant 消息\n * → 收到 tool_call → 累计\n * → finish\n * if no tool_calls: break\n * for each tool_call:\n * PreToolUse hook(可阻断 / 改写 args)\n * check permission → execute\n * ResultPipeline.run(ctx) — 截断 / 检测二进制 / summary / 错误归一化\n * PostToolUse hook(可改写 content / summary)\n * push tool result\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.2 / §4.3。\n */\n\nimport type { LLMClient, LLMEvent } from \"../llm/types.js\";\nimport type { Message, AssistantMessage, ContentPart, ToolUsePart, TokenUsage } from \"../types/index.js\";\nimport type { ToolRegistry } from \"../tools/registry.js\";\nimport type { ToolContext, ToolExecuteResult } from \"../tools/types.js\";\nimport type { PermissionGate, Decision, PermissionDecision } from \"../permission/index.js\";\nimport type { Session } from \"../session/jsonl.js\";\nimport { TodoStore } from \"./todos.js\";\nimport { log } from \"../log/index.js\";\nimport type { Pipeline } from \"../preprocess/pipeline.js\";\nimport { PipelineBlockedError } from \"../preprocess/pipeline.js\";\nimport type { RequestCtx, RequestServices } from \"../preprocess/request/index.js\";\nimport { createRequestCtx, BudgetExceededError } from \"../preprocess/request/index.js\";\nimport { countMessages } from \"../preprocess/tokenize.js\";\nimport { compactMessages } from \"./context.js\";\nimport { findProjectRoot, loadSubdirMemory } from \"./hierarchy.js\";\nimport { upsertMemoryEntry, removeMemoryEntry } from \"./memory-index.js\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { ResultCtx, ResultPreprocessSettings } from \"../preprocess/result/index.js\";\nimport { createResultCtx } from \"../preprocess/result/index.js\";\nimport type { HooksConfig } from \"../preprocess/hooks.js\";\nimport { runHooks } from \"../preprocess/hooks.js\";\nimport type { PreprocessLogger } from \"../preprocess/types.js\";\n\n/**\n * 合并 0..N 个 AbortSignal:任一 aborted → 返回的 signal aborted。\n * 全 undefined 时返 undefined,保持 LLM stream 的\"无中断\"行为不变。\n */\nfunction combineSignals(...signals: Array<AbortSignal | undefined>): AbortSignal | undefined {\n const live = signals.filter((s): s is AbortSignal => !!s);\n if (live.length === 0) return undefined;\n if (live.length === 1) return live[0];\n const combined = new AbortController();\n for (const s of live) {\n if (s.aborted) {\n combined.abort(s.reason);\n break;\n }\n s.addEventListener(\"abort\", () => combined.abort(s.reason), { once: true });\n }\n return combined.signal;\n}\n\n/**\n * 判断是否 AbortError(node fetch / execa / undici / spec / Vercel SDK 几种风格都覆盖)。\n *\n * 之前用 name === \"AbortError\" 漏检了 Vercel AI SDK 在 abort 时抛的\n * \"This operation was aborted\" 错(name 是 APICallError / DOMException 等),\n * 加 message 关键字兜底。\n */\nfunction isAbortError(err: unknown): boolean {\n if (!err) return false;\n if (err instanceof Error) {\n if (err.name === \"AbortError\") return true;\n const code = (err as Error & { code?: string }).code;\n if (code === \"ABORT_ERR\" || code === \"ECANCELED\") return true;\n const msg = err.message.toLowerCase();\n if (msg.includes(\"aborted\") || msg.includes(\"cancelled\") || msg.includes(\"canceled\")) return true;\n }\n return false;\n}\n\nexport interface AgentEvents {\n onText?: (delta: string) => void;\n onToolCallStart?: (id: string, name: string) => void;\n onToolCallArgs?: (id: string, args: unknown) => void;\n onToolResult?: (id: string, name: string, content: string, isError: boolean, summary?: string) => void;\n onPermissionRequest?: (toolName: string, args: unknown, summary: string) => Promise<PermissionDecision>;\n onAskQuestions?: (\n questions: import(\"../tools/builtin/ask-user-question.js\").AskQuestion[],\n ) => Promise<import(\"../tools/builtin/ask-user-question.js\").AskQuestionResponse[]>;\n onUsage?: (usage: TokenUsage) => void;\n /**\n * 流式开始前 chars/4 估算 input tokens,推给 UI 让 StatusLine/ctx 立刻显示。\n * 与 onUsage 解耦:这是\"本轮 ctx 占用快照\"信号,不应进 session 累计(避免重复计费)。\n * 真实 finish usage 到达时 onUsage 会再用真实 inputTokens **覆盖**(不是累加)turn 快照。\n */\n onEstimate?: (inputTokens: number) => void;\n /**\n * 队列里的 guidance 被 inject 进 messages 数组后触发(在新一轮 LLM stream 启动**之前**)。\n * UI 用来清空\"待引导\"小框 — 内容已经\"上车\"了,不再 pending。\n */\n onGuidanceInjected?: (parts: ContentPart[]) => void;\n onError?: (error: Error) => void;\n /**\n * 一段 assistant 流结束、assistantMessage 已 push 进 messages,但工具还没开始执行时触发。\n * 用于 UI 立刻把这一批 tool_use calls 显示出来——避免\"流完 → 第一个 result 到达\"\n * 之间用户面对空屏。turn 直接结束(无 tool calls)的场景不会触发,走 onTurnEnd。\n */\n onAssistantTurn?: () => void;\n onTurnEnd?: () => void;\n /** Pipeline 被 hook 阻断 / 致命错误时触发。 */\n onBlocked?: (reason: string) => void;\n}\n\nexport interface AgentContext {\n llm: LLMClient;\n tools: ToolRegistry;\n permissions: PermissionGate;\n session: Session;\n cwd: string;\n /**\n * Legacy system prompt(向后兼容 runOneShot / 测试)。\n * 与 requestPipeline 互斥:有 pipeline 时优先 pipeline,无 pipeline 时回退到 systemPrompt + 内置 mode filter。\n */\n systemPrompt?: string;\n /** 注入式预处理:每轮 LLM 请求前跑。 */\n requestPipeline?: Pipeline<RequestCtx>;\n /** 与 requestPipeline 配套的 services(memoryIndex / provider / lang 等)。 */\n requestServices?: RequestServices;\n /** 工具结果后处理 pipeline。 */\n resultPipeline?: Pipeline<ResultCtx>;\n /** result pipeline 的运行时设置(每轮统一)。 */\n resultSettings?: ResultPreprocessSettings;\n /** 用户配置的 hooks(MVP 只跑 PreToolUse / PostToolUse)。 */\n hooks?: HooksConfig;\n /** 预处理日志器,串到 pino。 */\n hookLogger?: PreprocessLogger;\n /** Pipeline disable 列表(来自 settings.preprocess.disable)。 */\n pipelineDisable?: ReadonlyArray<string>;\n abortSignal?: AbortSignal;\n events?: AgentEvents;\n /** 注入式 TodoStore:与 requestServices.todos 共享同一实例。 */\n todos?: TodoStore;\n}\n\nexport class Agent {\n private messages: Message[] = [];\n readonly todos: TodoStore;\n /** 本轮 stream 发出时的 input tokens 估算值;finish 真实 usage 回来时减去,补差量给 UI。\n * 为什么:OpenAI 兼容 stream 的 usage 只在 finish 下发,期间 StatusLine 拿不到 token 数;\n * 先用 chars/4 估算并即刻推一次 onUsage,流式中就能显示 \"↑ N tokens\",真实值到达时无缝覆盖。 */\n private lastEstimateInputTokens = 0;\n /** 当前轮次的 abort signal(runTurn 开始时设,结束清);runToolCall 读它给 execa 等用。 */\n private turnAbortSignal?: AbortSignal;\n /**\n * \"引导(guidance)\"队列:模型还在跑时用户继续输入的内容暂存这里。\n * 主循环每轮 stream 启动前 check + flush;合并成一条 role:user 注入 messages,\n * 让 LLM 在下一轮看到\"已跑完的 tool result + 用户新输入\"一起决策。\n *\n * 注入点:工具批跑完、下一轮 LLM stream 之前。**不打断**正在跑的工具,避免模型\n * 因丢失中间结果而重跑(用户原话:\"不应该直接终止某一个小的命令或者工具执行\")。\n *\n * Esc 单击时若队列非空,优先清队列(轻撤销),还有空也不 abort turn。\n */\n private pendingGuidance: ContentPart[][] = [];\n\n /**\n * II-1.3 子目录惰性加载状态:已注入过子目录 MUSE.md / AGENTS.md 的绝对路径集合。\n *\n * tool 操作触及未加载过的子目录(包含 MUSE.md 或 AGENTS.md)时,把内容附加到 tool result\n * prefix,让 LLM 看到该子目录的 guidance。同一子目录只注入一次(去重)。\n *\n * /clear 调 clearLoadedSubdirs() 重置;/resume 不重置(假设旧 session 已加载过)。\n */\n private loadedSubdirs = new Set<string>();\n private readonly projectRoot: string;\n\n constructor(private ctx: AgentContext) {\n this.todos = ctx.todos ?? new TodoStore();\n this.projectRoot = findProjectRoot(ctx.cwd);\n }\n\n /** 给 /clear 等场景重置子目录加载状态。 */\n clearLoadedSubdirs(): void {\n this.loadedSubdirs.clear();\n }\n\n /** 估算 input tokens:走 src/preprocess/tokenize.ts(js-tiktoken cl100k_base)。\n * 比旧 chars/4 精度高,trim-history / budget-guard 也共享同一个估算口径。 */\n private estimateInputTokens(\n messages: Message[],\n systemPrompt: string,\n tools: import(\"../types/index.js\").ToolDefinition[],\n ): number {\n return countMessages(messages, systemPrompt, tools);\n }\n\n getMessages(): Message[] {\n return this.messages;\n }\n\n setMessages(msgs: Message[]): void {\n this.messages = msgs;\n }\n\n /**\n * 把一段\"引导\"内容塞进队列。下一轮 stream 启动前会被合并成一条 role:user 注入 messages。\n * 调用方:App 的 handleSubmit 在 state.status !== \"idle\" 时走这条路径。\n */\n enqueueGuidance(content: string | ContentPart[]): void {\n const parts: ContentPart[] = typeof content === \"string\"\n ? [{ type: \"text\", text: content }]\n : content;\n this.pendingGuidance.push(parts);\n }\n\n /** 用户单击 Esc 时若队列非空,清掉(轻撤销;不 abort 当前 turn)。 */\n clearGuidance(): void {\n this.pendingGuidance.length = 0;\n }\n\n getPendingGuidanceCount(): number {\n return this.pendingGuidance.length;\n }\n\n /**\n * 把当前 pendingGuidance 合并成一条 role:user message push 进 messages,清空队列。\n * 多条 guidance 之间用空行分隔(模型把它们读成\"一次性补充的几点\")。\n * 返回 true 表示真的注入了内容;false 表示队列本就空。\n */\n private flushGuidance(): boolean {\n if (this.pendingGuidance.length === 0) return false;\n const queued = this.pendingGuidance;\n this.pendingGuidance = [];\n\n // 合并:每条 guidance 是 ContentPart[];多条之间塞一段分隔 text。\n // 优先合并所有相邻 text part 成一段(避免一堆零散 part 在 LLM 端看起来怪)。\n const merged: ContentPart[] = [];\n const SEP = \"\\n\\n---\\n\\n\";\n for (let i = 0; i < queued.length; i++) {\n const parts = queued[i];\n if (i > 0) {\n // 分隔符尽量并入前一段 text 末尾\n const tail = merged[merged.length - 1];\n if (tail && tail.type === \"text\") tail.text += SEP;\n else merged.push({ type: \"text\", text: SEP });\n }\n for (const p of parts) {\n const tail = merged[merged.length - 1];\n if (p.type === \"text\" && tail && tail.type === \"text\") {\n tail.text += p.text;\n } else {\n // 浅拷贝避免外部突变影响 messages\n merged.push({ ...p });\n }\n }\n }\n\n const guidanceMsg: Message = { role: \"user\", content: merged };\n this.messages.push(guidanceMsg);\n this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: guidanceMsg });\n this.ctx.events?.onGuidanceInjected?.(merged);\n return true;\n }\n\n /**\n * 执行一次完整的\"用户输入 → 助手响应(含工具循环) → 等待下一轮输入\"。\n *\n * userInput 可以是:\n * - string:纯文本(向后兼容,无附件场景)\n * - ContentPart[]:多 part 内容(text + file/image 附件)\n *\n * abortSignal:本轮专属信号(每轮新建,App.handleSubmit 传入);Esc 触发 abort\n * 时立刻打断 LLM stream + execa 工具 + 等待循环。优先级高于 ctx.abortSignal\n * (后者是进程级 / 启动时签名,用于全局退出)。\n */\n async runTurn(userInput: string | ContentPart[], abortSignal?: AbortSignal): Promise<void> {\n const turnSignal = combineSignals(abortSignal, this.ctx.abortSignal);\n this.turnAbortSignal = turnSignal;\n const userMessage: Message = { role: \"user\", content: userInput };\n this.messages.push(userMessage);\n await this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: userMessage });\n\n // 内部循环:工具调用可能多轮\n while (true) {\n // 上一轮 tool 跑完(或 turn 刚开始)→ stream 启动前 flush guidance 队列。\n // 注入点:已落到 messages 的\"tool_result 序列\"之后 + 下一轮 stream 之前,\n // 这样 LLM 在 prompt 里看到的就是「上轮工具结果 + 用户新输入」,顺势继续推进\n // 而不会因为消息丢失重跑刚才的工具。\n this.flushGuidance();\n\n let systemPrompt: string;\n let tools: import(\"../types/index.js\").ToolDefinition[];\n let messagesForStream: Message[];\n try {\n const built = await this.buildRequest();\n systemPrompt = built.systemPrompt;\n tools = built.tools;\n messagesForStream = built.messages;\n } catch (err) {\n // budget-guard 抛 BudgetExceededError → 报给用户,turn 结束\n if (err instanceof BudgetExceededError) {\n this.ctx.events?.onError?.(err);\n log.error(\"budget exceeded\", { msg: err.message });\n this.turnAbortSignal = undefined;\n return;\n }\n throw err;\n }\n\n // PreLLMRequest hook 可改写 messages / systemPrompt / tools 或 block\n try {\n const hookOut = await runHooks(\n \"PreLLMRequest\",\n { messages: this.messages, systemPrompt, tools, modelId: this.ctx.llm.model },\n this.ctx.hooks,\n this.ctx.hookLogger,\n );\n if (typeof hookOut.systemPrompt === \"string\") systemPrompt = hookOut.systemPrompt;\n if (Array.isArray(hookOut.messages)) messagesForStream = hookOut.messages as Message[];\n if (Array.isArray(hookOut.tools)) tools = hookOut.tools as import(\"../types/index.js\").ToolDefinition[];\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n this.ctx.events?.onBlocked?.(err.reason);\n this.ctx.events?.onError?.(new Error(`PreLLMRequest blocked: ${err.reason}`));\n return;\n }\n throw err;\n }\n\n // 流式开始前用 chars/4 估算 input tokens 即刻推给 UI,让 StatusLine 立刻显示。\n // 走 onEstimate(不是 onUsage)避免污染 session 累计计费;finish 真实 usage 到达后\n // 上层 reducer 会用真实 inputTokens 覆盖本轮 ctx 快照(不累加)。\n const estimate = this.estimateInputTokens(messagesForStream, systemPrompt, tools);\n this.lastEstimateInputTokens = estimate;\n this.ctx.events?.onEstimate?.(estimate);\n\n const stream = this.ctx.llm.stream({\n messages: messagesForStream,\n tools,\n systemPrompt,\n abortSignal: turnSignal,\n });\n\n const assistantParts: ContentPart[] = [];\n const toolCallsToRun: ToolUsePart[] = [];\n let lastError: Error | undefined;\n\n try {\n for await (const ev of stream) {\n this.handleEvent(ev, assistantParts, toolCallsToRun, (e) => {\n lastError = e;\n });\n if (lastError) break;\n if (turnSignal?.aborted) break;\n }\n } catch (err) {\n if (isAbortError(err) || turnSignal?.aborted) {\n // Esc 触发的优雅中断:保留已生成的 assistant 文本 + 任何已完成的 tool_use 在 history,\n // 但**不**进入工具执行环节(toolCallsToRun 直接清空)。让 UI 看到\"我已经说了一半\"。\n this.persistInterruptedAssistant(assistantParts);\n this.ctx.events?.onTurnEnd?.();\n this.turnAbortSignal = undefined;\n return;\n }\n throw err;\n }\n\n if (lastError) {\n this.ctx.events?.onError?.(lastError);\n log.error(\"agent stream error\", { msg: lastError.message });\n this.turnAbortSignal = undefined;\n return;\n }\n\n // Esc 在 stream loop 内 break 但未抛错(turnSignal.aborted)\n if (turnSignal?.aborted) {\n this.persistInterruptedAssistant(assistantParts);\n this.ctx.events?.onTurnEnd?.();\n this.turnAbortSignal = undefined;\n return;\n }\n\n // 把 assistant 消息加入历史\n const assistantMessage: AssistantMessage = { role: \"assistant\", content: assistantParts };\n this.messages.push(assistantMessage);\n await this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: assistantMessage });\n\n // PostLLMResponse hook(不阻断,仅审计 / 镜像;返回值忽略)\n const assistantText = assistantParts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\");\n const toolCalls = toolCallsToRun.map((t) => ({ id: t.id, name: t.name, args: t.args }));\n try {\n await runHooks(\n \"PostLLMResponse\",\n { assistantText, toolCalls },\n this.ctx.hooks,\n this.ctx.hookLogger,\n );\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n log.warn(\"PostLLMResponse tried to block, ignored\", { reason: err.reason });\n } else {\n throw err;\n }\n }\n\n if (toolCallsToRun.length === 0) {\n // 模型刚说完一段 text 没要工具——本该 turn 结束。但若用户在生成期间塞了 guidance\n // 进队列,把\"结束\"折叠成\"继续下一轮\":循环顶上 flushGuidance 会把它注入成新的\n // user message,LLM 在新一轮 stream 里基于\"刚答完的内容 + 用户追问\"自然推进。\n if (this.pendingGuidance.length > 0) continue;\n this.ctx.events?.onTurnEnd?.();\n this.turnAbortSignal = undefined;\n return;\n }\n\n // 流刚结束、tool 还没跑——给 UI 一个钩子立刻展示这一批 calls\n this.ctx.events?.onAssistantTurn?.();\n\n // 执行工具调用;每个工具开始前再检查 abort,避免 stream 中断后还硬跑工具。\n // 每个工具跑完后 yield 一次 event loop:让 React commit + Ink paint 完成,\n // 避免快速本地工具(ls/cat 等 ~30ms)让 React 18 auto-batching 把多次 history_set\n // 合并成单次 commit——那样用户会错过 active row 切换的全部中间帧。\n for (const call of toolCallsToRun) {\n if (turnSignal?.aborted) {\n this.recordToolResult(call.id, call.name, `Interrupted by user (Esc).`, true);\n } else {\n await this.runToolCall(call);\n await new Promise<void>((resolve) => setImmediate(resolve));\n }\n }\n // 工具循环跑完后若已 abort,本轮直接收尾,不再开新一轮 LLM stream\n if (turnSignal?.aborted) {\n this.ctx.events?.onTurnEnd?.();\n this.turnAbortSignal = undefined;\n return;\n }\n }\n }\n\n /** 拼装本轮 system prompt + tools(+ 可能 trim 后的 messages)。\n * 优先走 RequestPipeline,无 pipeline 时回退到 legacy 路径。\n *\n * 注意:trim-history 可能替换 ctx.messages,这里把它回流出去给主循环作为\n * messagesForStream。**不污染** this.messages — 因为 trim 是临时为本次请求\n * 做的窗口缩减,真正的历史不动(budget-guard 触发的 compact 例外:那是\n * 通过 services.compact 真实写回 this.messages 的)。 */\n private async buildRequest(): Promise<{\n systemPrompt: string;\n tools: import(\"../types/index.js\").ToolDefinition[];\n messages: Message[];\n }> {\n if (this.ctx.requestPipeline && this.ctx.requestServices) {\n const ctx = createRequestCtx({\n messages: this.messages,\n modelId: this.ctx.llm.model,\n mode: this.ctx.permissions.getMode(),\n cwd: this.ctx.cwd,\n services: {\n ...this.ctx.requestServices,\n todos: this.todos,\n contextWindow: this.ctx.llm.capabilities.maxContextWindow,\n abortSignal: this.turnAbortSignal,\n // compact 闭包:budget-guard 触发时调用。真实改写 this.messages\n // (compact 是历史压缩,不可逆,要落到 agent state)。\n compact: async (signal) => {\n // I-5 联动:传 cwd 触发 facts 自动 promote 到 long-term memory\n const result = await compactMessages(this.messages, {\n llm: this.ctx.llm,\n abortSignal: signal,\n hooks: this.ctx.hooks,\n cwd: this.ctx.cwd,\n });\n this.messages = result.newMessages;\n // II-5 联动:把成功 promote 的 facts upsert 到 in-memory 向量索引(session 内立即可召回)\n if (result.promotedFacts && this.ctx.requestServices?.memoryEmbeddingIndex) {\n for (const f of result.promotedFacts) {\n if (f.status !== \"saved\") continue;\n try {\n await upsertMemoryEntry(this.ctx.requestServices.memoryEmbeddingIndex, f.name, \"project\");\n } catch (err) {\n log.warn(\"memory index upsert (compact-promote) failed\", { name: f.name, msg: (err as Error).message });\n }\n }\n }\n return this.messages;\n },\n },\n });\n await this.ctx.requestPipeline.run(ctx);\n return { systemPrompt: ctx.systemPrompt, tools: ctx.tools, messages: ctx.messages };\n }\n // Legacy fallback\n const mode = this.ctx.permissions.getMode();\n const tools = this.ctx.tools.toLLMDefinitions(\n mode === \"plan\" ? (t) => t.permission === \"read\" : undefined,\n );\n const todoSection = this.todos.toPromptSection();\n const base = this.ctx.systemPrompt ?? \"\";\n const systemPrompt = todoSection ? `${base}\\n\\n${todoSection}` : base;\n return { systemPrompt, tools, messages: this.messages };\n }\n\n private handleEvent(\n ev: LLMEvent,\n assistantParts: ContentPart[],\n toolCallsToRun: ToolUsePart[],\n onError: (e: Error) => void,\n ): void {\n switch (ev.type) {\n case \"text\":\n {\n const last = assistantParts[assistantParts.length - 1];\n if (last && last.type === \"text\") {\n last.text += ev.delta;\n } else {\n assistantParts.push({ type: \"text\", text: ev.delta });\n }\n }\n this.ctx.events?.onText?.(ev.delta);\n break;\n\n case \"tool_call_start\":\n this.ctx.events?.onToolCallStart?.(ev.id, ev.name);\n break;\n\n case \"tool_call_complete\": {\n const callPart: ToolUsePart = { type: \"tool_use\", id: ev.id, name: ev.name, args: ev.args };\n assistantParts.push(callPart);\n toolCallsToRun.push(callPart);\n this.ctx.events?.onToolCallArgs?.(ev.id, ev.args);\n break;\n }\n\n case \"finish\":\n if (ev.usage) {\n // 推 delta:已经通过 estimate 注入了 lastEstimateInputTokens,这里只补 (real - estimate);\n // outputTokens 没估算过,直接推真实值。\n const adjusted: TokenUsage = {\n inputTokens: ev.usage.inputTokens - this.lastEstimateInputTokens,\n outputTokens: ev.usage.outputTokens,\n totalTokens: ev.usage.totalTokens - this.lastEstimateInputTokens,\n };\n this.ctx.events?.onUsage?.(adjusted);\n this.ctx.session.append({\n type: \"usage\",\n time: new Date().toISOString(),\n usage: ev.usage, // session 写真实值,不写 estimate\n provider: this.ctx.llm.providerName,\n model: this.ctx.llm.model,\n });\n }\n this.lastEstimateInputTokens = 0; // 不论 usage 是否回都复位,下一轮 stream 重新估\n break;\n\n case \"error\":\n onError(ev.error);\n break;\n }\n }\n\n /** Esc 中断时:把\"已经流出来\"的 assistant 内容存进 history,标 [interrupted] 后缀。 */\n private persistInterruptedAssistant(parts: ContentPart[]): void {\n const cleanedParts: ContentPart[] = parts.filter((p) => p.type !== \"tool_use\");\n // 在最后一段 text 末尾追加 [interrupted] 标识;无 text 时新建一段\n const lastIdx = cleanedParts.length - 1;\n if (lastIdx >= 0 && cleanedParts[lastIdx].type === \"text\") {\n const t = cleanedParts[lastIdx] as { type: \"text\"; text: string };\n cleanedParts[lastIdx] = { type: \"text\", text: `${t.text}\\n\\n[interrupted]` };\n } else {\n cleanedParts.push({ type: \"text\", text: \"[interrupted]\" });\n }\n const assistantMessage: AssistantMessage = { role: \"assistant\", content: cleanedParts };\n this.messages.push(assistantMessage);\n this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: assistantMessage });\n }\n\n private async runToolCall(call: ToolUsePart): Promise<void> {\n const tool = this.ctx.tools.get(call.name);\n if (!tool) {\n const result = `Tool \"${call.name}\" is not available.`;\n this.recordToolResult(call.id, call.name, result, true);\n return;\n }\n\n const summary = tool.summarize?.(call.args) ?? `${call.name}(...)`;\n const decision: Decision = this.ctx.permissions.decide({\n toolName: call.name,\n args: call.args,\n permission: tool.permission,\n });\n\n if (decision === \"deny\") {\n const reason =\n this.ctx.permissions.getMode() === \"plan\"\n ? `Denied: you are in plan mode. Only read-only tools are available. Propose changes instead of executing.`\n : `Denied by policy: ${call.name}.`;\n this.recordToolResult(call.id, call.name, reason, true);\n return;\n }\n if (decision === \"ask\") {\n const userDecision =\n (await this.ctx.events?.onPermissionRequest?.(call.name, call.args, summary)) ?? \"no\";\n if (userDecision === \"no\") {\n this.recordToolResult(call.id, call.name, `User rejected ${call.name}.`, true);\n return;\n }\n if (userDecision === \"session_allow\") {\n this.ctx.permissions.allowForSession(call.name);\n }\n }\n\n // PreToolUse hook 可改写 args 或阻断\n let effectiveArgs = call.args;\n try {\n const hookOut = await runHooks(\n \"PreToolUse\",\n { toolName: call.name, args: effectiveArgs },\n this.ctx.hooks,\n this.ctx.hookLogger,\n );\n if (hookOut.args !== undefined) effectiveArgs = hookOut.args;\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n this.ctx.events?.onBlocked?.(err.reason);\n this.recordToolResult(call.id, call.name, `Blocked by PreToolUse hook: ${err.reason}`, true);\n return;\n }\n throw err;\n }\n\n const toolCtx: ToolContext = {\n cwd: this.ctx.cwd,\n abortSignal: this.turnAbortSignal ?? this.ctx.abortSignal,\n askPermission: async () => true, // 已在外层处理\n todos: this.todos,\n askQuestions: this.ctx.events?.onAskQuestions\n ? (qs) => this.ctx.events!.onAskQuestions!(qs)\n : undefined,\n };\n\n const raw: ToolExecuteResult = await this.ctx.tools.execute(call.name, effectiveArgs, toolCtx);\n\n // ResultPipeline 后处理 + PostToolUse hook\n const processed = await this.postProcessResult({\n toolName: call.name,\n toolUseId: call.id,\n args: effectiveArgs,\n raw,\n });\n\n this.recordToolResult(\n call.id,\n call.name,\n processed.content,\n processed.isError,\n processed.summary,\n processed.diff,\n processed.kind,\n );\n }\n\n private async postProcessResult(input: {\n toolName: string;\n toolUseId: string;\n args: unknown;\n raw: ToolExecuteResult;\n }): Promise<{ content: string; isError: boolean; summary?: string; diff?: string; kind?: \"success\" | \"error\" | \"warn\" }> {\n let content = input.raw.content;\n let summary = input.raw.summary;\n let diff = input.raw.diff;\n const isError = input.raw.isError ?? false;\n let kind = input.raw.kind;\n\n if (this.ctx.resultPipeline) {\n const rctx = createResultCtx({\n toolName: input.toolName,\n toolUseId: input.toolUseId,\n args: input.args,\n raw: input.raw,\n settings: this.ctx.resultSettings,\n });\n try {\n await this.ctx.resultPipeline.run(rctx);\n content = rctx.content;\n summary = rctx.summary;\n diff = rctx.diff;\n } catch (err) {\n log.warn(\"result pipeline error\", { msg: (err as Error).message });\n }\n }\n\n // PostToolUse hook(默认不阻断,仅改写 content / summary)\n try {\n const hookOut = await runHooks(\n \"PostToolUse\",\n { toolName: input.toolName, args: input.args, content, summary, isError },\n this.ctx.hooks,\n this.ctx.hookLogger,\n );\n if (typeof hookOut.content === \"string\") content = hookOut.content;\n if (typeof hookOut.summary === \"string\") summary = hookOut.summary;\n } catch (err) {\n if (err instanceof PipelineBlockedError) {\n // PostToolUse 不允许阻断;降级为告警\n log.warn(\"PostToolUse hook tried to block, ignored\", { reason: err.reason });\n } else {\n throw err;\n }\n }\n\n // II-5:MemoryWrite 完成后,如果当前 session 有 memoryEmbeddingIndex,\n // 触发增量 upsert 让本轮新 memory 立即可召回(避免要等下次 muse 启动)\n if (input.toolName === \"MemoryWrite\" && !isError) {\n const index = this.ctx.requestServices?.memoryEmbeddingIndex;\n if (index) {\n try {\n const args = input.args as { name?: string; scope?: string } | null | undefined;\n const name = typeof args?.name === \"string\" ? args.name : undefined;\n const scope = args?.scope === \"user\" ? \"user\" : \"project\";\n if (name) {\n await upsertMemoryEntry(index, name, scope);\n }\n } catch (err) {\n log.warn(\"memory index upsert failed\", { msg: (err as Error).message });\n }\n }\n }\n\n // II-1.3 子目录惰性加载:tool 操作触及未加载子目录(有 MUSE.md / AGENTS.md)\n // 时,把子目录内容附加到 result content 前面,让 LLM 看到该子目录的额外约束。\n try {\n const subdirInjection = await this.maybeInjectSubdirHierarchy(input.toolName, input.args);\n if (subdirInjection) {\n content = `${subdirInjection}\\n\\n---\\n\\n[Original tool result]\\n${content}`;\n }\n } catch (err) {\n // 子目录加载失败不应阻塞工具结果;只记 warn\n log.warn(\"subdir hierarchy inject failed\", { msg: (err as Error).message });\n }\n\n return { content, isError, summary, diff, kind };\n }\n\n /**\n * 检查工具操作的路径是否落入未加载过的子目录;子目录(向上找最近的)若含 MUSE.md / AGENTS.md\n * 就把内容封装成 system 注释返回(由 caller 前置到 tool result)。\n */\n private async maybeInjectSubdirHierarchy(toolName: string, args: unknown): Promise<string | null> {\n const path = extractToolPath(toolName, args);\n if (!path) return null;\n const absPath = isAbsolute(path) ? path : resolve(this.ctx.cwd, path);\n const subdir = findContainingSubdirWithHierarchy(absPath, this.projectRoot);\n if (!subdir) return null;\n if (this.loadedSubdirs.has(subdir)) return null;\n this.loadedSubdirs.add(subdir);\n const loaded = await loadSubdirMemory(subdir);\n if (!loaded) return null;\n const relPath = relative(this.projectRoot, subdir) || \".\";\n const truncatedNote = loaded.truncated ? \" (content truncated; use Read to view full file)\" : \"\";\n return `[System: loaded ${loaded.source} from ${relPath}/${truncatedNote}]\\n${loaded.content}`;\n }\n\n private recordToolResult(\n id: string,\n name: string,\n content: string,\n isError: boolean,\n summary?: string,\n diff?: string,\n kind?: \"success\" | \"error\" | \"warn\",\n ): void {\n const toolMsg: Message = {\n role: \"tool\",\n toolUseId: id,\n content,\n isError,\n toolName: name,\n ...(diff ? { diff } : {}),\n ...(summary ? { summary } : {}),\n ...(kind ? { kind } : {}),\n };\n this.messages.push(toolMsg);\n this.ctx.session.append({ type: \"message\", time: new Date().toISOString(), message: toolMsg });\n this.ctx.events?.onToolResult?.(id, name, content, isError, summary);\n }\n}\n\n// ============================== II-1.3 子目录惰性 helpers ==============================\n\n/**\n * 从工具 args 提路径字段。\n * - Read / Edit / Write 用 file_path\n * - Grep / Glob 用 path(可选)\n * - Bash 命令字符串不可靠(可能含多路径,跳过)\n * - 其他工具不提路径(返 null)\n */\nexport function extractToolPath(toolName: string, args: unknown): string | null {\n if (typeof args !== \"object\" || args === null) return null;\n if (toolName === \"Read\" || toolName === \"Edit\" || toolName === \"Write\") {\n const fp = (args as { file_path?: unknown }).file_path;\n if (typeof fp === \"string\") return fp;\n }\n if (toolName === \"Grep\" || toolName === \"Glob\") {\n const p = (args as { path?: unknown }).path;\n if (typeof p === \"string\") return p;\n }\n return null;\n}\n\n/**\n * 从 absPath 的 dirname 开始向上找,直到 projectRoot(不含 root 本身) — 返回第一个\n * 含 MUSE.md 或 AGENTS.md 的目录绝对路径。找不到返 null。\n *\n * 不返回 projectRoot 本身:root 的 MUSE.md / AGENTS.md 已在启动时由 loadHierarchy 加载,\n * 不属于\"子目录惰性\"范围。\n */\nexport function findContainingSubdirWithHierarchy(absPath: string, projectRoot: string): string | null {\n const rel = relative(projectRoot, absPath);\n if (!rel || rel.startsWith(\"..\") || isAbsolute(rel)) return null; // 不在 root 下\n\n let cur = dirname(absPath);\n // 边界:cur 必须严格在 projectRoot 内部\n while (cur !== projectRoot && cur.startsWith(projectRoot)) {\n if (existsSync(join(cur, \"MUSE.md\")) || existsSync(join(cur, \"AGENTS.md\"))) {\n return cur;\n }\n const parent = dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n return null;\n}\n","/**\n * detect-binary:NUL 字节 / 非 ASCII 比例阈值检测,命中替换为占位说明。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.2。\n *\n * 阈值:NUL > 0 或 非 ASCII printable > 30%。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { ResultCtx } from \"./ctx.js\";\n\nconst SAMPLE_BYTES = 4096;\nconst NON_ASCII_RATIO = 0.3;\n\nexport class DetectBinaryStage implements PipelineStage<ResultCtx> {\n readonly name = \"detect-binary\";\n\n skip(ctx: ResultCtx): boolean {\n return ctx.settings.detectBinary?.enabled === false;\n }\n\n run(ctx: ResultCtx): void {\n const buf = Buffer.from(ctx.content, \"utf-8\");\n const len = Math.min(buf.byteLength, SAMPLE_BYTES);\n if (len === 0) return;\n let nul = 0;\n let nonPrintable = 0;\n for (let i = 0; i < len; i++) {\n const c = buf[i];\n if (c === 0) nul++;\n else if (c < 0x09 || (c > 0x0d && c < 0x20)) nonPrintable++;\n }\n const ratio = nonPrintable / len;\n if (nul > 0 || ratio > NON_ASCII_RATIO) {\n const reason = nul > 0 ? `contains ${nul} NUL bytes` : `${(ratio * 100).toFixed(1)}% non-printable bytes in sample`;\n ctx.binaryDetected = { reason, bytes: buf.byteLength };\n ctx.content = `[binary content suppressed: ${reason}; ${buf.byteLength} bytes]`;\n ctx.warnings.push({ stage: this.name, message: reason });\n }\n }\n}\n","/**\n * 统一截断算法。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §5.1。\n *\n * 默认策略:头 70% + 尾 30%,中间替换为 `... [omitted N bytes] ...`。\n * Why 头+尾:bash/grep 关键信息常在两端(开头声明、末尾错误),纯头部截断会丢错误码。\n */\n\nexport interface TruncateConfig {\n /** 字节预算(默认 64 × 1024)。 */\n budgetBytes?: number;\n /** 触发后保留头/尾的字节比例(默认 0.7 / 0.3)。 */\n headTailRatio?: [number, number];\n /** 截断 marker 文本工厂。 */\n marker?: (omitted: number) => string;\n /** 行边界对齐(默认 true,不切坏行)。 */\n alignToLine?: boolean;\n}\n\nexport interface TruncateResult {\n content: string;\n truncated: boolean;\n /** 被丢弃的字节数(按 utf-8 编码计)。 */\n omittedBytes: number;\n}\n\nconst DEFAULT_BUDGET = 64 * 1024;\nconst DEFAULT_RATIO: [number, number] = [0.7, 0.3];\nconst DEFAULT_MARKER = (omitted: number) => `\\n... [omitted ${omitted.toLocaleString()} bytes] ...\\n`;\n\nexport function truncate(content: string, cfg: TruncateConfig = {}): TruncateResult {\n const budget = cfg.budgetBytes ?? DEFAULT_BUDGET;\n const [headRatio, tailRatio] = cfg.headTailRatio ?? DEFAULT_RATIO;\n const marker = cfg.marker ?? DEFAULT_MARKER;\n const alignToLine = cfg.alignToLine ?? true;\n\n const bytes = Buffer.byteLength(content, \"utf-8\");\n if (bytes <= budget) {\n return { content, truncated: false, omittedBytes: 0 };\n }\n\n const markerStr = marker(bytes - budget);\n const markerBytes = Buffer.byteLength(markerStr, \"utf-8\");\n const available = Math.max(1024, budget - markerBytes);\n const headBudget = Math.floor(available * headRatio);\n const tailBudget = available - headBudget;\n\n let head = takePrefix(content, headBudget);\n let tail = takeSuffix(content, tailBudget);\n\n if (alignToLine) {\n const lastNL = head.lastIndexOf(\"\\n\");\n if (lastNL > headBudget * 0.5) head = head.slice(0, lastNL + 1);\n const firstNL = tail.indexOf(\"\\n\");\n if (firstNL >= 0 && firstNL < tail.length * 0.5) tail = tail.slice(firstNL);\n }\n\n const omitted = bytes - Buffer.byteLength(head, \"utf-8\") - Buffer.byteLength(tail, \"utf-8\");\n return {\n content: head + marker(Math.max(omitted, 0)) + tail,\n truncated: true,\n omittedBytes: Math.max(omitted, 0),\n };\n}\n\n/** 按字节预算从前往后取,不切坏 utf-8 多字节字符。 */\nfunction takePrefix(s: string, bytes: number): string {\n if (bytes <= 0) return \"\";\n const buf = Buffer.from(s, \"utf-8\");\n if (buf.byteLength <= bytes) return s;\n // 找一个不切坏 utf-8 的边界:回退到上一字符\n let cut = bytes;\n while (cut > 0 && (buf[cut] & 0xc0) === 0x80) cut--;\n return buf.subarray(0, cut).toString(\"utf-8\");\n}\n\n/** 按字节预算从后往前取。 */\nfunction takeSuffix(s: string, bytes: number): string {\n if (bytes <= 0) return \"\";\n const buf = Buffer.from(s, \"utf-8\");\n if (buf.byteLength <= bytes) return s;\n let cut = buf.byteLength - bytes;\n while (cut < buf.byteLength && (buf[cut] & 0xc0) === 0x80) cut++;\n return buf.subarray(cut).toString(\"utf-8\");\n}\n","/**\n * truncate:统一截断算法,字节预算 64KB / 工具,超出尾部加 marker。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.2、§5.1。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { truncate } from \"../truncate.js\";\nimport type { ResultCtx } from \"./ctx.js\";\n\nexport class TruncateStage implements PipelineStage<ResultCtx> {\n readonly name = \"truncate\";\n\n skip(ctx: ResultCtx): boolean {\n return ctx.binaryDetected != null;\n }\n\n run(ctx: ResultCtx): void {\n const budgetBytes = ctx.settings.truncate?.budgetBytes;\n const result = truncate(ctx.content, budgetBytes ? { budgetBytes } : {});\n if (!result.truncated) return;\n ctx.content = result.content;\n ctx.truncated = { omittedBytes: result.omittedBytes };\n ctx.warnings.push({\n stage: this.name,\n message: `Truncated ${result.omittedBytes} bytes`,\n });\n }\n}\n","/**\n * summarize:给长结果加一行 summary(规则化,不调 LLM)。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.2。\n *\n * 规则:\n * - Bash: 抽 exit code(已被 normalize-error / 工具内部填,可能已有 summary)\n * - Read: 行数\n * - Grep: 匹配数\n * - WebFetch: title(粗略)\n *\n * 仅在 ctx.summary 为空时填。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { ResultCtx } from \"./ctx.js\";\n\nexport class SummarizeStage implements PipelineStage<ResultCtx> {\n readonly name = \"summarize\";\n\n skip(ctx: ResultCtx): boolean {\n if (ctx.settings.summarize?.enabled === false) return true;\n return !!ctx.summary;\n }\n\n run(ctx: ResultCtx): void {\n const lines = ctx.content.split(\"\\n\");\n switch (ctx.toolName) {\n case \"Read\": {\n const content = lines.length > 0 ? lines.length : 0;\n ctx.summary = `Read ${content} lines`;\n break;\n }\n case \"Grep\": {\n // 粗略:非空行计为 match\n const matches = lines.filter((l) => l.trim().length > 0).length;\n ctx.summary = `Grep ${matches} match${matches === 1 ? \"\" : \"es\"}`;\n break;\n }\n case \"Bash\": {\n ctx.summary = ctx.raw.isError ? `Bash failed` : `Bash ok`;\n break;\n }\n case \"WebFetch\": {\n const titleLine = lines.find((l) => /^#\\s/.test(l));\n ctx.summary = titleLine ? titleLine.replace(/^#\\s*/, \"\").slice(0, 80) : `WebFetch ${lines.length} lines`;\n break;\n }\n case \"Glob\": {\n const files = lines.filter((l) => l.trim().length > 0).length;\n ctx.summary = `Glob ${files} file${files === 1 ? \"\" : \"s\"}`;\n break;\n }\n default:\n if (lines.length > 1) ctx.summary = `${ctx.toolName}: ${lines.length} lines`;\n }\n }\n}\n","/**\n * normalize-error:把工具错误归一为 { kind, message },内容顶部加一行 [error: <kind>] <message>。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.2、§5.3。\n *\n * 不丢弃原文,只前置一行提示,让 LLM 用稳定格式决策。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { ResultCtx, NormalizedError, NormalizedErrorKind } from \"./ctx.js\";\n\nexport class NormalizeErrorStage implements PipelineStage<ResultCtx> {\n readonly name = \"normalize-error\";\n\n skip(ctx: ResultCtx): boolean {\n if (ctx.settings.normalizeError?.enabled === false) return true;\n return !ctx.raw.isError;\n }\n\n run(ctx: ResultCtx): void {\n const kind = classifyError(ctx.content);\n const firstLine = ctx.content.split(\"\\n\").find((l) => l.trim().length > 0) ?? \"(no message)\";\n const message = firstLine.replace(/^Refused:\\s*/i, \"\").slice(0, 200);\n const normalized: NormalizedError = { kind, message, raw: ctx.content };\n ctx.normalizedError = normalized;\n const prefix = `[error: ${kind}] ${message}`;\n if (!ctx.content.startsWith(prefix)) {\n ctx.content = `${prefix}\\n${ctx.content}`;\n }\n }\n}\n\nfunction classifyError(text: string): NormalizedErrorKind {\n const lower = text.toLowerCase();\n if (/permission|denied|refused|forbidden|sensitive/.test(lower)) return \"permission\";\n if (/timeout|timed out|deadline/.test(lower)) return \"timeout\";\n if (/not found|enoent|no such file/.test(lower)) return \"not_found\";\n if (/ssrf|network|fetch failed|enotfound|econnrefused/.test(lower)) return \"network\";\n if (/binary|nul byte/.test(lower)) return \"binary\";\n return \"unknown\";\n}\n","/**\n * 敏感信息脱敏规则注册表。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §5.2。\n *\n * 与 src/tools/_sensitive.ts 并存不合并:\n * - _sensitive.ts = 路径硬拦截(不让工具读 .ssh/ 等)\n * - redact.ts = 内容模式扫描(扫到的 API key / token 替换为 [REDACTED])\n */\n\nexport interface RedactRule {\n name: string;\n pattern: RegExp;\n /** 替换文本工厂(默认 [REDACTED:<name>])。 */\n replacement?: (match: string) => string;\n}\n\nexport interface RedactResult {\n content: string;\n hits: Array<{ rule: string; count: number }>;\n}\n\nexport const DEFAULT_RULES: RedactRule[] = [\n { name: \"openai-key\", pattern: /sk-[A-Za-z0-9]{32,}/g },\n { name: \"anthropic-key\", pattern: /sk-ant-[A-Za-z0-9_\\-]{32,}/g },\n { name: \"github-pat\", pattern: /ghp_[A-Za-z0-9]{36}/g },\n { name: \"github-oauth\", pattern: /gho_[A-Za-z0-9]{36}/g },\n { name: \"github-app\", pattern: /(?:ghu|ghs)_[A-Za-z0-9]{36}/g },\n { name: \"google-api-key\", pattern: /AIza[0-9A-Za-z_\\-]{35}/g },\n { name: \"slack-token\", pattern: /xox[bpars]-[A-Za-z0-9-]{10,}/g },\n { name: \"aws-access-key\", pattern: /AKIA[0-9A-Z]{16}/g },\n { name: \"private-key-block\", pattern: /-----BEGIN [A-Z ]+PRIVATE KEY-----[\\s\\S]+?-----END [A-Z ]+PRIVATE KEY-----/g },\n];\n\nexport function redact(content: string, rules: ReadonlyArray<RedactRule> = DEFAULT_RULES): RedactResult {\n let out = content;\n const hits: Array<{ rule: string; count: number }> = [];\n for (const rule of rules) {\n let count = 0;\n out = out.replace(rule.pattern, (m) => {\n count++;\n return rule.replacement ? rule.replacement(m) : `[REDACTED:${rule.name}]`;\n });\n if (count > 0) hits.push({ rule: rule.name, count });\n }\n return { content: out, hits };\n}\n","/**\n * redact (ResultPipeline):扫工具结果 content 中的 secret pattern。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.2、§5.2。\n *\n * 默认开启:bash / read / webfetch 等工具的输出极易含密钥(.env、git diff\n * 误带 PEM、API 错误响应里回显的 token 等)。LLM 直接看到这些字符比 user\n * 误粘进输入还危险,因为它会原样 echo 进对话历史。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { redact } from \"../redact.js\";\nimport type { ResultCtx } from \"./ctx.js\";\n\nexport class RedactResultStage implements PipelineStage<ResultCtx> {\n readonly name = \"redact\";\n\n skip(ctx: ResultCtx): boolean {\n if (ctx.settings.redact?.enabled === false) return true;\n return ctx.binaryDetected != null;\n }\n\n run(ctx: ResultCtx): void {\n const { content, hits } = redact(ctx.content);\n if (hits.length === 0) return;\n ctx.content = content;\n const labels = hits.map((h) => `${h.count}× ${h.rule}`).join(\", \");\n ctx.warnings.push({ stage: this.name, message: `Redacted ${labels}` });\n // 在 summary 上加 [contains redacted] 提示\n if (ctx.summary) {\n if (!ctx.summary.includes(\"[contains redacted]\")) {\n ctx.summary = `${ctx.summary} [contains redacted]`;\n }\n } else {\n ctx.summary = `[contains redacted: ${labels}]`;\n }\n }\n}\n","/**\n * inject-diff:把 Edit/Write 等工具的 diff 拼到回灌给 LLM 的 content 末尾。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.2。\n *\n * 默认关闭:diff 仅进 UI(ctx.diff 字段不被消费到 content);开启时让 LLM\n * 看见自己改了什么,便于自检 / 下一步推理。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { diffHunksOnly } from \"../render/index.js\";\nimport type { ResultCtx } from \"./ctx.js\";\n\nexport class InjectDiffStage implements PipelineStage<ResultCtx> {\n readonly name = \"inject-diff\";\n\n skip(ctx: ResultCtx): boolean {\n if (ctx.settings.injectDiff !== true) return true;\n return !ctx.diff;\n }\n\n run(ctx: ResultCtx): void {\n if (!ctx.diff) return;\n const hunks = diffHunksOnly(ctx.diff).join(\"\\n\");\n ctx.content = `${ctx.content}\\n\\n--- diff ---\\n${hunks}`;\n }\n}\n","/**\n * ResultPipeline 上下文。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3.1。\n */\n\nimport type { ToolExecuteResult } from \"../../tools/types.js\";\n\nexport type NormalizedErrorKind = \"permission\" | \"timeout\" | \"not_found\" | \"network\" | \"binary\" | \"unknown\";\n\nexport interface NormalizedError {\n kind: NormalizedErrorKind;\n message: string;\n raw?: string;\n}\n\nexport interface ResultPreprocessSettings {\n truncate?: {\n /** 字节预算(默认 64KB)。 */\n budgetBytes?: number;\n };\n detectBinary?: {\n enabled?: boolean;\n };\n summarize?: {\n enabled?: boolean;\n };\n normalizeError?: {\n enabled?: boolean;\n };\n redact?: {\n /** 默认 true。 */\n enabled?: boolean;\n };\n /** inject-diff:把 diff 拼到 LLM 看见的 content 末尾(默认 false)。 */\n injectDiff?: boolean;\n}\n\nexport interface ResultCtx {\n /** 工具名(用于 stage skip 判断与 hook matcher)。 */\n toolName: string;\n /** 工具调用 ID,与 tool_use 配对。 */\n toolUseId: string;\n /** 工具调用参数(只读;用于 summarize 等 stage 判断)。 */\n args: unknown;\n /** 工具返回的原始结构。 */\n raw: ToolExecuteResult;\n /** stage 累积修改的 content(回灌给 LLM 的最终文本)。 */\n content: string;\n /** stage 累积修改的 summary(顶部一行展示)。 */\n summary?: string;\n /** stage 累积修改的 diff(只用于 UI,不进 LLM)。 */\n diff?: string;\n /** 检测到的二进制告警。 */\n binaryDetected?: { reason: string; bytes: number };\n /** stage 标的错误归一化结果。 */\n normalizedError?: NormalizedError;\n /** 截断信息(给 UI / 日志参考)。 */\n truncated?: { omittedBytes: number };\n /** stage 标的告警。 */\n warnings: Array<{ stage: string; message: string }>;\n settings: ResultPreprocessSettings;\n}\n\nexport function createResultCtx(init: {\n toolName: string;\n toolUseId: string;\n args: unknown;\n raw: ToolExecuteResult;\n settings?: ResultPreprocessSettings;\n}): ResultCtx {\n return {\n toolName: init.toolName,\n toolUseId: init.toolUseId,\n args: init.args,\n raw: init.raw,\n content: init.raw.content,\n summary: init.raw.summary,\n diff: init.raw.diff,\n warnings: [],\n settings: init.settings ?? {},\n };\n}\n","/**\n * ResultPipeline 装配。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.3。\n *\n * Stage 顺序:\n * detect-binary → truncate → summarize → normalize-error → redact → inject-diff\n *\n * - redact 默认开(2026-06-06 Phase 2 加入)\n * - inject-diff 默认关\n */\n\nimport { Pipeline, type PipelineRunOptions } from \"../pipeline.js\";\nimport { DetectBinaryStage } from \"./detect-binary.js\";\nimport { TruncateStage } from \"./truncate.js\";\nimport { SummarizeStage } from \"./summarize.js\";\nimport { NormalizeErrorStage } from \"./normalize-error.js\";\nimport { RedactResultStage } from \"./redact.js\";\nimport { InjectDiffStage } from \"./inject-diff.js\";\nimport type { ResultCtx } from \"./ctx.js\";\n\nexport type { ResultCtx, ResultPreprocessSettings, NormalizedError, NormalizedErrorKind } from \"./ctx.js\";\nexport { createResultCtx } from \"./ctx.js\";\n\nexport function ResultPipeline(opts: PipelineRunOptions = {}): Pipeline<ResultCtx> {\n return new Pipeline<ResultCtx>(\n [\n new DetectBinaryStage(),\n new TruncateStage(),\n new SummarizeStage(),\n new NormalizeErrorStage(),\n new RedactResultStage(),\n new InjectDiffStage(),\n ],\n { ...opts, pipelineName: \"result\" },\n );\n}\n","/**\n * Slash 命令注册表与解析器。\n */\n\nimport type { SlashCommand } from \"./types.js\";\n\nexport class SlashRegistry {\n private byName = new Map<string, SlashCommand>();\n private order: SlashCommand[] = [];\n\n register(cmd: SlashCommand): void {\n if (this.byName.has(cmd.name)) {\n throw new Error(`Duplicate slash command: /${cmd.name}`);\n }\n this.byName.set(cmd.name, cmd);\n this.order.push(cmd);\n for (const a of cmd.aliases ?? []) {\n if (!this.byName.has(a)) this.byName.set(a, cmd);\n }\n }\n\n registerAll(cmds: SlashCommand[]): void {\n for (const c of cmds) this.register(c);\n }\n\n get(name: string): SlashCommand | undefined {\n return this.byName.get(name);\n }\n\n list(): SlashCommand[] {\n return [...this.order];\n }\n}\n\nexport interface ParsedSlash {\n name: string;\n args: string;\n}\n\n/** \"/foo bar baz\" → { name: \"foo\", args: \"bar baz\" };非 slash 返回 null。 */\nexport function parseSlash(input: string): ParsedSlash | null {\n const trimmed = input.trim();\n if (!trimmed.startsWith(\"/\") || trimmed.length < 2) return null;\n const body = trimmed.slice(1);\n const space = body.search(/\\s/);\n if (space === -1) return { name: body, args: \"\" };\n return { name: body.slice(0, space), args: body.slice(space + 1).trim() };\n}\n","/**\n * slash-dispatch:识别 `/cmd args`,命中后短路 pipeline,交给 SlashRegistry。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { PipelineShortCircuit } from \"../pipeline.js\";\nimport { parseSlash } from \"../../slash/registry.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nexport class SlashDispatchStage implements PipelineStage<InputCtx> {\n readonly name = \"slash-dispatch\";\n run(ctx: InputCtx): void {\n const parsed = parseSlash(ctx.text);\n if (!parsed) return;\n ctx.slashCommand = { name: parsed.name, args: parsed.args };\n throw new PipelineShortCircuit(`slash:/${parsed.name}`);\n }\n}\n","/**\n * paste-expand:把 `[Pasted text #N +M lines]` 占位符还原为原文。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2。\n *\n * paste registry 由 BgTextInput 持有(用 ref);本 stage 通过构造函数注入。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nconst PASTE_PLACEHOLDER_RE = /\\[Pasted text #(\\d+) \\+\\d+ lines\\]/g;\n\nexport class PasteExpandStage implements PipelineStage<InputCtx> {\n readonly name = \"paste-expand\";\n\n constructor(private readonly registry: Map<number, string>) {}\n\n run(ctx: InputCtx): void {\n ctx.text = ctx.text.replace(PASTE_PLACEHOLDER_RE, (full, id) => {\n const text = this.registry.get(Number(id));\n return text ?? full;\n });\n }\n}\n\n/** 不接 paste registry 时的 noop 版本(单次 CLI / 单测用)。 */\nexport class NoopPasteExpandStage implements PipelineStage<InputCtx> {\n readonly name = \"paste-expand\";\n run(): void {}\n}\n","/**\n * at-file-expand:识别 `@<path>` 引用,读文件内容塞 attachments 作 FilePart;\n * 路径白名单过滤。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2。\n *\n * 协议层升级(2026-06-06):\n * - 旧:wrap `<file path=\"...\">…</file>` XML 拼到 ctx.text 末尾\n * - 新:仅 push FilePart 到 ctx.attachments;ctx.text 保留 `@<path>` 引用(供 LLM 上下文)\n *\n * 下游(buildUserMessage)负责把 attachments 与 text 组装成 ContentPart[];\n * LLM client 序列化时按 provider 能力决定 file part native 还是退化为 wrap text。\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { isAbsolute, resolve, extname } from \"node:path\";\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { checkSensitivePath } from \"../../tools/_sensitive.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nconst AT_PATTERN = /(?:^|\\s)@((?:\\/|\\.\\/|~\\/)[^\\s]+|[A-Za-z0-9_.\\-/]+)/g;\nconst DEFAULT_MAX_BYTES = 64 * 1024;\n// 图片由后续 at-image stage(Phase B)处理,这里跳过,避免按文本读坏。\nconst IMAGE_EXTS = new Set([\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\"]);\n\nexport class AtFileExpandStage implements PipelineStage<InputCtx> {\n readonly name = \"at-file-expand\";\n\n skip(ctx: InputCtx): boolean {\n return ctx.settings.atFileExpand?.enabled === false;\n }\n\n async run(ctx: InputCtx): Promise<void> {\n const maxBytes = ctx.settings.atFileExpand?.maxBytes ?? DEFAULT_MAX_BYTES;\n const refs = collectRefs(ctx.text);\n if (refs.length === 0) return;\n\n const seen = new Set<string>();\n for (const ref of refs) {\n const abs = toAbsolute(ref, ctx.cwd);\n if (seen.has(abs)) continue;\n seen.add(abs);\n\n // 图片走 Phase B 的 at-image stage,这里不动\n if (IMAGE_EXTS.has(extname(abs).toLowerCase())) continue;\n\n const sensitive = checkSensitivePath(abs);\n if (sensitive.blocked) {\n ctx.warnings.push({\n stage: this.name,\n message: `Skipped @${ref}: ${sensitive.reason}`,\n });\n continue;\n }\n\n try {\n const info = await stat(abs);\n if (!info.isFile()) {\n ctx.warnings.push({ stage: this.name, message: `@${ref}: not a regular file` });\n continue;\n }\n if (info.size > maxBytes) {\n ctx.warnings.push({\n stage: this.name,\n message: `@${ref}: file too large (${info.size} bytes > ${maxBytes})`,\n });\n continue;\n }\n const body = await readFile(abs, \"utf-8\");\n ctx.attachments.push({\n type: \"file\",\n path: abs,\n mimeType: guessMimeType(abs),\n text: body,\n });\n } catch (err) {\n ctx.warnings.push({\n stage: this.name,\n message: `@${ref}: ${(err as Error).message}`,\n });\n }\n }\n }\n}\n\nfunction collectRefs(text: string): string[] {\n const out: string[] = [];\n for (const m of text.matchAll(AT_PATTERN)) {\n out.push(m[1]);\n }\n return out;\n}\n\nfunction toAbsolute(ref: string, cwd: string): string {\n if (ref.startsWith(\"~/\")) {\n return resolve(process.env.HOME ?? \"\", ref.slice(2));\n }\n if (isAbsolute(ref)) return ref;\n return resolve(cwd, ref.replace(/^\\.\\//, \"\"));\n}\n\n/** 粗略 mime,不强约束;主要给 LLM 一个语义提示。 */\nfunction guessMimeType(path: string): string {\n const ext = extname(path).toLowerCase();\n switch (ext) {\n case \".ts\": case \".tsx\": return \"text/x-typescript\";\n case \".js\": case \".jsx\": case \".mjs\": case \".cjs\": return \"text/javascript\";\n case \".py\": return \"text/x-python\";\n case \".go\": return \"text/x-go\";\n case \".rs\": return \"text/x-rust\";\n case \".md\": return \"text/markdown\";\n case \".json\": return \"application/json\";\n case \".yaml\": case \".yml\": return \"text/yaml\";\n case \".toml\": return \"text/toml\";\n case \".html\": case \".htm\": return \"text/html\";\n case \".css\": return \"text/css\";\n case \".sh\": case \".bash\": case \".zsh\": return \"text/x-shellscript\";\n case \".sql\": return \"text/x-sql\";\n case \".xml\": return \"text/xml\";\n default: return \"text/plain\";\n }\n}\n","/**\n * 敏感文件路径默认 deny。设计文档 §12.3。\n *\n * 工具层做硬拦截(不通过 PermissionGate)。即使 settings.permissions.allow 加了 Read/Write,\n * 这层也兜底;用户要绕过必须在 PermissionGate 之外显式同意(v1.0 才考虑)。\n *\n * 规则:\n * - ~/.ssh (SSH 私钥 / known_hosts)\n * - ~/.aws (AWS 凭证)\n * - ~/.gnupg (GPG 私钥)\n * - ~/.kube/config (集群 token)\n * - .env / .env.* (任何位置的环境文件)\n * - id_rsa / id_ed25519 等私钥文件名\n */\n\nimport { homedir } from \"node:os\";\nimport { basename, resolve } from \"node:path\";\n\nconst HOME = homedir();\nconst SENSITIVE_DIRS = [\n resolve(HOME, \".ssh\"),\n resolve(HOME, \".aws\"),\n resolve(HOME, \".gnupg\"),\n resolve(HOME, \".config\", \"gh\"),\n];\nconst SENSITIVE_FILES = [\n resolve(HOME, \".kube\", \"config\"),\n resolve(HOME, \".netrc\"),\n resolve(HOME, \".pypirc\"),\n];\nconst SENSITIVE_BASENAMES = new Set([\n \"id_rsa\",\n \"id_ed25519\",\n \"id_ecdsa\",\n \"id_dsa\",\n]);\nconst ENV_PATTERN = /(?:^|\\/)\\.env(\\..+)?$/;\n\nexport interface SensitiveCheck {\n blocked: boolean;\n reason?: string;\n}\n\nexport function checkSensitivePath(path: string): SensitiveCheck {\n const abs = resolve(path);\n for (const dir of SENSITIVE_DIRS) {\n if (abs === dir || abs.startsWith(dir + \"/\")) {\n return { blocked: true, reason: `sensitive directory ${dir.replace(HOME, \"~\")}` };\n }\n }\n for (const f of SENSITIVE_FILES) {\n if (abs === f) return { blocked: true, reason: `sensitive file ${f.replace(HOME, \"~\")}` };\n }\n const base = basename(abs);\n if (SENSITIVE_BASENAMES.has(base)) {\n return { blocked: true, reason: `private key filename ${base}` };\n }\n if (ENV_PATTERN.test(abs)) {\n return { blocked: true, reason: `.env file (may contain secrets)` };\n }\n return { blocked: false };\n}\n","/**\n * at-image:识别 `@<path>` 中的图片引用(.png/.jpg/.jpeg/.gif/.webp),读 buffer→base64→push ImagePart。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2。\n *\n * 与 at-file-expand 平行:\n * - at-file-expand 跳过图片扩展名(只处理文本)\n * - at-image 只处理图片扩展名(读为 base64)\n *\n * 能力门:ctx.capabilities.supportsImages === false 时,识别但丢弃 + warning,\n * 不读 buffer(节省 IO + 不让大图浪费内存)。\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { basename, extname, isAbsolute, resolve } from \"node:path\";\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { checkSensitivePath } from \"../../tools/_sensitive.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nconst AT_PATTERN = /(?:^|\\s)@((?:\\/|\\.\\/|~\\/)[^\\s]+|[A-Za-z0-9_.\\-/]+)/g;\nconst DEFAULT_MAX_BYTES = 5 * 1024 * 1024; // 5MB\nconst IMAGE_EXTS: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\nexport class AtImageStage implements PipelineStage<InputCtx> {\n readonly name = \"at-image\";\n\n skip(ctx: InputCtx): boolean {\n return ctx.settings.atImage?.enabled === false;\n }\n\n async run(ctx: InputCtx): Promise<void> {\n const refs = collectRefs(ctx.text);\n if (refs.length === 0) return;\n\n const maxBytes = ctx.settings.atImage?.maxBytes ?? DEFAULT_MAX_BYTES;\n const supportsImages = ctx.capabilities?.supportsImages ?? false;\n const seen = new Set<string>();\n\n for (const ref of refs) {\n const abs = toAbsolute(ref, ctx.cwd);\n if (seen.has(abs)) continue;\n\n const ext = extname(abs).toLowerCase();\n const mediaType = IMAGE_EXTS[ext];\n if (!mediaType) continue; // 非图片,留给 at-file-expand 处理\n\n seen.add(abs);\n\n // 能力门:active model 不支持图片 → 直接 warning,不读 buffer\n if (!supportsImages) {\n ctx.warnings.push({\n stage: this.name,\n message: `@${basename(abs)}: active model does not support images; image skipped`,\n });\n continue;\n }\n\n const sensitive = checkSensitivePath(abs);\n if (sensitive.blocked) {\n ctx.warnings.push({\n stage: this.name,\n message: `Skipped @${ref}: ${sensitive.reason}`,\n });\n continue;\n }\n\n try {\n const info = await stat(abs);\n if (!info.isFile()) {\n ctx.warnings.push({ stage: this.name, message: `@${ref}: not a regular file` });\n continue;\n }\n if (info.size > maxBytes) {\n ctx.warnings.push({\n stage: this.name,\n message: `@${ref}: image too large (${info.size} bytes > ${maxBytes})`,\n });\n continue;\n }\n const buf = await readFile(abs);\n ctx.attachments.push({\n type: \"image\",\n mediaType,\n data: buf.toString(\"base64\"),\n path: abs,\n });\n } catch (err) {\n ctx.warnings.push({\n stage: this.name,\n message: `@${ref}: ${(err as Error).message}`,\n });\n }\n }\n }\n}\n\nfunction collectRefs(text: string): string[] {\n const out: string[] = [];\n for (const m of text.matchAll(AT_PATTERN)) {\n out.push(m[1]);\n }\n return out;\n}\n\nfunction toAbsolute(ref: string, cwd: string): string {\n if (ref.startsWith(\"~/\")) {\n return resolve(process.env.HOME ?? \"\", ref.slice(2));\n }\n if (isAbsolute(ref)) return ref;\n return resolve(cwd, ref.replace(/^\\.\\//, \"\"));\n}\n","/**\n * expand-image-placeholder:把 `[Image #N]` 占位符还原为 ImagePart attachment。\n *\n * 由 BgTextInput 的 onPasteImage 写入 image registry(in-memory),输入框只显示\n * `[Image #N]` 占位符;提交时本 stage 扫占位符 → 从 registry 取 → push ImagePart\n * + 从 text 中**移除**占位符。\n *\n * 与 at-image stage 平行:at-image 走 `@<path>` 引用读盘;本 stage 走 Cmd+V 剪贴板\n * 内存中转。两者最终都产出 ImagePart attachment。\n *\n * 能力门:capabilities.supportsImages=false 时,占位符仍移除(避免污染 LLM 文本),\n * 但不 push ImagePart,加 warning。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nconst PLACEHOLDER_RE = /\\[Image #(\\d+)\\]/g;\n\nexport class ExpandImagePlaceholderStage implements PipelineStage<InputCtx> {\n readonly name = \"expand-image-placeholder\";\n\n constructor(\n private readonly registry: Map<number, { data: Buffer; mediaType: \"image/png\" }>,\n ) {}\n\n run(ctx: InputCtx): void {\n const matches = [...ctx.text.matchAll(PLACEHOLDER_RE)];\n if (matches.length === 0) return;\n\n const supportsImages = ctx.capabilities?.supportsImages ?? false;\n const seen = new Set<number>();\n const dropped: number[] = []; // 因为能力 / 缺失被丢弃,占位符要留说明文本\n\n for (const m of matches) {\n const id = Number(m[1]);\n if (seen.has(id)) continue;\n seen.add(id);\n\n const entry = this.registry.get(id);\n if (!entry) {\n ctx.warnings.push({\n stage: this.name,\n message: `[Image #${id}]: not found in registry (already consumed?)`,\n });\n dropped.push(id);\n continue;\n }\n\n if (!supportsImages) {\n ctx.warnings.push({\n stage: this.name,\n message: `[Image #${id}]: active model does not support images; image skipped`,\n });\n dropped.push(id);\n continue;\n }\n\n ctx.attachments.push({\n type: \"image\",\n mediaType: entry.mediaType,\n data: entry.data.toString(\"base64\"),\n // path 借位存原占位符标签,UserMessage 渲染时直接显示这串作子项标识\n path: `[Image #${id}]`,\n });\n }\n\n // 成功消费的占位符**保留**在 text 里 — 让 UI 渲染时能在 user 消息里\n // 仍看到 `[Image #N]`(配合 MessageView 把 ImagePart 渲染为子项 `└ [Image #N]`),\n // 也让 LLM 知道用户在文本里 explicit 引用了哪张图。\n // 被丢弃的占位符替换为说明文本,避免\"text 全空让模型自由发挥\"。\n ctx.text = ctx.text\n .replace(PLACEHOLDER_RE, (full, idStr) => {\n const id = Number(idStr);\n if (!dropped.includes(id)) return full;\n return supportsImages\n ? `[image attachment unavailable]`\n : `[image attached by user, but current model does not support vision — ask the user to switch to a vision-capable model (e.g. mimo-v2.5) and resend]`;\n })\n .replace(/[ \\t]{2,}/g, \" \")\n .trim();\n }\n}\n\n/** registry 未注入时的 noop 版本(单测 / cli runOneShot 用)。 */\nexport class NoopExpandImagePlaceholderStage implements PipelineStage<InputCtx> {\n readonly name = \"expand-image-placeholder\";\n run(): void {}\n}\n","/**\n * template-expand:`{{env:VAR}}` / `{{cwd}}` / `{{date}}` 等模板插值。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2、§九-2。\n *\n * 白名单变量,绝不暴露任意 env(避免泄露 MUSE_ACTIVE_API_KEY)。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nconst ENV_WHITELIST = new Set([\"HOME\", \"USER\", \"SHELL\", \"LANG\"]);\nconst TEMPLATE_RE = /\\{\\{([a-zA-Z][a-zA-Z0-9_]*)(?::([A-Z_][A-Z0-9_]*))?\\}\\}/g;\n\nexport class TemplateExpandStage implements PipelineStage<InputCtx> {\n readonly name = \"template-expand\";\n\n skip(ctx: InputCtx): boolean {\n return ctx.settings.templateExpand?.enabled === false;\n }\n\n run(ctx: InputCtx): void {\n ctx.text = ctx.text.replace(TEMPLATE_RE, (full, key: string, sub?: string) => {\n switch (key) {\n case \"cwd\":\n return ctx.cwd;\n case \"date\":\n return new Date().toISOString().slice(0, 10);\n case \"env\":\n if (!sub || !ENV_WHITELIST.has(sub)) {\n ctx.warnings.push({\n stage: this.name,\n message: `{{env:${sub ?? \"\"}}}: var not in whitelist`,\n });\n return full;\n }\n return process.env[sub] ?? \"\";\n default:\n return full;\n }\n });\n }\n}\n","/**\n * validate-length:超过 maxChars(默认 32k)截断 + warning。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nconst DEFAULT_MAX_CHARS = 32 * 1024;\n\nexport class ValidateLengthStage implements PipelineStage<InputCtx> {\n readonly name = \"validate-length\";\n\n run(ctx: InputCtx): void {\n const maxChars = ctx.settings.maxChars ?? DEFAULT_MAX_CHARS;\n if (ctx.text.length <= maxChars) return;\n const omitted = ctx.text.length - maxChars;\n ctx.text = ctx.text.slice(0, maxChars) + `\\n... [truncated ${omitted} chars by validate-length]`;\n ctx.warnings.push({\n stage: this.name,\n message: `Input truncated: ${omitted} chars over ${maxChars} limit`,\n });\n }\n}\n","/**\n * redact-pre-scan:用 redact 规则扫用户输入,命中替换为 [REDACTED] + warning。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.2、§5.2。\n *\n * 这里默认开启:用户粘贴含 API key 的代码进 LLM 是高频风险点,先兜底再说。\n */\n\nimport type { PipelineStage } from \"../pipeline.js\";\nimport { redact } from \"../redact.js\";\nimport type { InputCtx } from \"./ctx.js\";\n\nexport class RedactPreScanStage implements PipelineStage<InputCtx> {\n readonly name = \"redact-pre-scan\";\n\n skip(ctx: InputCtx): boolean {\n return ctx.settings.redactPreScan?.enabled === false;\n }\n\n run(ctx: InputCtx): void {\n const { content, hits } = redact(ctx.text);\n if (hits.length === 0) return;\n ctx.text = content;\n for (const hit of hits) {\n ctx.warnings.push({\n stage: this.name,\n message: `Redacted ${hit.count}× ${hit.rule}`,\n });\n }\n }\n}\n","/**\n * InputPipeline 上下文。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1.1。\n */\n\nimport type { PermissionMode } from \"../../permission/index.js\";\nimport type { FilePart, ImagePart } from \"../../types/index.js\";\n\n/** InputPipeline 累积的附件:作为独立 ContentPart 输出,不再 XML wrap 到 text。 */\nexport type InputAttachment = FilePart | ImagePart;\n\nexport interface InputWarning {\n stage: string;\n message: string;\n}\n\nexport interface InputSlashCommand {\n name: string;\n args: string;\n}\n\nexport interface InputPreprocessSettings {\n atFileExpand?: {\n enabled?: boolean;\n /** 单文件上限(字节)。 */\n maxBytes?: number;\n };\n atImage?: {\n enabled?: boolean;\n /** 单图上限(字节,base64 前)。默认 5MB。 */\n maxBytes?: number;\n };\n templateExpand?: {\n enabled?: boolean;\n };\n /** 用户消息总字符上限(超出截断 + warning)。默认 32768。 */\n maxChars?: number;\n redactPreScan?: {\n enabled?: boolean;\n };\n}\n\n/** Active model 的能力描述,由 caller 在创建 InputCtx 时注入。 */\nexport interface InputCapabilities {\n /** 当前 model 是否能消费 image part。false 时 at-image stage skip + warning。 */\n supportsImages?: boolean;\n}\n\nexport interface InputCtx {\n /** 用户原始输入(已展开 paste 占位符)。 */\n raw: string;\n /** stage 之间累计修改的当前值。 */\n text: string;\n /** 来源。 */\n source: \"tty\" | \"stdin\" | \"argv\";\n /** 当前会话的 cwd,用于 @file 解析。 */\n cwd: string;\n /** 命中的 slash 命令(若有);命中后 pipeline 短路。 */\n slashCommand?: InputSlashCommand;\n /** stage 附加的 attachments。 */\n attachments: InputAttachment[];\n /** 不阻断的告警。 */\n warnings: InputWarning[];\n /** 当前 PermissionMode。 */\n mode: PermissionMode;\n /** settings.preprocess.input 配置。 */\n settings: InputPreprocessSettings;\n /** Active model 能力(用于 at-image 等需要 vision 的 stage 判断)。 */\n capabilities?: InputCapabilities;\n}\n\nexport function createInputCtx(init: {\n raw: string;\n source: InputCtx[\"source\"];\n cwd: string;\n mode: PermissionMode;\n settings?: InputPreprocessSettings;\n capabilities?: InputCapabilities;\n}): InputCtx {\n return {\n raw: init.raw,\n text: init.raw,\n source: init.source,\n cwd: init.cwd,\n attachments: [],\n warnings: [],\n mode: init.mode,\n settings: init.settings ?? {},\n capabilities: init.capabilities,\n };\n}\n","/**\n * InputPipeline 装配。\n *\n * 设计文档:模块设计/消息预处理工程/设计.md §4.1。\n *\n * Stage 顺序:slash-dispatch → paste-expand → at-file-expand → template-expand →\n * validate-length → redact-pre-scan\n *\n * 注意:slash-dispatch 命中后立即 PipelineShortCircuit,后续 stage 不执行;\n * caller 检查 ctx.slashCommand 决定路由到 SlashRegistry 还是 Agent。\n */\n\nimport { Pipeline, type PipelineRunOptions } from \"../pipeline.js\";\nimport { SlashDispatchStage } from \"./slash-dispatch.js\";\nimport { PasteExpandStage, NoopPasteExpandStage } from \"./paste-expand.js\";\nimport { AtFileExpandStage } from \"./at-file-expand.js\";\nimport { AtImageStage } from \"./at-image.js\";\nimport { ExpandImagePlaceholderStage, NoopExpandImagePlaceholderStage } from \"./expand-image-placeholder.js\";\nimport { TemplateExpandStage } from \"./template-expand.js\";\nimport { ValidateLengthStage } from \"./validate-length.js\";\nimport { RedactPreScanStage } from \"./redact-pre-scan.js\";\nimport type { InputCtx } from \"./ctx.js\";\nimport type { ContentPart } from \"../../types/index.js\";\n\nexport type { InputCtx, InputAttachment, InputWarning, InputSlashCommand, InputPreprocessSettings, InputCapabilities } from \"./ctx.js\";\nexport { createInputCtx } from \"./ctx.js\";\n\n/**\n * 把 InputCtx 输出组装为 Agent.runTurn 接受的 user content。\n *\n * - 无 attachment → 返 string(向后兼容,session 历史可读性更好)\n * - 有 attachment → 返 ContentPart[](TextPart + FilePart/ImagePart...)\n *\n * text 始终作为第一个 part(用户的纯指令);attachments 按 push 顺序追加。\n */\nexport function buildUserMessage(ctx: InputCtx): string | ContentPart[] {\n if (ctx.attachments.length === 0) return ctx.text;\n const parts: ContentPart[] = [{ type: \"text\", text: ctx.text }];\n for (const att of ctx.attachments) parts.push(att);\n return parts;\n}\n\nexport interface InputPipelineOpts extends PipelineRunOptions {\n /** Paste registry(BgTextInput 持有);为空则跳过 paste-expand。 */\n pasteRegistry?: Map<number, string>;\n /** Image registry(BgTextInput 持有);为空则跳过 expand-image-placeholder。 */\n imageRegistry?: Map<number, { data: Buffer; mediaType: \"image/png\" }>;\n}\n\nexport function InputPipeline(opts: InputPipelineOpts = {}): Pipeline<InputCtx> {\n const pasteStage = opts.pasteRegistry\n ? new PasteExpandStage(opts.pasteRegistry)\n : new NoopPasteExpandStage();\n const imageStage = opts.imageRegistry\n ? new ExpandImagePlaceholderStage(opts.imageRegistry)\n : new NoopExpandImagePlaceholderStage();\n return new Pipeline<InputCtx>(\n [\n new SlashDispatchStage(),\n pasteStage,\n imageStage,\n new AtFileExpandStage(),\n new AtImageStage(),\n new TemplateExpandStage(),\n new ValidateLengthStage(),\n new RedactPreScanStage(),\n ],\n { ...opts, pipelineName: \"input\" },\n );\n}\n","/**\n * 配置加载:\n * 1. 内置默认值\n * 2. ~/.muse/settings.json\n * 3. <cwd>/.muse/settings.json\n * 4. <cwd>/.muse/settings.local.json\n * 5. 环境变量 (MUSE_*)\n * 6. CLI flags (在 cli.tsx 里覆盖)\n *\n * ${ENV_VAR} 占位符在加载后展开。\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { z } from \"zod\";\nimport { SettingsSchema, type Settings } from \"./types.js\";\nimport { expandEnvVars } from \"./_env.js\";\nimport { log } from \"../log/index.js\";\n\nfunction formatZodIssues(issues: z.ZodIssue[]): string {\n return issues\n .map((i) => `${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"; \");\n}\n\nconst DEFAULTS: Settings = {\n llm: {\n provider: \"deepseek\",\n model: \"deepseek-chat\",\n },\n providers: {\n deepseek: { apiKey: \"${DEEPSEEK_API_KEY}\" },\n openai: { apiKey: \"${OPENAI_API_KEY}\" },\n qwen: { apiKey: \"${DASHSCOPE_API_KEY}\" },\n moonshot: { apiKey: \"${MOONSHOT_API_KEY}\" },\n zhipu: { apiKey: \"${ZHIPU_API_KEY}\" },\n openrouter: { apiKey: \"${OPENROUTER_API_KEY}\" },\n ollama: { baseUrl: \"http://localhost:11434/v1\" },\n },\n permissions: {\n allow: [\"Read\", \"Grep\", \"Glob\", \"TodoWrite\"],\n ask: [\"Write\", \"Edit\", \"Bash\"],\n deny: [],\n defaultMode: \"ask\",\n },\n ui: {\n showBanner: true,\n lang: \"en\",\n },\n};\n\nasync function readJsonIfExists(path: string): Promise<unknown | undefined> {\n if (!existsSync(path)) return undefined;\n try {\n const raw = await readFile(path, \"utf-8\");\n return JSON.parse(raw);\n } catch (err) {\n log.warn(`Failed to parse settings at ${path}: ${err instanceof Error ? err.message : String(err)}`);\n return undefined;\n }\n}\n\n/** 深合并:高优先级覆盖低优先级。对象递归,数组/标量覆盖。 */\nfunction deepMerge<T>(low: T, high: Partial<T>): T {\n if (high == null) return low;\n if (typeof low !== \"object\" || typeof high !== \"object\" || low === null || high === null) {\n return high as T;\n }\n if (Array.isArray(high)) return high as unknown as T;\n const result: Record<string, unknown> = { ...(low as Record<string, unknown>) };\n for (const [k, v] of Object.entries(high)) {\n const existing = (low as Record<string, unknown>)[k];\n if (\n v !== null &&\n typeof v === \"object\" &&\n !Array.isArray(v) &&\n existing !== null &&\n typeof existing === \"object\" &&\n !Array.isArray(existing)\n ) {\n result[k] = deepMerge(existing, v as Record<string, unknown>);\n } else {\n result[k] = v;\n }\n }\n return result as T;\n}\n\nexport interface LoadedSettings {\n settings: Settings;\n sources: string[];\n}\n\nexport async function loadSettings(cwd: string = process.cwd()): Promise<LoadedSettings> {\n const sources: string[] = [\"<defaults>\"];\n let merged: Settings = DEFAULTS;\n\n const candidates = [\n join(homedir(), \".muse\", \"settings.json\"),\n join(cwd, \".muse\", \"settings.json\"),\n join(cwd, \".muse\", \"settings.local.json\"),\n ];\n\n for (const path of candidates) {\n const raw = await readJsonIfExists(path);\n if (raw != null) {\n const parsed = SettingsSchema.safeParse(raw);\n if (parsed.success) {\n merged = deepMerge(merged, parsed.data);\n sources.push(path);\n } else {\n log.warn(`Invalid settings at ${path}: ${formatZodIssues(parsed.error.issues)}`);\n }\n }\n }\n\n // Env overrides for the active LLM\n if (process.env.MUSE_PROVIDER && merged.llm) {\n merged = { ...merged, llm: { ...merged.llm, provider: process.env.MUSE_PROVIDER } };\n sources.push(\"env:MUSE_PROVIDER\");\n }\n if (process.env.MUSE_MODEL && merged.llm) {\n merged = { ...merged, llm: { ...merged.llm, model: process.env.MUSE_MODEL } };\n sources.push(\"env:MUSE_MODEL\");\n }\n\n // 展开 ${ENV_VAR} 占位符\n merged = expandEnvVars(merged) as Settings;\n\n // settings.env 注入 process.env(对齐业界 CLI Agent 形态)。\n // 已存在的环境变量不覆盖 — shell / CLI 显式设置优先级最高。\n if (merged.env) {\n for (const [key, value] of Object.entries(merged.env)) {\n if (process.env[key] === undefined) {\n process.env[key] = value;\n }\n }\n }\n\n return { settings: merged, sources };\n}\n\nexport { DEFAULTS };\nexport { resolve as resolvePath };\n","/**\n * 配置 schema。对应 ~/.muse/settings.json + .muse/settings.json 的内容。\n */\n\nimport { z } from \"zod\";\n\nexport const ProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n baseUrl: z.string().optional(),\n extraHeaders: z.record(z.string()).optional(),\n}).passthrough();\n\n// 新设计:model id 由 ~/.muse/models.local.json 提供,settings.json 只保留 active 选择。\n// provider 字段仅用于\"无 models.local.json 时的 fallback 路径\"(设计文档 §8 兼容层)。\n// 因此两者都可选——/model 切换只写 model,不写 provider。\nexport const LLMConfigSchema = z.object({\n provider: z.string().optional().describe(\"Fallback provider preset (only used when no models.local.json entry matches).\"),\n model: z.string().optional().describe(\"Active model id; should match an id in models.local.json.\"),\n temperature: z.number().min(0).max(2).optional(),\n maxTokens: z.number().int().positive().optional(),\n});\n\nexport const PermissionsSchema = z.object({\n allow: z.array(z.string()).optional(),\n ask: z.array(z.string()).optional(),\n deny: z.array(z.string()).optional(),\n defaultMode: z.enum([\"strict\", \"relaxed\", \"ask\"]).optional(),\n});\n\nexport const UISchema = z.object({\n theme: z.enum([\"dark\", \"light\"]).optional(),\n lang: z.enum([\"en\", \"zh-CN\"]).optional(),\n showBanner: z.boolean().optional(),\n});\n\n// 消息预处理工程(模块设计/消息预处理工程/设计.md §6.2)。\n// MVP:settings 暴露 4 段管线开关 + 部分参数;hooks 只在 PreToolUse / PostToolUse 触发,\n// 其余点位 schema 保留但不接代码。\n\nexport const HookSpecSchema = z.object({\n matcher: z.string().optional(),\n command: z.string(),\n timeout: z.number().int().positive().optional(),\n onError: z.enum([\"skip\", \"throw\"]).optional(),\n});\n\nexport const HooksConfigSchema = z.object({\n SessionStart: z.array(HookSpecSchema).optional(),\n SessionEnd: z.array(HookSpecSchema).optional(),\n UserPromptSubmit: z.array(HookSpecSchema).optional(),\n PreLLMRequest: z.array(HookSpecSchema).optional(),\n PostLLMResponse: z.array(HookSpecSchema).optional(),\n PreToolUse: z.array(HookSpecSchema).optional(),\n PostToolUse: z.array(HookSpecSchema).optional(),\n PreCompact: z.array(HookSpecSchema).optional(),\n PostCompact: z.array(HookSpecSchema).optional(),\n MemoryPromote: z.array(HookSpecSchema).optional(),\n}).passthrough();\n\nexport const InputPreprocessSettingsSchema = z.object({\n atFileExpand: z.object({\n enabled: z.boolean().optional(),\n maxBytes: z.number().int().positive().optional(),\n }).optional(),\n templateExpand: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n maxChars: z.number().int().positive().optional(),\n redactPreScan: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n}).passthrough();\n\nexport const RequestPreprocessSettingsSchema = z.object({\n trimHistory: z.object({\n enabled: z.boolean().optional(),\n budgetRatio: z.number().min(0).max(1).optional(),\n }).optional(),\n budgetGuard: z.object({\n enabled: z.boolean().optional(),\n budgetRatio: z.number().min(0).max(1).optional(),\n }).optional(),\n redact: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n}).passthrough();\n\nexport const ResultPreprocessSettingsSchema = z.object({\n truncate: z.object({\n budgetBytes: z.number().int().positive().optional(),\n }).optional(),\n detectBinary: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n summarize: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n normalizeError: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n redact: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n injectDiff: z.boolean().optional(),\n}).passthrough();\n\nexport const RenderPreprocessSettingsSchema = z.object({\n streamMarkdown: z.object({\n enabled: z.boolean().optional(),\n }).optional(),\n collapseLong: z.object({\n enabled: z.boolean().optional(),\n threshold: z.number().int().positive().optional(),\n }).optional(),\n}).passthrough();\n\nexport const PreprocessSettingsSchema = z.object({\n input: InputPreprocessSettingsSchema.optional(),\n request: RequestPreprocessSettingsSchema.optional(),\n result: ResultPreprocessSettingsSchema.optional(),\n render: RenderPreprocessSettingsSchema.optional(),\n /** 全局禁用的 stage name 列表(kebab-case)。 */\n disable: z.array(z.string()).optional(),\n}).passthrough();\n\nexport const SettingsSchema = z.object({\n llm: LLMConfigSchema.optional(),\n providers: z.record(ProviderConfigSchema).optional(),\n permissions: PermissionsSchema.optional(),\n ui: UISchema.optional(),\n mcpServers: z.record(z.unknown()).optional(),\n skills: z.object({\n enabled: z.boolean().optional(),\n disabled: z.array(z.string()).optional(),\n }).optional(),\n hooks: HooksConfigSchema.optional(),\n preprocess: PreprocessSettingsSchema.optional(),\n /**\n * 启动时注入到 process.env 的额外环境变量(对齐业界 CLI Agent 的 settings.env 模式)。\n * 值必须是字符串(JSON 无 number→env 的隐式转换;约束传 \"1\" / \"0\" 这种字面值)。\n *\n * 当前支持的 muse 自识别变量:\n * MUSE_DISABLE_CURSOR_BLINK=1 关闭输入框光标闪烁(默认闪烁)\n * 其他 muse 模块可自行约定 MUSE_* 名字读取。\n *\n * 注意:这里写入的变量会进入 process.env,**但 Hook 子进程仍走环境变量白名单**\n * (见 src/preprocess/hooks.ts),不会自动透传给 hook 命令,避免泄露密钥。\n */\n env: z.record(z.string()).optional(),\n /** Memory 模块设置(II-5 向量索引)。 */\n memory: z.object({\n embedding: z.object({\n /** 启用 embedding 召回(默认 false;关闭时 inject-memory 走传统全文)。 */\n enabled: z.boolean().optional(),\n /** 后端 provider。默认 hash-bag(零依赖);设了 preset 自动走 openai-compatible。 */\n provider: z.enum([\"hash-bag\", \"openai-compatible\", \"openai\", \"local-minilm\"]).optional(),\n /** Preset 名(dashscope-v3 / openai-3-small / openai-3-large / zhipu-3 / ollama-nomic / ollama-bge-m3)。 */\n preset: z.string().optional(),\n /** Base URL(覆盖 preset 默认或自定义 provider 时填)。 */\n baseUrl: z.string().optional(),\n /** 模型名(覆盖 preset 默认或自定义 provider 时填)。 */\n model: z.string().optional(),\n /** 向量维度(用户根据模型官方说明调整;preset 给推荐默认,可覆盖)。\n * 设了此字段 → HTTP 请求带 dimensions 参数(MRL truncation);\n * 没设 → 走模型默认。\n * 启动期 muse 会 probe 一次校验实际维度,不匹配则降级 hash-bag + 提示修正。 */\n dim: z.number().int().positive().optional(),\n /** API key(${ENV_VAR} 或明文;Ollama 等本地端点可省)。 */\n apiKey: z.string().optional(),\n /** 检索 top-K(默认 5)。 */\n topK: z.number().int().positive().optional(),\n /** memory 数量低于此值时退化到全注入(默认 3,2026-06-07 R5 修订)。 */\n minMemoryCount: z.number().int().nonnegative().optional(),\n /** 注入 token 预算上限,超出按 trust 优先保留(默认 1500)。 */\n maxInjectTokens: z.number().int().positive().optional(),\n }).optional(),\n }).optional(),\n}).passthrough();\n\nexport type Settings = z.infer<typeof SettingsSchema>;\nexport type LLMConfig = z.infer<typeof LLMConfigSchema>;\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\nexport type Permissions = z.infer<typeof PermissionsSchema>;\nexport type HookSpec = z.infer<typeof HookSpecSchema>;\nexport type HooksConfig = z.infer<typeof HooksConfigSchema>;\nexport type PreprocessSettings = z.infer<typeof PreprocessSettingsSchema>;\nexport type InputPreprocessSettings = z.infer<typeof InputPreprocessSettingsSchema>;\nexport type RequestPreprocessSettings = z.infer<typeof RequestPreprocessSettingsSchema>;\nexport type ResultPreprocessSettings = z.infer<typeof ResultPreprocessSettingsSchema>;\nexport type RenderPreprocessSettings = z.infer<typeof RenderPreprocessSettingsSchema>;\n","/**\n * ${ENV_VAR} 占位符递归展开。\n *\n * settings.json / models.local.json 都共用这套机制,避免把明文凭证落到可入 git 的文件。\n * 未定义的 env var → 空字符串(不抛错,让上层校验\"必填字段是否非空\"决定行为)。\n */\n\nconst ENV_PATTERN = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\n\nexport function expandEnvVars(value: unknown): unknown {\n if (typeof value === \"string\") {\n return value.replace(ENV_PATTERN, (_match, name) => process.env[name] ?? \"\");\n }\n if (Array.isArray(value)) {\n return value.map(expandEnvVars);\n }\n if (value && typeof value === \"object\") {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n result[k] = expandEnvVars(v);\n }\n return result;\n }\n return value;\n}\n","/**\n * 单一版本号源。与 package.json \"version\" 字段手动同步。\n * 多处引用(commander --version、启动 banner 等)避免漏改不一致。\n */\nexport const VERSION = \"0.1.3\";\n","/**\n * Models registry:用户级模型库。\n *\n * 位置:~/.muse/models.local.json (单文件,本机本地;从不入 git)\n *\n * 设计:\n * - models 数组的 id 是**用户起的名字**,不在代码里硬编码;数组里所有 entry 都自动进\n * /model selector,无需额外过滤字段\n * - apiKey 字段可以直接写明文(推荐:文件就在本机本地),也支持 ${ENV_VAR} 占位符\n * - baseUrl 是基址,SDK 自己拼 /chat/completions;用户填全 endpoint 时自动剥后缀\n * - 不存在文件 → 返回 undefined(调用方回退到 settings.json llm 配置)\n *\n * Why `.local.json` 单文件而非 `models.json`:\n * muse 0.1.x 早期是双文件(models.json git-tracked + models.local.json 本地兜底),\n * 但实际使用中并没有 \"git-track 一份不含 key 的模板\" 的场景——用户的模型清单本就\n * 是私人物件。为避免新用户被两份文件混淆,合并为单文件,沿用 `.local.json`\n * 后缀作为 \"本机本地,绝不入 git\" 的视觉提示。\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { expandEnvVars } from \"./_env.js\";\nimport { log } from \"../log/index.js\";\n\n/**\n * 内部规整后的 ModelEntry 类型。schema 解析后的对象会通过 normalize 步骤\n * 把 url/baseUrl 合一,最终 baseUrl 保证非空。业务(client / selector)只看本类型。\n */\nexport interface ModelEntry {\n id: string;\n name?: string;\n vendor?: string;\n apiKey?: string;\n baseUrl: string;\n supportsToolCall?: boolean;\n supportsImages?: boolean;\n contextWindow?: number;\n [k: string]: unknown;\n}\n\n/**\n * 输入校验:baseUrl / url 任一非空即可。\n * 用户实际写的 models.local.json 多用 `url`(OpenAI 兼容协议惯例命名),\n * 我们接受两种别名,normalize 阶段归一。\n */\nexport const ModelEntryInputSchema = z\n .object({\n id: z.string().min(1),\n name: z.string().optional(),\n vendor: z.string().optional(),\n apiKey: z.string().optional(),\n baseUrl: z.string().optional(),\n url: z.string().optional(),\n supportsToolCall: z.boolean().optional(),\n supportsImages: z.boolean().optional(),\n contextWindow: z.number().int().positive().optional(),\n })\n .passthrough()\n .refine((d) => Boolean(d.baseUrl || d.url), {\n message: \"Either 'baseUrl' or 'url' is required\",\n path: [\"baseUrl\"],\n });\n\nexport type ModelEntryInput = z.infer<typeof ModelEntryInputSchema>;\n\nexport const ModelsRegistryInputSchema = z\n .object({\n models: z.array(ModelEntryInputSchema),\n })\n .passthrough();\n\nexport type ModelsRegistryInput = z.infer<typeof ModelsRegistryInputSchema>;\n\n/** Normalize 后的 registry:models[*].baseUrl 保证非空。 */\nexport interface ModelsRegistry {\n models: ModelEntry[];\n [k: string]: unknown;\n}\n\nexport interface LoadError {\n path: string;\n message: string;\n}\n\nexport interface LoadedModels {\n registry: ModelsRegistry | undefined;\n sources: string[];\n errors: LoadError[];\n}\n\nexport const MODELS_PATH = (): string => join(homedir(), \".muse\", \"models.local.json\");\n\nexport async function loadModelsRegistry(): Promise<LoadedModels> {\n const sources: string[] = [];\n const errors: LoadError[] = [];\n const path = MODELS_PATH();\n\n if (!existsSync(path)) {\n return { registry: undefined, sources, errors };\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(await readFile(path, \"utf-8\"));\n } catch (err) {\n const msg = `JSON parse error: ${err instanceof Error ? err.message : String(err)}`;\n log.warn(`Failed to parse ${path}: ${msg}`);\n errors.push({ path, message: msg });\n return { registry: undefined, sources, errors };\n }\n\n const parsed = ModelsRegistryInputSchema.safeParse(raw);\n if (!parsed.success) {\n const msg = formatZodIssues(parsed.error.issues);\n log.warn(`Invalid models registry at ${path}: ${msg}`);\n errors.push({ path, message: msg });\n return { registry: undefined, sources, errors };\n }\n\n const normalized: ModelsRegistry = {\n ...parsed.data,\n models: parsed.data.models.map(normalizeModelEntry),\n };\n sources.push(path);\n const expanded = expandEnvVars(normalized) as ModelsRegistry;\n return { registry: expanded, sources, errors };\n}\n\nfunction formatZodIssues(issues: z.ZodIssue[]): string {\n return issues\n .map((i) => `${i.path.join(\".\") || \"<root>\"}: ${i.message}`)\n .join(\"; \");\n}\n\n/**\n * 输入归一:url ↔ baseUrl 二选一;剥 trailing `/` 与 `/chat/completions`。\n * 经过校验后 baseUrl/url 至少一个非空(zod refine 保证),输出 baseUrl 必填。\n *\n * 同时记录 apiKey 字段里出现的 ${ENV_VAR} 占位符名(_apiKeyEnvVars),让 expand 后\n * apiKey 变空时 client.ts 能给出\"缺哪个 env var\"的精确提示。\n */\nfunction normalizeModelEntry(entry: ModelEntryInput): ModelEntry {\n let baseUrl = (entry.baseUrl ?? entry.url ?? \"\").replace(/\\/+$/, \"\");\n if (baseUrl.endsWith(\"/chat/completions\")) {\n baseUrl = baseUrl.slice(0, -\"/chat/completions\".length);\n }\n const { url: _url, ...rest } = entry;\n const apiKeyEnvVars = entry.apiKey ? extractEnvVars(entry.apiKey) : [];\n return {\n ...rest,\n baseUrl,\n ...(apiKeyEnvVars.length > 0 ? { _apiKeyEnvVars: apiKeyEnvVars } : {}),\n };\n}\n\nconst ENV_PLACEHOLDER = /\\$\\{([A-Z_][A-Z0-9_]*)\\}/g;\nfunction extractEnvVars(s: string): string[] {\n const out: string[] = [];\n let m: RegExpExecArray | null;\n ENV_PLACEHOLDER.lastIndex = 0;\n while ((m = ENV_PLACEHOLDER.exec(s)) !== null) out.push(m[1]);\n return out;\n}\n\n// ---------- selector / lookup helpers ----------\n\nexport function findEntry(registry: ModelsRegistry, modelId: string): ModelEntry | undefined {\n return registry.models.find((m) => m.id === modelId);\n}\n\n","/**\n * 模型单价表(USD per 1M tokens)。\n *\n * 设计文档:muse-design.md §11.2 Token / 费用统计。\n *\n * 数据来源:各 provider 公开价格页(2026 年初快照)。仅供 /cost 命令展示估算用,\n * 不保证准确性,价格变动用户可在 ~/.muse/settings.json 自定义覆盖(v0.2 起)。\n */\n\nexport interface ModelPricing {\n /** 输入 token 单价(USD per 1M)。 */\n inputPer1M: number;\n /** 输出 token 单价(USD per 1M)。 */\n outputPer1M: number;\n}\n\nconst PRICING: Record<string, Record<string, ModelPricing>> = {\n openai: {\n \"gpt-4o\": { inputPer1M: 2.5, outputPer1M: 10 },\n \"gpt-4o-mini\": { inputPer1M: 0.15, outputPer1M: 0.6 },\n \"gpt-4-turbo\": { inputPer1M: 10, outputPer1M: 30 },\n },\n deepseek: {\n \"deepseek-chat\": { inputPer1M: 0.14, outputPer1M: 0.28 },\n \"deepseek-reasoner\": { inputPer1M: 0.55, outputPer1M: 2.19 },\n },\n qwen: {\n \"qwen-plus\": { inputPer1M: 0.4, outputPer1M: 1.2 },\n \"qwen-max\": { inputPer1M: 2.8, outputPer1M: 8.4 },\n \"qwen-turbo\": { inputPer1M: 0.05, outputPer1M: 0.2 },\n },\n moonshot: {\n \"moonshot-v1-8k\": { inputPer1M: 1.68, outputPer1M: 1.68 },\n \"moonshot-v1-32k\": { inputPer1M: 3.36, outputPer1M: 3.36 },\n \"moonshot-v1-128k\": { inputPer1M: 8.4, outputPer1M: 8.4 },\n },\n zhipu: {\n \"glm-4-flash\": { inputPer1M: 0, outputPer1M: 0 },\n \"glm-4-plus\": { inputPer1M: 7, outputPer1M: 7 },\n },\n ollama: {\n // 本地模型零成本\n },\n};\n\nexport function lookupPricing(provider: string, model: string): ModelPricing | undefined {\n return PRICING[provider]?.[model];\n}\n\nexport function estimateCostUSD(\n provider: string,\n model: string,\n inputTokens: number,\n outputTokens: number,\n): number | undefined {\n const p = lookupPricing(provider, model);\n if (!p) return undefined;\n return (inputTokens / 1_000_000) * p.inputPer1M + (outputTokens / 1_000_000) * p.outputPer1M;\n}\n\n/** 把 USD 金额格式化成人类可读字符串。小于 1 美分用 micro-dollar 显示。 */\nexport function formatUSD(usd: number): string {\n if (usd === 0) return \"$0.00\";\n if (usd < 0.0001) return `<$0.0001`;\n if (usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(4)}`;\n}\n","/**\n * MCP 状态查询入口(v0.1 占位,v0.3 真接 SDK)。\n *\n * 当前仅根据 settings.mcpServers 配置返回\"已配置但未连接\"的状态。\n * /mcp 命令读这里;不依赖任何 MCP 运行时。\n */\n\nimport type { Settings } from \"../config/types.js\";\nimport type { MCPServerStatus, MCPServerConfig } from \"./types.js\";\n\nconst NOT_IMPLEMENTED = \"MCP client not implemented (planned for v0.3)\";\n\nexport function getMCPStatus(settings: Settings): MCPServerStatus[] {\n const servers = (settings.mcpServers ?? {}) as Record<string, MCPServerConfig>;\n return Object.entries(servers).map(([name, config]) => ({\n name,\n configured: true,\n connected: false,\n toolCount: 0,\n error: NOT_IMPLEMENTED,\n config,\n }));\n}\n\nexport type { MCPServerStatus, MCPServerConfig } from \"./types.js\";\n","/**\n * Session 持久化:append-only JSONL。\n * 路径:~/.muse/projects/<project-hash>/sessions/<uuid>.jsonl\n *\n * 每行一个事件:消息 / 工具调用 / 工具结果 / 使用统计 / ...\n */\n\nimport { appendFile, mkdir, readdir, readFile, stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport type { Message, TokenUsage } from \"../types/index.js\";\nimport { log } from \"../log/index.js\";\n\nexport type SessionEvent =\n | { type: \"session_start\"; time: string; cwd: string; provider: string; model: string }\n | { type: \"message\"; time: string; message: Message }\n | { type: \"usage\"; time: string; usage: TokenUsage; provider: string; model: string }\n | { type: \"session_end\"; time: string; reason: \"user_exit\" | \"error\" };\n\nexport interface SessionMeta {\n id: string;\n cwd: string;\n createdAt: string;\n path: string;\n}\n\nexport interface SessionSummary extends SessionMeta {\n /** 首个 user 消息前 60 字符。 */\n preview?: string;\n messageCount: number;\n}\n\nfunction projectHash(cwd: string): string {\n return createHash(\"sha256\").update(cwd).digest(\"hex\").slice(0, 16);\n}\n\nfunction sessionsDir(cwd: string): string {\n return join(homedir(), \".muse\", \"projects\", projectHash(cwd), \"sessions\");\n}\n\nexport class Session {\n readonly meta: SessionMeta;\n private writeQueue: Promise<void> = Promise.resolve();\n\n private constructor(meta: SessionMeta) {\n this.meta = meta;\n }\n\n static async create(cwd: string): Promise<Session> {\n const id = randomUUID();\n const dir = sessionsDir(cwd);\n await mkdir(dir, { recursive: true });\n const path = join(dir, `${id}.jsonl`);\n const meta: SessionMeta = {\n id,\n cwd,\n createdAt: new Date().toISOString(),\n path,\n };\n log.debug(\"session created\", { id, path });\n return new Session(meta);\n }\n\n static async findLatest(cwd: string): Promise<SessionMeta | undefined> {\n const list = await Session.listAll(cwd, 1);\n return list[0];\n }\n\n static async resolve(cwd: string, idOrPrefix: string): Promise<SessionMeta | undefined> {\n const dir = sessionsDir(cwd);\n if (!existsSync(dir)) return undefined;\n const entries = await readdir(dir);\n const matches = entries.filter((e) => e.endsWith(\".jsonl\") && e.startsWith(idOrPrefix));\n if (matches.length === 0) return undefined;\n if (matches.length > 1) {\n throw new Error(`Ambiguous session id \"${idOrPrefix}\" matches ${matches.length} sessions; use more characters.`);\n }\n const top = matches[0];\n const st = await stat(join(dir, top));\n return {\n id: top.replace(/\\.jsonl$/, \"\"),\n cwd,\n createdAt: st.mtime.toISOString(),\n path: join(dir, top),\n };\n }\n\n /**\n * 按修改时间倒序列出当前 cwd 下的 session,附带 preview 与消息数。\n * 读 preview 需要打开每个文件;调用方通过 limit 控制 IO 量。\n */\n static async listAll(cwd: string, limit?: number): Promise<SessionSummary[]> {\n const dir = sessionsDir(cwd);\n if (!existsSync(dir)) return [];\n const entries = await readdir(dir);\n const files = entries.filter((e) => e.endsWith(\".jsonl\"));\n if (files.length === 0) return [];\n\n const stats = await Promise.all(\n files.map(async (f) => {\n const path = join(dir, f);\n const st = await stat(path);\n return { file: f, path, mtime: st.mtime };\n }),\n );\n stats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n\n const truncated = typeof limit === \"number\" ? stats.slice(0, limit) : stats;\n\n const summaries: SessionSummary[] = [];\n for (const s of truncated) {\n const meta: SessionMeta = {\n id: s.file.replace(/\\.jsonl$/, \"\"),\n cwd,\n createdAt: s.mtime.toISOString(),\n path: s.path,\n };\n const summary = await readSummary(meta);\n summaries.push(summary);\n }\n return summaries;\n }\n\n static async open(meta: SessionMeta): Promise<{ session: Session; events: SessionEvent[] }> {\n const session = new Session(meta);\n const events = await session.readAll();\n return { session, events };\n }\n\n /** 从已加载的 events 重建 messages 数组(按时序)。 */\n static messagesFromEvents(events: SessionEvent[]): Message[] {\n const out: Message[] = [];\n for (const ev of events) {\n if (ev.type === \"message\") out.push(ev.message);\n }\n return out;\n }\n\n async append(event: SessionEvent): Promise<void> {\n const line = JSON.stringify(event) + \"\\n\";\n // 串行写入避免交错\n this.writeQueue = this.writeQueue.then(async () => {\n try {\n await mkdir(dirname(this.meta.path), { recursive: true });\n await appendFile(this.meta.path, line, \"utf-8\");\n } catch (err) {\n log.warn(`session append failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n });\n return this.writeQueue;\n }\n\n async readAll(): Promise<SessionEvent[]> {\n if (!existsSync(this.meta.path)) return [];\n const raw = await readFile(this.meta.path, \"utf-8\");\n const events: SessionEvent[] = [];\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as SessionEvent);\n } catch {\n // skip corrupt lines\n }\n }\n return events;\n }\n}\n\nasync function readSummary(meta: SessionMeta): Promise<SessionSummary> {\n let events: SessionEvent[] = [];\n try {\n const raw = await readFile(meta.path, \"utf-8\");\n for (const line of raw.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n events.push(JSON.parse(line) as SessionEvent);\n } catch {\n // skip\n }\n }\n } catch {\n // unreadable; return minimal summary\n }\n const messages = events.filter((e): e is Extract<SessionEvent, { type: \"message\" }> => e.type === \"message\");\n const firstUser = messages.find((e) => e.message.role === \"user\");\n let preview: string | undefined;\n if (firstUser) {\n const c = firstUser.message.content;\n const text = typeof c === \"string\"\n ? c\n : c.map((p) => {\n if (p.type === \"text\") return p.text;\n if (p.type === \"file\") return `📎`;\n if (p.type === \"image\") return `🖼`;\n return \"\";\n }).join(\" \").trim();\n preview = text.slice(0, 60).replace(/\\s+/g, \" \");\n }\n return { ...meta, preview, messageCount: messages.length };\n}\n","/**\n * Slash 命令体共享的格式化 helper。\n *\n * 之所以单独抽:命令文件应该薄、只编排;shortPath / 表格对齐 / flag 解析\n * 被多个命令复用,三处相似就抽(CLAUDE.md 代码风格条款)。\n */\n\nimport { homedir } from \"node:os\";\n\nexport function shortPath(p: string): string {\n const home = homedir();\n if (p === home) return \"~\";\n if (p.startsWith(home + \"/\")) return \"~\" + p.slice(home.length);\n return p;\n}\n\nexport function formatList(list: string[] | undefined): string {\n if (!list || list.length === 0) return \"(none)\";\n return list.join(\", \");\n}\n\n/**\n * 解析 \"--key val --flag pos1 pos2\" 形式。极简,够 v0.1 用:\n * - 不支持 = 形式\n * - 不支持引号转义\n * - bool flag 默认 false,出现即 true\n */\nexport function parseArgs(raw: string): { positional: string[]; flags: Record<string, string | boolean> } {\n const tokens = raw.trim().split(/\\s+/).filter(Boolean);\n const positional: string[] = [];\n const flags: Record<string, string | boolean> = {};\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n if (t.startsWith(\"--\")) {\n const key = t.slice(2);\n const next = tokens[i + 1];\n if (next && !next.startsWith(\"--\")) {\n flags[key] = next;\n i++;\n } else {\n flags[key] = true;\n }\n } else {\n positional.push(t);\n }\n }\n return { positional, flags };\n}\n\n/**\n * \"provider/model\" 或 \"model\" 解析。后者沿用当前 provider。\n */\nexport function parseModelSpec(\n spec: string,\n fallbackProvider: string,\n): { provider: string; model: string } {\n const slash = spec.indexOf(\"/\");\n if (slash === -1) return { provider: fallbackProvider, model: spec };\n return { provider: spec.slice(0, slash), model: spec.slice(slash + 1) };\n}\n\n/** \"yyyy-mm-dd hh:mm\" 紧凑时间。 */\nexport function formatTime(iso: string): string {\n const d = new Date(iso);\n if (isNaN(d.getTime())) return iso;\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;\n}\n","/**\n * 内置 slash 命令:/help /clear /compact /model /config /mcp /cost /resume /exit\n *\n * 设计文档:muse-design.md §7.2 表中 9 条全部覆盖。\n *\n * 设计原则:命令体只编排(解析参数 → 调 actions / 领域模块 → 构造 display)。\n * 真正的业务(压缩、列 session、查 MCP)在各自的领域模块里。\n */\n\nimport type { SlashCommand, SlashCommandContext } from \"./types.js\";\nimport { estimateCostUSD, formatUSD, lookupPricing } from \"../llm/pricing.js\";\nimport { redactApiKey } from \"../log/index.js\";\nimport { compactMessages } from \"../loop/context.js\";\nimport { getMCPStatus } from \"../mcp/index.js\";\nimport { Session } from \"../session/jsonl.js\";\nimport { loadModelsRegistry, type LoadError } from \"../config/models.js\";\nimport { shortPath, formatList, parseArgs, formatTime } from \"./_format.js\";\nimport { MODE_CYCLE, MODE_LABEL, type PermissionMode } from \"../permission/index.js\";\nimport {\n listMemories,\n readMemory,\n deleteMemory,\n setMemoryTrust,\n promoteScopeToUser,\n writeMemory,\n TRUST_LEVELS,\n SCOPES,\n type TrustLevel,\n type Scope,\n type MemoryType,\n} from \"../loop/memory.js\";\nimport { buildMemoryIndex, queryMemoryIndex } from \"../loop/memory-index.js\";\nimport { EMBEDDING_PRESETS, listPresetNames, createAndProbeProvider } from \"../loop/embedding/index.js\";\nimport { memoryDir, globalMemoryDir } from \"../loop/memory.js\";\nimport { existsSync } from \"node:fs\";\nimport { statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { LLMClient } from \"../llm/types.js\";\n\n// ----- /help -----\n\n/** /help 命令分类(命令名顺序即输出顺序)。未列入此处的新命令会进 \"Other\"。 */\nconst HELP_CATEGORIES: Array<{ title: string; names: string[] }> = [\n { title: \"Chat & turn control\", names: [\"help\", \"clear\", \"compact\", \"resume\", \"cost\", \"btw\"] },\n { title: \"Memory\", names: [\"memory\", \"remember\"] },\n { title: \"Configuration\", names: [\"model\", \"config\", \"mode\", \"mcp\"] },\n { title: \"Exit\", names: [\"exit\"] },\n];\n\nconst KEY_BINDINGS = [\n \"Key bindings:\",\n \" Enter submit\",\n \" \\\\ + Enter newline (multiline input)\",\n \" Esc cancel current LLM / tool, or clear guidance queue\",\n \" Esc Esc rewind: pull last user message back into input, drop everything after\",\n \" Shift+Tab cycle permission mode (default / acceptEdits / plan / bypassPermissions)\",\n \" Ctrl+C exit muse (or cancel running tool first)\",\n \" ↑ / ↓ history navigation\",\n \" Cmd/Ctrl+V paste (text or clipboard image)\",\n \" @<path> file reference autocomplete\",\n \" / slash command autocomplete\",\n].join(\"\\n\");\n\nconst HELP: SlashCommand = {\n name: \"help\",\n description: \"show available slash commands + key bindings\",\n execute(ctx) {\n const cmds = ctx.listCommands();\n const byName = new Map(cmds.map((c) => [c.name, c]));\n const maxHeadLen = Math.max(...cmds.map((c) => headOf(c).length));\n\n const lines: string[] = [\"Built-in commands:\"];\n const seen = new Set<string>();\n\n for (const cat of HELP_CATEGORIES) {\n const catCmds = cat.names.map((n) => byName.get(n)).filter((c): c is SlashCommand => !!c);\n if (catCmds.length === 0) continue;\n lines.push(\"\");\n lines.push(` ${cat.title}:`);\n for (const cmd of catCmds) {\n seen.add(cmd.name);\n const head = headOf(cmd);\n const aliasNote = cmd.aliases?.length\n ? ` (alias: ${cmd.aliases.map((a) => `/${a}`).join(\", \")})`\n : \"\";\n lines.push(` /${head.padEnd(maxHeadLen)} ${cmd.description}${aliasNote}`);\n }\n }\n\n // 漏网之鱼(防止新命令未分类时不显示)\n const uncat = cmds.filter((c) => !seen.has(c.name));\n if (uncat.length > 0) {\n lines.push(\"\");\n lines.push(` Other:`);\n for (const cmd of uncat) {\n const head = headOf(cmd);\n lines.push(` /${head.padEnd(maxHeadLen)} ${cmd.description}`);\n }\n }\n\n lines.push(\"\", KEY_BINDINGS);\n return { display: lines.join(\"\\n\") };\n },\n};\n\nfunction headOf(c: SlashCommand): string {\n return c.argsHint ? `${c.name} ${c.argsHint}` : c.name;\n}\n\n// ----- /clear -----\n\nconst CLEAR: SlashCommand = {\n name: \"clear\",\n description: \"clear conversation history\",\n execute(ctx) {\n ctx.actions.setMessages([]);\n return { display: \"(history cleared)\" };\n },\n};\n\n// ----- /exit -----\n\nconst FAREWELLS = [\n \"Goodbye\",\n \"Bye\",\n \"Bye, see ya\",\n \"See you later\",\n \"Take care\",\n \"Catch you later\",\n \"Adios\",\n \"Ciao\",\n \"Later\",\n \"Until next time\",\n] as const;\n\nfunction randomFarewell(): string {\n return FAREWELLS[Math.floor(Math.random() * FAREWELLS.length)];\n}\n\nconst EXIT: SlashCommand = {\n name: \"exit\",\n description: \"exit Muse\",\n execute() {\n // display + exit:app.tsx 在 exit 分支把 display 当 assistant message append,\n // 延后 exit() 让 Ink commit 一帧含告别语的 frame 后再 unmount。\n // Ink unmount 不主动清屏 — 最后一帧留在终端,告别语跟在 assistant 消息后、\n // 输入框之前(视觉与模型回复一致)。\n return { display: randomFarewell(), exit: true };\n },\n};\n\n// ----- /cost -----\n\nconst COST: SlashCommand = {\n name: \"cost\",\n description: \"show token usage and estimated cost for this session\",\n execute(ctx) {\n const { tokens, llm } = ctx;\n const pricing = lookupPricing(llm.providerName, llm.model);\n const lines = [\n `Session cost`,\n ` provider/model: ${llm.providerName} / ${llm.model}`,\n ` input tokens: ${tokens.inputTokens.toLocaleString()}`,\n ` output tokens: ${tokens.outputTokens.toLocaleString()}`,\n ` total tokens: ${tokens.totalTokens.toLocaleString()}`,\n ];\n if (pricing) {\n const cost = estimateCostUSD(llm.providerName, llm.model, tokens.inputTokens, tokens.outputTokens) ?? 0;\n lines.push(\n ` price (per 1M): input $${pricing.inputPer1M} / output $${pricing.outputPer1M}`,\n ` estimated cost: ${formatUSD(cost)}`,\n );\n } else {\n lines.push(` estimated cost: (no pricing data for ${llm.providerName}/${llm.model})`);\n }\n return { display: lines.join(\"\\n\") };\n },\n};\n\n// ----- /compact -----\n\nconst COMPACT_TIPS = [\n \"Shift+Tab cycles permission modes (default / acceptEdits / plan / bypass)\",\n \"/mode plan drafts changes without executing them\",\n \"/cost shows token usage and estimated spend\",\n \"/resume picks up a previous session in this directory\",\n \"muse --continue resumes the last session on startup\",\n \"MemoryWrite saves persistent knowledge across sessions\",\n \"TodoWrite keeps the model honest on multi-step tasks\",\n \"Pipe to muse: cat bug.log | muse \\\"explain this\\\"\",\n \"Ctrl+C exits immediately; Esc rejects a pending tool\",\n];\n\n// 经验值:muse-design §5.3 提的 200-400 词摘要约 1.2-1.8k 字符\nconst COMPACT_ESTIMATED_CHARS = 1800;\n\nconst COMPACT: SlashCommand = {\n name: \"compact\",\n description: \"summarize older messages to free up context space\",\n argsHint: \"[--keep N]\",\n async execute(ctx) {\n if (ctx.history.length === 0) return { display: \"(empty history; nothing to compact)\" };\n const { flags } = parseArgs(ctx.args);\n const keepRecent = typeof flags.keep === \"string\" ? Math.max(1, parseInt(flags.keep, 10)) : 4;\n if (Number.isNaN(keepRecent)) return { display: `Invalid --keep value: ${flags.keep}` };\n\n // ProgressBanner 每 tick 调 getPercent;用闭包持有的 ref 让 banner 看到最新值\n const progressRef = { chars: 0 };\n ctx.actions.showProgress({\n title: \"Compacting conversation\",\n tips: COMPACT_TIPS,\n getPercent: () => (progressRef.chars / COMPACT_ESTIMATED_CHARS) * 100,\n });\n\n try {\n const result = await compactMessages(ctx.history, {\n llm: ctx.llm,\n keepRecent,\n hooks: ctx.settings.hooks,\n cwd: ctx.cwd, // I-5:触发 facts → memory promote\n onProgress: (chars) => {\n progressRef.chars = chars;\n },\n });\n if (result.noop) {\n return { display: `(history has ${result.originalCount} messages; not enough to compact with --keep ${keepRecent})` };\n }\n ctx.actions.setMessages(result.newMessages);\n const preview = result.summary.length > 240 ? result.summary.slice(0, 240) + \"…\" : result.summary;\n const promoteNote = renderPromotedFactsNote(result.promotedFacts);\n return {\n display:\n `Compacted ${result.originalCount} → ${result.newCount} messages ` +\n `(kept last ${keepRecent}).\\n\\nSummary:\\n${preview}${promoteNote}`,\n };\n } finally {\n ctx.actions.hideProgress();\n }\n },\n};\n\nfunction renderPromotedFactsNote(facts?: import(\"../loop/context.js\").PromotedFact[]): string {\n if (!facts || facts.length === 0) return \"\";\n const saved = facts.filter((f) => f.status === \"saved\");\n const blocked = facts.filter((f) => f.status === \"blocked\");\n const failed = facts.filter((f) => f.status === \"failed\");\n const lines: string[] = [\"\\n\\nPromoted to long-term memory:\"];\n for (const f of saved) lines.push(` ✓ [${f.type}] ${f.name} — ${f.description}`);\n for (const f of blocked) lines.push(` ⊘ [${f.type}] ${f.name} (blocked by MemoryPromote hook${f.reason ? `: ${f.reason}` : \"\"})`);\n for (const f of failed) lines.push(` ✗ [${f.type}] ${f.name} (failed${f.reason ? `: ${f.reason}` : \"\"})`);\n return lines.join(\"\\n\");\n}\n\n// ----- /model -----\n\nconst MODELS: SlashCommand = {\n name: \"model\",\n description: \"pick a model from ~/.muse/models.local.json (↑↓ to navigate)\",\n async execute(ctx) {\n // ctx 没拿到 registry 时同步重读一次:可能 muse 启动后用户改了文件\n let registry = ctx.modelsRegistry;\n let errors: LoadError[] = [];\n if (!registry) {\n const r = await loadModelsRegistry();\n registry = r.registry;\n errors = r.errors;\n }\n\n if (!registry) {\n if (errors.length > 0) {\n return { display: renderLoadErrors(errors) };\n }\n return { display: renderEmptyRegistryHint() };\n }\n\n const visible = registry.models;\n if (visible.length === 0) {\n return {\n display:\n `models.local.json has no models.\\n` +\n `Add at least one entry to the \"models\" array.`,\n };\n }\n\n const picked = await ctx.actions.pickModel(visible, ctx.llm.model);\n if (!picked) return { display: \"(cancelled)\" };\n if (picked.id === ctx.llm.model) return { display: `Already on ${picked.id}.` };\n\n try {\n await ctx.actions.switchModel(picked.id);\n return { display: `Switched to ${picked.id}${picked.vendor ? ` (${picked.vendor})` : \"\"}.` };\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { display: `Failed to switch: ${msg}` };\n }\n },\n};\n\nfunction renderLoadErrors(errors: LoadError[]): string {\n return [\n `models.local.json was found but failed to load:`,\n ``,\n ...errors.flatMap((e) => [` ${shortPath(e.path)}`, ` ${e.message}`]),\n ``,\n `Fix the file above, then run /model again (it re-reads on each call).`,\n `Hint: each entry needs \"id\" and \"baseUrl\" (or \"url\"); \"apiKey\" supports \\${ENV_VAR}.`,\n ].join(\"\\n\");\n}\n\nfunction renderEmptyRegistryHint(): string {\n return [\n `No models registry found.`,\n `Create ~/.muse/models.local.json with a \"models\" array. Example:`,\n ``,\n `{`,\n ` \"models\": [`,\n ` {`,\n ` \"id\": \"<your-model-id>\",`,\n ` \"vendor\": \"<vendor-name>\",`,\n ` \"baseUrl\": \"https://...\",`,\n ` \"apiKey\": \"\\${YOUR_API_KEY}\",`,\n ` \"supportsToolCall\": true`,\n ` }`,\n ` ]`,\n `}`,\n ``,\n `Then run /model again (no restart needed).`,\n ].join(\"\\n\");\n}\n\n// ----- /config -----\n\nconst CONFIG: SlashCommand = {\n name: \"config\",\n description: \"show / reload configuration (API keys redacted)\",\n argsHint: \"[reload | path]\",\n async execute(ctx) {\n const sub = ctx.args.trim();\n\n if (sub === \"reload\") {\n try {\n const { sources } = await ctx.actions.reloadSettings();\n return { display: `Reloaded from ${sources.length} sources:\\n` + sources.map((s) => ` - ${shortPath(s)}`).join(\"\\n\") };\n } catch (err) {\n return { display: `Reload failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n }\n\n if (sub === \"path\") {\n return { display: renderConfigPaths(ctx) };\n }\n\n if (sub && sub !== \"show\") {\n return { display: `Unknown subcommand: /config ${sub}. Use: /config [show|reload|path]` };\n }\n\n return { display: renderConfigShow(ctx) };\n },\n};\n\nfunction renderConfigShow(ctx: SlashCommandContext): string {\n const s = ctx.settings;\n const lines = [\n `Effective configuration`,\n ` sources:`,\n ...ctx.settingsSources.map((src) => ` - ${shortPath(src)}`),\n ``,\n ` llm:`,\n ` provider: ${s.llm?.provider ?? \"(unset)\"}`,\n ` model: ${s.llm?.model ?? \"(unset)\"}`,\n ];\n if (s.llm?.temperature !== undefined) lines.push(` temperature: ${s.llm.temperature}`);\n if (s.llm?.maxTokens !== undefined) lines.push(` maxTokens: ${s.llm.maxTokens}`);\n\n lines.push(``, ` providers (apiKey redacted):`);\n for (const [name, cfg] of Object.entries(s.providers ?? {})) {\n lines.push(` ${name}: apiKey=${redactApiKey(cfg.apiKey)} baseUrl=${cfg.baseUrl ?? \"(default)\"}`);\n }\n\n lines.push(``, ` permissions:`);\n lines.push(` defaultMode: ${s.permissions?.defaultMode ?? \"ask\"}`);\n lines.push(` allow: ${formatList(s.permissions?.allow)}`);\n lines.push(` ask: ${formatList(s.permissions?.ask)}`);\n lines.push(` deny: ${formatList(s.permissions?.deny)}`);\n\n lines.push(``, ` ui:`);\n lines.push(` lang: ${s.ui?.lang ?? \"(default)\"}`);\n lines.push(` showBanner: ${s.ui?.showBanner ?? true}`);\n\n return lines.join(\"\\n\");\n}\n\nfunction renderConfigPaths(ctx: SlashCommandContext): string {\n const home = process.env.HOME ?? \"~\";\n return [\n `Configuration file paths (high to low precedence):`,\n ` 1. CLI flags / env (MUSE_PROVIDER, MUSE_MODEL, …)`,\n ` 2. ${shortPath(`${ctx.cwd}/.muse/settings.local.json`)} (project, gitignored)`,\n ` 3. ${shortPath(`${ctx.cwd}/.muse/settings.json`)} (project, committable)`,\n ` 4. ${shortPath(`${home}/.muse/settings.json`)} (global)`,\n ` 5. <built-in defaults>`,\n ``,\n `Edit any of the above, then run /config reload (no restart needed).`,\n ].join(\"\\n\");\n}\n\n// ----- /mcp -----\n\nconst MCP: SlashCommand = {\n name: \"mcp\",\n description: \"show MCP server status\",\n execute(ctx) {\n const status = getMCPStatus(ctx.settings);\n if (status.length === 0) {\n return {\n display:\n `No MCP servers configured.\\n` +\n `Add servers under \"mcpServers\" in your settings.json.\\n` +\n `Note: MCP client integration is planned for v0.3; current /mcp only inspects configuration.`,\n };\n }\n const lines = [`MCP servers (${status.length}):`];\n for (const s of status) {\n const indicator = s.connected ? \"●\" : \"○\";\n lines.push(` ${indicator} ${s.name}`);\n lines.push(` configured: ${s.configured}`);\n lines.push(` connected: ${s.connected}${s.error ? ` (${s.error})` : \"\"}`);\n if (s.connected) lines.push(` tools: ${s.toolCount}`);\n if (s.config?.command) lines.push(` command: ${s.config.command}${s.config.args ? \" \" + s.config.args.join(\" \") : \"\"}`);\n if (s.config?.url) lines.push(` url: ${s.config.url}`);\n }\n return { display: lines.join(\"\\n\") };\n },\n};\n\n// ----- /resume -----\n\nconst RESUME: SlashCommand = {\n name: \"resume\",\n description: \"resume a past session (↑↓ to pick, or pass an id-prefix)\",\n argsHint: \"[session-id-prefix]\",\n async execute(ctx) {\n // 带参快捷路径:直接按 id 前缀加载,不弹 selector\n if (ctx.args) {\n let meta;\n try {\n meta = await Session.resolve(ctx.cwd, ctx.args);\n } catch (err) {\n return { display: err instanceof Error ? err.message : String(err) };\n }\n if (!meta) return { display: `No session matches \"${ctx.args}\".` };\n return loadAndReport(meta, ctx);\n }\n\n // 无参:列出近 20 条交给 selector\n const list = await Session.listAll(ctx.cwd, 20);\n if (list.length === 0) return { display: \"No past sessions in this directory.\" };\n\n const picked = await ctx.actions.pickSession(list, ctx.session.meta.id);\n if (!picked) return { display: \"(cancelled)\" };\n if (picked.id === ctx.session.meta.id) return { display: \"Already on this session.\" };\n\n return loadAndReport(picked, ctx);\n },\n};\n\nasync function loadAndReport(\n meta: { id: string; createdAt: string; path: string; cwd: string },\n ctx: import(\"./types.js\").SlashCommandContext,\n): Promise<{ display: string }> {\n const { events } = await Session.open(meta);\n const messages = Session.messagesFromEvents(events);\n ctx.actions.setMessages(messages);\n return {\n display: `Resumed session ${meta.id.slice(0, 8)} (${messages.length} messages from ${formatTime(meta.createdAt)}).`,\n };\n}\n\n// ----- /mode -----\n\nconst MODE_ALIASES: Record<string, PermissionMode> = {\n default: \"default\",\n normal: \"default\",\n acceptedits: \"acceptEdits\",\n \"accept-edits\": \"acceptEdits\",\n accept: \"acceptEdits\",\n edits: \"acceptEdits\",\n plan: \"plan\",\n bypass: \"bypassPermissions\",\n bypasspermissions: \"bypassPermissions\",\n};\n\nconst MODE_CMD: SlashCommand = {\n name: \"mode\",\n description: \"show or switch the permission mode (alternative to Shift+Tab)\",\n argsHint: \"[default|acceptEdits|plan|bypassPermissions]\",\n execute(ctx) {\n const arg = ctx.args.trim().toLowerCase();\n if (!arg) {\n const cur = ctx.actions.getMode();\n const lines = [`Current permission mode: ${cur} — ${MODE_LABEL[cur]}`, ``, `Available modes:`];\n for (const m of MODE_CYCLE) {\n const marker = m === cur ? \"●\" : \" \";\n lines.push(` ${marker} ${m.padEnd(20)} ${MODE_LABEL[m]}`);\n }\n lines.push(``, `Switch: /mode <name> or Shift+Tab to cycle`);\n return { display: lines.join(\"\\n\") };\n }\n const target = MODE_ALIASES[arg];\n if (!target) {\n return {\n display: `Unknown mode \"${ctx.args.trim()}\". Valid: ${MODE_CYCLE.join(\" | \")}`,\n };\n }\n if (target === ctx.actions.getMode()) return { display: `Already in ${target} mode.` };\n ctx.actions.setMode(target);\n return { display: `Switched to ${target} — ${MODE_LABEL[target]}` };\n },\n};\n\n// ----- /btw -----\n\nconst BTW: SlashCommand = {\n name: \"btw\",\n description: \"ask a quick side question (answer in popup, not saved to history)\",\n argsHint: \"<question>\",\n async execute(ctx) {\n const q = ctx.args.trim();\n if (!q) {\n return {\n display:\n `Usage: /btw <question>\\n` +\n ` One-shot Q&A using the current conversation as context.\\n` +\n ` The Q & A are shown in an overlay and NOT added to history.\\n` +\n ` No tools — the model answers from context + its own knowledge.`,\n };\n }\n // askBtw 在浮层关闭时 resolve;display 返回空 → applySlashResult 不会追加任何 assistant 消息\n await ctx.actions.askBtw(q);\n return {};\n },\n};\n\n// ----- /memory -----\n\nconst MEMORY_HELP = [\n `Usage:`,\n ` /memory list all memories (default; both scopes)`,\n ` /memory list [--scope <s>] list (s = project | user | all)`,\n ` /memory view <name> [--scope <s>] show full content + frontmatter`,\n ` /memory edit <name> [--scope <s>] open in $EDITOR; trust auto→verified on save`,\n ` /memory delete <name> [--scope <s>] remove permanently`,\n ` /memory promote <name> auto → verified`,\n ` /memory promote-scope <name> project → user (lift to global scope)`,\n ` /memory trust <name> <level> set trust (verified | auto;`,\n ` trusted reserved for MUSE.md / AGENTS.md)`,\n ` /memory search <query> vector-based semantic search`,\n ` /memory diff [--scope <s>] show memories sorted by updated_at (recent first)`,\n ` /memory diagnose show embedding status + config + fix tips`,\n ``,\n `Scopes:`,\n ` [project] per-project memory: ~/.muse/projects/<hash>/memory/`,\n ` [user] global cross-project memory: ~/.muse/memory/`,\n ` Both are merged at recall time; project ranks higher when scores tie.`,\n].join(\"\\n\");\n\n/** 解析 --scope=<value> 或 --scope <value> 标志。返回 scope + 剩余 args 列表。 */\nfunction parseScopeFlag(parts: string[]): { scope?: Scope | \"all\"; rest: string[] } {\n const rest: string[] = [];\n let scope: Scope | \"all\" | undefined;\n for (let i = 0; i < parts.length; i++) {\n const p = parts[i];\n if (p === \"--scope\" && i + 1 < parts.length) {\n const v = parts[i + 1];\n if (v === \"all\" || (SCOPES as readonly string[]).includes(v)) {\n scope = v as Scope | \"all\";\n i++;\n continue;\n }\n } else if (p.startsWith(\"--scope=\")) {\n const v = p.slice(\"--scope=\".length);\n if (v === \"all\" || (SCOPES as readonly string[]).includes(v)) {\n scope = v as Scope | \"all\";\n continue;\n }\n }\n rest.push(p);\n }\n return { scope, rest };\n}\n\nconst MEMORY: SlashCommand = {\n name: \"memory\",\n description: \"manage long-term memory (list / view / delete / promote / promote-scope / trust / search)\",\n argsHint: \"[list | view <name> | delete <name> | promote <name> | promote-scope <name> | trust <name> <level> | search <query>] [--scope project|user|all]\",\n async execute(ctx) {\n const args = ctx.args.trim();\n const allParts = args.length ? args.split(/\\s+/) : [];\n const { scope, rest: parts } = parseScopeFlag(allParts);\n const sub = parts[0] ?? \"list\";\n try {\n switch (sub) {\n case \"list\":\n return await memoryList(ctx.cwd, scope ?? \"all\");\n case \"view\":\n if (!parts[1]) return { display: `Usage: /memory view <name> [--scope project|user]` };\n return await memoryView(ctx.cwd, parts[1], scope === \"all\" ? undefined : scope);\n case \"delete\":\n case \"rm\":\n if (!parts[1]) return { display: `Usage: /memory delete <name> [--scope project|user]` };\n return await memoryDelete(ctx.cwd, parts[1], scope === \"all\" ? undefined : scope);\n case \"promote\":\n if (!parts[1]) return { display: `Usage: /memory promote <name>` };\n return await memoryPromote(ctx.cwd, parts[1], scope === \"all\" ? undefined : scope);\n case \"promote-scope\":\n if (!parts[1]) return { display: `Usage: /memory promote-scope <name> (project → user)` };\n return await memoryPromoteScope(ctx.cwd, parts[1]);\n case \"trust\":\n if (!parts[1] || !parts[2]) return { display: `Usage: /memory trust <name> <verified|auto> [--scope project|user]` };\n return await memoryAssignTrust(ctx.cwd, parts[1], parts[2], scope === \"all\" ? undefined : scope);\n case \"search\": {\n const query = parts.slice(1).join(\" \");\n if (!query) return { display: `Usage: /memory search <query>` };\n return await memorySearch(ctx.cwd, query);\n }\n case \"diff\":\n return await memoryDiff(ctx.cwd, scope === \"all\" ? undefined : scope);\n case \"edit\":\n if (!parts[1]) return { display: `Usage: /memory edit <name> [--scope project|user]` };\n return await memoryEdit(ctx, parts[1], scope === \"all\" ? undefined : scope);\n case \"diagnose\":\n case \"doctor\":\n return await memoryDiagnose(ctx.cwd, ctx.settings);\n case \"help\":\n return { display: MEMORY_HELP };\n default:\n return { display: `Unknown subcommand: ${sub}\\n\\n${MEMORY_HELP}` };\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { display: `Memory operation failed: ${msg}` };\n }\n },\n};\n\nasync function memoryList(cwd: string, scope: Scope | \"all\") {\n const list = await listMemories(cwd, { scope });\n if (list.length === 0) {\n const where = scope === \"all\" ? \"either scope\" : `scope=${scope}`;\n return { display: `(no memories saved in ${where})\\n\\n${MEMORY_HELP}` };\n }\n const lines = list.map((m) => {\n const trustTag = `[${m.frontmatter.trust}]`.padEnd(11);\n const scopeTag = `[${m.scope}]`.padEnd(10);\n const typeTag = `(${m.frontmatter.type})`.padEnd(12);\n return ` ${trustTag} ${scopeTag} ${typeTag} ${m.frontmatter.name} — ${m.frontmatter.description}`;\n });\n const scopeNote = scope === \"all\" ? \"(both scopes merged)\" : `(scope=${scope})`;\n return {\n display: `Memories ${scopeNote} — ${list.length} total:\\n\\n${lines.join(\"\\n\")}\\n\\n${MEMORY_HELP}`,\n };\n}\n\nasync function memoryView(cwd: string, name: string, scope?: Scope) {\n const file = await readMemory(cwd, name, scope);\n const fm = file.frontmatter;\n return {\n display:\n `${name} (scope: ${file.scope})\\n` +\n ` trust: ${fm.trust}\\n` +\n ` type: ${fm.type}\\n` +\n ` source: ${fm.source}\\n` +\n ` created: ${fm.created_at}\\n` +\n ` updated: ${fm.updated_at}\\n` +\n ` description: ${fm.description}\\n\\n` +\n `--- Body ---\\n\\n${file.body}`,\n };\n}\n\nasync function memoryDelete(cwd: string, name: string, scope?: Scope) {\n // 先验证存在性,避免静默无效操作;返回的 actualScope 用作提示\n const file = await readMemory(cwd, name, scope);\n const removed = await deleteMemory(cwd, name, file.scope);\n return { display: `Deleted memory \"${name}\" (scope=${removed}).` };\n}\n\nasync function memoryPromote(cwd: string, name: string, scope?: Scope) {\n const before = await readMemory(cwd, name, scope);\n if (before.frontmatter.trust === \"trusted\") {\n return { display: `\"${name}\" (scope=${before.scope}) is already trusted (hierarchy-sourced).` };\n }\n if (before.frontmatter.trust === \"verified\") {\n return { display: `\"${name}\" (scope=${before.scope}) is already verified. Trusted is reserved for MUSE.md / AGENTS.md.` };\n }\n await setMemoryTrust(cwd, name, \"verified\", \"user-edit\", before.scope);\n return { display: `Promoted \"${name}\" (scope=${before.scope}): auto → verified.` };\n}\n\nasync function memoryPromoteScope(cwd: string, name: string) {\n const promoted = await promoteScopeToUser(cwd, name);\n if (!promoted) return { display: `\"${name}\" is already in user scope; nothing to promote.` };\n return {\n display:\n `Promoted \"${name}\" scope: project → user.\\n` +\n `It is now visible across ALL projects on this machine.\\n` +\n `(source set to \"promote-scope\"; trust preserved.)`,\n };\n}\n\n/** /memory diagnose: 当前 embedding 状态 + 配置 + 修复建议。\n * 这是用户启用 embedding 后失败排查的入口。 */\nasync function memoryDiagnose(cwd: string, settings: import(\"../config/types.js\").Settings) {\n const lines: string[] = [\"Memory diagnose:\"];\n const emb = settings.memory?.embedding;\n\n // 启用状态\n lines.push(``);\n lines.push(` Embedding enabled: ${emb?.enabled === true ? \"YES\" : \"NO (default; using MEMORY.md full-text injection)\"}`);\n if (!emb?.enabled) {\n lines.push(``);\n lines.push(` To enable embedding recall, add to ~/.muse/settings.local.json:`);\n lines.push(` {`);\n lines.push(` \"memory\": {`);\n lines.push(` \"embedding\": {`);\n lines.push(` \"enabled\": true,`);\n lines.push(` \"preset\": \"dashscope-v3\", // or openai-3-small / ollama-nomic / etc.`);\n lines.push(` \"apiKey\": \"\\${DASHSCOPE_API_KEY}\"`);\n lines.push(` }`);\n lines.push(` }`);\n lines.push(` }`);\n lines.push(``);\n lines.push(` Available presets:`);\n for (const name of listPresetNames()) {\n const p = EMBEDDING_PRESETS[name];\n lines.push(` ${name.padEnd(18)} dim=${String(p.dim).padEnd(5)} ${p.requiresKey ? \"needs key\" : \"no key\"} — ${p.description}`);\n }\n return { display: lines.join(\"\\n\") };\n }\n\n // 配置详情\n lines.push(``);\n lines.push(` Configuration:`);\n if (emb.preset) {\n const preset = EMBEDDING_PRESETS[emb.preset];\n if (preset) {\n lines.push(` preset: ${emb.preset}`);\n lines.push(` preset baseUrl: ${preset.baseUrl}${emb.baseUrl ? ` (overridden: ${emb.baseUrl})` : \"\"}`);\n lines.push(` preset model: ${preset.model}${emb.model ? ` (overridden: ${emb.model})` : \"\"}`);\n lines.push(` preset dim: ${preset.dim}${emb.dim !== undefined ? ` (overridden: ${emb.dim}, will send dimensions= parameter)` : \"\"}`);\n lines.push(` needs apiKey: ${preset.requiresKey ? \"yes\" : \"no\"}`);\n } else {\n lines.push(` preset: ${emb.preset} ⚠ UNKNOWN preset!`);\n lines.push(` Valid presets: ${listPresetNames().join(\", \")}`);\n }\n } else if (emb.provider) {\n lines.push(` provider: ${emb.provider} (custom)`);\n lines.push(` baseUrl: ${emb.baseUrl ?? \"(missing)\"}`);\n lines.push(` model: ${emb.model ?? \"(missing)\"}`);\n lines.push(` dim: ${emb.dim ?? \"(missing)\"}`);\n } else {\n lines.push(` ⚠ Neither preset nor provider set — embedding will be disabled`);\n }\n lines.push(` apiKey set: ${emb.apiKey ? \"yes (will be redacted in logs)\" : \"no\"}`);\n lines.push(` topK: ${emb.topK ?? 5} (default)`);\n lines.push(` minMemoryCount: ${emb.minMemoryCount ?? 3} (default)`);\n lines.push(` maxInjectTokens: ${emb.maxInjectTokens ?? 1500} (default)`);\n\n // 索引文件状态\n lines.push(``);\n lines.push(` Index files (.index.json):`);\n for (const [label, dir] of [[\"project\", memoryDir(cwd)], [\"user\", globalMemoryDir()]] as const) {\n const idxPath = join(dir, \".index.json\");\n if (existsSync(idxPath)) {\n let size = 0;\n let mtime = \"?\";\n try {\n const st = statSync(idxPath);\n size = st.size;\n mtime = st.mtime.toISOString();\n } catch {}\n lines.push(` [${label}] ${idxPath}`);\n lines.push(` size=${size}B mtime=${mtime}`);\n } else {\n lines.push(` [${label}] ${idxPath} (not built yet)`);\n }\n }\n\n // 实时 probe(可选;只做轻量探针,不构建索引)\n lines.push(``);\n lines.push(` Live probe:`);\n try {\n const provider = await createAndProbeProvider(emb);\n lines.push(` ✓ provider OK id=${provider.id} dim=${provider.dim}`);\n } catch (err) {\n lines.push(` ✗ FAILED: ${(err as Error).message}`);\n lines.push(``);\n lines.push(` Fix suggestions:`);\n const msg = (err as Error).message;\n if (msg.includes(\"dimension mismatch\")) {\n lines.push(` → Model returned a different dim than configured. Set settings.memory.embedding.dim to the actual value shown above.`);\n } else if (msg.includes(\"requires apiKey\")) {\n lines.push(` → Set settings.memory.embedding.apiKey (\\${ENV_VAR} supported).`);\n } else if (msg.includes(\"Unknown preset\") || msg.includes(\"Unknown embedding\")) {\n lines.push(` → Valid presets: ${listPresetNames().join(\", \")}`);\n } else if (msg.includes(\"HTTP 401\") || msg.includes(\"Unauthorized\")) {\n lines.push(` → API key invalid. Re-check the env var or value.`);\n } else if (msg.includes(\"HTTP 429\")) {\n lines.push(` → Rate-limited or quota exhausted. Wait, or upgrade your plan.`);\n } else if (msg.includes(\"HTTP 404\")) {\n lines.push(` → Model not found. Check the model name; for Ollama, run \\`ollama pull <model>\\`.`);\n } else if (msg.includes(\"timeout\") || msg.includes(\"network error\")) {\n lines.push(` → Network unreachable. Check baseUrl, firewall, VPN.`);\n } else {\n lines.push(` → See the error above for details. Common causes: wrong key / model / baseUrl / network.`);\n }\n lines.push(``);\n lines.push(` While embedding is broken, muse falls back to MEMORY.md full-text injection automatically.`);\n }\n\n return { display: lines.join(\"\\n\") };\n}\n\n/** /memory diff: 按 updated_at 降序列出 memory + 人类可读的\"X 时间前\"标签。 */\nasync function memoryDiff(cwd: string, scope?: Scope) {\n const list = await listMemories(cwd, { scope: scope ?? \"all\" });\n if (list.length === 0) {\n return { display: `(no memories to diff)\\n\\n${MEMORY_HELP}` };\n }\n const now = Date.now();\n const sorted = list.slice().sort((a, b) => {\n const ta = Date.parse(a.frontmatter.updated_at);\n const tb = Date.parse(b.frontmatter.updated_at);\n return tb - ta;\n });\n const lines = sorted.map((m) => {\n const t = Date.parse(m.frontmatter.updated_at);\n const ago = formatTimeAgo(now - t);\n const trustTag = `[${m.frontmatter.trust}]`.padEnd(11);\n const scopeTag = `[${m.scope}]`.padEnd(10);\n return ` ${ago.padEnd(20)} ${trustTag} ${scopeTag} ${m.frontmatter.name} — ${m.frontmatter.description}`;\n });\n return {\n display:\n `Memories sorted by updated_at (most recent first):\\n\\n${lines.join(\"\\n\")}\\n\\n` +\n `Tip: use /memory view <name> for full content; /memory edit <name> to open in $EDITOR.`,\n };\n}\n\nfunction formatTimeAgo(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return \"(unknown)\";\n const sec = Math.floor(ms / 1000);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const days = Math.floor(hr / 24);\n if (days < 30) return `${days}d ago`;\n const months = Math.floor(days / 30);\n if (months < 12) return `${months}mo ago`;\n return `${Math.floor(months / 12)}y ago`;\n}\n\n/** /memory edit: 在 $VISUAL || $EDITOR || vi 中打开 memory 文件;退出后自动升 auto → verified。 */\nasync function memoryEdit(ctx: import(\"./types.js\").SlashCommandContext, name: string, scope?: Scope) {\n // 找文件并校验存在\n const file = await readMemory(ctx.cwd, name, scope);\n const before = file.frontmatter.updated_at;\n const beforeBody = file.body;\n\n try {\n await ctx.actions.openInEditor(file.filePath);\n } catch (err) {\n return { display: `Editor failed: ${(err as Error).message}` };\n }\n\n // 重读检查变化\n let after;\n try {\n after = await readMemory(ctx.cwd, name, file.scope);\n } catch (err) {\n return { display: `Memory \"${name}\" no longer exists after edit (deleted or renamed).` };\n }\n\n const changed = after.frontmatter.updated_at !== before || after.body !== beforeBody;\n\n if (!changed) {\n return {\n display: `No changes to \"${name}\" (scope=${file.scope}).`,\n };\n }\n\n // 文件被改了 — 如果原 trust 是 auto,自动升 verified\n let trustNote = \"\";\n if (after.frontmatter.trust === \"auto\") {\n try {\n await setMemoryTrust(ctx.cwd, name, \"verified\", \"user-edit\", file.scope);\n trustNote = \"\\n trust: auto → verified (user edit)\";\n } catch (err) {\n trustNote = `\\n trust upgrade failed: ${(err as Error).message}`;\n }\n }\n\n return {\n display:\n `Saved memory \"${name}\" (scope=${file.scope})${trustNote}\\n` +\n ` → ${file.filePath}`,\n };\n}\n\nasync function memorySearch(cwd: string, query: string) {\n const index = await buildMemoryIndex(cwd);\n if (index.entries.length === 0) {\n return { display: `(no memories saved for this project)\\n\\nWrite some first with MemoryWrite (LLM-side) or /remember.` };\n }\n const results = await queryMemoryIndex(index, query, { topK: 5 });\n if (results.length === 0) {\n return { display: `(no memories matched \"${query}\")\\n\\nTry simpler keywords; current provider is \"${index.provider.id}\" — pure keyword + simple semantic matching.` };\n }\n const lines = results.map((r, i) => {\n const score = (r.score * 100).toFixed(1);\n const w = r.weighted.toFixed(3);\n return ` ${i + 1}. [${r.entry.trust}] [${r.entry.scope}] (${r.entry.type}) ${r.entry.name} score=${score}% w=${w}\\n — ${r.entry.description}`;\n });\n return {\n display:\n `Top ${results.length} match${results.length === 1 ? \"\" : \"es\"} for \"${query}\":\\n\\n` +\n lines.join(\"\\n\\n\") +\n `\\n\\n(provider: ${index.provider.id}; use /memory view <name> to see full content)`,\n };\n}\n\nasync function memoryAssignTrust(cwd: string, name: string, levelArg: string, scope?: Scope) {\n if (!(TRUST_LEVELS as readonly string[]).includes(levelArg)) {\n return { display: `Invalid trust level: ${levelArg}. Use one of: ${TRUST_LEVELS.join(\" / \")}.` };\n }\n if (levelArg === \"trusted\") {\n return {\n display:\n `Cannot set trust=trusted via /memory; trusted is reserved for hierarchy files ` +\n `(MUSE.md / AGENTS.md). To make this content trusted, move it into one of those files.`,\n };\n }\n await setMemoryTrust(cwd, name, levelArg as TrustLevel, \"user-edit\", scope);\n return { display: `Set \"${name}\" trust → ${levelArg}${scope ? ` (scope=${scope})` : \"\"}.` };\n}\n\n// ----- /remember -----\n\nconst REMEMBER_TIPS = [\n \"Default scope is user (cross-project)\",\n \"Use --project to save only to current project\",\n \"trust=verified because YOU asked muse to remember\",\n \"Edit later via /memory view <name> or shell\",\n];\n\nconst REMEMBER: SlashCommand = {\n name: \"remember\",\n description: \"save a memory from user-described text (LLM distills structure); default scope=user\",\n argsHint: \"[--user|--project] <text>\",\n async execute(ctx) {\n const raw = ctx.args.trim();\n if (!raw) {\n return {\n display:\n `Usage: /remember [--user|--project] <text>\\n` +\n ` Default scope is \"user\" (cross-project; saved to ~/.muse/memory/).\\n` +\n ` Use --project to scope to current project only.\\n` +\n ` muse will call the active LLM to extract { name, type, description, body }, ` +\n `then save with trust=verified, source=user-remember.`,\n };\n }\n // 解析 scope flag(必须在最前)\n let scope: Scope = \"user\";\n let text = raw;\n if (text.startsWith(\"--user\")) {\n scope = \"user\";\n text = text.slice(\"--user\".length).trim();\n } else if (text.startsWith(\"--project\")) {\n scope = \"project\";\n text = text.slice(\"--project\".length).trim();\n }\n if (!text) return { display: \"Usage: /remember [--user|--project] <text>\" };\n\n ctx.actions.showProgress({\n title: `Distilling memory (scope=${scope})`,\n tips: REMEMBER_TIPS,\n });\n try {\n const extracted = await distillMemoryStructure(ctx.llm, text, scope);\n if (!extracted) {\n return {\n display:\n `Failed to extract structured memory from your text.\\n` +\n `Try a clearer statement, e.g.:\\n` +\n ` /remember I prefer pnpm over npm in all projects\\n` +\n ` /remember --project this team uses semantic-release for versioning`,\n };\n }\n const result = await writeMemory(ctx.cwd, {\n name: extracted.name,\n description: extracted.description,\n type: extracted.type,\n body: extracted.body,\n trust: \"verified\",\n source: \"user-remember\",\n scope,\n });\n const action = result.created ? \"Created\" : \"Updated\";\n return {\n display:\n `${action} memory \"${extracted.name}\"\\n` +\n ` scope: ${result.scope}\\n` +\n ` type: ${extracted.type}\\n` +\n ` trust: verified (source: user-remember)\\n` +\n ` description: ${extracted.description}\\n` +\n ` → ${result.filePath}`,\n };\n } finally {\n ctx.actions.hideProgress();\n }\n },\n};\n\ninterface ExtractedMemory {\n name: string;\n type: MemoryType;\n description: string;\n body: string;\n}\n\nasync function distillMemoryStructure(\n llm: LLMClient,\n userText: string,\n scope: Scope,\n): Promise<ExtractedMemory | null> {\n const scopeNote =\n scope === \"user\"\n ? \"user-level (cross-project preference / role / style)\"\n : \"project-level (specific to the current project)\";\n const prompt =\n `User wants to save a long-term memory. Extract structured fields.\\n\\n` +\n `Target scope: ${scope} — ${scopeNote}\\n\\n` +\n `User said:\\n\"\"\"\\n${userText}\\n\"\"\"\\n\\n` +\n `Reply with ONE json code block in this exact shape:\\n\\n` +\n \"```json\\n\" +\n `{\\n` +\n ` \"name\": \"kebab-case-slug\",\\n` +\n ` \"type\": \"user\" | \"feedback\" | \"project\" | \"reference\",\\n` +\n ` \"description\": \"one-line summary, ≤ 80 chars\",\\n` +\n ` \"body\": \"markdown body\"\\n` +\n `}\\n` +\n \"```\\n\\n\" +\n `Field rules:\\n` +\n `- name: kebab- or snake-style slug, ≤ 40 chars, captures the topic\\n` +\n `- type: user(role/prefs) | feedback(validated practice) | project(decisions/facts) | reference(URL/path pointers)\\n` +\n `- description: short hook used in MEMORY.md index\\n` +\n `- body: markdown; for feedback/project, structure as: rule line + \"Why: ...\" + \"How to apply: ...\"\\n\\n` +\n `Output ONLY the json block. No prose before or after.`;\n\n let text = \"\";\n try {\n for await (const ev of llm.stream({ messages: [{ role: \"user\", content: prompt }] })) {\n if (ev.type === \"text\") text += ev.delta;\n else if (ev.type === \"error\") throw ev.error;\n }\n } catch {\n return null;\n }\n\n const m = text.match(/```(?:json)?\\s*\\n([\\s\\S]*?)\\n```/);\n if (!m) return null;\n try {\n const parsed = JSON.parse(m[1].trim());\n const name = typeof parsed.name === \"string\" ? parsed.name : \"\";\n const description = typeof parsed.description === \"string\" ? parsed.description : \"\";\n const body = typeof parsed.body === \"string\" ? parsed.body : \"\";\n const type = parsed.type;\n if (!name || !description || !body) return null;\n if (!/^[a-z0-9][a-z0-9-_]*$/i.test(name)) return null;\n if (type !== \"user\" && type !== \"feedback\" && type !== \"project\" && type !== \"reference\") return null;\n return { name, type, description, body };\n } catch {\n return null;\n }\n}\n\n// ----- registry -----\n\nexport const BUILTIN_SLASH_COMMANDS: SlashCommand[] = [\n HELP,\n CLEAR,\n COMPACT,\n MODELS,\n CONFIG,\n MCP,\n MEMORY,\n REMEMBER,\n MODE_CMD,\n COST,\n BTW,\n RESUME,\n EXIT,\n];\n","/**\n * 工具注册中心:管理所有可用工具,提供查询、调用、转 LLM-tool-definition 的能力。\n */\n\nimport { z } from \"zod\";\nimport type { AnyTool, ToolContext, ToolExecuteResult } from \"./types.js\";\nimport type { ToolDefinition as LLMToolDefinition } from \"../types/index.js\";\nimport { ToolError } from \"../types/index.js\";\n\n/** zod schema → JSON Schema (subset)。仅覆盖 v0.1 需要的类型。 */\nfunction zodToJsonSchema(schema: z.ZodType<unknown>): Record<string, unknown> {\n const def = (schema as unknown as { _def: { typeName: string } })._def;\n\n if (def.typeName === \"ZodObject\") {\n const shape = (schema as unknown as z.ZodObject<Record<string, z.ZodTypeAny>>).shape;\n const properties: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as z.ZodType<unknown>);\n if (!(value as unknown as { isOptional?: () => boolean }).isOptional?.()) {\n required.push(key);\n }\n }\n return {\n type: \"object\",\n properties,\n ...(required.length > 0 ? { required } : {}),\n additionalProperties: false,\n };\n }\n\n if (def.typeName === \"ZodString\") {\n const d = def as unknown as { description?: string };\n return { type: \"string\", ...(d.description ? { description: d.description } : {}) };\n }\n\n if (def.typeName === \"ZodNumber\") {\n return { type: \"number\" };\n }\n\n if (def.typeName === \"ZodBoolean\") {\n return { type: \"boolean\" };\n }\n\n if (def.typeName === \"ZodArray\") {\n const inner = (def as unknown as { type: z.ZodType<unknown> }).type;\n return { type: \"array\", items: zodToJsonSchema(inner) };\n }\n\n if (def.typeName === \"ZodOptional\" || def.typeName === \"ZodDefault\") {\n const inner = (def as unknown as { innerType: z.ZodType<unknown> }).innerType;\n return zodToJsonSchema(inner);\n }\n\n if (def.typeName === \"ZodEnum\") {\n const values = (def as unknown as { values: string[] }).values;\n return { type: \"string\", enum: values };\n }\n\n if (def.typeName === \"ZodUnion\") {\n const opts = (def as unknown as { options: z.ZodType<unknown>[] }).options;\n return { anyOf: opts.map(zodToJsonSchema) };\n }\n\n // Fallback: 任意类型\n return {};\n}\n\nfunction getDescription(schema: z.ZodType<unknown>): string | undefined {\n return (schema as unknown as { description?: string }).description;\n}\n\nexport class ToolRegistry {\n private tools = new Map<string, AnyTool>();\n\n register(tool: AnyTool): void {\n if (this.tools.has(tool.name)) {\n throw new Error(`Tool \"${tool.name}\" already registered.`);\n }\n this.tools.set(tool.name, tool);\n }\n\n registerAll(tools: AnyTool[]): void {\n for (const tool of tools) this.register(tool);\n }\n\n get(name: string): AnyTool | undefined {\n return this.tools.get(name);\n }\n\n has(name: string): boolean {\n return this.tools.has(name);\n }\n\n list(): AnyTool[] {\n return Array.from(this.tools.values());\n }\n\n /** 转为 LLM 可读的 tool definition 数组。可选 filter(如 plan 模式过滤只读工具)。 */\n toLLMDefinitions(filter?: (tool: AnyTool) => boolean): LLMToolDefinition[] {\n let tools = this.list();\n if (filter) tools = tools.filter(filter);\n return tools.map((t) => {\n const schema = zodToJsonSchema(t.parameters);\n // 顶层描述:从 zod schema 的 .describe 拿\n const desc = getDescription(t.parameters);\n if (desc && typeof schema === \"object\" && schema !== null) {\n (schema as Record<string, unknown>).description = desc;\n }\n return {\n name: t.name,\n description: t.description,\n parameters: schema,\n };\n });\n }\n\n /** 调用工具:校验参数 → 执行。 */\n async execute(name: string, rawArgs: unknown, ctx: ToolContext): Promise<ToolExecuteResult> {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new ToolError(`Tool \"${name}\" not found.`, name);\n }\n const parseResult = tool.parameters.safeParse(rawArgs);\n if (!parseResult.success) {\n return {\n content: `Invalid arguments for ${name}: ${parseResult.error.message}`,\n isError: true,\n };\n }\n try {\n return await tool.execute(parseResult.data, ctx);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return { content: `Tool ${name} threw: ${msg}`, isError: true };\n }\n }\n}\n","/**\n * Read 工具:读取本地文件,支持 offset/limit 分页。\n * 返回带行号的 `cat -n` 格式,方便 LLM 引用具体行做编辑。\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { resolve, isAbsolute } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { ToolError } from \"../../types/index.js\";\nimport { checkSensitivePath } from \"../_sensitive.js\";\n\nconst ReadArgs = z.object({\n file_path: z.string().describe(\"Absolute or cwd-relative path to the file.\"),\n offset: z.number().int().min(0).optional().describe(\"Line offset (0-based).\"),\n limit: z.number().int().positive().optional().describe(\"Max lines to read. Default 2000.\"),\n});\n\nconst DEFAULT_LIMIT = 2000;\nconst MAX_LINE_LENGTH = 2000; // 单行超长时截断\n\nexport const ReadTool = defineTool({\n name: \"Read\",\n description: \"Read a file from the local filesystem. Returns content with 1-indexed line numbers (cat -n format). Use offset/limit for large files.\",\n parameters: ReadArgs,\n permission: \"read\",\n summarize: (args) => `Read(${args.file_path}${args.offset != null ? `, offset=${args.offset}` : \"\"}${args.limit != null ? `, limit=${args.limit}` : \"\"})`,\n async execute(args, ctx) {\n const path = isAbsolute(args.file_path) ? args.file_path : resolve(ctx.cwd, args.file_path);\n\n const sensitive = checkSensitivePath(path);\n if (sensitive.blocked) {\n return { content: `Refused: ${path} matches sensitive path policy (${sensitive.reason}).`, isError: true };\n }\n\n let info;\n try {\n info = await stat(path);\n } catch (err) {\n throw new ToolError(`File not found: ${path}`, \"Read\", err);\n }\n\n if (!info.isFile()) {\n throw new ToolError(`Not a regular file: ${path}`, \"Read\");\n }\n\n const content = await readFile(path, \"utf-8\");\n const lines = content.split(/\\r?\\n/);\n const offset = args.offset ?? 0;\n const limit = args.limit ?? DEFAULT_LIMIT;\n const slice = lines.slice(offset, offset + limit);\n\n const numbered = slice.map((line, i) => {\n const lineNo = offset + i + 1;\n const truncated = line.length > MAX_LINE_LENGTH ? line.slice(0, MAX_LINE_LENGTH) + \"... [truncated]\" : line;\n return `${String(lineNo).padStart(5, \" \")}\\t${truncated}`;\n });\n\n let result = numbered.join(\"\\n\");\n if (offset + limit < lines.length) {\n result += `\\n... [${lines.length - offset - limit} more lines, use offset=${offset + limit} to read next]`;\n }\n\n return {\n content: result || \"(empty file)\",\n summary: `Read ${slice.length} lines from ${args.file_path}`,\n };\n },\n});\n","/**\n * 工具系统类型。\n * 内置工具与 MCP 工具都遵循同一接口。\n */\n\nimport type { z } from \"zod\";\nimport type { TodoStore } from \"../loop/todos.js\";\nimport type { AskQuestion, AskQuestionResponse } from \"./builtin/ask-user-question.js\";\n\nexport type PermissionLevel = \"read\" | \"write\" | \"execute\" | \"network\";\n\nexport interface ToolContext {\n cwd: string;\n abortSignal?: AbortSignal;\n /** 询问用户对该工具调用的批准。返回 true=允许,false=拒绝。 */\n askPermission: (toolName: string, args: unknown, summary: string) => Promise<boolean>;\n /** 主代理可能想在工具内部发起子任务,预留口子。 */\n invokeSubagent?: (prompt: string) => Promise<string>;\n /** Session 内 todo 清单(TodoWrite 写入;system prompt 读取注入下一轮)。 */\n todos?: TodoStore;\n /**\n * AskUserQuestion 工具用:一次性弹出整批选择题(链式 tab UI)。\n * 返回数组与入参 questions 等长;Esc 取消时所有项 cancelled=true。\n */\n askQuestions?: (questions: AskQuestion[]) => Promise<AskQuestionResponse[]>;\n}\n\nexport interface ToolExecuteResult {\n /** 给 LLM 看的文本结果。 */\n content: string;\n /** 标记为错误:让 LLM 知道需要修复。 */\n isError?: boolean;\n /** 给 TUI 展示的摘要(一行)。 */\n summary?: string;\n /** Unified diff(Write/Edit 等改文件工具填),交给 UI 渲染绿/红行;不进 LLM 上下文。 */\n diff?: string;\n /** 状态点颜色(仅 UI):success 绿 / error 红 / warn 黄。不填则由 isError 推断。 */\n kind?: \"success\" | \"error\" | \"warn\";\n}\n\nexport interface ToolDefinition<TArgs = unknown> {\n name: string;\n description: string;\n /** zod schema 用于参数校验 + 自动转 JSON Schema。 */\n parameters: z.ZodType<TArgs>;\n /** 权限级别:UI 与 permission 模块据此决定 ask/allow/deny。 */\n permission: PermissionLevel;\n /** 一行摘要,给 TUI 在 \"→ ToolName(...)\" 之后显示。 */\n summarize?: (args: TArgs) => string;\n /** 实际执行函数。 */\n execute: (args: TArgs, ctx: ToolContext) => Promise<ToolExecuteResult>;\n}\n\n/** 类型擦除后的工具,用于 registry 存储 / 调用。 */\nexport interface AnyTool {\n name: string;\n description: string;\n parameters: z.ZodType<unknown>;\n permission: PermissionLevel;\n summarize?: (args: unknown) => string;\n execute: (args: unknown, ctx: ToolContext) => Promise<ToolExecuteResult>;\n}\n\nexport function defineTool<TArgs>(def: ToolDefinition<TArgs>): AnyTool {\n return {\n name: def.name,\n description: def.description,\n parameters: def.parameters as z.ZodType<unknown>,\n permission: def.permission,\n summarize: def.summarize as ((args: unknown) => string) | undefined,\n execute: def.execute as (args: unknown, ctx: ToolContext) => Promise<ToolExecuteResult>,\n };\n}\n","/**\n * Write 工具:写入文件(创建或覆盖)。\n *\n * 为防误覆盖,约定调用前必须先 Read 过同一路径(除非文件不存在)。\n * 这个约束实际由 LLM 遵守 (prompt 引导);本工具不强制,但记录到日志。\n */\n\nimport { readFile, writeFile, mkdir, stat } from \"node:fs/promises\";\nimport { resolve, isAbsolute, dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { makeUnifiedDiff } from \"../_diff.js\";\nimport { checkSensitivePath } from \"../_sensitive.js\";\n\nconst WriteArgs = z.object({\n file_path: z.string().describe(\"Absolute or cwd-relative path to the file.\"),\n content: z.string().describe(\"Full content of the file.\"),\n});\n\nexport const WriteTool = defineTool({\n name: \"Write\",\n description: \"Write a complete file to the local filesystem. Creates parent directories if needed. Overwrites existing files — prefer Edit for partial updates.\",\n parameters: WriteArgs,\n permission: \"write\",\n summarize: (args) => `Write(${args.file_path}, ${args.content.length} chars)`,\n async execute(args, ctx) {\n const path = isAbsolute(args.file_path) ? args.file_path : resolve(ctx.cwd, args.file_path);\n\n const sensitive = checkSensitivePath(path);\n if (sensitive.blocked) {\n return { content: `Refused: ${path} matches sensitive path policy (${sensitive.reason}).`, isError: true };\n }\n\n let existed = false;\n let oldContent = \"\";\n try {\n const info = await stat(path);\n existed = info.isFile();\n if (existed) oldContent = await readFile(path, \"utf-8\");\n } catch {\n // 文件不存在,正常情况\n }\n\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, args.content, \"utf-8\");\n\n const diff = makeUnifiedDiff(args.file_path, oldContent, args.content);\n\n return {\n content: existed\n ? `Overwrote ${path} (${args.content.length} bytes).`\n : `Created ${path} (${args.content.length} bytes).`,\n summary: `${existed ? \"Overwrote\" : \"Created\"} ${args.file_path}`,\n diff: diff || undefined,\n };\n },\n});\n","/**\n * 文件改动 → unified diff(jsdiff),仅给 UI 渲染用,不进 LLM 上下文。\n *\n * 上下文行数 3(GNU diff 默认);新文件 / 整体覆盖时呈现为全 + 行。\n */\n\nimport { createPatch } from \"diff\";\n\nconst MAX_DIFF_LINES = 200;\n\nexport function makeUnifiedDiff(filePath: string, oldContent: string, newContent: string): string {\n if (oldContent === newContent) return \"\";\n const patch = createPatch(filePath, oldContent, newContent, \"before\", \"after\", { context: 3 });\n return truncate(patch);\n}\n\nfunction truncate(diff: string): string {\n const lines = diff.split(\"\\n\");\n if (lines.length <= MAX_DIFF_LINES) return diff;\n return lines.slice(0, MAX_DIFF_LINES).join(\"\\n\") + `\\n... [${lines.length - MAX_DIFF_LINES} more diff lines truncated]`;\n}\n","/**\n * Edit 工具:在文件中做精确字符串替换。\n *\n * 必须先 Read 过文件(由调用方/LLM 遵守,不强制校验)。\n * old_string 必须在文件中唯一出现;replace_all=true 时不要求唯一。\n */\n\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve, isAbsolute } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport { ToolError } from \"../../types/index.js\";\nimport { makeUnifiedDiff } from \"../_diff.js\";\nimport { checkSensitivePath } from \"../_sensitive.js\";\n\nconst EditArgs = z.object({\n file_path: z.string().describe(\"Absolute or cwd-relative path to the file.\"),\n old_string: z.string().describe(\"Exact substring to replace. Must be unique unless replace_all=true.\"),\n new_string: z.string().describe(\"Replacement string.\"),\n replace_all: z.boolean().optional().describe(\"Replace every occurrence. Default false.\"),\n});\n\nexport const EditTool = defineTool({\n name: \"Edit\",\n description: \"Perform an exact string replacement in a file. Old string must be unique unless replace_all=true. Cheaper than Write when only a small part needs to change.\",\n parameters: EditArgs,\n permission: \"write\",\n summarize: (args) => `Edit(${args.file_path})`,\n async execute(args, ctx) {\n const path = isAbsolute(args.file_path) ? args.file_path : resolve(ctx.cwd, args.file_path);\n\n const sensitive = checkSensitivePath(path);\n if (sensitive.blocked) {\n return { content: `Refused: ${path} matches sensitive path policy (${sensitive.reason}).`, isError: true };\n }\n\n let content: string;\n try {\n content = await readFile(path, \"utf-8\");\n } catch (err) {\n throw new ToolError(`Cannot read ${path}: ${err instanceof Error ? err.message : String(err)}`, \"Edit\", err);\n }\n\n if (args.old_string === args.new_string) {\n return { content: \"old_string is identical to new_string; nothing to do.\", isError: true };\n }\n\n const occurrences = countOccurrences(content, args.old_string);\n if (occurrences === 0) {\n return {\n content: `old_string not found in ${args.file_path}. Did you read the file first? Check whitespace and indentation.`,\n isError: true,\n };\n }\n if (occurrences > 1 && !args.replace_all) {\n return {\n content: `old_string occurs ${occurrences} times in ${args.file_path}. Either expand context to make it unique, or set replace_all=true.`,\n isError: true,\n };\n }\n\n const newContent = args.replace_all\n ? content.split(args.old_string).join(args.new_string)\n : content.replace(args.old_string, args.new_string);\n\n await writeFile(path, newContent, \"utf-8\");\n\n const diff = makeUnifiedDiff(args.file_path, content, newContent);\n\n return {\n content: `Edited ${path}: replaced ${args.replace_all ? occurrences : 1} occurrence(s).`,\n summary: `Edited ${args.file_path}`,\n diff: diff || undefined,\n };\n },\n});\n\nfunction countOccurrences(haystack: string, needle: string): number {\n if (needle.length === 0) return 0;\n let count = 0;\n let pos = 0;\n while ((pos = haystack.indexOf(needle, pos)) !== -1) {\n count += 1;\n pos += needle.length;\n }\n return count;\n}\n","/**\n * Bash 工具:执行 shell 命令。\n *\n * 安全:内置 deny 列表(无法 allow 绕过)。\n * 上限:超时 + stdout 截断。\n */\n\nimport { execa } from \"execa\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst BashArgs = z.object({\n command: z.string().describe(\"Shell command to run. Will be executed via sh -c.\"),\n timeout: z.number().int().positive().optional().describe(\"Timeout in milliseconds. Default 120000 (2 min). Max 600000.\"),\n description: z.string().optional().describe(\"Brief description (3-10 words) for the UI.\"),\n});\n\nconst DEFAULT_TIMEOUT_MS = 120_000;\nconst MAX_TIMEOUT_MS = 600_000;\nconst MAX_OUTPUT_BYTES = 100_000;\n\n/** 即使在 allow 列表里也强制阻断的危险命令模式。 */\nconst HARD_DENY_PATTERNS: RegExp[] = [\n /\\brm\\s+-rf\\s+\\/(?:\\s|$)/, // rm -rf /\n /\\brm\\s+-rf\\s+~(?:\\/|\\s|$)/, // rm -rf ~ or ~/...\n /\\brm\\s+-rf\\s+\\*/, // rm -rf *\n /\\bdd\\s+.*of=\\/dev\\//, // dd of=/dev/*\n /\\bmkfs\\b/, // mkfs\n /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\}\\s*;\\s*:/, // fork bomb\n /\\bsudo\\b/, // sudo(v0.1 简单粗暴禁掉)\n /\\bcurl\\s+[^|]*\\|\\s*(?:sh|bash|zsh)/, // curl ... | sh\n /\\bwget\\s+[^|]*\\|\\s*(?:sh|bash|zsh)/, // wget ... | sh\n];\n\nfunction checkDangerous(command: string): { dangerous: true; reason: string } | { dangerous: false } {\n for (const pattern of HARD_DENY_PATTERNS) {\n if (pattern.test(command)) {\n return { dangerous: true, reason: `matches pattern ${pattern}` };\n }\n }\n return { dangerous: false };\n}\n\nexport const BashTool = defineTool({\n name: \"Bash\",\n description: \"Execute a shell command via sh -c. Use for git, file system listings, builds, tests, etc. Avoid interactive commands (prefer non-interactive flags). For file edits use Edit/Write, not sed/echo.\",\n parameters: BashArgs,\n permission: \"execute\",\n summarize: (args) => args.description ?? `Bash: ${args.command.length > 60 ? args.command.slice(0, 60) + \"...\" : args.command}`,\n async execute(args, ctx) {\n const danger = checkDangerous(args.command);\n if (danger.dangerous) {\n return {\n content: `Refused: command blocked by hard deny list (${danger.reason}). If you really need this, ask the user to run it manually.`,\n isError: true,\n };\n }\n\n const timeout = Math.min(args.timeout ?? DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n try {\n const result = await execa(args.command, {\n shell: \"/bin/sh\",\n cwd: ctx.cwd,\n timeout,\n reject: false,\n stripFinalNewline: false,\n maxBuffer: MAX_OUTPUT_BYTES * 2,\n cancelSignal: ctx.abortSignal,\n });\n\n const stdout = truncate(result.stdout ?? \"\", MAX_OUTPUT_BYTES, \"stdout\");\n const stderr = truncate(result.stderr ?? \"\", MAX_OUTPUT_BYTES, \"stderr\");\n\n const parts: string[] = [];\n if (stdout) parts.push(`<stdout>\\n${stdout}\\n</stdout>`);\n if (stderr) parts.push(`<stderr>\\n${stderr}\\n</stderr>`);\n if (result.timedOut) parts.push(`<timeout>Command exceeded ${timeout}ms.</timeout>`);\n if (result.failed && !result.timedOut) parts.push(`<exit_code>${result.exitCode ?? \"unknown\"}</exit_code>`);\n\n const body = parts.length > 0 ? parts.join(\"\\n\") : \"(no output)\";\n return {\n content: body,\n isError: result.failed,\n summary: result.failed ? `Bash exited ${result.exitCode ?? \"?\"}` : `Bash ok`,\n };\n } catch (err) {\n return {\n content: `Bash threw: ${err instanceof Error ? err.message : String(err)}`,\n isError: true,\n };\n }\n },\n});\n\nfunction truncate(text: string, max: number, label: string): string {\n if (text.length <= max) return text;\n return text.slice(0, max) + `\\n... [${label} truncated, original ${text.length} bytes]`;\n}\n","/**\n * Grep 工具:基于 ripgrep 包装(若可用),fallback 到 bash grep。\n * v0.1 简单实现:直接调 system rg / grep。\n */\n\nimport { execa } from \"execa\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst GrepArgs = z.object({\n pattern: z.string().describe(\"Regex pattern to search for.\"),\n path: z.string().optional().describe(\"File or directory to search in. Default: cwd.\"),\n glob: z.string().optional().describe('Glob filter, e.g. \"*.ts\" or \"src/**/*.tsx\".'),\n output_mode: z.enum([\"content\", \"files_with_matches\", \"count\"]).optional().describe(\"Default: files_with_matches.\"),\n context: z.number().int().min(0).max(50).optional().describe(\"Context lines around each match (use only with output_mode=content).\"),\n case_insensitive: z.boolean().optional(),\n});\n\nlet rgChecked = false;\nlet rgAvailable = false;\n\nasync function checkRipgrep(): Promise<boolean> {\n if (rgChecked) return rgAvailable;\n try {\n await execa(\"rg\", [\"--version\"], { reject: false });\n rgAvailable = true;\n } catch {\n rgAvailable = false;\n }\n rgChecked = true;\n return rgAvailable;\n}\n\nexport const GrepTool = defineTool({\n name: \"Grep\",\n description: \"Search file contents using regex. Prefer this over Bash(grep|find) — handles ignore files & is much faster on large trees.\",\n parameters: GrepArgs,\n permission: \"read\",\n summarize: (args) => `Grep(${args.pattern}${args.path ? `, ${args.path}` : \"\"})`,\n async execute(args, ctx) {\n const hasRg = await checkRipgrep();\n const mode = args.output_mode ?? \"files_with_matches\";\n\n if (hasRg) {\n const cliArgs: string[] = [];\n if (args.case_insensitive) cliArgs.push(\"-i\");\n if (mode === \"files_with_matches\") cliArgs.push(\"-l\");\n else if (mode === \"count\") cliArgs.push(\"-c\");\n else if (args.context != null) cliArgs.push(\"-C\", String(args.context));\n if (args.glob) cliArgs.push(\"--glob\", args.glob);\n cliArgs.push(\"--\", args.pattern, args.path ?? \".\");\n\n const result = await execa(\"rg\", cliArgs, { cwd: ctx.cwd, reject: false, cancelSignal: ctx.abortSignal });\n const out = (result.stdout ?? \"\").trim();\n if (result.exitCode === 0 || result.exitCode === 1) {\n return { content: out || \"(no matches)\", summary: `Grep ${args.pattern}` };\n }\n return { content: `rg failed: ${result.stderr}`, isError: true };\n }\n\n // Fallback: bash grep -r\n const cliArgs = [\"-r\", \"-n\"];\n if (args.case_insensitive) cliArgs.push(\"-i\");\n if (mode === \"files_with_matches\") cliArgs.push(\"-l\");\n else if (mode === \"count\") cliArgs.push(\"-c\");\n cliArgs.push(\"-E\", args.pattern, args.path ?? \".\");\n\n const result = await execa(\"grep\", cliArgs, { cwd: ctx.cwd, reject: false, cancelSignal: ctx.abortSignal });\n const out = (result.stdout ?? \"\").trim();\n if (result.exitCode === 0 || result.exitCode === 1) {\n return { content: out || \"(no matches)\", summary: `Grep ${args.pattern}` };\n }\n return { content: `grep failed: ${result.stderr}`, isError: true };\n },\n});\n","/**\n * Glob 工具:用 fast-glob 列出匹配文件。\n */\n\nimport fg from \"fast-glob\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst GlobArgs = z.object({\n pattern: z.string().describe('Glob pattern, e.g. \"src/**/*.ts\" or \"**/*.{md,json}\".'),\n path: z.string().optional().describe(\"Base directory to search from. Default: cwd.\"),\n limit: z.number().int().positive().max(1000).optional().describe(\"Max results. Default 100.\"),\n});\n\nconst DEFAULT_LIMIT = 100;\n\nexport const GlobTool = defineTool({\n name: \"Glob\",\n description: \"Find files by glob pattern. Returns relative paths sorted by modification time (newest first).\",\n parameters: GlobArgs,\n permission: \"read\",\n summarize: (args) => `Glob(${args.pattern}${args.path ? `, ${args.path}` : \"\"})`,\n async execute(args, ctx) {\n const cwd = args.path ?? ctx.cwd;\n const limit = args.limit ?? DEFAULT_LIMIT;\n\n const entries = await fg(args.pattern, {\n cwd,\n onlyFiles: true,\n stats: true,\n dot: false,\n ignore: [\"**/node_modules/**\", \"**/.git/**\", \"**/dist/**\", \"**/.muse/**\"],\n });\n\n // 按 mtime 倒序\n entries.sort((a, b) => {\n const ta = a.stats?.mtime?.getTime() ?? 0;\n const tb = b.stats?.mtime?.getTime() ?? 0;\n return tb - ta;\n });\n\n const truncated = entries.length > limit;\n const paths = entries.slice(0, limit).map((e) => e.path);\n\n let result = paths.join(\"\\n\") || \"(no matches)\";\n if (truncated) {\n result += `\\n... [${entries.length - limit} more, increase limit to see]`;\n }\n return { content: result, summary: `Glob found ${entries.length} file(s)` };\n },\n});\n","/**\n * TodoWrite 工具:维护 session 内任务清单。\n *\n * 把完整 todos 数组替换进 ctx.todos。约定:一次只一个 in_progress;完成立即标 completed\n * 不要批;任务尽量原子。MessageView 会读 args.todos 渲染 checkbox 清单。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nexport type TodoStatus = \"pending\" | \"in_progress\" | \"completed\";\n\nexport interface TodoItem {\n content: string;\n status: TodoStatus;\n activeForm?: string;\n}\n\nconst TodoSchema = z.object({\n content: z.string().describe(\"Imperative one-line task description (e.g. 'Run the test suite').\"),\n status: z.enum([\"pending\", \"in_progress\", \"completed\"]).describe(\"Current status.\"),\n activeForm: z.string().optional().describe(\"Present-continuous form for the spinner (e.g. 'Running the test suite').\"),\n});\n\nconst TodoWriteArgs = z.object({\n todos: z.array(TodoSchema).describe(\"Full list. Replaces the current store.\"),\n listTitle: z\n .string()\n .optional()\n .describe(\n \"Short (2-6 word) imperative title describing the OVERALL goal of this todo list, e.g. \" +\n \"'Refactor auth flow' / '分析 Muse 架构' / 'Migrate to ESM'. Shown as the list header in UI. \" +\n \"Keep it stable across calls within the same task; only change it if the goal genuinely shifts.\",\n ),\n});\n\nexport const TodoWriteTool = defineTool({\n name: \"TodoWrite\",\n description:\n \"Maintain a structured task list for the current session. Pass the FULL list every call (it replaces the store). \" +\n \"Mark exactly one task in_progress at a time; mark completed immediately when done; do not batch completions. \" +\n \"Use when the task has 3+ distinct steps or is non-trivial. Skip for single trivial actions. \" +\n \"Always include `listTitle` summarizing the overall goal so the UI can label this batch meaningfully.\",\n parameters: TodoWriteArgs,\n permission: \"read\",\n summarize: (args) => `TodoWrite(${args.todos.length} items)`,\n async execute(args, ctx) {\n if (!ctx.todos) {\n return {\n content: \"TodoWrite is unavailable: this agent run has no todo store. (Internal bug; tell the user.)\",\n isError: true,\n };\n }\n ctx.todos.set(args.todos);\n const summary = args.todos\n .map((t, i) => `${i + 1}. ${t.status === \"completed\" ? \"[x]\" : t.status === \"in_progress\" ? \"[~]\" : \"[ ]\"} ${t.content}`)\n .join(\"\\n\");\n return {\n content: `Updated todos (${args.todos.length} items):\\n${summary}`,\n summary: `Todos: ${args.todos.filter((t) => t.status === \"completed\").length}/${args.todos.length} done`,\n };\n },\n});\n","/**\n * WebFetch 工具:抓 URL → 文本 / 简易 markdown。\n *\n * 安全:\n * - 拒绝本机回环 / 链接本地 / 私有网段(SSRF 防护)\n * - http → https 自动升级\n * - 30s 超时;最大 1MB 响应体\n *\n * 输出:以 HTML 解析时 strip 标签后近似 markdown;非 HTML 直接返回文本(截断)。\n *\n * 不引入 turndown:v0.1 用 minimal regex 转换,够 LLM 阅读;\n * 后续如需精细 markdown(保留 link / list 嵌套),再换专门库。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nconst WebFetchArgs = z.object({\n url: z.string().describe(\"Fully-qualified URL. http will be upgraded to https.\"),\n prompt: z\n .string()\n .optional()\n .describe(\n \"What information to look for. The host returns the page content; the LLM should then read it to answer the prompt.\",\n ),\n});\n\nconst MAX_RESPONSE_BYTES = 1_000_000;\nconst FETCH_TIMEOUT_MS = 30_000;\n\nconst PRIVATE_HOST_PATTERNS: RegExp[] = [\n /^localhost$/i,\n /^127\\./,\n /^0\\.0\\.0\\.0$/,\n /^169\\.254\\./,\n /^10\\./,\n /^192\\.168\\./,\n /^172\\.(1[6-9]|2[0-9]|3[0-1])\\./,\n /^::1$/,\n /^fc[0-9a-f]{2}:/i,\n /^fe80:/i,\n];\n\nfunction isPrivateHost(hostname: string): boolean {\n return PRIVATE_HOST_PATTERNS.some((p) => p.test(hostname));\n}\n\nexport const WebFetchTool = defineTool({\n name: \"WebFetch\",\n description:\n \"Fetch a URL and return its textual content (HTML stripped to a markdown-ish form). \" +\n \"Use for reading documentation, blog posts, or API specs. Private/loopback hosts are blocked. \" +\n \"If the URL redirects to a different host, the redirect target is returned for you to re-fetch.\",\n parameters: WebFetchArgs,\n permission: \"network\",\n summarize: (args) => `WebFetch(${args.url})`,\n async execute(args, ctx) {\n let target: URL;\n try {\n target = new URL(args.url);\n } catch {\n return { content: `Invalid URL: ${args.url}`, isError: true };\n }\n if (target.protocol === \"http:\") {\n target.protocol = \"https:\";\n }\n if (target.protocol !== \"https:\") {\n return { content: `Refused: only http(s) URLs are allowed.`, isError: true };\n }\n if (isPrivateHost(target.hostname)) {\n return { content: `Refused: ${target.hostname} is a private/loopback host (SSRF guard).`, isError: true };\n }\n\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n ctx.abortSignal?.addEventListener(\"abort\", onAbort);\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n try {\n const resp = await fetch(target.toString(), {\n redirect: \"manual\",\n signal: controller.signal,\n headers: { \"user-agent\": \"muse-cli/0.1\" },\n });\n\n // 跨主机 redirect → 提示重试,不自动跟随\n if (resp.status >= 300 && resp.status < 400) {\n const loc = resp.headers.get(\"location\");\n if (loc) {\n try {\n const redirectURL = new URL(loc, target);\n if (redirectURL.hostname !== target.hostname) {\n return {\n content: `Redirect to a different host: ${redirectURL.toString()}\\nRe-fetch the new URL explicitly if you trust it.`,\n summary: `Redirect to a different host: ${redirectURL.toString()}`,\n kind: \"warn\",\n };\n }\n // 同 host redirect 也提示一下,让 LLM 决定是否跟\n return {\n content: `Redirect (same host): ${redirectURL.toString()}\\nRe-fetch the new URL to continue.`,\n summary: `Redirect → ${redirectURL.pathname}`,\n kind: \"warn\",\n };\n } catch {\n return { content: `Redirect with unparseable location: ${loc}`, isError: true };\n }\n }\n }\n\n if (!resp.ok) {\n return { content: `HTTP ${resp.status} ${resp.statusText} for ${target.toString()}`, isError: true };\n }\n\n const contentType = resp.headers.get(\"content-type\") ?? \"\";\n const reader = resp.body?.getReader();\n if (!reader) return { content: `Empty response body.`, isError: true };\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n if (value) {\n total += value.byteLength;\n if (total > MAX_RESPONSE_BYTES) {\n await reader.cancel();\n chunks.push(value.slice(0, value.byteLength - (total - MAX_RESPONSE_BYTES)));\n break;\n }\n chunks.push(value);\n }\n }\n const body = new TextDecoder(\"utf-8\", { fatal: false }).decode(Buffer.concat(chunks.map((c) => Buffer.from(c))));\n\n let processed = body;\n if (/^text\\/html|application\\/xhtml/i.test(contentType)) {\n processed = htmlToText(body);\n }\n\n const summary = args.prompt\n ? `# WebFetch result for: ${args.prompt}`\n : `Fetched ${target.hostname} (${total} bytes${total >= MAX_RESPONSE_BYTES ? \", truncated\" : \"\"})`;\n const truncated = processed.length > 200_000 ? processed.slice(0, 200_000) + \"\\n\\n... [truncated]\" : processed;\n const preface = args.prompt ? `# WebFetch result for: ${args.prompt}\\n\\nSource: ${target.toString()}\\n\\n` : `Source: ${target.toString()}\\n\\n`;\n return { content: preface + truncated, summary };\n } catch (err) {\n if ((err as Error).name === \"AbortError\") {\n return { content: `WebFetch aborted (timeout or user cancel).`, isError: true };\n }\n return { content: `WebFetch failed: ${err instanceof Error ? err.message : String(err)}`, isError: true };\n } finally {\n clearTimeout(timer);\n ctx.abortSignal?.removeEventListener(\"abort\", onAbort);\n }\n },\n});\n\n/**\n * 极简 HTML → 文本:删 script/style,保留段落 / 列表 / 标题 / 链接。\n * 不追求精确——给 LLM 看的近似版本即可。\n */\nexport function htmlToText(html: string): string {\n let s = html;\n // 删 script / style / svg / noscript\n s = s.replace(/<(script|style|svg|noscript)\\b[^>]*>[\\s\\S]*?<\\/\\1>/gi, \"\");\n // 注释\n s = s.replace(/<!--[\\s\\S]*?-->/g, \"\");\n // 标题\n s = s.replace(/<h([1-6])\\b[^>]*>([\\s\\S]*?)<\\/h\\1>/gi, (_m, lvl: string, txt: string) => {\n return `\\n\\n${\"#\".repeat(parseInt(lvl, 10))} ${stripTags(txt).trim()}\\n\\n`;\n });\n // a 链接\n s = s.replace(/<a\\b[^>]*href=[\"']([^\"']+)[\"'][^>]*>([\\s\\S]*?)<\\/a>/gi, (_m, href: string, txt: string) => {\n const label = stripTags(txt).trim();\n return label ? `[${label}](${href})` : href;\n });\n // 列表项\n s = s.replace(/<li\\b[^>]*>([\\s\\S]*?)<\\/li>/gi, (_m, txt: string) => `\\n- ${stripTags(txt).trim()}`);\n // 段落 / 块级\n s = s.replace(/<(p|div|section|article|header|footer|main|aside|nav|pre|blockquote|br|hr)\\b[^>]*>/gi, \"\\n\");\n s = s.replace(/<\\/(p|div|section|article|header|footer|main|aside|nav|pre|blockquote)>/gi, \"\\n\");\n // code 行内\n s = s.replace(/<code\\b[^>]*>([\\s\\S]*?)<\\/code>/gi, (_m, txt: string) => `\\`${stripTags(txt)}\\``);\n // 删剩余标签\n s = stripTags(s);\n // entity 简版\n s = s\n .replace(/ /g, \" \")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\");\n // 合并多空行\n s = s.replace(/\\n{3,}/g, \"\\n\\n\").trim();\n return s;\n}\n\nfunction stripTags(s: string): string {\n return s.replace(/<[^>]+>/g, \"\");\n}\n","/**\n * MemoryWrite / MemoryRead 工具:长期 memory 操作。\n *\n * 两层 scope(2026-06-07):\n * - \"project\"(默认 / 安全偏向):跟当前 cwd 强相关的事实\n * - \"user\":跨项目用户级偏好 / 工作风格\n *\n * 由 ctx.cwd 决定项目身份;切目录后 project memory 自动隔离;user memory 跨项目共享。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\nimport {\n readMemoryFile,\n writeMemory,\n type MemoryType,\n type Scope,\n SCOPES,\n} from \"../../loop/memory.js\";\n\nconst TYPES: [MemoryType, ...MemoryType[]] = [\"user\", \"feedback\", \"project\", \"reference\"];\nconst SCOPE_VALUES: [Scope, ...Scope[]] = [\"project\", \"user\"];\n\nconst MemoryWriteArgs = z.object({\n name: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-_]*$/i, \"must be a kebab- or snake-style slug\")\n .describe(\"Short kebab/snake slug; used as filename (<name>.md) and index key.\"),\n description: z\n .string()\n .describe(\"One-line summary used in MEMORY.md index (decides future relevance).\"),\n type: z.enum(TYPES).describe(\"user | feedback | project | reference\"),\n body: z.string().describe(\"Memory content (markdown). For feedback/project, lead with the rule/fact then **Why:** and **How to apply:** lines.\"),\n scope: z\n .enum(SCOPE_VALUES)\n .optional()\n .describe(\n 'Storage scope. \"project\"(default — safe bias) = saved under current project, not visible to other projects. ' +\n '\"user\"(global) = saved under ~/.muse/memory/, visible across ALL projects. ' +\n \"Choose carefully:\\n\" +\n \" scope=project — project architecture / file conventions / team agreements (pnpm vs npm) / project-specific bugs+fixes / API contracts.\\n\" +\n \" When unsure, choose project (safer; user can /memory promote-scope later).\\n\" +\n \" scope=user — user role / working language / timezone / cross-project editor preferences (tabs/spaces, naming style, comment language) / \" +\n \"tool preferences that apply EVERYWHERE / recurring feedback that reveals user personality.\\n\" +\n \" HARD RULE: personal preference items (tabs/spaces, comment language, editor) MUST be scope=user — \" +\n \"do NOT save them as project memory just because cwd is in a project. \" +\n \"If you cannot tell whether a fact is personal or project-specific, ask the user or default to project.\",\n ),\n});\n\nexport const MemoryWriteTool = defineTool({\n name: \"MemoryWrite\",\n description:\n \"Save a long-term memory file under ~/.muse/[projects/<hash>/]memory/<name>.md and update MEMORY.md index. \" +\n \"Choose scope carefully (see scope arg). \" +\n \"Use for: user role/preferences (scope=user), validated approach decisions (feedback), \" +\n \"project facts (auto-convert relative dates), external system references. \" +\n \"Do NOT save: code patterns derivable from the repo, git history, fix recipes, ephemeral task state.\",\n parameters: MemoryWriteArgs,\n permission: \"write\",\n summarize: (args) => `MemoryWrite(${args.name}, ${args.scope ?? \"project\"}, type=${args.type})`,\n async execute(args, ctx) {\n // LLM 自主写入强制 trust=auto + source=manual-write — LLM 不能自封 verified/trusted\n const result = await writeMemory(ctx.cwd, {\n name: args.name,\n description: args.description,\n type: args.type as MemoryType,\n body: args.body,\n trust: \"auto\",\n source: \"manual-write\",\n scope: args.scope as Scope | undefined, // defaults to \"project\" inside writeMemory\n });\n return {\n content: `Saved memory \"${args.name}\" (${args.type}, scope=${result.scope}, trust=auto) → ${result.filePath}${result.indexUpdated ? \"\\nMEMORY.md updated.\" : \"\"}`,\n summary: `MemoryWrite ${args.name} (${result.scope})`,\n };\n },\n});\n\nconst MemoryReadArgs = z.object({\n name: z.string().describe(\"Memory slug to read (no .md extension).\"),\n scope: z\n .enum(SCOPE_VALUES)\n .optional()\n .describe('Optional scope to read from. Default: project first, fallback user. Specify when name exists in both scopes.'),\n});\n\nexport const MemoryReadTool = defineTool({\n name: \"MemoryRead\",\n description:\n \"Read a specific long-term memory file by name. Default lookup: project scope first, then user scope. \" +\n \"Use after seeing it referenced in MEMORY.md (which is auto-injected into the system prompt). \" +\n \"Pass scope='project' or 'user' to disambiguate when the same name exists in both.\",\n parameters: MemoryReadArgs,\n permission: \"read\",\n summarize: (args) => `MemoryRead(${args.name}${args.scope ? `, ${args.scope}` : \"\"})`,\n async execute(args, ctx) {\n try {\n const content = await readMemoryFile(ctx.cwd, args.name, args.scope as Scope | undefined);\n return { content, summary: `MemoryRead ${args.name}` };\n } catch (err) {\n return { content: err instanceof Error ? err.message : String(err), isError: true };\n }\n },\n});\n","/**\n * AskUserQuestion 工具:在 agent loop 内同步弹出选择题让用户作答。\n *\n * 流程:tool.execute → ctx.askQuestion(req) → App 渲染 QuestionPicker → 用户 ↑↓ 选 + Enter\n * → resolve 把结果传回 → tool 把答案拼成文本喂给 LLM。Esc 取消会返回 cancelled=true。\n *\n * 一次调用可塞多个 questions(对齐业界 Q&A picker 形态),逐题展示,任一题 Esc 视为整批取消。\n *\n * 注意:tool 本身不调任何外部资源,permission 用 read(不弹权限确认)。\n */\n\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.js\";\n\nexport const AskQuestionOptionSchema = z.object({\n label: z.string().min(1).describe(\"Option text shown to the user. Concise (1-5 words).\"),\n description: z\n .string()\n .optional()\n .describe(\"Optional one-line explanation of what this option means.\"),\n preview: z\n .string()\n .optional()\n .describe(\n \"Optional rich preview rendered in a right-side panel when this option is focused. \" +\n \"Use for code/diagram/config snippets that help compare options visually. \" +\n \"Multi-line text supported.\",\n ),\n});\n\nexport const AskQuestionSchema = z.object({\n question: z.string().min(1).describe(\"Full question text (end with ?).\"),\n header: z\n .string()\n .min(1)\n .max(16)\n .describe(\"Very short label (chip), max 12 chars. E.g. 'Auth method'.\"),\n options: z\n .array(AskQuestionOptionSchema)\n .min(2)\n .max(4)\n .describe(\"2-4 options. Mutually exclusive unless multiSelect=true.\"),\n multiSelect: z\n .boolean()\n .optional()\n .describe(\"Allow multiple selections. Default false.\"),\n});\n\nexport type AskQuestion = z.infer<typeof AskQuestionSchema>;\nexport type AskQuestionOption = z.infer<typeof AskQuestionOptionSchema>;\n\nexport interface AskQuestionResponse {\n cancelled: boolean;\n /** 单选:单元素数组;多选:所选 label 列表。cancelled=true 时为空。 */\n selections: string[];\n /** 用户对该题用 'n' 添加的自由备注。空字符串表示未填。 */\n notes?: string;\n}\n\nconst AskUserQuestionArgs = z.object({\n questions: z\n .array(AskQuestionSchema)\n .min(1)\n .max(4)\n .describe(\"1-4 questions to ask the user sequentially.\"),\n});\n\nexport const AskUserQuestionTool = defineTool({\n name: \"AskUserQuestion\",\n description:\n \"Ask the user one or more multiple-choice questions when their input is needed to proceed. \" +\n \"Each question has 2-4 options. Use multiSelect=true for non-mutually-exclusive choices. \" +\n \"Prefer this over plain-text questions when the answer space is bounded. \" +\n \"If the user presses Esc, the entire batch is treated as cancelled.\",\n parameters: AskUserQuestionArgs,\n permission: \"read\",\n summarize: (args) =>\n `AskUserQuestion(${args.questions.length} question${args.questions.length === 1 ? \"\" : \"s\"})`,\n async execute(args, ctx) {\n if (!ctx.askQuestions) {\n return {\n content:\n \"AskUserQuestion is unavailable: this agent run has no question handler. \" +\n \"(Internal bug; tell the user.)\",\n isError: true,\n };\n }\n\n const responses = await ctx.askQuestions(args.questions);\n // Esc 取消时所有项 cancelled=true(UI 一次性返回整批)\n if (responses.length > 0 && responses[0].cancelled) {\n return {\n content: \"User cancelled (Esc). No answers were collected.\",\n isError: false,\n };\n }\n\n const blocks = args.questions.map((q, qi) => {\n const r = responses[qi];\n const sel = r?.selections ?? [];\n const ans = sel.length === 0 ? \"(no answer)\" : sel.join(\", \");\n const notes = r?.notes?.trim();\n return notes ? `Q: ${q.question}\\nA: ${ans}\\nNotes: ${notes}` : `Q: ${q.question}\\nA: ${ans}`;\n });\n\n return {\n content: blocks.join(\"\\n\\n\"),\n summary: `Asked ${args.questions.length} question${args.questions.length === 1 ? \"\" : \"s\"}`,\n };\n },\n});\n","import type { AnyTool } from \"../types.js\";\nimport { ReadTool } from \"./read.js\";\nimport { WriteTool } from \"./write.js\";\nimport { EditTool } from \"./edit.js\";\nimport { BashTool } from \"./bash.js\";\nimport { GrepTool } from \"./grep.js\";\nimport { GlobTool } from \"./glob.js\";\nimport { TodoWriteTool } from \"./todo.js\";\nimport { WebFetchTool } from \"./webfetch.js\";\nimport { MemoryReadTool, MemoryWriteTool } from \"./memory.js\";\nimport { AskUserQuestionTool } from \"./ask-user-question.js\";\n\nexport {\n ReadTool,\n WriteTool,\n EditTool,\n BashTool,\n GrepTool,\n GlobTool,\n TodoWriteTool,\n WebFetchTool,\n MemoryReadTool,\n MemoryWriteTool,\n AskUserQuestionTool,\n};\n\nexport const BUILTIN_TOOLS: AnyTool[] = [\n ReadTool,\n WriteTool,\n EditTool,\n BashTool,\n GrepTool,\n GlobTool,\n TodoWriteTool,\n WebFetchTool,\n MemoryReadTool,\n MemoryWriteTool,\n AskUserQuestionTool,\n];\n"],"mappings":"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","names":["React","useEffect","useMemo","useRef","useState","Box","Text","useInput","useStdout","homedir","join","join","placeholder","padLen","after","mkdir","readFile","writeFile","existsSync","homedir","basename","dirname","join","Text","jsx","jsxs","React","useEffect","useState","Box","Text","process","styles","chalk","styles","useEffect","useState","Text","jsx","jsx","jsxs","Box","Text","React","useState","useEffect","jsx","Box","jsxs","Text","useState","useEffect","useState","Box","Text","useInput","jsx","jsxs","useState","useInput","Box","Text","Box","Text","useState","Box","Text","useInput","jsx","jsxs","useState","useInput","Box","Text","jsx","jsxs","resolve","Box","Text","Box","Text","jsx","jsxs","resolve","Box","Text","useState","Box","Text","useInput","jsx","jsxs","useState","useInput","s","Box","Text","useEffect","useState","Box","Text","useInput","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","Box","Text","jsx","jsxs","DEFAULT_MAX","Box","Row","Text","join","join","Box","Text","jsx","jsxs","Box","Text","Box","Text","Fragment","jsx","jsxs","useEffect","useState","Box","Text","jsx","jsxs","useEffect","useState","Box","Text","jsx","jsxs","TICK_MS","useState","useEffect","formatTokens","Box","Text","React","useEffect","useMemo","useRef","useState","Box","Text","marked","jsx","jsxs","useState","useRef","useEffect","useMemo","unstable","marked","Box","Text","React","StableBlock","resolve","homedir","existsSync","homedir","dirname","join","resolve","readFile","writeFile","mkdir","unlink","existsSync","join","mkdir","readFile","writeFile","readdir","existsSync","statSync","homedir","join","createHash","indexPath","join","existsSync","readFile","mkdir","writeFile","execa","execa","existsSync","dirname","join","relative","resolve","resolve","tool","relative","dirname","existsSync","join","readFile","stat","isAbsolute","resolve","homedir","basename","resolve","stat","readFile","resolve","isAbsolute","readFile","stat","basename","extname","isAbsolute","resolve","AT_PATTERN","DEFAULT_MAX_BYTES","IMAGE_EXTS","collectRefs","toAbsolute","extname","basename","stat","readFile","resolve","isAbsolute","readFile","existsSync","homedir","join","resolve","ENV_PATTERN","existsSync","readFile","join","homedir","readFile","existsSync","homedir","join","z","z","join","homedir","existsSync","readFile","formatZodIssues","mkdir","readdir","readFile","stat","existsSync","homedir","dirname","join","createHash","projectHash","createHash","join","homedir","mkdir","existsSync","readdir","stat","dirname","readFile","homedir","formatTime","existsSync","statSync","join","formatTime","jsx","jsxs","useStdout","useState","useRef","useMemo","useEffect","basename","resolve","useInput","pending","Box","React","Text","homedir","join","existsSync","readFile","mkdir","dirname","writeFile","tool","readFile","stat","resolve","isAbsolute","z","z","isAbsolute","resolve","stat","readFile","readFile","writeFile","mkdir","stat","resolve","isAbsolute","dirname","z","truncate","z","isAbsolute","resolve","stat","readFile","mkdir","dirname","writeFile","readFile","writeFile","resolve","isAbsolute","z","z","isAbsolute","resolve","readFile","writeFile","execa","z","z","execa","truncate","execa","z","z","execa","cliArgs","result","out","fg","z","z","DEFAULT_LIMIT","fg","z","z","z","z","z","z","z","z","jsx"]}
|