@qxbyte/muse 0.1.0 → 0.1.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/llm/providers/openai-compatible.ts","../src/log/index.ts","../src/types/index.ts","../src/llm/client.ts","../src/tools/registry.ts","../src/tools/types.ts","../src/tools/builtin/read.ts","../src/tools/builtin/write.ts","../src/tools/builtin/edit.ts","../src/tools/builtin/bash.ts","../src/tools/builtin/grep.ts","../src/tools/builtin/glob.ts","../src/tools/builtin/index.ts","../src/permission/index.ts","../src/session/jsonl.ts","../src/loop/agent.ts","../src/loop/system-prompt.ts","../src/config/loader.ts","../src/config/types.ts","../src/config/_env.ts"],"sourcesContent":["/**\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 try {\n const result = streamText({\n model: this.modelProvider,\n messages: aiMessages,\n tools: aiTools,\n temperature,\n maxTokens,\n abortSignal,\n });\n\n const seenToolCalls = new Set<string>();\n\n for await (const part of result.fullStream) {\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 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}\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.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(\n `Model \"${entry.id}\" has no apiKey in env ${ACTIVE_API_KEY_ENV}. ` +\n `Check models.json (or models.local.json) and ensure setActiveModelEnv() was called.`,\n \"MISSING_API_KEY\",\n );\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\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 * 工具注册中心:管理所有可用工具,提供查询、调用、转 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 * 工具系统类型。\n * 内置工具与 MCP 工具都遵循同一接口。\n */\n\nimport type { z } from \"zod\";\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}\n\nexport interface ToolExecuteResult {\n /** 给 LLM 看的文本结果。 */\n content: string;\n /** 标记为错误:让 LLM 知道需要修复。 */\n isError?: boolean;\n /** 给 TUI 展示的摘要(一行)。 */\n summary?: string;\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 * Read 工具:读取本地文件,支持 offset/limit 分页。\n * 设计对齐 Claude Code:返回带行号的 `cat -n` 格式。\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\";\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 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 * Write 工具:写入文件(创建或覆盖)。\n *\n * 为防误覆盖,约定调用前必须先 Read 过同一路径(除非文件不存在)。\n * 这个约束实际由 LLM 遵守 (prompt 引导);本工具不强制,但记录到日志。\n */\n\nimport { writeFile, mkdir, stat } from \"node:fs/promises\";\nimport { resolve, isAbsolute, dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { defineTool } from \"../types.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 let existed = false;\n try {\n const info = await stat(path);\n existed = info.isFile();\n } catch {\n // 文件不存在,正常情况\n }\n\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, args.content, \"utf-8\");\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 };\n },\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\";\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 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 return {\n content: `Edited ${path}: replaced ${args.replace_all ? occurrences : 1} occurrence(s).`,\n summary: `Edited ${args.file_path}`,\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","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\";\n\nexport { ReadTool, WriteTool, EditTool, BashTool, GrepTool, GlobTool };\n\nexport const BUILTIN_TOOLS: AnyTool[] = [\n ReadTool,\n WriteTool,\n EditTool,\n BashTool,\n GrepTool,\n GlobTool,\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\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\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 decide(input: PermissionInput): Decision {\n // 用户显式 deny 永远生效,所有模式不可绕过\n if (this.matches(this.rules.deny, input)) return \"deny\";\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 * 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 * 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 } from \"../permission/index.js\";\nimport type { Session } from \"../session/jsonl.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<boolean>;\n onUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => 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\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 const stream = this.ctx.llm.stream({\n messages: this.messages,\n tools,\n systemPrompt: this.ctx.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 // 执行工具调用\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 approved = (await this.ctx.events?.onPermissionRequest?.(call.name, call.args, summary)) ?? false;\n if (!approved) {\n this.recordToolResult(call.id, call.name, `User rejected ${call.name}.`, true);\n return;\n }\n }\n\n const toolCtx: ToolContext = {\n cwd: this.ctx.cwd,\n abortSignal: this.ctx.abortSignal,\n askPermission: async () => true, // 已在外层处理\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);\n }\n\n private recordToolResult(id: string, name: string, content: string, isError: boolean, summary?: string): void {\n const toolMsg: Message = {\n role: \"tool\",\n toolUseId: id,\n content,\n isError,\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 * 风格对齐 Claude Code:简短、命令式、把可用工具与约束摆出来。\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}\n\nexport function buildSystemPrompt(opts: SystemPromptOpts): string {\n const { cwd, model, provider, lang, toolNames } = 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 (lang === \"zh-CN\") {\n sections.push(`# Output language\\nReply in Chinese (简体中文) unless the user writes in English.`);\n }\n\n return sections.join(\"\\n\\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\"],\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.json 提供,settings.json 只保留 active 选择。\n// provider 字段仅用于\"无 models.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.json entry matches).\"),\n model: z.string().optional().describe(\"Active model id; should match an id in models.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.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"],"mappings":"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","names":["tool","stat","resolve","isAbsolute","dirname","z","z","isAbsolute","resolve","stat","dirname","readFile","writeFile","resolve","isAbsolute","z","z","isAbsolute","resolve","readFile","writeFile","z","z","execa","z","z","execa","cliArgs","result","out","z","z","DEFAULT_LIMIT","mkdir","readFile","stat","homedir","dirname","join","join","homedir","mkdir","stat","dirname","readFile","tool","result","homedir","readFile","existsSync","homedir","join","resolve","z","existsSync","readFile","join","homedir"]}
1
+ {"version":3,"sources":["../src/llm/providers/openai-compatible.ts","../src/log/index.ts","../src/types/index.ts","../src/llm/client.ts","../src/tools/registry.ts","../src/tools/types.ts","../src/tools/builtin/read.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/loop/memory.ts","../src/tools/builtin/index.ts","../src/permission/index.ts","../src/session/jsonl.ts","../src/loop/todos.ts","../src/loop/agent.ts","../src/loop/system-prompt.ts","../src/config/loader.ts","../src/config/types.ts","../src/config/_env.ts"],"sourcesContent":["/**\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 * 工具注册中心:管理所有可用工具,提供查询、调用、转 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 * 工具系统类型。\n * 内置工具与 MCP 工具都遵循同一接口。\n */\n\nimport type { z } from \"zod\";\nimport type { TodoStore } from \"../loop/todos.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\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 * 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 * 敏感文件路径默认 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(/&nbsp;/g, \" \")\n .replace(/&amp;/g, \"&\")\n .replace(/&lt;/g, \"<\")\n .replace(/&gt;/g, \">\")\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/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 * 长期 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","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\";\n\nexport {\n ReadTool,\n WriteTool,\n EditTool,\n BashTool,\n GrepTool,\n GlobTool,\n TodoWriteTool,\n WebFetchTool,\n MemoryReadTool,\n MemoryWriteTool,\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];\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 * 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 * 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 onUsage?: (usage: TokenUsage) => void;\n onError?: (error: Error) => 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 // 执行工具调用\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 };\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 * 配置加载:\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"],"mappings":"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","names":["resolve","tool","resolve","homedir","resolve","readFile","stat","resolve","isAbsolute","dirname","z","z","isAbsolute","resolve","stat","readFile","dirname","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","mkdir","readFile","writeFile","homedir","join","readFile","mkdir","writeFile","z","mkdir","readFile","stat","existsSync","homedir","dirname","join","createHash","projectHash","createHash","join","homedir","mkdir","existsSync","stat","dirname","readFile","tool","result","homedir","readFile","existsSync","homedir","join","resolve","z","ENV_PATTERN","existsSync","readFile","join","homedir"]}