@yachiyo-5i/xlyra-agent 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +306 -0
- package/dist/chunk-QH6SEOO6.js +3590 -0
- package/dist/chunk-QH6SEOO6.js.map +1 -0
- package/dist/cli.cjs +3833 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +287 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +3703 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1171 -0
- package/dist/index.d.ts +1171 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/llm/models.ts","../src/llm/errors.ts","../src/llm/sse.ts","../src/llm/stream-assembler.ts","../src/llm/protocols/messages.ts","../src/llm/protocols/responses.ts","../src/llm/router.ts","../src/llm/validate.ts","../src/agent/events.ts","../src/agent/prompts.ts","../src/agent/compaction.ts","../src/agent/sessions.ts","../src/agent/runner.ts","../src/tools/types.ts","../src/agent/escalation.ts","../src/tools/workdir.ts","../src/tools/apply-patch.ts","../src/tools/create.ts","../src/tools/edit.ts","../src/tools/process-manager.ts","../src/tools/exec-command.ts","../src/tools/list.ts","../src/tools/read.ts","../src/tools/search.ts","../src/tools/write.ts","../src/tools/write-stdin.ts","../src/tools/index.ts","../src/server/config.ts","../src/server/run-registry.ts","../src/server/recorder.ts","../src/server/routes.ts","../src/server/session-index.ts","../src/server/index.ts","../src/server/config-routes.ts"],"sourcesContent":["/**\n * 内部规范模型 —— 协议无关的对话数据表达。\n *\n * 分层定位:llm/protocols/ 下的两个适配器(OpenAI Responses / Anthropic\n * Messages)负责把各自 wire 格式翻译成这里的模型;agent 层(runner/压缩/\n * 工具)永远只面对本文件定义的结构,不感知任何协议细节。\n *\n * 设计要点:\n * - ToolCall 始终保留 raw_arguments 原文(字符串),parse 发生在使用方——\n * 流式分片期间参数是不完整 JSON,只有归并完成后才可能解析成功;\n * - ChatMessage 带 thinking / thinking_signature:Anthropic 多轮工具往返\n * 要求带签名的 thinking block 原样回喂(评审定案透传),无签名的旧消息\n * 回喂时整块省略(API 允许);\n * - tool 角色的 is_error:Anthropic tool_result block 需要显式标注失败。\n */\nimport { z } from \"zod\";\n\nexport const toolCallSchema = z.object({\n id: z.string(),\n name: z.string(),\n /** 参数 JSON 原文(流式归并后的完整串;可能不是合法 JSON,由校验阶段兜底) */\n raw_arguments: z.string(),\n});\nexport type ToolCall = z.infer<typeof toolCallSchema>;\n\nexport const chatMessageSchema = z.object({\n role: z.enum([\"system\", \"user\", \"assistant\", \"tool\"]),\n content: z.string().default(\"\"),\n tool_calls: z.array(toolCallSchema).optional(),\n tool_call_id: z.string().optional(),\n name: z.string().optional(),\n is_error: z.boolean().optional(),\n thinking: z.string().optional(),\n thinking_signature: z.string().optional(),\n});\nexport type ChatMessage = z.infer<typeof chatMessageSchema>;\n\n/** 消息正文文本(当前为纯文本管线,直接返回 content;保留函数形态便于将来多模态扩展) */\nexport function messageText(message: ChatMessage): string {\n return message.content ?? \"\";\n}\n\nexport const tokenUsageSchema = z.object({\n prompt_tokens: z.number().default(0),\n completion_tokens: z.number().default(0),\n total_tokens: z.number().default(0),\n cache_read_tokens: z.number().default(0),\n});\nexport type TokenUsage = z.infer<typeof tokenUsageSchema>;\n\nexport function emptyUsage(): TokenUsage {\n return { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, cache_read_tokens: 0 };\n}\n\nexport function addUsage(total: TokenUsage, step: TokenUsage): TokenUsage {\n return {\n prompt_tokens: total.prompt_tokens + step.prompt_tokens,\n completion_tokens: total.completion_tokens + step.completion_tokens,\n total_tokens: total.total_tokens + step.total_tokens,\n cache_read_tokens: total.cache_read_tokens + step.cache_read_tokens,\n };\n}\n\nexport const modelSettingsSchema = z.object({\n temperature: z.number().optional(),\n max_tokens: z.number().optional(),\n /** 思考强度:映射到 Anthropic thinking budget / OpenAI reasoning effort */\n reasoning_effort: z.enum([\"low\", \"medium\", \"high\"]).optional(),\n});\nexport type ModelSettings = z.infer<typeof modelSettingsSchema>;\n\n/** 暴露给模型的工具声明(parameters 为 JSON Schema object) */\nexport interface ToolDefinition {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}\n\n/** 一次模型调用的定稿响应(done 事件的载荷) */\nexport interface ChatResponse {\n content: string;\n thinking: string | null;\n thinking_signature: string | null;\n tool_calls: ToolCall[];\n usage: TokenUsage;\n finish_reason: string | null;\n model: string;\n provider: string;\n}\n\n/** 定稿响应 → 入对话历史的 assistant 消息(思考链与签名随消息保存,供历史回喂) */\nexport function responseToMessage(response: ChatResponse): ChatMessage {\n const message: ChatMessage = { role: \"assistant\", content: response.content };\n if (response.tool_calls.length > 0) message.tool_calls = response.tool_calls;\n if (response.thinking) message.thinking = response.thinking;\n if (response.thinking_signature) message.thinking_signature = response.thinking_signature;\n return message;\n}\n","/**\n * LLM 层错误:路由解析失败(没配端点/模型不存在)等**调用前**错误抛出;\n * 调用中的流错误一律走 StreamEvent error 事件,不抛异常。\n */\nexport class LlmError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LlmError\";\n }\n}\n","/**\n * 极简 SSE 解析器 —— 两套协议适配器共用。\n *\n * 覆盖 SSE 规范的常用子集:`event:` / 多行 `data:` 拼接 / `: comment`\n * 心跳行 / \\r\\n 与 \\n 换行 / OpenAI 的 `data: [DONE]` 哨兵。\n * 不依赖任何第三方库;输入是 fetch 响应的 body 流。\n */\n\nexport interface SseEvent {\n /** event 字段值;缺省为空串(OpenAI 系协议通常不写 event,靠 data 里的 type) */\n event: string;\n /** 多行 data 已按规范以 \\n 拼接 */\n data: string;\n}\n\nexport async function* parseSse(body: ReadableStream<Uint8Array>): AsyncGenerator<SseEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n let eventName = \"\";\n let dataLines: string[] = [];\n\n const flush = (): SseEvent | null => {\n if (dataLines.length === 0) {\n eventName = \"\";\n return null;\n }\n const evt: SseEvent = { event: eventName, data: dataLines.join(\"\\n\") };\n eventName = \"\";\n dataLines = [];\n return evt;\n };\n\n const handleLine = function* (line: string): Generator<SseEvent> {\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1);\n if (line === \"\") {\n const evt = flush();\n if (evt) yield evt;\n return;\n }\n if (line.startsWith(\":\")) return; // 心跳/注释行\n const colon = line.indexOf(\":\");\n const field = colon === -1 ? line : line.slice(0, colon);\n // 规范:冒号后的一个前导空格要剥掉\n let value = colon === -1 ? \"\" : line.slice(colon + 1);\n if (value.startsWith(\" \")) value = value.slice(1);\n if (field === \"event\") eventName = value;\n else if (field === \"data\") dataLines.push(value);\n // id:/retry: 等字段当前协议均不需要,忽略\n };\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n yield* handleLine(line);\n }\n }\n // 流末尾可能残留未以空行收尾的事件\n if (buffer.length > 0) yield* handleLine(buffer);\n const tail = flush();\n if (tail) yield tail;\n } finally {\n reader.releaseLock();\n }\n}\n","/**\n * 流式 tool_call 归并器 —— 两个协议适配器共用。\n *\n * 两套协议的参数都是逐片增量(Responses 的 function_call_arguments.delta /\n * Anthropic 的 input_json_delta),适配器以各自的归并键(item_id / block\n * index)调用本类累积,end 时得到 raw_arguments 全量。\n *\n * 刻意不在增量阶段做 partial parse(避免 O(n²) 重复解析);end 时的\n * JSON.parse 失败也不报错——raw_arguments 保留原文,由 runner 的参数\n * 校验阶段统一报错回喂模型。\n */\nimport type { ToolCall } from \"./models.js\";\n\ninterface BufferEntry {\n id: string;\n name: string;\n raw: string;\n}\n\nexport class ToolCallBuffer {\n private readonly buffers = new Map<string, BufferEntry>();\n\n /** 名称确定的第一刻登记;返回仅含 id/name 的 ToolCall(供 toolcall_start 事件) */\n start(key: string, id: string, name: string): ToolCall {\n this.buffers.set(key, { id, name, raw: \"\" });\n return { id, name, raw_arguments: \"\" };\n }\n\n /** 追加参数分片;返回当前快照(供 toolcall_delta 事件携带归属信息) */\n append(key: string, delta: string): ToolCall | null {\n const entry = this.buffers.get(key);\n if (!entry) return null;\n entry.raw += delta;\n return { id: entry.id, name: entry.name, raw_arguments: entry.raw };\n }\n\n /** 结束归并;fullRaw 提供时以全量为准(Responses 的 .done 事件自带全量串) */\n finish(key: string, fullRaw?: string): ToolCall | null {\n const entry = this.buffers.get(key);\n if (!entry) return null;\n this.buffers.delete(key);\n return { id: entry.id, name: entry.name, raw_arguments: fullRaw ?? entry.raw };\n }\n\n /** 流异常终止时丢弃全部未完成归并 */\n clear(): void {\n this.buffers.clear();\n }\n\n get pendingCount(): number {\n return this.buffers.size;\n }\n}\n","/**\n * Anthropic Messages API 适配器。\n *\n * 按官方文档实现(https://docs.claude.com/en/api/messages-streaming):\n * - 请求:POST {base_url}/v1/messages,system 是顶层字段;assistant 的\n * tool_calls → tool_use content blocks;tool 结果并入 user 消息的\n * tool_result blocks;max_tokens 必填;\n * - 流式:content_block 状态机按 block index 归并;input_json_delta\n * 累积到 content_block_stop 才 parse(避免每片 partial parse 的 O(n²));\n * signature_delta 必须采集——评审定案 thinking 签名透传进历史,\n * 多轮工具往返要求带签名的 thinking block 原样回喂。\n *\n * 实现纪律(来自公开 issue 的已知坑):\n * - delta 类型与当前 block 类型不符 → 按流损坏处理,error 事件收尾,不猜;\n * - tool_result 必须与此前 assistant 的 tool_use 严格配对(runner 保证),\n * 否则 API 400。\n */\nimport type { ChatMessage, ChatResponse, ToolDefinition } from \"../models.js\";\nimport type { ChatRequest, LlmProtocol, StreamEvent } from \"../protocol.js\";\nimport { parseSse } from \"../sse.js\";\nimport { ToolCallBuffer } from \"../stream-assembler.js\";\n\nexport interface MessagesEndpointOptions {\n baseUrl: string;\n apiKey: string;\n providerName?: string;\n /** anthropic-version 头;默认官方当前版本 */\n apiVersion?: string;\n /** 测试注入用;默认全局 fetch */\n fetchImpl?: typeof fetch;\n}\n\ntype Json = Record<string, unknown>;\n\nconst DEFAULT_MAX_TOKENS = 8192;\n\n/** reasoning_effort → thinking budget(官方建议 budget ≥ 1024 且 < max_tokens) */\nconst THINKING_BUDGET = { low: 2048, medium: 8192, high: 24576 } as const;\n\n/** 内部消息 → Anthropic messages 数组 + 顶层 system */\nexport function toAnthropicMessages(messages: ChatMessage[]): {\n system: string | undefined;\n messages: Json[];\n} {\n const systemParts: string[] = [];\n const out: Json[] = [];\n\n const flushToolResults = (pending: Json[]): void => {\n if (pending.length > 0) {\n // 连续的 tool 结果合并进同一条 user 消息(多个 tool_result block)\n out.push({ role: \"user\", content: pending.splice(0, pending.length) });\n }\n };\n\n const pendingToolResults: Json[] = [];\n for (const m of messages) {\n if (m.role === \"system\") {\n if (m.content) systemParts.push(m.content);\n continue;\n }\n if (m.role === \"tool\") {\n const block: Json = {\n type: \"tool_result\",\n tool_use_id: m.tool_call_id ?? \"\",\n content: m.content,\n };\n if (m.is_error) block.is_error = true;\n pendingToolResults.push(block);\n continue;\n }\n flushToolResults(pendingToolResults);\n if (m.role === \"user\") {\n out.push({ role: \"user\", content: m.content });\n continue;\n }\n // assistant:thinking(有签名才回喂)→ text → tool_use blocks\n const blocks: Json[] = [];\n if (m.thinking && m.thinking_signature) {\n blocks.push({ type: \"thinking\", thinking: m.thinking, signature: m.thinking_signature });\n }\n if (m.content) blocks.push({ type: \"text\", text: m.content });\n for (const tc of m.tool_calls ?? []) {\n blocks.push({ type: \"tool_use\", id: tc.id, name: tc.name, input: parseArgs(tc.raw_arguments) });\n }\n out.push({ role: \"assistant\", content: blocks.length ? blocks : [{ type: \"text\", text: \"\" }] });\n }\n flushToolResults(pendingToolResults);\n return { system: systemParts.length ? systemParts.join(\"\\n\\n\") : undefined, messages: out };\n}\n\nfunction parseArgs(raw: string): Json {\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" && !Array.isArray(parsed) ? (parsed as Json) : {};\n } catch {\n return {}; // 参数原文非法时给空对象:模型会在工具结果里收到校验错误并自行修正\n }\n}\n\nfunction toAnthropicTools(tools: ToolDefinition[]): Json[] {\n return tools.map((t) => ({ name: t.name, description: t.description, input_schema: t.parameters }));\n}\n\ntype BlockKind = \"text\" | \"thinking\" | \"tool_use\";\n\nexport class AnthropicMessagesProtocol implements LlmProtocol {\n readonly name = \"anthropic-messages\";\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly provider: string;\n private readonly apiVersion: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(opts: MessagesEndpointOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n this.provider = opts.providerName ?? \"anthropic\";\n this.apiVersion = opts.apiVersion ?? \"2023-06-01\";\n this.fetchImpl = opts.fetchImpl ?? fetch;\n }\n\n async *chatStream(req: ChatRequest): AsyncIterable<StreamEvent> {\n const { system, messages } = toAnthropicMessages(req.messages);\n const maxTokens = req.settings.max_tokens ?? DEFAULT_MAX_TOKENS;\n const body: Json = { model: req.model, max_tokens: maxTokens, messages, stream: true };\n if (system) body.system = system;\n if (req.tools?.length) body.tools = toAnthropicTools(req.tools);\n if (req.settings.temperature !== undefined) body.temperature = req.settings.temperature;\n if (req.settings.reasoning_effort) {\n const budget = Math.min(THINKING_BUDGET[req.settings.reasoning_effort], maxTokens - 1);\n if (budget >= 1024) body.thinking = { type: \"enabled\", budget_tokens: budget };\n }\n\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.baseUrl}/v1/messages`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-api-key\": this.apiKey,\n \"anthropic-version\": this.apiVersion,\n },\n body: JSON.stringify(body),\n signal: req.signal ?? null,\n });\n } catch (err) {\n if (req.signal?.aborted) return; // 取消:静默结束,终态事件由编排层负责\n yield { type: \"error\", error: `请求失败(网络错误):${errMsg(err)}` };\n return;\n }\n\n if (!res.ok || !res.body) {\n const detail = await res.text().catch(() => \"\");\n yield {\n type: \"error\",\n error: `请求失败(HTTP ${res.status}):${detail.slice(0, 500) || res.statusText}`,\n };\n return;\n }\n\n // content_block 状态机:index → 当前 block 类别\n const blockKinds = new Map<number, BlockKind>();\n const calls = new ToolCallBuffer();\n const finishedCalls: import(\"../models.js\").ToolCall[] = [];\n let text = \"\";\n let thinking = \"\";\n let thinkingSignature: string | null = null;\n let stopReason: string | null = null;\n const usage = { input: 0, output: 0, cacheRead: 0 };\n let model = \"\";\n let sawTerminal = false;\n\n try {\n for await (const sse of parseSse(res.body)) {\n const evt = safeParse(sse.data);\n if (!evt) continue;\n const type = String(evt.type ?? \"\");\n\n if (type === \"message_start\") {\n const msg = (evt.message as Json) ?? {};\n model = String(msg.model ?? \"\");\n const u = (msg.usage as Json) ?? {};\n usage.input = Number(u.input_tokens ?? 0);\n usage.cacheRead = Number(u.cache_read_input_tokens ?? 0);\n } else if (type === \"content_block_start\") {\n const index = Number(evt.index ?? 0);\n const block = (evt.content_block as Json) ?? {};\n const kind = String(block.type ?? \"\") as BlockKind;\n blockKinds.set(index, kind);\n if (kind === \"tool_use\") {\n const tc = calls.start(String(index), String(block.id ?? \"\"), String(block.name ?? \"\"));\n yield { type: \"toolcall_start\", tool_call: tc };\n }\n } else if (type === \"content_block_delta\") {\n const index = Number(evt.index ?? 0);\n const delta = (evt.delta as Json) ?? {};\n const kind = blockKinds.get(index);\n const deltaType = String(delta.type ?? \"\");\n if (deltaType === \"text_delta\" && kind === \"text\") {\n const d = String(delta.text ?? \"\");\n text += d;\n yield { type: \"text_delta\", delta: d };\n } else if (deltaType === \"thinking_delta\" && kind === \"thinking\") {\n const d = String(delta.thinking ?? \"\");\n thinking += d;\n yield { type: \"thinking_delta\", delta: d };\n } else if (deltaType === \"signature_delta\" && kind === \"thinking\") {\n thinkingSignature = String(delta.signature ?? \"\") || thinkingSignature;\n } else if (deltaType === \"input_json_delta\" && kind === \"tool_use\") {\n const d = String(delta.partial_json ?? \"\");\n const tc = calls.append(String(index), d);\n if (tc) yield { type: \"toolcall_delta\", tool_call: tc, delta: d };\n } else if (deltaType) {\n // delta 类型与 block 类型不符 → 流损坏,不猜\n yield { type: \"error\", error: `流损坏:block ${index}(${kind})收到 ${deltaType}` };\n return;\n }\n } else if (type === \"content_block_stop\") {\n const index = Number(evt.index ?? 0);\n if (blockKinds.get(index) === \"tool_use\") {\n const tc = calls.finish(String(index));\n if (tc) {\n finishedCalls.push(tc);\n yield { type: \"toolcall_end\", tool_call: tc };\n }\n }\n blockKinds.delete(index);\n } else if (type === \"message_delta\") {\n stopReason = String((evt.delta as Json)?.stop_reason ?? \"\") || stopReason;\n usage.output = Number((evt.usage as Json)?.output_tokens ?? usage.output);\n } else if (type === \"message_stop\") {\n sawTerminal = true;\n yield {\n type: \"done\",\n response: {\n content: text,\n thinking: thinking || null,\n thinking_signature: thinkingSignature,\n tool_calls: finishedCalls,\n usage: {\n prompt_tokens: usage.input,\n completion_tokens: usage.output,\n total_tokens: usage.input + usage.output,\n cache_read_tokens: usage.cacheRead,\n },\n finish_reason: stopReason,\n model,\n provider: this.provider,\n },\n };\n return;\n } else if (type === \"error\") {\n const err = (evt.error as Json)?.message;\n yield { type: \"error\", error: `模型调用失败:${String(err ?? \"原因未知\")}` };\n return;\n }\n // ping 等其他事件忽略\n }\n } catch (err) {\n if (req.signal?.aborted) return;\n yield { type: \"error\", error: `流读取失败:${errMsg(err)}` };\n return;\n }\n if (!sawTerminal) yield { type: \"error\", error: \"模型流异常终止,未返回结果\" };\n }\n}\n\nfunction safeParse(data: string): Json | null {\n try {\n return JSON.parse(data) as Json;\n } catch {\n return null;\n }\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","/**\n * OpenAI Responses API 适配器。\n *\n * 按官方文档实现(https://platform.openai.com/docs/api-reference/responses-streaming):\n * - 请求:POST {base_url}/responses,system → instructions,历史 → input items\n * (message / function_call / function_call_output),stream: true;\n * - 流式:tool_call 以 output_item.added(function_call) 确定 id/name,\n * function_call_arguments.delta 逐片累积、.done 给全量;\n * response.completed / failed / incomplete 为终态。\n *\n * 终态怪癖处理(继承 MovieClaw 兼容层经验):\n * - response.incomplete:已累积出完整 tool_calls 时按 done 处理(让循环继续),\n * 否则报 error;\n * - 流中途断开(无终态事件)→ error,不静默。\n */\nimport { LlmError } from \"../errors.js\";\nimport type { ChatMessage, ChatResponse, ToolDefinition } from \"../models.js\";\nimport { emptyUsage } from \"../models.js\";\nimport type { ChatRequest, LlmProtocol, StreamEvent } from \"../protocol.js\";\nimport { parseSse } from \"../sse.js\";\nimport { ToolCallBuffer } from \"../stream-assembler.js\";\n\nexport interface ResponsesEndpointOptions {\n baseUrl: string;\n apiKey: string;\n /** 展示与日志用的端点名 */\n providerName?: string;\n /** 测试注入用;默认全局 fetch */\n fetchImpl?: typeof fetch;\n}\n\ntype Json = Record<string, unknown>;\n\n/** 内部消息 → Responses input items(一条内部消息可能展开成多个 item) */\nexport function toResponsesInput(messages: ChatMessage[]): {\n instructions: string | undefined;\n input: Json[];\n} {\n const instructions: string[] = [];\n const input: Json[] = [];\n for (const m of messages) {\n if (m.role === \"system\") {\n if (m.content) instructions.push(m.content);\n continue;\n }\n if (m.role === \"user\") {\n input.push({ type: \"message\", role: \"user\", content: [{ type: \"input_text\", text: m.content }] });\n continue;\n }\n if (m.role === \"assistant\") {\n if (m.content) {\n input.push({ type: \"message\", role: \"assistant\", content: [{ type: \"output_text\", text: m.content }] });\n }\n for (const tc of m.tool_calls ?? []) {\n input.push({ type: \"function_call\", call_id: tc.id, name: tc.name, arguments: tc.raw_arguments });\n }\n continue;\n }\n // tool 结果 → function_call_output\n input.push({ type: \"function_call_output\", call_id: m.tool_call_id ?? \"\", output: m.content });\n }\n return { instructions: instructions.length ? instructions.join(\"\\n\\n\") : undefined, input };\n}\n\nfunction toResponsesTools(tools: ToolDefinition[]): Json[] {\n return tools.map((t) => ({\n type: \"function\",\n name: t.name,\n description: t.description,\n parameters: t.parameters,\n }));\n}\n\n/** 从 response.completed 的完整响应体提取定稿 ChatResponse */\nfunction responseFromCompleted(response: Json, provider: string): ChatResponse {\n let content = \"\";\n let thinking = \"\";\n const toolCalls: ChatResponse[\"tool_calls\"] = [];\n for (const item of (response.output as Json[] | undefined) ?? []) {\n if (item.type === \"message\") {\n for (const part of (item.content as Json[] | undefined) ?? []) {\n if (part.type === \"output_text\" && typeof part.text === \"string\") content += part.text;\n }\n } else if (item.type === \"reasoning\") {\n for (const part of (item.summary as Json[] | undefined) ?? []) {\n if (part.type === \"summary_text\" && typeof part.text === \"string\") {\n thinking += (thinking ? \"\\n\" : \"\") + part.text;\n }\n }\n } else if (item.type === \"function_call\") {\n toolCalls.push({\n id: String(item.call_id ?? item.id ?? \"\"),\n name: String(item.name ?? \"\"),\n raw_arguments: String(item.arguments ?? \"\"),\n });\n }\n }\n const usage = (response.usage as Json | undefined) ?? {};\n const cached = (usage.input_tokens_details as Json | undefined)?.cached_tokens;\n return {\n content,\n thinking: thinking || null,\n thinking_signature: null, // Responses 的思考摘要无签名概念\n tool_calls: toolCalls,\n usage: {\n prompt_tokens: Number(usage.input_tokens ?? 0),\n completion_tokens: Number(usage.output_tokens ?? 0),\n total_tokens: Number(usage.total_tokens ?? 0),\n cache_read_tokens: Number(cached ?? 0),\n },\n finish_reason: (response.status as string | undefined) ?? \"completed\",\n model: String(response.model ?? \"\"),\n provider,\n };\n}\n\nexport class OpenAIResponsesProtocol implements LlmProtocol {\n readonly name = \"openai-responses\";\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly provider: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(opts: ResponsesEndpointOptions) {\n this.baseUrl = opts.baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = opts.apiKey;\n this.provider = opts.providerName ?? \"openai\";\n this.fetchImpl = opts.fetchImpl ?? fetch;\n }\n\n async *chatStream(req: ChatRequest): AsyncIterable<StreamEvent> {\n const { instructions, input } = toResponsesInput(req.messages);\n const body: Json = { model: req.model, input, stream: true };\n if (instructions) body.instructions = instructions;\n if (req.tools?.length) body.tools = toResponsesTools(req.tools);\n if (req.settings.max_tokens) body.max_output_tokens = req.settings.max_tokens;\n if (req.settings.temperature !== undefined) body.temperature = req.settings.temperature;\n if (req.settings.reasoning_effort) {\n body.reasoning = { effort: req.settings.reasoning_effort, summary: \"auto\" };\n body.include = [\"reasoning.encrypted_content\"];\n }\n\n let res: Response;\n try {\n res = await this.fetchImpl(`${this.baseUrl}/responses`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n signal: req.signal ?? null,\n });\n } catch (err) {\n if (req.signal?.aborted) return; // 取消:静默结束,终态事件由编排层负责\n yield { type: \"error\", error: `请求失败(网络错误):${errMsg(err)}` };\n return;\n }\n\n if (!res.ok || !res.body) {\n const detail = await res.text().catch(() => \"\");\n yield {\n type: \"error\",\n error: `请求失败(HTTP ${res.status}):${detail.slice(0, 500) || res.statusText}`,\n };\n return;\n }\n\n const calls = new ToolCallBuffer();\n // item_id → call_id:delta 事件只带 item_id,事件里的 ToolCall.id 用 call_id\n // (function_call_output 回喂以 call_id 关联)\n const callIdByItem = new Map<string, string>();\n let streamedText = \"\";\n let streamedThinking = \"\";\n let doneCalls: ChatResponse[\"tool_calls\"] = [];\n\n try {\n for await (const sse of parseSse(res.body)) {\n if (sse.data === \"[DONE]\") break;\n const evt = safeParse(sse.data);\n if (!evt) continue;\n const type = String(evt.type ?? \"\");\n\n if (type === \"response.output_item.added\") {\n const item = evt.item as Json | undefined;\n if (item?.type === \"function_call\") {\n const itemId = String(item.id ?? \"\");\n const callId = String(item.call_id ?? itemId);\n callIdByItem.set(itemId, callId);\n const tc = calls.start(itemId, callId, String(item.name ?? \"\"));\n yield { type: \"toolcall_start\", tool_call: tc };\n }\n } else if (type === \"response.function_call_arguments.delta\") {\n const itemId = String(evt.item_id ?? \"\");\n const tc = calls.append(itemId, String(evt.delta ?? \"\"));\n if (tc) yield { type: \"toolcall_delta\", tool_call: tc, delta: String(evt.delta ?? \"\") };\n } else if (type === \"response.function_call_arguments.done\") {\n const itemId = String(evt.item_id ?? \"\");\n const tc = calls.finish(itemId, String(evt.arguments ?? \"\"));\n if (tc) {\n doneCalls.push(tc);\n yield { type: \"toolcall_end\", tool_call: tc };\n }\n } else if (type === \"response.output_item.done\") {\n // 兜底:arguments.done 缺失时,function_call item 完结也带全量 arguments\n const item = evt.item as Json | undefined;\n const itemId = String(item?.id ?? \"\");\n if (item?.type === \"function_call\" && itemId && callIdByItem.has(itemId)) {\n const tc = calls.finish(itemId, String(item.arguments ?? \"\"));\n if (tc) {\n doneCalls.push(tc);\n yield { type: \"toolcall_end\", tool_call: tc };\n }\n }\n } else if (type === \"response.output_text.delta\") {\n const delta = String(evt.delta ?? \"\");\n streamedText += delta;\n yield { type: \"text_delta\", delta };\n } else if (type === \"response.reasoning_summary_text.delta\") {\n const delta = String(evt.delta ?? \"\");\n streamedThinking += delta;\n yield { type: \"thinking_delta\", delta };\n } else if (type === \"response.completed\") {\n const response = responseFromCompleted((evt.response as Json) ?? {}, this.provider);\n yield { type: \"done\", response };\n return;\n } else if (type === \"response.incomplete\") {\n // 已累积出完整 tool_calls → 按 done 处理让循环继续;否则报错\n if (doneCalls.length > 0) {\n const response = responseFromCompleted((evt.response as Json) ?? {}, this.provider);\n yield {\n type: \"done\",\n response: {\n ...response,\n content: response.content || streamedText,\n thinking: response.thinking ?? (streamedThinking || null),\n tool_calls: doneCalls,\n },\n };\n } else {\n const detail = ((evt.response as Json)?.incomplete_details as Json)?.reason;\n yield { type: \"error\", error: `响应不完整${detail ? `(${String(detail)})` : \"\"},请重试` };\n }\n return;\n } else if (type === \"response.failed\") {\n const err = ((evt.response as Json)?.error as Json)?.message;\n yield { type: \"error\", error: `模型调用失败:${String(err ?? \"原因未知\")}` };\n return;\n } else if (type === \"error\") {\n yield { type: \"error\", error: `模型调用失败:${String(evt.message ?? \"原因未知\")}` };\n return;\n }\n // 其余事件(created / in_progress / output_text.done / ping 等)忽略\n }\n } catch (err) {\n if (req.signal?.aborted) return;\n yield { type: \"error\", error: `流读取失败:${errMsg(err)}` };\n return;\n }\n // 流结束但没有任何终态事件——视为异常断流\n yield { type: \"error\", error: \"模型流异常终止,未返回结果\" };\n }\n}\n\nfunction safeParse(data: string): Json | null {\n try {\n return JSON.parse(data) as Json;\n } catch {\n return null;\n }\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nexport { LlmError };\n","/**\n * 端点配置与模型解析 —— 刻意简化的路由层(不做多供应商目录体系)。\n *\n * 模型引用写法:\n * - \"端点名/模型id\":显式指定端点(如 \"anthropic/claude-sonnet-4-5\");\n * - 裸 \"模型id\":在全部端点中查找,唯一命中即用,多命中报错;\n * - 空串:第一个端点的 default_model。\n *\n * context_window 优先取端点配置;未配置时回落内置常识表;都未命中返回\n * undefined——自动压缩随之停用(宁放行到供应商报错,不瞎猜预算)。\n */\nimport { LlmError } from \"./errors.js\";\nimport type { LlmProtocol } from \"./protocol.js\";\nimport { AnthropicMessagesProtocol } from \"./protocols/messages.js\";\nimport { OpenAIResponsesProtocol } from \"./protocols/responses.js\";\n\nexport interface EndpointConfig {\n name: string;\n protocol: \"openai-responses\" | \"anthropic-messages\";\n base_url: string;\n api_key: string;\n /** 可用模型表:key 为模型 id;context_window 可选 */\n models?: Record<string, { context_window?: number }>;\n default_model?: string;\n}\n\nexport interface ResolvedModel {\n endpoint: EndpointConfig;\n protocol: LlmProtocol;\n /** 端点内的模型 id(已剥离端点前缀) */\n modelId: string;\n contextWindow: number | undefined;\n}\n\n/** 内置 context window 常识表(前缀匹配,先到先得;保守取值,可被配置覆盖) */\nconst BUILTIN_CONTEXT_WINDOWS: Array<[prefix: string, window: number]> = [\n [\"claude-\", 200_000],\n [\"gpt-4o\", 128_000],\n [\"gpt-4.1\", 1_047_576],\n [\"gpt-5\", 400_000],\n [\"o1\", 200_000],\n [\"o3\", 200_000],\n [\"o4\", 200_000],\n];\n\nexport function builtinContextWindow(modelId: string): number | undefined {\n for (const [prefix, win] of BUILTIN_CONTEXT_WINDOWS) {\n if (modelId.startsWith(prefix)) return win;\n }\n return undefined;\n}\n\nexport class EndpointResolver {\n private readonly endpoints: EndpointConfig[];\n private readonly protocols = new Map<string, LlmProtocol>();\n\n constructor(endpoints: EndpointConfig[]) {\n if (endpoints.length === 0) throw new LlmError(\"未配置任何模型端点\");\n this.endpoints = endpoints;\n }\n\n resolve(model: string): ResolvedModel {\n let endpoint: EndpointConfig | undefined;\n let modelId: string;\n\n if (!model) {\n // 构造函数已保证 endpoints 非空\n endpoint = this.endpoints[0]!;\n modelId = endpoint.default_model ?? \"\";\n if (!modelId) throw new LlmError(`端点 ${endpoint.name} 未配置默认模型`);\n } else if (model.includes(\"/\")) {\n const [name, ...rest] = model.split(\"/\");\n modelId = rest.join(\"/\");\n endpoint = this.endpoints.find((e) => e.name === name);\n if (!endpoint) throw new LlmError(`模型端点不存在:${name}`);\n } else {\n modelId = model;\n const hits = this.endpoints.filter((e) => e.models && model in e.models);\n if (hits.length > 1) {\n throw new LlmError(`模型 ${model} 在多个端点中均有配置,请用「端点名/模型id」显式指定`);\n }\n // 裸模型 id 且无端点声明:回落到第一个端点(兼容官方端点的自由模型名)\n endpoint = hits[0] ?? this.endpoints[0]!;\n }\n\n return {\n endpoint,\n protocol: this.protocolFor(endpoint),\n modelId,\n contextWindow: endpoint.models?.[modelId]?.context_window ?? builtinContextWindow(modelId),\n };\n }\n\n private protocolFor(endpoint: EndpointConfig): LlmProtocol {\n let protocol = this.protocols.get(endpoint.name);\n if (!protocol) {\n const opts = {\n baseUrl: endpoint.base_url,\n apiKey: endpoint.api_key,\n providerName: endpoint.name,\n };\n protocol =\n endpoint.protocol === \"anthropic-messages\"\n ? new AnthropicMessagesProtocol(opts)\n : new OpenAIResponsesProtocol(opts);\n this.protocols.set(endpoint.name, protocol);\n }\n return protocol;\n }\n}\n","/**\n * 工具参数校验 —— 调用前对 raw_arguments 做 JSON Schema 校验。\n *\n * 覆盖我们工具声明用到的 JSON Schema 子集(object / properties / required /\n * string / number / integer / boolean / array / enum / default),不引 ajv:\n * 我们的 schema 全部来自自家工具的 Zod 定义,结构可控。将来支持外部工具\n * 声明时,可在此替换为完整 JSON Schema 校验器,接口不变。\n *\n * 校验失败返回中文错误文本(喂回模型自行修正),不抛异常。\n */\nimport type { ToolDefinition } from \"./models.js\";\nimport type { ToolCall } from \"./models.js\";\n\nexport interface ValidatedArgs {\n args: Record<string, unknown> | null;\n error: string | null;\n}\n\nexport function validateToolCall(\n definitions: ToolDefinition[],\n call: ToolCall,\n): ValidatedArgs {\n const def = definitions.find((d) => d.name === call.name);\n if (!def) {\n return { args: null, error: `工具不存在:${call.name};可用工具:${definitions.map((d) => d.name).join(\"、\")}` };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(call.raw_arguments || \"{}\");\n } catch {\n return {\n args: null,\n error: `工具 ${call.name} 的参数不是合法 JSON,请修正后重试。原文:${call.raw_arguments.slice(0, 200)}`,\n };\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n return { args: null, error: `工具 ${call.name} 的参数必须是 JSON object` };\n }\n const err = validateAgainstSchema(parsed as Record<string, unknown>, def.parameters);\n if (err) return { args: null, error: `工具 ${call.name} 参数校验失败:${err}` };\n return { args: parsed as Record<string, unknown>, error: null };\n}\n\nfunction validateAgainstSchema(\n args: Record<string, unknown>,\n schema: Record<string, unknown>,\n): string | null {\n // required 语义修正:Zod 的 .default() 字段会被 z.toJSONSchema 同时列入\n // required 与 properties[x].default——带默认值的参数模型省略是合法的,\n // 官方 API 也不要求它出现。这里以「required 且无 default」为真正必填。\n const properties = (schema.properties as Record<string, Record<string, unknown>> | undefined) ?? {};\n const required = ((schema.required as string[] | undefined) ?? []).filter(\n (key) => properties[key]?.default === undefined,\n );\n for (const key of required) {\n if (!(key in args) || args[key] === undefined || args[key] === null) {\n return `缺少必填参数 ${key}`;\n }\n }\n for (const [key, value] of Object.entries(args)) {\n const prop = properties[key];\n if (!prop) continue; // additionalProperties 放行\n const expected = prop.type as string | undefined;\n if (value === undefined || !expected) continue;\n const ok =\n (expected === \"string\" && typeof value === \"string\") ||\n (expected === \"number\" && typeof value === \"number\") ||\n (expected === \"integer\" && typeof value === \"number\" && Number.isInteger(value)) ||\n (expected === \"boolean\" && typeof value === \"boolean\") ||\n (expected === \"array\" && Array.isArray(value)) ||\n (expected === \"object\" && typeof value === \"object\" && !Array.isArray(value));\n if (!ok) return `参数 ${key} 类型应为 ${expected}`;\n const enumValues = prop.enum as unknown[] | undefined;\n if (enumValues && !enumValues.includes(value)) {\n return `参数 ${key} 取值须为 ${enumValues.join(\" / \")}`;\n }\n }\n return null;\n}\n","/**\n * Agent 执行过程的事件协议 —— 前后端之间的「执行进度语言」。\n *\n * 设计原则(移植自 MovieClaw,对齐 pi 的 agent 事件思路):\n * 1. 事件类型面向「渲染语义」而非模型协议:调用方拿到事件就知道往哪个区域\n * 画什么,不需要理解底层 LLM 流的细节;\n * 2. 增量事件(*_delta)负责打字机效果,结束事件(agent_done)带完整结果,\n * 断线重连/中途加入也能靠终态恢复;\n * 3. 工具调用三段式:名称确定即发 tool_call_start,参数逐片发 tool_call_delta,\n * 参数完整后发 tool_call——调用方从名称确定的一刻起就能展示进度。\n *\n * 事件序列(每一步 = 一次模型调用):\n * agent_start → [ (thinking_delta|text_delta)*\n * → (tool_call_start → tool_call_delta* → tool_call)*\n * → tool_result* ]×N\n * → agent_done | agent_error | agent_cancelled\n * (任意安全点可插 context_compacted)\n */\nimport { z } from \"zod\";\nimport {\n chatMessageSchema,\n modelSettingsSchema,\n tokenUsageSchema,\n toolCallSchema,\n} from \"../llm/models.js\";\n\nexport const agentStartParamsSchema = z.object({\n /** 用户的任务描述(作为本轮 user 消息) */\n input: z.string(),\n /** 是否把 input 追加为新的 user 消息;提权续跑沿用 history 中的原始输入 */\n include_input: z.boolean().default(true),\n /** 多轮历史(可选):追加在 system 之后、本轮 input 之前 */\n history: z.array(chatMessageSchema).default([]),\n /** 模型引用(\"端点名/模型id\" 或裸模型 id);空串 = 第一个端点的默认模型 */\n model: z.string().default(\"\"),\n /** 覆盖默认系统提示词(缺省用 prompts.buildSystemPrompt()) */\n system_prompt: z.string().nullish(),\n settings: modelSettingsSchema.default({}),\n});\nexport type AgentStartParams = z.input<typeof agentStartParamsSchema>;\n\nexport const agentToolResultSchema = z.object({\n tool_call_id: z.string(),\n name: z.string(),\n /** 喂回模型的文本(事件里截断到 2000 字符,完整版进对话上下文) */\n output: z.string(),\n is_error: z.boolean().default(false),\n elapsed_ms: z.number().default(0),\n});\nexport type AgentToolResult = z.infer<typeof agentToolResultSchema>;\n\nexport const agentCompactionSchema = z.object({\n summary: z.string(),\n tokens_before: z.number(),\n tokens_after: z.number(),\n});\nexport type AgentCompaction = z.infer<typeof agentCompactionSchema>;\n\n/** 提权请求(escalation_request 事件载荷):工具访问越界路径时发起,\n * 前端展示并等待用户确认;确认后服务端登记授权并重发消息续跑 */\nexport const agentEscalationSchema = z.object({\n /** 本次提权请求的唯一 id(确认接口的定位参数) */\n escalation_id: z.string(),\n /** 用户/模型给出的原始路径(展示用) */\n requested_path: z.string(),\n /** 沙箱解析后的绝对路径(确认后登记的授权键) */\n resolved_path: z.string(),\n /** 触发提权的工具名(如 list/read) */\n tool_name: z.string(),\n resource_type: z.enum([\"path\", \"command\"]).default(\"path\"),\n requested_command: z.array(z.string()).nullish(),\n /** 当前工作区根(展示给用户看边界在哪) */\n workdir: z.string(),\n});\nexport type AgentEscalation = z.infer<typeof agentEscalationSchema>;\n\nexport const agentDoneSchema = z.object({\n /** 最后一步的产出(loop 的最终答复) */\n text: z.string().nullish(),\n thinking: z.string().nullish(),\n finish_reason: z.string().nullish(),\n /** 全部步骤的累计用量 */\n usage: tokenUsageSchema.default({ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, cache_read_tokens: 0 }),\n /** 模型调用次数 */\n steps: z.number().default(1),\n model: z.string().default(\"\"),\n provider: z.string().default(\"\"),\n elapsed_ms: z.number().default(0),\n});\nexport type AgentDone = z.infer<typeof agentDoneSchema>;\n\n/** Agent 事件:type 决定哪些字段有值;作为 SSE 载荷时 type 同时用作 SSE 的 event 名 */\nexport const agentEventSchema = z.object({\n type: z.enum([\n \"agent_start\",\n \"thinking_delta\",\n \"text_delta\",\n \"tool_call_start\",\n \"tool_call_delta\",\n \"tool_call\",\n \"tool_result\",\n \"context_compacted\",\n \"escalation_request\",\n \"agent_done\",\n \"agent_error\",\n \"agent_cancelled\",\n ]),\n /** 本次运行的唯一 id,一次 start 产生的所有事件共享同一个值 */\n run_id: z.string(),\n delta: z.string().nullish(),\n tool_call: toolCallSchema.nullish(),\n tool_call_id: z.string().nullish(),\n tool_result: agentToolResultSchema.nullish(),\n compaction: agentCompactionSchema.nullish(),\n /** escalation_request 事件:路径提权请求 */\n escalation: agentEscalationSchema.nullish(),\n /** agent_start:实际路由到的端点名与模型 id */\n provider: z.string().nullish(),\n model: z.string().nullish(),\n /** agent_done 的终态载荷 */\n result: agentDoneSchema.nullish(),\n /** agent_error 的中文错误说明 */\n error: z.string().nullish(),\n});\nexport type AgentEvent = z.infer<typeof agentEventSchema>;\n\nexport type AgentEventType = AgentEvent[\"type\"];\n\nexport const TERMINAL_EVENT_TYPES: ReadonlySet<AgentEventType> = new Set([\n \"agent_done\",\n \"agent_error\",\n \"agent_cancelled\",\n]);\n","/**\n * Agent 系统提示词。\n *\n * 设计原则(移植自 MovieClaw,对齐 Claude Code 的提示词架构):\n * - 正文只写通用行为准则(运行方式 / 并行调用 / 工作循环 / 回复风格),\n * 不含任何领域词汇——领域语义由各工具的 description 和运行时环境段承载;\n * - 环境事实(日期等)随时会变,由 buildSystemPrompt 在每次运行时拼接,\n * 绝不写死在正文里。\n */\n\n/** 压缩摘要消息的固定前缀——重建历史时靠它识别「这条 user 消息是压缩摘要」,\n * 再次压缩时旧摘要不会被当成用户原话保留(codex SUMMARY_PREFIX 同款机制) */\nexport const SUMMARY_PREFIX = \"【上下文压缩摘要】此前的对话已被压缩,以下是交接摘要:\";\n\n/** 交接摘要指令(codex SUMMARIZATION_PROMPT 的中文对齐版)。作为一条普通\n * user 消息追加到全量历史末尾发起压缩请求,不是系统提示词。 */\nexport const COMPACT_PROMPT = `\\\n你正在执行一次上下文压缩。请为将要接手这段对话的另一个 LLM 写一份交接摘要。\n\n摘要必须包含:\n- 任务目标与当前进度、已做出的关键决定\n- 用户提出的约束、偏好和重要背景\n- 尚未完成的事项(明确的下一步)\n- 继续工作必须保留的关键数据(路径、ID、编号、查询结果要点等)\n\n保持简洁、结构化,以帮助下一个 LLM 无缝接续工作为唯一目标。只输出摘要正文。\n`;\n\nconst SYSTEM_PROMPT_TEMPLATE = `\\\n你是 {agentName},一个友好的智能助理。{persona}\n\n# 运行方式\n- 你的文字输出以 Markdown 渲染在会话页,工具调用过程用户全程可见。执行中不要旁白「我现在要去做什么」——工具调用本身就是过程展示。\n- 需要事实时永远先调用工具查证,一律以工具返回为准,绝不凭印象臆断。\n- 文件与工作状态都具有时效性;每次用户询问此类信息时,必须在当前轮次重新调用工具查询最新数据,不要相信或复用历史对话中已经获取的结果。\n- 工具报错或被拒绝,不要原样重发:读懂原因,修正参数或换一条路。\n\n# 工具使用规则\n- 工具列表会随当前会话配置动态注入;只能调用列表中实际存在的工具,不要臆造工具名或参数。\n- 先用 search 定位代码或文本,再用 read 查看必要上下文;不要为寻找内容递归读取大量文件。\n- 修改已有文件优先使用 edit;需要同时修改多个文件时使用 apply_patch;只有明确需要整体替换时才使用 write。\n- 修改后如果当前会话提供 exec_command,应运行最相关的格式化、类型检查或测试,并根据结果继续修正。\n- exec_command 使用 argv 数组而不是 shell 字符串;命令会话返回 session_id 时,用 write_stdin 继续读取,不要重复启动同一个命令。\n- exec_command 与 write_stdin 即使需要授权也会出现在工具目录中;调用后若收到提权请求,应等待用户确认,不要声称当前没有命令工具。\n- 任何工具被拒绝、越界或取消时,先理解返回原因;不要通过换写法绕过权限边界。\n\n# 并行工具调用\n需要多项互不依赖的信息时,在同一轮里一次性发起全部调用,而不是一轮一个。独立的检索、查询、状态读取都应合并到同一次回复中——运行时会安全并发执行连续的只读调用并按原顺序返回结果,合并调用避免了每多一轮就把整个对话重新发送一遍的开销。\n只有当后一个调用确实依赖前一个的结果时才分轮串行。拿不准且调用之间相互独立时,一律合并。\n\n# 工作循环\n以「思考 → 行动 → 观察」持续循环,直到任务完成:\n- 每次观察结果后重新评估:推进了就走下一步;没推进就换一种方式再试,而不是原样重试。\n- 坚持到底,不把做了一半的任务交回用户。同一障碍连续两次绕不过去,才停下向用户说明卡点。\n- 允许停下提问的只有两种情况:缺少只有用户能做的决定,或动作超出了本次的明确授权。\n\n# 回复风格\n- 全程中文。最终答复先结论、后关键依据,不复述执行过程。\n- 找不到就说找不到,绝不虚构任何数据。\n- 简短优先:一句能说清的不用三句。\n- 友好、有温度:像一个长期陪伴用户的真人伙伴那样交流,在恰当的时候给用户情绪价值。可以适度使用表情符号,但别泛滥。\n`;\n\nexport interface SystemPromptOptions {\n /** 助理名称,默认 \"xlyra 助理\" */\n agentName?: string;\n /** 一句话人设(拼在首段),默认空 */\n persona?: string;\n /** 运行时环境段(每行一个事实,拼在「# 环境」下) */\n extraEnvironment?: string;\n /** 当前会话实际暴露给模型的工具;由 Runner 动态注入,避免静态提示漂移。 */\n availableTools?: Array<Pick<import(\"../llm/models.js\").ToolDefinition, \"name\" | \"description\">>;\n}\n\nexport function buildAvailableToolsPrompt(\n availableTools: Array<Pick<import(\"../llm/models.js\").ToolDefinition, \"name\" | \"description\">>,\n): string {\n if (availableTools.length === 0) {\n return \"# 当前会话可用工具\\n- 当前会话没有可用工具;不要尝试调用工具。\";\n }\n return [\n \"# 当前会话可用工具\",\n ...availableTools.map((tool) => `- ${tool.name}:${tool.description.replace(/\\s+/g, \" \").trim()}`),\n ].join(\"\\n\");\n}\n\nexport function buildSystemPrompt(opts: SystemPromptOptions = {}): string {\n const body = SYSTEM_PROMPT_TEMPLATE.replace(\"{agentName}\", opts.agentName ?? \"xlyra 助理\").replace(\n \"{persona}\",\n opts.persona ? ` ${opts.persona}` : \"\",\n );\n const lines = [body, \"# 环境\", `- 当前日期:${new Date().toISOString().slice(0, 10)}`];\n if (opts.extraEnvironment) lines.push(opts.extraEnvironment);\n lines.push(buildAvailableToolsPrompt(opts.availableTools ?? []));\n return lines.join(\"\\n\");\n}\n","/**\n * 上下文压缩 —— codex 本地压缩策略的移植(经 MovieClaw 验证的取舍)。\n *\n * 核心思路:\n * 1. 触发以服务端上报的 usage 为准:每步响应带回真实 prompt_tokens,无需引入\n * tokenizer;仅在没有服务端数据的场合(续聊冷启动、尚未发送的工具结果)用\n * 「UTF-8 字节数 ≈ 4 字节/token」的启发式补估;\n * 2. 压缩就是一次普通模型调用:把交接摘要指令作为 user 消息追加到全量历史\n * 末尾,不带任何工具定义——模型只能输出文本,天然保证这一轮只写摘要;\n * 3. 重建历史「宽进严出」:生成摘要时模型看得到全部现场;压缩落地后只保留\n * 「预算内最近的用户原话 + 摘要」,工具轨迹全部丢弃——用户原话永不经过\n * 有损摘要,防多次压缩后忘记原始意图;\n * 4. 失败一律降级:压缩失败只记日志、返回 null,绝不中断正在进行的运行。\n */\nimport type { ChatMessage, ModelSettings } from \"../llm/models.js\";\nimport type { LlmProtocol } from \"../llm/protocol.js\";\nimport { COMPACT_PROMPT, SUMMARY_PREFIX } from \"./prompts.js\";\n\n/** 自动压缩水位线:上下文占用 ≥ 窗口的 90% 时触发(codex 同款比例) */\nexport const COMPACT_TRIGGER_RATIO = 0.9;\n\n/** 重建历史时保留近期用户消息的 token 预算(codex 同款 20k) */\nexport const RETAINED_USER_TOKEN_BUDGET = 20_000;\n\n/** 无 tokenizer 时的估算系数:约 4 字节(UTF-8)≈ 1 token。对中文同样适用——\n * 一个汉字 3 字节 ≈ 0.75 token,与主流 tokenizer 的量级一致,偏保守即可 */\nexport const APPROX_BYTES_PER_TOKEN = 4;\n\nexport interface CompactionResult {\n /** 交接摘要文本 */\n summary: string;\n /** 重建后的历史(不含 system,system 每次运行重拼) */\n replacement_history: ChatMessage[];\n /** 压缩前后的估算 token 数(bytes/4 启发式,展示与观测用,非精确值) */\n tokens_before: number;\n tokens_after: number;\n}\n\nexport function estimateTokens(target: ChatMessage[] | ChatMessage | string): number {\n if (typeof target === \"string\") {\n return Math.floor(Buffer.byteLength(target, \"utf-8\") / APPROX_BYTES_PER_TOKEN);\n }\n if (Array.isArray(target)) {\n return target.reduce((sum, m) => sum + estimateTokens(m), 0);\n }\n let total = Buffer.byteLength(target.content ?? \"\", \"utf-8\");\n for (const tc of target.tool_calls ?? []) {\n total += Buffer.byteLength(tc.name, \"utf-8\");\n total += Buffer.byteLength(tc.raw_arguments, \"utf-8\");\n }\n return Math.floor(total / APPROX_BYTES_PER_TOKEN);\n}\n\n/** 是否达到自动压缩水位线;模型未声明窗口时永不自动压缩(调用方负责日志) */\nexport function shouldCompact(contextTokens: number, contextWindow: number | undefined): boolean {\n if (!contextWindow) return false;\n return contextTokens >= Math.floor(contextWindow * COMPACT_TRIGGER_RATIO);\n}\n\n/** 识别历史里由压缩产生的摘要消息(user 角色 + 固定前缀) */\nexport function isSummaryMessage(message: ChatMessage): boolean {\n return message.role === \"user\" && (message.content ?? \"\").startsWith(SUMMARY_PREFIX);\n}\n\n/** 中部截断:头尾各留一半预算,中间以标记替代(用户消息开头是诉求、结尾是\n * 最新补充,头尾信息密度最高)。按字节预算切,落在多字节字符中间时由\n * Buffer.toString 自动退回合法边界。 */\nfunction truncateMiddle(text: string, maxTokens: number): string {\n const budgetBytes = maxTokens * APPROX_BYTES_PER_TOKEN;\n const data = Buffer.from(text, \"utf-8\");\n if (data.length <= budgetBytes) return text;\n const half = Math.floor(budgetBytes / 2);\n const head = data.subarray(0, half).toString(\"utf-8\");\n const tail = data.subarray(data.length - half).toString(\"utf-8\");\n const omitted = Math.floor((data.length - budgetBytes) / APPROX_BYTES_PER_TOKEN);\n return `${head}\\n…(中间约 ${omitted} token 已截断)…\\n${tail}`;\n}\n\n/** 按 codex 策略重建历史:预算内逆序保留的用户原话 + 摘要收尾。\n * - 只保留真实 user 消息(排除 system / 旧压缩摘要),从最新往旧装入预算,\n * 装不下的最旧一条中部截断;\n * - assistant / tool / 思考内容全部丢弃,信息由摘要承载;\n * - 摘要带固定前缀、作为最后一条 user 消息。 */\nexport function buildReplacementHistory(\n messages: ChatMessage[],\n summary: string,\n): ChatMessage[] {\n const retained: ChatMessage[] = [];\n let remaining = RETAINED_USER_TOKEN_BUDGET;\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]!;\n if (message.role !== \"user\" || isSummaryMessage(message)) continue;\n if (remaining <= 0) break;\n const tokens = estimateTokens(message);\n if (tokens <= remaining) {\n retained.push(message);\n remaining -= tokens;\n } else {\n retained.push({ role: \"user\", content: truncateMiddle(message.content ?? \"\", remaining) });\n break;\n }\n }\n retained.reverse();\n return [...retained, { role: \"user\", content: `${SUMMARY_PREFIX}\\n${summary}` }];\n}\n\n/**\n * 执行一次压缩:全量历史 + 摘要指令 → 模型写交接摘要 → 重建历史。\n *\n * messages 是完整现场(含 system 与全部工具往返);返回的\n * replacement_history 不含 system。任何失败(流错误、异常、空摘要)都\n * 返回 null,由调用方决定降级方式——本函数绝不抛异常。\n */\nexport async function compact(\n protocol: LlmProtocol,\n model: string,\n messages: ChatMessage[],\n settings: ModelSettings,\n): Promise<CompactionResult | null> {\n let summary: string | null = null;\n try {\n for await (const event of protocol.chatStream({\n model,\n // 摘要指令是普通 user 消息;不带工具定义,模型只能输出文本\n messages: [...messages, { role: \"user\", content: COMPACT_PROMPT }],\n settings,\n })) {\n if (event.type === \"error\") {\n console.warn(`上下文压缩失败(模型调用出错):${event.error}`);\n return null;\n }\n if (event.type === \"done\") summary = (event.response.content ?? \"\").trim();\n }\n } catch (err) {\n console.warn(`上下文压缩失败(请求异常):${err instanceof Error ? err.message : err}`);\n return null;\n }\n if (!summary) {\n console.warn(\"上下文压缩失败:模型返回了空摘要\");\n return null;\n }\n const replacement = buildReplacementHistory(messages, summary);\n const system = messages.slice(0, 1).filter((m) => m.role === \"system\");\n return {\n summary,\n replacement_history: replacement,\n tokens_before: estimateTokens(messages),\n tokens_after: estimateTokens([...system, ...replacement]),\n };\n}\n","/**\n * Agent 会话的 JSONL 持久化存储(事实源)。\n *\n * 设计定案(移植自 MovieClaw,调研 pi / codex / Claude Code 后的共识 + 取舍):\n *\n * 1. 一个会话一个 append-only JSONL 文件:首行是会话头,之后每行一条\n * 消息 entry。历史行永不改写——中断、重启都只会追加。唯一例外是\n * discardFromUserMessage(retry 的历史替换),见该方法说明;\n * 2. 只落定稿消息,不落流式 delta:文件里的 message 就是内部规范模型原样\n * 格式(ChatMessage),resume 重建上下文零转换;\n * 3. entry 带 uuid / parent_uuid:当前是纯线性链(parent 永远指向上一条),\n * 字段先留好,将来做历史分支时无需迁移文件格式;\n * 4. 读取容错:进程崩溃可能留下半行,逐行解析时静默跳过坏行并计数,\n * 绝不让整个会话打不开;\n * 5. 压缩行(type: \"compaction\"):含摘要与完整替换历史,buildHistory 从\n * 最后一条压缩行起重建(codex 的 Compacted 记录同款思路)。压缩前的\n * 原始消息仍完整留在文件里(回放展示用),但不再进入模型上下文。\n *\n * 存储位置默认 ~/.xlyra-agent/sessions(评审定案),构造参数可覆盖。\n */\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { chatMessageSchema, tokenUsageSchema, type ChatMessage } from \"../llm/models.js\";\nimport type { CompactionResult } from \"./compaction.js\";\n\n/** 文件格式版本;结构变化时 +1,读取端按版本做迁移\n * v3:新增 type=\"escalation\" 的提权请求行(读端向后兼容 v1/v2) */\nexport const SESSION_FORMAT_VERSION = 3;\n\n/** 会话标题 / 最后提示预览的截断长度 */\nexport const PREVIEW_MAX_CHARS = 80;\n\n/** 默认数据根目录(~/.xlyra-agent),sessions 与 index.json 均在其下 */\nexport function defaultDataDir(): string {\n return path.join(os.homedir(), \".xlyra-agent\");\n}\n\nexport function defaultSessionsDir(): string {\n return path.join(defaultDataDir(), \"sessions\");\n}\n\nconst sessionHeaderSchema = z.object({\n type: z.literal(\"session\").default(\"session\"),\n version: z.number().default(SESSION_FORMAT_VERSION),\n session_id: z.string(),\n created_at: z.string(),\n});\nexport type SessionHeader = z.infer<typeof sessionHeaderSchema>;\n\nconst sessionMessageEntrySchema = z.object({\n type: z.literal(\"message\").default(\"message\"),\n uuid: z.string(),\n parent_uuid: z.string().nullish(),\n timestamp: z.string(),\n message: chatMessageSchema,\n /** 以下仅 assistant 消息携带(运行元数据,不属于 message 本身,放信封层) */\n model: z.string().nullish(),\n usage: tokenUsageSchema.nullish(),\n finish_reason: z.string().nullish(),\n});\nexport type SessionMessageEntry = z.infer<typeof sessionMessageEntrySchema>;\n\nconst sessionCompactionEntrySchema = z.object({\n type: z.literal(\"compaction\").default(\"compaction\"),\n uuid: z.string(),\n parent_uuid: z.string().nullish(),\n timestamp: z.string(),\n summary: z.string(),\n replacement_history: z.array(chatMessageSchema),\n tokens_before: z.number().nullish(),\n tokens_after: z.number().nullish(),\n});\nexport type SessionCompactionEntry = z.infer<typeof sessionCompactionEntrySchema>;\n\n/** 提权请求行:越界访问的协商记录(回放时前端据此渲染确认卡片)。\n * granted=null 待确认;true 已授权;false 已拒绝 */\nconst sessionEscalationEntrySchema = z.object({\n type: z.literal(\"escalation\").default(\"escalation\"),\n uuid: z.string(),\n parent_uuid: z.string().nullish(),\n timestamp: z.string(),\n requested_path: z.string(),\n resolved_path: z.string(),\n tool_name: z.string(),\n resource_type: z.enum([\"path\", \"command\"]).default(\"path\"),\n requested_command: z.array(z.string()).nullish(),\n /** 旧记录可能省略待确认状态;读取时统一规范化为 null。 */\n granted: z.boolean().nullish().default(null),\n});\nexport type SessionEscalationEntry = z.infer<typeof sessionEscalationEntrySchema>;\n\nexport type SessionEntry = SessionMessageEntry | SessionCompactionEntry | SessionEscalationEntry;\n\nexport interface SessionSummary {\n session_id: string;\n created_at: string;\n entry_count: number;\n leaf_uuid: string | null;\n /** 首条 user 消息的截断文本;作为无自定义标题时的会话标题 */\n title: string | null;\n /** 最后一条 user 消息的截断文本 */\n last_prompt: string | null;\n last_timestamp: string;\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction entryUuid(): string {\n return crypto.randomUUID().replaceAll(\"-\", \"\").slice(0, 12);\n}\n\nexport function isMessageEntry(e: SessionEntry): e is SessionMessageEntry {\n return e.type === \"message\";\n}\n\nexport function isCompactionEntry(e: SessionEntry): e is SessionCompactionEntry {\n return e.type === \"compaction\";\n}\n\nexport function isEscalationEntry(e: SessionEntry): e is SessionEscalationEntry {\n return e.type === \"escalation\";\n}\n\nfunction lastCompactionIndex(entries: SessionEntry[]): number {\n for (let i = entries.length - 1; i >= 0; i--) {\n if (isCompactionEntry(entries[i]!)) return i;\n }\n return -1;\n}\n\n/** 最后一条压缩行之后的消息(无压缩行时即全部消息) */\nfunction messagesAfterLastCompaction(entries: SessionEntry[]): ChatMessage[] {\n const last = lastCompactionIndex(entries);\n return entries.slice(last + 1).filter(isMessageEntry).map((e) => e.message);\n}\n\nexport class AgentSessionStore {\n private readonly root: string;\n /** session_id → 最后一条 entry 的 uuid(避免每次 append 都重读文件) */\n private readonly leafCache = new Map<string, string | null>();\n\n constructor(root?: string) {\n this.root = path.resolve(root ?? defaultSessionsDir());\n }\n\n get rootDir(): string {\n return this.root;\n }\n\n pathOf(sessionId: string): string {\n return path.join(this.root, `${sessionId}.jsonl`);\n }\n\n exists(sessionId: string): boolean {\n return fs.existsSync(this.pathOf(sessionId));\n }\n\n // ------------------------------------------------------------------\n // 写入\n // ------------------------------------------------------------------\n\n /** 新建会话文件并写入头行,返回头信息 */\n create(sessionId?: string): SessionHeader {\n const header: SessionHeader = {\n type: \"session\",\n version: SESSION_FORMAT_VERSION,\n session_id: sessionId ?? crypto.randomUUID().replaceAll(\"-\", \"\"),\n created_at: nowIso(),\n };\n fs.mkdirSync(this.root, { recursive: true });\n // wx:会话 id 冲突(几乎不可能)时宁可报错也不覆盖已有文件\n fs.writeFileSync(this.pathOf(header.session_id), JSON.stringify(header) + \"\\n\", { flag: \"wx\" });\n this.leafCache.set(header.session_id, null);\n return header;\n }\n\n /** 追加一条定稿消息,自动接到当前链尾,返回写入的 entry */\n append(\n sessionId: string,\n message: ChatMessage,\n meta?: { model?: string; usage?: z.infer<typeof tokenUsageSchema>; finish_reason?: string },\n ): SessionMessageEntry {\n const parent = this.currentLeaf(sessionId);\n const entry: SessionMessageEntry = {\n type: \"message\",\n uuid: entryUuid(),\n parent_uuid: parent,\n timestamp: nowIso(),\n message,\n model: meta?.model ?? null,\n usage: meta?.usage ?? null,\n finish_reason: meta?.finish_reason ?? null,\n };\n this.appendLine(sessionId, stripNulls(entry));\n this.leafCache.set(sessionId, entry.uuid);\n return entry;\n }\n\n /** 追加一条压缩行,与 append 同款接到当前链尾(parent 链线性穿过压缩行) */\n appendCompaction(sessionId: string, result: CompactionResult): SessionCompactionEntry {\n const parent = this.currentLeaf(sessionId);\n const entry: SessionCompactionEntry = {\n type: \"compaction\",\n uuid: entryUuid(),\n parent_uuid: parent,\n timestamp: nowIso(),\n summary: result.summary,\n replacement_history: result.replacement_history,\n tokens_before: result.tokens_before,\n tokens_after: result.tokens_after,\n };\n this.appendLine(sessionId, stripNulls(entry));\n this.leafCache.set(sessionId, entry.uuid);\n return entry;\n }\n\n /** 追加一条提权请求行(granted=null 待确认) */\n appendEscalation(\n sessionId: string,\n info: {\n escalation_id: string;\n requested_path: string;\n resolved_path: string;\n tool_name: string;\n resource_type?: \"path\" | \"command\";\n requested_command?: string[];\n },\n ): SessionEscalationEntry {\n const parent = this.currentLeaf(sessionId);\n const entry: SessionEscalationEntry = {\n type: \"escalation\",\n uuid: info.escalation_id,\n parent_uuid: parent,\n timestamp: nowIso(),\n requested_path: info.requested_path,\n resolved_path: info.resolved_path,\n tool_name: info.tool_name,\n resource_type: info.resource_type ?? \"path\",\n requested_command: info.requested_command,\n granted: null,\n };\n this.appendLine(sessionId, stripNulls(entry));\n this.leafCache.set(sessionId, entry.uuid);\n return entry;\n }\n\n /** 标记提权请求的确认结果(granted=true 授权 / false 拒绝)。\n * 这是 append-only 原则的第二个例外(另一个是 discardFromUserMessage):\n * 提权行的 granted 字段需要就地更新,否则确认状态无法在回放时保留。\n * 实现上仍是整文件原子重写(tmp + rename),与 discard 同款安全保证。 */\n resolveEscalation(sessionId: string, escalationId: string, granted: boolean): boolean {\n const { header, entries } = this.read(sessionId);\n const index = entries.findIndex((e) => isEscalationEntry(e) && e.uuid === escalationId);\n if (index === -1) return false;\n const target = entries[index]!;\n if (!isEscalationEntry(target)) return false;\n entries[index] = { ...target, granted };\n const filePath = this.pathOf(sessionId);\n const tmp = `${filePath}.tmp`;\n const lines = [JSON.stringify(header), ...entries.map((e) => JSON.stringify(stripNulls(e)))];\n fs.writeFileSync(tmp, lines.join(\"\\n\") + \"\\n\");\n fs.renameSync(tmp, filePath);\n return true;\n }\n\n /**\n * 中断收尾:给没有结果的 tool_call 补写错误回执,返回补写条数。\n *\n * 保证文件里 assistant 的 tool_calls 与 tool 消息任何时刻都配对完整,\n * resume 直接回喂 API 不需要修复逻辑(在写入侧一次做对)。\n * 只检查最后一条压缩行之后的消息:更早的往返已被压缩挡在上下文之外,\n * 给死上下文补回执毫无意义。\n */\n sealPendingToolCalls(sessionId: string): number {\n const { entries } = this.read(sessionId);\n const messages = messagesAfterLastCompaction(entries);\n const answered = new Set(\n messages.filter((m) => m.role === \"tool\").map((m) => m.tool_call_id),\n );\n let sealed = 0;\n for (const message of messages) {\n for (const tc of message.tool_calls ?? []) {\n if (answered.has(tc.id)) continue;\n this.append(sessionId, {\n role: \"tool\",\n content: \"操作已被中断,工具未执行完成。\",\n tool_call_id: tc.id,\n name: tc.name,\n is_error: true,\n });\n sealed += 1;\n }\n }\n return sealed;\n }\n\n /**\n * 删除指定 user message 及其之后的全部 entry,返回删除条数。\n *\n * 这是本模块唯一改写历史行的方法,与「append-only」约定相悖,属于刻意的\n * 例外:用户要的就是「这些记录不该再存在」。整文件重写,写临时文件后\n * rename 原子换入:中途崩溃要么旧文件完好、要么新文件完整。\n * 只允许从 user message 切:从 assistant/tool 中间切会留下没有回执的\n * tool_call,重建出的上下文喂回模型直接 400。\n */\n discardFromUserMessage(sessionId: string, messageId: string): number {\n const { header, entries } = this.read(sessionId);\n const index = entries.findIndex((e) => e.uuid === messageId);\n if (index === -1) throw new Error(\"会话中没有这条记录,可能已被改写\");\n const target = entries[index]!;\n if (!isMessageEntry(target) || target.message.role !== \"user\") {\n throw new Error(\"只能重试用户消息\");\n }\n const kept = entries.slice(0, index);\n const filePath = this.pathOf(sessionId);\n const tmp = `${filePath}.tmp`;\n const lines = [JSON.stringify(header), ...kept.map((e) => JSON.stringify(stripNulls(e)))];\n fs.writeFileSync(tmp, lines.join(\"\\n\") + \"\\n\");\n fs.renameSync(tmp, filePath);\n this.leafCache.set(sessionId, kept.length > 0 ? kept[kept.length - 1]!.uuid : null);\n return entries.length - kept.length;\n }\n\n /** 删除会话文件(幂等) */\n delete(sessionId: string): void {\n fs.rmSync(this.pathOf(sessionId), { force: true });\n this.leafCache.delete(sessionId);\n }\n\n // ------------------------------------------------------------------\n // 读取\n // ------------------------------------------------------------------\n\n /** 读取整个会话(头 + 全部 entry,含压缩行),坏行静默跳过 */\n read(sessionId: string): { header: SessionHeader; entries: SessionEntry[]; badLines: number } {\n const filePath = this.pathOf(sessionId);\n if (!fs.existsSync(filePath)) throw new Error(\"会话不存在或转录文件已被删除\");\n const lines = fs.readFileSync(filePath, \"utf-8\").split(\"\\n\");\n let header: SessionHeader | null = null;\n const entries: SessionEntry[] = [];\n let bad = 0;\n for (const [lineNo, raw] of lines.entries()) {\n const line = raw.trim();\n if (!line) continue;\n if (lineNo === 0) {\n header = sessionHeaderSchema.parse(JSON.parse(line));\n continue;\n }\n try {\n const parsed: unknown = JSON.parse(line);\n const type = (parsed as { type?: string }).type;\n entries.push(\n type === \"compaction\"\n ? sessionCompactionEntrySchema.parse(parsed)\n : type === \"escalation\"\n ? sessionEscalationEntrySchema.parse(parsed)\n : sessionMessageEntrySchema.parse(parsed),\n );\n } catch {\n bad += 1;\n }\n }\n if (!header) throw new Error(\"会话文件为空或头记录损坏\");\n if (bad > 0) {\n console.warn(`会话文件存在 ${bad} 行无法解析的记录,已跳过(可能来自异常退出):${filePath}`);\n }\n return { header, entries, badLines: bad };\n }\n\n /**\n * 把会话重建成模型上下文消息列表(resume 喂回模型用)。\n * 有压缩行时,从最后一条压缩行的替换历史起步、只追加其后的增量消息;\n * system 提示词不入库(随代码版本演进),由 runner 每次运行时重新拼装。\n */\n buildHistory(sessionId: string): ChatMessage[] {\n const { entries } = this.read(sessionId);\n const last = lastCompactionIndex(entries);\n if (last < 0) return entries.filter(isMessageEntry).map((e) => e.message);\n const compaction = entries[last] as SessionCompactionEntry;\n return [\n ...compaction.replacement_history,\n ...entries.slice(last + 1).filter(isMessageEntry).map((e) => e.message),\n ];\n }\n\n /**\n * 重建提权中断前的上下文:保留原始 user 输入,但丢弃被中断的\n * assistant/tool 往返,授权后由 runner 从原输入继续推理。\n */\n buildHistoryBeforeEscalation(sessionId: string, escalationId: string): ChatMessage[] {\n const { entries } = this.read(sessionId);\n const escalationIndex = entries.findIndex(\n (entry) => isEscalationEntry(entry) && entry.uuid === escalationId,\n );\n if (escalationIndex < 0) return this.buildHistory(sessionId);\n const escalation = entries[escalationIndex]!;\n const assistantIndex = entries.findIndex(\n (entry) => entry.uuid === escalation.parent_uuid && isMessageEntry(entry)\n && entry.message.role === \"assistant\",\n );\n const cut = assistantIndex >= 0 ? assistantIndex : escalationIndex;\n const last = lastCompactionIndex(entries);\n if (last >= 0 && last < cut) {\n const compaction = entries[last] as SessionCompactionEntry;\n return [\n ...compaction.replacement_history,\n ...entries.slice(last + 1, cut).filter(isMessageEntry).map((e) => e.message),\n ];\n }\n return entries.slice(0, cut).filter(isMessageEntry).map((e) => e.message);\n }\n\n /** 扫描单个会话文件生成索引摘要 */\n summarize(sessionId: string): SessionSummary {\n const { header, entries } = this.read(sessionId);\n const userTexts = entries\n .filter(isMessageEntry)\n .filter((e) => e.message.role === \"user\" && (e.message.content ?? \"\").trim())\n .map((e) => (e.message.content ?? \"\").trim());\n const last = entries[entries.length - 1];\n return {\n session_id: header.session_id,\n created_at: header.created_at,\n entry_count: entries.length,\n leaf_uuid: last?.uuid ?? null,\n title: userTexts[0]?.slice(0, PREVIEW_MAX_CHARS) ?? null,\n last_prompt: userTexts[userTexts.length - 1]?.slice(0, PREVIEW_MAX_CHARS) ?? null,\n last_timestamp: last?.timestamp ?? header.created_at,\n };\n }\n\n /** 遍历目录下全部会话文件生成摘要(索引整体重建用;单文件损坏只跳过) */\n scanAll(): SessionSummary[] {\n if (!fs.existsSync(this.root)) return [];\n const summaries: SessionSummary[] = [];\n for (const name of fs.readdirSync(this.root).sort()) {\n if (!name.endsWith(\".jsonl\")) continue;\n const sessionId = name.slice(0, -\".jsonl\".length);\n try {\n summaries.push(this.summarize(sessionId));\n } catch (err) {\n console.warn(`会话文件无法解析,重建索引时已跳过:${name}(${err instanceof Error ? err.message : err})`);\n }\n }\n return summaries;\n }\n\n // ------------------------------------------------------------------\n\n private currentLeaf(sessionId: string): string | null {\n if (!this.leafCache.has(sessionId)) {\n const { entries } = this.read(sessionId);\n this.leafCache.set(sessionId, entries[entries.length - 1]?.uuid ?? null);\n }\n return this.leafCache.get(sessionId) ?? null;\n }\n\n private appendLine(sessionId: string, entry: SessionEntry): void {\n const filePath = this.pathOf(sessionId);\n if (!fs.existsSync(filePath)) throw new Error(\"会话不存在或转录文件已被删除\");\n fs.appendFileSync(filePath, JSON.stringify(entry) + \"\\n\");\n }\n}\n\n/** JSONL 序列化前去 null 字段(与 MovieClaw 的 exclude_none 对齐,文件更紧凑) */\nfunction stripNulls<T>(obj: T): T {\n return JSON.parse(\n JSON.stringify(obj, (_key, value: unknown) => (value === null || value === undefined ? undefined : value)),\n ) as T;\n}\n","/**\n * AgentRunner —— Agent loop 执行器。\n *\n * 循环语义(移植自 MovieClaw runner.py,设计要点逐条保留):\n * - 每一步 = 一次流式模型调用;模型输出的工具调用**以内容为准**判断是否\n * 继续循环——finish_reason 只作参考,因为兼容端点存在「stop 但带调用」\n * 「tool_calls 但数组为空」两类在案怪癖;\n * - 有工具调用 → 顺序执行每一个(参数先过 JSON Schema 校验),结果作为\n * tool 消息回喂,进入下一步;无工具调用 → STOP,正常结束;\n * - 工具的校验失败与执行异常都不中断循环:错误文本作为失败结果回喂,\n * 让模型自行修正;\n * - maxSteps(默认 200)防失控;错误一律以 agent_error 事件收尾,不抛异常。\n *\n * 取消语义(与编排层的分工):\n * - runner 接受外部 AbortSignal;signal 触发后本生成器尽快、安静地结束,\n * **不落终态事件**——agent_cancelled 由编排层在 abort 之前先落\n * (RunRegistry.cancel),保证订阅者永远先看到终态。\n */\nimport crypto from \"node:crypto\";\nimport type { ChatMessage, ChatResponse, TokenUsage } from \"../llm/models.js\";\nimport { addUsage, chatMessageSchema, emptyUsage, modelSettingsSchema, responseToMessage } from \"../llm/models.js\";\nimport type { LlmProtocol } from \"../llm/protocol.js\";\nimport { LlmError } from \"../llm/errors.js\";\nimport type { EndpointResolver } from \"../llm/router.js\";\nimport { validateToolCall } from \"../llm/validate.js\";\nimport type { AgentTool } from \"../tools/types.js\";\nimport { truncateMiddle } from \"../tools/types.js\";\nimport type { CompactionResult } from \"./compaction.js\";\nimport { compact, estimateTokens, shouldCompact } from \"./compaction.js\";\nimport { EscalationRequiredError } from \"./escalation.js\";\nimport type { AgentDone, AgentEvent, AgentStartParams, AgentToolResult } from \"./events.js\";\nimport { buildAvailableToolsPrompt, buildSystemPrompt } from \"./prompts.js\";\n\n/** tool_result 事件里输出的截断长度(完整输出仍进对话上下文喂给模型) */\nconst EVENT_OUTPUT_LIMIT = 2000;\n\nexport interface AgentRunnerOptions {\n /** 直接使用单个协议实例(库形态的典型用法) */\n protocol?: LlmProtocol;\n /** 或经端点路由按 params.model 解析(服务层用法);两者必传其一 */\n resolver?: EndpointResolver;\n tools?: AgentTool[];\n maxSteps?: number;\n /** 定稿消息回调(会话持久化挂点):中间步 assistant(含 tool_calls)、\n * 每条 tool 结果、终答 assistant 各调用一次;流式 delta 不经过这里 */\n onMessage?: (message: ChatMessage, response: ChatResponse | null) => Promise<void>;\n /** 压缩定稿回调(转录落盘挂点):每次上下文压缩成功后调用一次 */\n onCompaction?: (result: CompactionResult) => Promise<void>;\n /** 提权请求回调(转录落盘挂点):回放时前端据此渲染确认卡片 */\n onEscalation?: (info: {\n escalation_id: string;\n requested_path: string;\n resolved_path: string;\n tool_name: string;\n resource_type: \"path\" | \"command\";\n requested_command?: string[];\n }) => Promise<void>;\n /** 日志输出(默认 console);测试可注入静默 logger */\n logger?: Pick<Console, \"info\" | \"warn\" | \"error\">;\n /** 提权事件里展示的工作区根(用户判断边界用);服务装配层从工具配置传入 */\n workdirHint?: string;\n}\n\nexport interface AgentRunOptions {\n runId?: string;\n signal?: AbortSignal;\n}\n\nexport class AgentRunner {\n private readonly protocol?: LlmProtocol;\n private readonly resolver?: EndpointResolver;\n private readonly tools: AgentTool[];\n private readonly toolsByName: Map<string, AgentTool>;\n private readonly maxSteps: number;\n private readonly onMessage?: AgentRunnerOptions[\"onMessage\"];\n private readonly onCompaction?: AgentRunnerOptions[\"onCompaction\"];\n private readonly onEscalation?: AgentRunnerOptions[\"onEscalation\"];\n private readonly logger: Pick<Console, \"info\" | \"warn\" | \"error\">;\n /** 提权事件里展示的工作区根(用户判断边界用);由构造方从工具配置传入 */\n private readonly workdirHint: string;\n\n constructor(opts: AgentRunnerOptions) {\n if (!opts.protocol && !opts.resolver) {\n throw new Error(\"AgentRunner 需要 protocol 或 resolver 之一\");\n }\n this.protocol = opts.protocol;\n this.resolver = opts.resolver;\n this.tools = opts.tools ?? [];\n this.toolsByName = new Map(this.tools.map((t) => [t.definition.name, t]));\n this.maxSteps = opts.maxSteps ?? 200;\n this.onMessage = opts.onMessage;\n this.onCompaction = opts.onCompaction;\n this.onEscalation = opts.onEscalation;\n this.logger = opts.logger ?? console;\n this.workdirHint = opts.workdirHint ?? \"\";\n }\n\n async *start(\n params: AgentStartParams,\n runOpts: AgentRunOptions = {},\n ): AsyncGenerator<AgentEvent> {\n const runId = runOpts.runId ?? crypto.randomUUID().replaceAll(\"-\", \"\").slice(0, 12);\n const started = Date.now();\n\n // 路由解析放在发事件之前:解析失败也要以 agent_error 事件告知,而不是断流\n let protocol: LlmProtocol;\n let providerName: string;\n let modelId: string;\n let contextWindow: number | undefined;\n try {\n if (this.resolver) {\n const resolved = this.resolver.resolve(params.model ?? \"\");\n protocol = resolved.protocol;\n providerName = resolved.endpoint.name;\n modelId = resolved.modelId;\n contextWindow = resolved.contextWindow;\n } else {\n protocol = this.protocol!;\n providerName = protocol.name;\n modelId = params.model ?? \"\";\n contextWindow = undefined;\n }\n } catch (err) {\n if (err instanceof LlmError) {\n yield { type: \"agent_error\", run_id: runId, error: err.message };\n return;\n }\n throw err;\n }\n if (!contextWindow) {\n this.logger.info(`模型未声明上下文窗口,自动压缩停用 model=${modelId}`);\n }\n\n // history 来自外部输入(z.input 形态,content 可选):统一过一遍 schema\n // 补全默认值,同时挡掉调用方传来的结构错误\n const history = (params.history ?? []).map((m) => chatMessageSchema.parse(m));\n const settings = modelSettingsSchema.parse(params.settings ?? {});\n const definitions = this.tools.map((t) => t.definition);\n const availableToolsPrompt = buildAvailableToolsPrompt(\n definitions.map(({ name, description }) => ({ name, description })),\n );\n const messages: ChatMessage[] = [\n {\n role: \"system\",\n content:\n params.system_prompt\n ? `${params.system_prompt.trim()}\\n\\n${availableToolsPrompt}`\n : buildSystemPrompt({ availableTools: definitions.map(({ name, description }) => ({ name, description })) }),\n },\n ...history,\n ...(params.include_input === false ? [] : [{ role: \"user\" as const, content: params.input }]),\n ];\n\n yield { type: \"agent_start\", run_id: runId, provider: providerName, model: modelId };\n\n // pre-run 检查:续聊重建的历史可能已经逼近窗口(此时还没有服务端 usage\n // 可用,用字节启发式估算),先压缩再进入循环\n const preCompact = await this.maybeCompact(\n protocol, runId, modelId, messages, estimateTokens(messages), contextWindow, settings,\n );\n if (preCompact) yield preCompact;\n\n let usage = emptyUsage();\n for (let step = 1; step <= this.maxSteps; step++) {\n if (runOpts.signal?.aborted) return; // 取消:安静退出,终态已由编排层落\n\n let final: ChatResponse | null = null;\n for await (const event of protocol.chatStream({\n model: modelId,\n messages,\n tools: definitions.length ? definitions : undefined,\n settings,\n signal: runOpts.signal,\n })) {\n if (event.type === \"thinking_delta\") {\n yield { type: \"thinking_delta\", run_id: runId, delta: event.delta };\n } else if (event.type === \"text_delta\") {\n yield { type: \"text_delta\", run_id: runId, delta: event.delta };\n } else if (event.type === \"toolcall_start\") {\n yield { type: \"tool_call_start\", run_id: runId, tool_call: event.tool_call };\n } else if (event.type === \"toolcall_delta\") {\n yield {\n type: \"tool_call_delta\",\n run_id: runId,\n delta: event.delta,\n tool_call_id: event.tool_call.id,\n };\n } else if (event.type === \"toolcall_end\") {\n yield { type: \"tool_call\", run_id: runId, tool_call: event.tool_call };\n } else if (event.type === \"error\") {\n this.logger.warn(`Agent 运行失败 run=${runId}:${event.error}`);\n yield { type: \"agent_error\", run_id: runId, error: event.error || \"模型调用失败,原因未知\" };\n return;\n } else if (event.type === \"done\") {\n final = event.response;\n }\n }\n\n if (runOpts.signal?.aborted) return;\n if (!final) {\n yield { type: \"agent_error\", run_id: runId, error: \"模型流异常终止,未返回结果\" };\n return;\n }\n usage = addUsage(usage, final.usage);\n\n // 循环判据:以 tool_calls 内容为准(finish_reason 只作参考)\n if (final.tool_calls.length === 0) {\n await this.notify(responseToMessage(final), final);\n const result: AgentDone = {\n text: final.content,\n thinking: final.thinking,\n finish_reason: final.finish_reason,\n usage,\n steps: step,\n model: final.model,\n provider: final.provider,\n elapsed_ms: Date.now() - started,\n };\n yield { type: \"agent_done\", run_id: runId, result };\n return;\n }\n\n // assistant 消息(含 tool_calls)入上下文,随后逐个执行工具\n messages.push(responseToMessage(final));\n await this.notify(responseToMessage(final), final);\n const stepToolMessages: ChatMessage[] = [];\n let callIndex = 0;\n while (callIndex < final.tool_calls.length) {\n const firstCall = final.tool_calls[callIndex]!;\n const firstTool = this.toolsByName.get(firstCall.name);\n const canRunParallel =\n firstTool?.annotations?.readOnly === true &&\n firstTool.annotations.parallelSafe === true;\n const batch = [firstCall];\n callIndex += 1;\n if (canRunParallel) {\n while (callIndex < final.tool_calls.length) {\n const candidate = final.tool_calls[callIndex]!;\n const tool = this.toolsByName.get(candidate.name);\n if (tool?.annotations?.readOnly !== true || tool.annotations.parallelSafe !== true) break;\n batch.push(candidate);\n callIndex += 1;\n }\n }\n\n const settled = await Promise.allSettled(\n batch.map((tc) => this.executeTool(tc, definitions, {\n signal: runOpts.signal,\n runId,\n })),\n );\n for (const [index, outcome] of settled.entries()) {\n const tc = batch[index]!;\n // 提权协商:工具抛 EscalationRequiredError 时,发协商事件并以\n // agent_cancelled 收尾暂停本轮(assistant 的 tool_calls 已由\n // recorder 终态收尾补配对)。用户确认后由编排层授权并重发续跑。\n let result: Awaited<ReturnType<typeof this.executeTool>>;\n if (outcome.status === \"rejected\") {\n const err = outcome.reason;\n if (err instanceof EscalationRequiredError) {\n const escalation = {\n escalation_id: crypto.randomUUID().replaceAll(\"-\", \"\").slice(0, 12),\n requested_path: err.requestedPath,\n resolved_path: err.resolvedPath,\n tool_name: tc.name,\n workdir: this.workdirHint,\n resource_type: err.resourceType,\n requested_command: err.requestedCommand,\n };\n // 先落盘(回放时前端才能渲染确认卡片),再发事件\n await this.notifyEscalation(escalation);\n yield { type: \"escalation_request\", run_id: runId, escalation };\n yield { type: \"agent_cancelled\", run_id: runId };\n return;\n }\n throw err;\n } else {\n result = outcome.value;\n }\n const toolResult: AgentToolResult = {\n tool_call_id: result.tool_call_id,\n name: result.name,\n output: result.output.slice(0, EVENT_OUTPUT_LIMIT),\n is_error: result.is_error,\n elapsed_ms: result.elapsed_ms,\n };\n yield { type: \"tool_result\", run_id: runId, tool_result: toolResult };\n const toolMessage: ChatMessage = {\n role: \"tool\",\n content: result.output,\n tool_call_id: tc.id,\n name: tc.name,\n ...(result.is_error ? { is_error: true } : {}),\n };\n messages.push(toolMessage);\n stepToolMessages.push(toolMessage);\n await this.notify(toolMessage, null);\n }\n }\n\n // mid-run 检查:本步全部工具结果已回喂、call/output 配对完整,\n // 此刻丢弃历史不会产生孤儿调用,是压缩的安全点。用量以服务端上报为准,\n // 仅对尚未发送的新工具结果补估\n const stepUsage = final.usage.prompt_tokens + final.usage.completion_tokens;\n const contextTokens =\n stepUsage > 0 ? stepUsage + estimateTokens(stepToolMessages) : estimateTokens(messages);\n const midCompact = await this.maybeCompact(\n protocol, runId, modelId, messages, contextTokens, contextWindow, settings,\n );\n if (midCompact) yield midCompact;\n }\n\n this.logger.warn(`Agent 达到最大步数上限 run=${runId} steps=${this.maxSteps}`);\n yield {\n type: \"agent_error\",\n run_id: runId,\n error:\n `已达到最大执行步数上限(${this.maxSteps} 步)仍未完成,运行终止。` +\n \"请把任务拆小后重试,或检查是否陷入了循环。\",\n };\n }\n\n /** 达到水位线时压缩上下文并原地替换 messages,返回压缩事件。\n * 任何失败都降级为「本次不压缩」:记日志后照常返回 null,运行继续。 */\n private async maybeCompact(\n protocol: LlmProtocol,\n runId: string,\n modelId: string,\n messages: ChatMessage[],\n contextTokens: number,\n contextWindow: number | undefined,\n settings: import(\"../llm/models.js\").ModelSettings,\n ): Promise<AgentEvent | null> {\n if (!shouldCompact(contextTokens, contextWindow)) return null;\n let result: CompactionResult | null = null;\n try {\n result = await compact(protocol, modelId, messages, settings);\n } catch (err) {\n // 压缩是优化路径,任何故障都不应拖垮运行\n this.logger.warn(`上下文压缩发生意外错误,本次跳过压缩 run=${runId}:${err instanceof Error ? err.message : err}`);\n return null;\n }\n if (!result) return null;\n // 原地替换:system 保留在首位,其后是重建历史(保留的用户原话 + 摘要)\n messages.splice(0, messages.length, messages[0]!, ...result.replacement_history);\n await this.notifyCompaction(result);\n this.logger.info(\n `上下文已压缩 run=${runId} tokens=${result.tokens_before}→${result.tokens_after}`,\n );\n return {\n type: \"context_compacted\",\n run_id: runId,\n compaction: {\n summary: result.summary,\n tokens_before: result.tokens_before,\n tokens_after: result.tokens_after,\n },\n };\n }\n\n private async notifyCompaction(result: CompactionResult): Promise<void> {\n if (!this.onCompaction) return;\n try {\n await this.onCompaction(result);\n } catch (err) {\n this.logger.warn(`压缩记录持久化回调失败(本次压缩可能未落盘):${err instanceof Error ? err.message : err}`);\n }\n }\n\n private async notifyEscalation(info: {\n escalation_id: string;\n requested_path: string;\n resolved_path: string;\n tool_name: string;\n resource_type: \"path\" | \"command\";\n requested_command?: string[];\n }): Promise<void> {\n if (!this.onEscalation) return;\n try {\n await this.onEscalation(info);\n } catch (err) {\n this.logger.warn(`提权请求持久化回调失败(本次请求可能未落盘):${err instanceof Error ? err.message : err}`);\n }\n }\n\n private async notify(message: ChatMessage, response: ChatResponse | null): Promise<void> {\n if (!this.onMessage) return;\n try {\n await this.onMessage(message, response);\n } catch (err) {\n this.logger.warn(`Agent 消息持久化回调失败(本条消息可能未落盘):${err instanceof Error ? err.message : err}`);\n }\n }\n\n /** 执行单个工具调用:校验 → 执行;任何失败都转为回喂文本,不抛异常 */\n private async executeTool(\n tc: { id: string; name: string; raw_arguments: string },\n definitions: { name: string; description: string; parameters: Record<string, unknown> }[],\n context: import(\"../tools/types.js\").ToolContext = {},\n ): Promise<{ tool_call_id: string; name: string; output: string; is_error: boolean; elapsed_ms: number }> {\n const started = Date.now();\n const { args, error } = validateToolCall(definitions, tc);\n let output: string;\n let isError: boolean;\n if (error !== null) {\n output = error;\n isError = true;\n } else {\n const tool = this.toolsByName.get(tc.name)!; // validate 已确认工具存在\n try {\n const handled = await tool.handler(args!, context);\n output = truncateMiddle(typeof handled === \"string\" ? handled : handled.content);\n isError = typeof handled === \"string\" ? false : (handled.isError ?? false);\n } catch (err) {\n // 提权信号不上行到普通失败路径——由 runner 转成协商事件\n if (err instanceof EscalationRequiredError) throw err;\n this.logger.warn(`工具执行失败 tool=${tc.name}:${err instanceof Error ? err.message : err}`);\n output = `工具执行失败:${err instanceof Error ? err.message : err}`;\n isError = true;\n }\n }\n return {\n tool_call_id: tc.id,\n name: tc.name,\n output,\n is_error: isError,\n elapsed_ms: Date.now() - started,\n };\n }\n}\n","/**\n * 工具挂点:声明 + 执行器的绑定。\n *\n * 工具的「声明」(definition,暴露给模型)与「执行」(handler,真正干活)\n * 在此绑成一个单元——改行为时提示词与实现不会漂移。handler 约定:\n * - 入参是已通过 JSON Schema 校验的参数 dict;\n * - 返回喂回模型的文本(紧凑、模型可读即可);\n * - 业务失败 throw new Error(中文说明):runner 会把异常转成失败结果\n * 回喂模型,不中断 loop。\n */\nimport type { ToolDefinition } from \"../llm/models.js\";\n\nexport interface ToolAnnotations {\n /** 不修改文件、进程或外部状态。 */\n readOnly: boolean;\n /** 可与同一模型响应中的其他只读工具并发执行。 */\n parallelSafe: boolean;\n}\n\nexport interface ToolContext {\n /** 当前 Agent 运行的取消信号;长任务必须主动监听。 */\n signal?: AbortSignal;\n /** 当前运行编号,供进程会话与诊断日志关联。 */\n runId?: string;\n}\n\nexport interface ToolHandlerResult {\n /** 回喂模型的紧凑文本。 */\n content: string;\n /** 工具可显式返回业务失败,而不必抛异常。 */\n isError?: boolean;\n /** 仅供宿主扩展使用;当前消息协议不会把它回喂模型。 */\n metadata?: Record<string, unknown>;\n}\n\nexport interface AgentTool {\n definition: ToolDefinition;\n /** 省略时按“有副作用、不可并行”的保守策略处理。 */\n annotations?: ToolAnnotations;\n /** 字符串返回值继续兼容已有自定义工具。 */\n handler: (\n args: Record<string, unknown>,\n context?: ToolContext,\n ) => Promise<string | ToolHandlerResult>;\n}\n\n/** 工具输出统一上限:单工具单次输出 ≤ 50KB,超限保留头尾(中部截断) */\nexport const TOOL_OUTPUT_MAX_BYTES = 50_000;\n\n/** 中部截断:头尾各留一半预算(头尾信息密度最高),按字节切、退回合法 UTF-8 边界 */\nexport function truncateMiddle(text: string, maxBytes = TOOL_OUTPUT_MAX_BYTES): string {\n const data = Buffer.from(text, \"utf-8\");\n if (data.length <= maxBytes) return text;\n const half = Math.floor(maxBytes / 2);\n const head = data.subarray(0, half).toString(\"utf-8\");\n const tail = data.subarray(data.length - half).toString(\"utf-8\");\n const omitted = Math.floor((data.length - maxBytes) / 4);\n return `${head}\\n…(中间约 ${omitted} token 已截断)…\\n${tail}`;\n}\n","/**\n * 路径提权协商 —— 沙箱硬闸与「用户明确授权」之间的桥梁。\n *\n * 设计(与沙箱的关系):\n * - resolveSandboxed 的硬闸不变:默认一切越界访问都被拦下;\n * - 新增「提权请求」通道:工具 handler 在拒绝时抛出 EscalationRequiredError\n * (携带目标路径),runner 捕获后不发 tool_result,而是发 escalation_request\n * 事件并暂停本轮运行;用户在前端确认后,服务端把路径登记进会话级授权\n * 清单并自动重发上一条用户消息(续跑);\n * - 授权粒度是「会话 × 路径前缀」,随会话生命周期存在(不落盘到全局配置,\n * 重启服务即失效)——宁可每次新会话重新确认,也不留持久的越界后门。\n */\n\nexport const COMMAND_EXECUTION_GRANT = \"capability://exec_command\";\n\nexport type EscalationResourceType = \"path\" | \"command\";\n\n/** 工具层抛出的提权信号(runner 识别它并转成协商流程,不作为普通工具失败回喂) */\nexport class EscalationRequiredError extends Error {\n constructor(\n /** 请求访问的原始路径(用户或模型给出的形态,用于展示) */\n public readonly requestedPath: string,\n /** 沙箱解析后的绝对路径(授权登记的键) */\n public readonly resolvedPath: string,\n message?: string,\n public readonly resourceType: EscalationResourceType = \"path\",\n public readonly requestedCommand?: string[],\n ) {\n super(message ?? (resourceType === \"command\"\n ? \"执行本机命令需要用户授权\"\n : `路径超出工作区范围,需要用户授权:${resolvedPath}`));\n this.name = \"EscalationRequiredError\";\n }\n}\n\n/**\n * 会话级路径授权登记表(进程内)。\n * key = sessionId,value = 已授权的路径前缀集合(realpath 后的绝对路径)。\n */\nexport class EscalationGrants {\n private readonly grants = new Map<string, Set<string>>();\n\n grant(sessionId: string, resolvedPath: string): void {\n let set = this.grants.get(sessionId);\n if (!set) {\n set = new Set();\n this.grants.set(sessionId, set);\n }\n set.add(resolvedPath);\n }\n\n grantCapability(sessionId: string, capability: string): void {\n this.grant(sessionId, capability);\n }\n\n /** 已授权路径或其子路径视为已放开 */\n isGranted(sessionId: string, resolvedPath: string): boolean {\n const set = this.grants.get(sessionId);\n if (!set) return false;\n for (const prefix of set) {\n if (resolvedPath === prefix || resolvedPath.startsWith(prefix + \"/\")) return true;\n }\n return false;\n }\n\n isCapabilityGranted(sessionId: string, capability: string): boolean {\n return this.grants.get(sessionId)?.has(capability) ?? false;\n }\n\n /** 会话删除时清掉授权(授权随会话生命周期) */\n drop(sessionId: string): void {\n this.grants.delete(sessionId);\n }\n}\n","/**\n * 工作区沙箱:四个文件工具共用的路径解析。\n *\n * 默认全部路径限制在 workdir 内:相对路径基于 workdir 解析;解析结果经\n * realpath 校验仍须落在 workdir 内——**含符号链接逃逸拦截**(指向 workdir\n * 外的符号链接会被拒绝)。\n *\n * 越界时的行为分两层:\n * - 无授权 → 抛 EscalationRequiredError(runner 转成提权协商事件,等待用户确认);\n * - 会话级授权清单(grants)已覆盖该路径 → 放行;\n * - allowOutsideWorkdir 显式放开(本机部署的完全信任模式)→ 直接放行。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { EscalationRequiredError, type EscalationGrants } from \"../agent/escalation.js\";\n\n/**\n * 解析目标路径并做沙箱校验;返回可直接用于 fs 操作的绝对路径。\n * 目标不存在时(create 场景):取最深的已存在祖先做 realpath,再拼回剩余段。\n */\nexport function resolveSandboxed(\n workdir: string,\n raw: string,\n opts: {\n allowOutsideWorkdir?: boolean;\n /** 会话级授权清单(提供 sessionId 时生效) */\n grants?: EscalationGrants;\n sessionId?: string;\n } = {},\n): string {\n const baseReal = fs.realpathSync(workdir);\n const candidate = path.resolve(path.isAbsolute(raw) ? raw : path.join(baseReal, raw));\n if (opts.allowOutsideWorkdir) return candidate;\n\n // 目标或最深已存在祖先的 realpath(处理符号链接与 .. 逃逸)\n let existing = candidate;\n const missing: string[] = [];\n while (!fs.existsSync(existing)) {\n missing.unshift(path.basename(existing));\n const parent = path.dirname(existing);\n if (parent === existing) break; // 已到根\n existing = parent;\n }\n const existingReal = fs.realpathSync(existing);\n const realTarget = path.join(existingReal, ...missing);\n\n if (realTarget !== baseReal && !realTarget.startsWith(baseReal + path.sep)) {\n // 会话级授权覆盖 → 放行\n if (opts.grants && opts.sessionId && opts.grants.isGranted(opts.sessionId, realTarget)) {\n return realTarget;\n }\n throw new EscalationRequiredError(raw, realTarget);\n }\n return realTarget;\n}\n","/** 多文件补丁工具:解析 Codex 风格补丁,全部预校验后再原子落盘。 */\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\n\nconst argsSchema = z.object({ patch: z.string().min(1) });\n\ntype PatchOperation =\n | { kind: \"add\"; rawPath: string; file: string; content: string }\n | { kind: \"delete\"; rawPath: string; file: string }\n | { kind: \"update\"; rawPath: string; file: string; hunks: Hunk[] };\n\ninterface Hunk {\n before: string[];\n after: string[];\n}\n\ninterface PreparedWrite {\n kind: \"add\" | \"update\";\n rawPath: string;\n file: string;\n content: string;\n}\n\nexport function makeApplyPatchTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"apply_patch\",\n description:\n \"应用 Codex 风格的多文件补丁。输入须以 *** Begin Patch 开始、*** End Patch 结束,\" +\n \"支持 *** Add File、*** Update File、*** Delete File。所有文件先校验,任何一处失败都不会写入。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: false, parallelSafe: false },\n handler: async (args) => {\n const { patch } = argsSchema.parse(args);\n const operations = parsePatch(patch, workdir, sandbox);\n const writes: PreparedWrite[] = [];\n const deletes: Array<{ rawPath: string; file: string }> = [];\n\n for (const operation of operations) {\n if (operation.kind === \"add\") {\n if (fs.existsSync(operation.file)) throw new Error(`新增文件已存在:${operation.rawPath}`);\n writes.push({ ...operation, kind: \"add\" });\n } else if (operation.kind === \"delete\") {\n assertRegularFile(operation.rawPath, operation.file);\n deletes.push(operation);\n } else {\n assertRegularFile(operation.rawPath, operation.file);\n let content = fs.readFileSync(operation.file, \"utf-8\");\n for (const hunk of operation.hunks) content = applyHunk(content, hunk, operation.rawPath);\n writes.push({ kind: \"update\", rawPath: operation.rawPath, file: operation.file, content });\n }\n }\n\n const staged: Array<PreparedWrite & { tmp: string }> = [];\n try {\n for (const write of writes) staged.push(stageWrite(write));\n } catch (err) {\n for (const item of staged) fs.rmSync(item.tmp, { force: true });\n throw err;\n }\n const backups = new Map<string, string>();\n const installedAdds: string[] = [];\n try {\n for (const item of staged) {\n if (item.kind === \"update\") {\n const backup = backupPath(item.file);\n fs.renameSync(item.file, backup);\n backups.set(item.file, backup);\n } else {\n installedAdds.push(item.file);\n }\n fs.mkdirSync(path.dirname(item.file), { recursive: true });\n fs.renameSync(item.tmp, item.file);\n }\n for (const deletion of deletes) {\n const backup = backupPath(deletion.file);\n fs.renameSync(deletion.file, backup);\n backups.set(deletion.file, backup);\n }\n } catch (err) {\n for (const item of staged) fs.rmSync(item.tmp, { force: true });\n for (const file of installedAdds) fs.rmSync(file, { force: true });\n for (const [file, backup] of [...backups].reverse()) {\n fs.rmSync(file, { force: true });\n if (fs.existsSync(backup)) fs.renameSync(backup, file);\n }\n throw err;\n }\n for (const backup of backups.values()) fs.rmSync(backup, { force: true });\n\n const summary = operations.map((operation) => `${operation.kind} ${operation.rawPath}`).join(\"\\n\");\n return `补丁已应用(${operations.length} 个文件):\\n${summary}`;\n },\n };\n}\n\nfunction parsePatch(patch: string, workdir: string, sandbox: SandboxOptions): PatchOperation[] {\n const lines = patch.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n if (lines[0] !== \"*** Begin Patch\") throw new Error(\"补丁必须以 *** Begin Patch 开始\");\n const end = lines.lastIndexOf(\"*** End Patch\");\n if (end < 0) throw new Error(\"补丁缺少 *** End Patch\");\n if (lines.slice(end + 1).some((line) => line.trim())) throw new Error(\"*** End Patch 后不能有内容\");\n\n const operations: PatchOperation[] = [];\n const seen = new Set<string>();\n let index = 1;\n while (index < end) {\n if (!lines[index]) {\n index += 1;\n continue;\n }\n const header = lines[index]!;\n const matched = header.match(/^\\*\\*\\* (Add|Update|Delete) File: (.+)$/);\n if (!matched) throw new Error(`无法识别的补丁行 ${index + 1}:${header}`);\n const kind = matched[1]!.toLowerCase() as PatchOperation[\"kind\"];\n const rawPath = matched[2]!.trim();\n if (!rawPath) throw new Error(`补丁第 ${index + 1} 行缺少文件路径`);\n const file = resolveSandboxed(workdir, rawPath, sandbox);\n if (seen.has(file)) throw new Error(`同一补丁不能多次操作文件:${rawPath}`);\n seen.add(file);\n index += 1;\n\n const body: string[] = [];\n while (index < end && !lines[index]!.startsWith(\"*** \")) {\n body.push(lines[index]!);\n index += 1;\n }\n if (kind === \"add\") {\n if (body.some((line) => !line.startsWith(\"+\"))) {\n throw new Error(`新增文件 ${rawPath} 的每一行都必须以 + 开头`);\n }\n operations.push({ kind, rawPath, file, content: body.map((line) => line.slice(1)).join(\"\\n\") });\n } else if (kind === \"delete\") {\n if (body.some((line) => line.length > 0)) throw new Error(`删除文件 ${rawPath} 不接受补丁正文`);\n operations.push({ kind, rawPath, file });\n } else {\n const hunks = parseHunks(body, rawPath);\n operations.push({ kind, rawPath, file, hunks });\n }\n }\n if (operations.length === 0) throw new Error(\"补丁不包含任何文件操作\");\n return operations;\n}\n\nfunction parseHunks(lines: string[], rawPath: string): Hunk[] {\n const hunks: Hunk[] = [];\n let current: Hunk | null = null;\n for (const line of lines) {\n if (line.startsWith(\"@@\")) {\n current = { before: [], after: [] };\n hunks.push(current);\n continue;\n }\n if (!current) throw new Error(`更新文件 ${rawPath} 的正文必须从 @@ 开始`);\n const marker = line[0];\n const text = line.slice(1);\n if (marker === \" \") {\n current.before.push(text);\n current.after.push(text);\n } else if (marker === \"-\") {\n current.before.push(text);\n } else if (marker === \"+\") {\n current.after.push(text);\n } else {\n throw new Error(`更新文件 ${rawPath} 包含非法补丁行:${line}`);\n }\n }\n if (hunks.length === 0) throw new Error(`更新文件 ${rawPath} 缺少 @@ hunk`);\n return hunks;\n}\n\nfunction applyHunk(content: string, hunk: Hunk, rawPath: string): string {\n const before = hunk.before.join(\"\\n\");\n const after = hunk.after.join(\"\\n\");\n if (!before) throw new Error(`更新文件 ${rawPath} 的 hunk 缺少上下文或删除行`);\n const first = content.indexOf(before);\n if (first < 0) throw new Error(`更新文件 ${rawPath} 时未找到 hunk 上下文`);\n if (content.indexOf(before, first + before.length) >= 0) {\n throw new Error(`更新文件 ${rawPath} 的 hunk 上下文不唯一`);\n }\n return content.slice(0, first) + after + content.slice(first + before.length);\n}\n\nfunction assertRegularFile(rawPath: string, file: string): void {\n if (!fs.existsSync(file)) throw new Error(`文件不存在:${rawPath}`);\n if (!fs.statSync(file).isFile()) throw new Error(`${rawPath} 不是普通文件`);\n}\n\nfunction stageWrite(write: PreparedWrite): PreparedWrite & { tmp: string } {\n fs.mkdirSync(path.dirname(write.file), { recursive: true });\n const tmp = path.join(path.dirname(write.file), `.xlyra-tmp-${crypto.randomUUID()}${path.extname(write.file)}`);\n fs.writeFileSync(tmp, write.content);\n return { ...write, tmp };\n}\n\nfunction backupPath(file: string): string {\n return path.join(path.dirname(file), `.xlyra-backup-${crypto.randomUUID()}${path.extname(file)}`);\n}\n","/**\n * create 工具:新建文件(已存在则失败)。\n *\n * 与 write 形成对称硬闸:create 只建不覆盖(wx 语义),write 只覆盖不新建。\n * 设计意图是把「覆盖已有内容」变成模型必须显式选择的动作,防误覆盖。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\n\nconst argsSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport function makeCreateTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"create\",\n description:\n \"新建文件并写入内容(自动创建父目录)。目标已存在时失败——\" +\n \"如需修改已有文件请用 write 工具。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: false, parallelSafe: false },\n handler: async (args) => {\n const { path: rawPath, content } = argsSchema.parse(args);\n const file = resolveSandboxed(workdir, rawPath, sandbox);\n fs.mkdirSync(path.dirname(file), { recursive: true });\n try {\n fs.writeFileSync(file, content, { flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new Error(`文件已存在:${rawPath};如需修改请用 write 工具`);\n }\n throw err;\n }\n return `已创建 ${rawPath}(${content.length} 字符,${content.split(\"\\n\").length} 行)`;\n },\n };\n}\n","/** 精确编辑工具:old_text 唯一命中替换,避免整文件重写。 */\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\n\nconst argsSchema = z.object({\n path: z.string(),\n old_text: z.string().min(1),\n new_text: z.string(),\n replace_all: z.boolean().default(false),\n});\n\nexport function makeEditTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"edit\",\n description:\n \"精确修改已有文本文件。默认要求 old_text 在文件中恰好出现一次;\" +\n \"未命中或多次命中都会失败。确需替换全部匹配时传 replace_all=true。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: false, parallelSafe: false },\n handler: async (args) => {\n const { path: rawPath, old_text: oldText, new_text: newText, replace_all: replaceAll } =\n argsSchema.parse(args);\n const file = resolveSandboxed(workdir, rawPath, sandbox);\n if (!fs.existsSync(file)) throw new Error(`文件不存在:${rawPath}`);\n if (fs.statSync(file).isDirectory()) throw new Error(`${rawPath} 是目录不是文件`);\n\n const original = fs.readFileSync(file, \"utf-8\");\n const matches = countMatches(original, oldText);\n if (matches === 0) throw new Error(`未找到要替换的 old_text:${rawPath}`);\n if (!replaceAll && matches !== 1) {\n throw new Error(\n `old_text 在 ${rawPath} 中出现 ${matches} 次;请提供更长的唯一上下文,` +\n \"或明确传 replace_all=true\",\n );\n }\n\n const first = original.indexOf(oldText);\n const updated = replaceAll\n ? original.split(oldText).join(newText)\n : original.slice(0, first) + newText + original.slice(first + oldText.length);\n atomicReplace(file, updated);\n return `已编辑 ${rawPath}(替换 ${replaceAll ? matches : 1} 处)`;\n },\n };\n}\n\nfunction countMatches(text: string, needle: string): number {\n let count = 0;\n let cursor = 0;\n while (true) {\n const index = text.indexOf(needle, cursor);\n if (index < 0) return count;\n count += 1;\n cursor = index + needle.length;\n }\n}\n\nfunction atomicReplace(file: string, content: string): void {\n const tmp = path.join(path.dirname(file), `.xlyra-tmp-${crypto.randomUUID()}${path.extname(file)}`);\n try {\n fs.writeFileSync(tmp, content);\n fs.renameSync(tmp, file);\n } catch (err) {\n fs.rmSync(tmp, { force: true });\n throw err;\n }\n}\n","import crypto from \"node:crypto\";\nimport { spawn, type ChildProcessWithoutNullStreams } from \"node:child_process\";\nimport { truncateMiddle } from \"./types.js\";\n\nconst TRANSCRIPT_MAX_CHARS = 200_000;\nconst COMPLETED_SESSION_RETENTION_MS = 60 * 60 * 1000;\nconst MAX_SESSIONS = 128;\n\ninterface ProcessSession {\n id: string;\n child: ChildProcessWithoutNullStreams;\n output: string;\n readCursor: number;\n exitCode: number | null;\n exitSignal: NodeJS.Signals | null;\n error: string | null;\n completedAt: number | null;\n done: Promise<void>;\n resolveDone: () => void;\n timeout: ReturnType<typeof setTimeout>;\n abortSignal?: AbortSignal;\n abortListener?: () => void;\n}\n\nexport interface SpawnProcessOptions {\n command: string[];\n cwd: string;\n timeoutMs: number;\n signal?: AbortSignal;\n}\n\nexport interface ProcessPollResult {\n sessionId: string;\n output: string;\n running: boolean;\n exitCode: number | null;\n exitSignal: NodeJS.Signals | null;\n error: string | null;\n}\n\nexport class ProcessManager {\n private readonly sessions = new Map<string, ProcessSession>();\n\n start(options: SpawnProcessOptions): string {\n this.prune();\n if (this.sessions.size >= MAX_SESSIONS) {\n const completed = [...this.sessions.values()]\n .filter((session) => session.completedAt !== null)\n .sort((a, b) => a.completedAt! - b.completedAt!);\n for (const session of completed) {\n this.sessions.delete(session.id);\n if (this.sessions.size < MAX_SESSIONS) break;\n }\n }\n if (this.sessions.size >= MAX_SESSIONS) {\n throw new Error(`进程会话已达到上限(${MAX_SESSIONS});请等待已有命令结束后重试`);\n }\n const id = crypto.randomUUID().replaceAll(\"-\", \"\").slice(0, 12);\n const child = spawn(options.command[0]!, options.command.slice(1), {\n cwd: options.cwd,\n env: process.env,\n stdio: \"pipe\",\n shell: false,\n });\n let resolveDone = (): void => {};\n const done = new Promise<void>((resolve) => { resolveDone = resolve; });\n const session: ProcessSession = {\n id,\n child,\n output: \"\",\n readCursor: 0,\n exitCode: null,\n exitSignal: null,\n error: null,\n completedAt: null,\n done,\n resolveDone,\n timeout: setTimeout(() => this.terminate(id, \"命令执行超时\"), options.timeoutMs),\n abortSignal: options.signal,\n };\n session.timeout.unref?.();\n this.sessions.set(id, session);\n\n const append = (chunk: Buffer): void => {\n session.output += chunk.toString(\"utf-8\");\n if (session.output.length > TRANSCRIPT_MAX_CHARS) {\n const removed = session.output.length - TRANSCRIPT_MAX_CHARS;\n session.output = session.output.slice(removed);\n session.readCursor = Math.max(0, session.readCursor - removed);\n }\n };\n child.stdout.on(\"data\", append);\n child.stderr.on(\"data\", append);\n child.once(\"error\", (err) => {\n session.error = err.message;\n this.finish(session, child.exitCode, child.signalCode);\n });\n child.once(\"close\", (code, signal) => this.finish(session, code, signal));\n\n if (options.signal) {\n const onAbort = (): void => this.terminate(id, \"命令已取消\");\n session.abortListener = onAbort;\n if (options.signal.aborted) onAbort();\n else options.signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n return id;\n }\n\n async poll(sessionId: string, yieldTimeMs: number, maxOutputBytes: number): Promise<ProcessPollResult> {\n const session = this.require(sessionId);\n if (session.child.exitCode === null && session.exitSignal === null && !session.error) {\n await Promise.race([\n session.done,\n new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, yieldTimeMs);\n timer.unref?.();\n }),\n ]);\n }\n const unread = session.output.slice(session.readCursor);\n session.readCursor = session.output.length;\n return {\n sessionId,\n output: truncateMiddle(unread, maxOutputBytes),\n running: session.child.exitCode === null && session.exitSignal === null && !session.error,\n exitCode: session.exitCode,\n exitSignal: session.exitSignal,\n error: session.error,\n };\n }\n\n write(sessionId: string, chars: string): void {\n const session = this.require(sessionId);\n if (session.child.exitCode !== null || session.exitSignal !== null || session.error) {\n throw new Error(`进程会话已结束:${sessionId}`);\n }\n session.child.stdin.write(chars);\n }\n\n private require(sessionId: string): ProcessSession {\n this.prune();\n const session = this.sessions.get(sessionId);\n if (!session) throw new Error(`进程会话不存在:${sessionId}`);\n return session;\n }\n\n private terminate(sessionId: string, reason: string): void {\n const session = this.sessions.get(sessionId);\n if (!session || session.completedAt !== null) return;\n session.error = reason;\n session.child.kill(\"SIGTERM\");\n const force = setTimeout(() => session.child.kill(\"SIGKILL\"), 1_000);\n force.unref?.();\n }\n\n private finish(\n session: ProcessSession,\n code: number | null,\n signal: NodeJS.Signals | null,\n ): void {\n if (session.completedAt !== null) return;\n clearTimeout(session.timeout);\n session.exitCode = code;\n session.exitSignal = signal;\n session.completedAt = Date.now();\n if (session.abortSignal && session.abortListener) {\n session.abortSignal.removeEventListener(\"abort\", session.abortListener);\n }\n session.resolveDone();\n }\n\n private prune(): void {\n const cutoff = Date.now() - COMPLETED_SESSION_RETENTION_MS;\n for (const [id, session] of this.sessions) {\n if (session.completedAt !== null && session.completedAt <= cutoff) this.sessions.delete(id);\n }\n }\n}\n","import fs from \"node:fs\";\nimport { z } from \"zod\";\nimport { COMMAND_EXECUTION_GRANT, EscalationRequiredError } from \"../agent/escalation.js\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\nimport { ProcessManager, type ProcessPollResult } from \"./process-manager.js\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\n\nconst argsSchema = z.object({\n command: z.array(z.string()).min(1),\n cwd: z.string().default(\".\"),\n timeout_ms: z.number().int().min(100).max(300_000).default(30_000),\n yield_time_ms: z.number().int().min(0).max(30_000).default(10_000),\n max_output_bytes: z.number().int().min(1_000).max(100_000).default(50_000),\n});\n\nexport function makeExecCommandTool(\n workdir: string,\n manager: ProcessManager,\n sandbox: SandboxOptions = {},\n): AgentTool {\n return {\n definition: {\n name: \"exec_command\",\n description:\n \"直接执行命令 argv,不经过 shell。command 必须是字符串数组,例如 \" +\n '[\"pnpm\",\"test\"]。命令超过 yield_time_ms 仍在运行时返回 session_id,' +\n \"后续用 write_stdin 读取输出或输入内容。执行前可能需要用户授权。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: false, parallelSafe: false },\n handler: async (args, context) => {\n const parsed = argsSchema.parse(args);\n const commandAllowed = sandbox.commandExecutionEnabled === true\n || (sandbox.grants !== undefined && sandbox.sessionId !== undefined\n && sandbox.grants.isCapabilityGranted(sandbox.sessionId, COMMAND_EXECUTION_GRANT));\n if (!commandAllowed) {\n throw new EscalationRequiredError(\n parsed.command.join(\" \"),\n COMMAND_EXECUTION_GRANT,\n \"执行本机命令需要用户授权\",\n \"command\",\n parsed.command,\n );\n }\n const cwd = resolveSandboxed(workdir, parsed.cwd, sandbox);\n if (!fs.existsSync(cwd)) throw new Error(`工作目录不存在:${parsed.cwd}`);\n if (!fs.statSync(cwd).isDirectory()) throw new Error(`cwd 不是目录:${parsed.cwd}`);\n const sessionId = manager.start({\n command: parsed.command,\n cwd,\n timeoutMs: parsed.timeout_ms,\n signal: context?.signal,\n });\n const result = await manager.poll(sessionId, parsed.yield_time_ms, parsed.max_output_bytes);\n return formatProcessResult(result);\n },\n };\n}\n\nexport function formatProcessResult(result: ProcessPollResult): { content: string; isError: boolean } {\n const sections = [\n `session_id: ${result.sessionId}`,\n result.running\n ? \"status: running\"\n : `status: exited${result.exitCode !== null ? `\\nexit_code: ${result.exitCode}` : \"\"}` +\n `${result.exitSignal ? `\\nexit_signal: ${result.exitSignal}` : \"\"}`,\n ];\n if (result.output) sections.push(`output:\\n${result.output}`);\n else sections.push(\"output: (暂无新输出)\");\n if (result.error) sections.push(`error: ${result.error}`);\n return {\n content: sections.join(\"\\n\"),\n isError: Boolean(result.error) || (!result.running && result.exitCode !== null && result.exitCode !== 0),\n };\n}\n","/**\n * list 工具:列目录内容。\n *\n * 落地细节:\n * - 内置 ignore 清单(.git / node_modules / dist 等),否则一次递归列目录\n * 可能产出几万行直接打爆上下文;\n * - 单次最多 500 条,截断时附「共 N 条,已省略 M 条」;\n * - 输出相对 workdir 的路径,目录带 / 后缀;\n * - pattern 是简化 glob:* 匹配段内任意字符,** 跨段匹配,? 匹配单字符。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\n\nconst MAX_ENTRIES = 500;\n\nconst IGNORE_NAMES = new Set([\n \".git\",\n \"node_modules\",\n \"dist\",\n \".next\",\n \"out\",\n \"coverage\",\n \".turbo\",\n \".cache\",\n \"__pycache__\",\n \".venv\",\n]);\n\nconst argsSchema = z.object({\n path: z.string().default(\".\"),\n recursive: z.boolean().default(false),\n pattern: z.string().optional(),\n});\n\n/** 简化 glob → RegExp(* 段内任意,** 跨段,? 单字符) */\nfunction globToRegExp(pattern: string): RegExp {\n const escaped = pattern\n .replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\*\\*/g, \"\u0000\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\?/g, \"[^/]\")\n .replace(/\u0000/g, \".*\");\n return new RegExp(`(^|/)${escaped}$|^${escaped}$`);\n}\n\nexport function makeListTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"list\",\n description:\n \"列出目录内容(文件与子目录,目录带 / 后缀)。默认只列一层,\" +\n `recursive=true 递归列出。内置忽略 .git、node_modules 等目录。` +\n `单次最多返回 ${MAX_ENTRIES} 条,超出时提示省略数量。`,\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: true, parallelSafe: true },\n handler: async (args) => {\n const { path: rawPath, recursive, pattern } = argsSchema.parse(args);\n const dir = resolveSandboxed(workdir, rawPath, sandbox);\n if (!fs.existsSync(dir)) throw new Error(`目录不存在:${rawPath}`);\n if (!fs.statSync(dir).isDirectory()) throw new Error(`${rawPath} 是文件不是目录;读取文件请用 read 工具`);\n\n const matcher = pattern ? globToRegExp(pattern) : null;\n const results: string[] = [];\n let omitted = 0;\n\n const walk = (current: string): void => {\n if (results.length >= MAX_ENTRIES) {\n omitted += countRemaining(current, recursive);\n return;\n }\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(current, { withFileTypes: true });\n } catch {\n return; // 无权限等:跳过该目录\n }\n entries.sort((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n if (IGNORE_NAMES.has(entry.name)) continue;\n const full = path.join(current, entry.name);\n const rel = path.relative(dir, full);\n const display = entry.isDirectory() ? `${rel}/` : rel;\n if (!matcher || matcher.test(display)) {\n if (results.length < MAX_ENTRIES) results.push(display);\n else omitted += 1;\n }\n if (recursive && entry.isDirectory()) walk(full);\n }\n };\n walk(dir);\n\n const header = `目录 ${rawPath} 的内容:`;\n if (results.length === 0) return `${header}\\n(空目录或无匹配项)`;\n const body = results.join(\"\\n\");\n return omitted > 0\n ? `${header}\\n${body}\\n(共 ${results.length + omitted} 条,已省略 ${omitted} 条;可用 pattern 缩小范围)`\n : `${header}\\n${body}`;\n },\n };\n}\n\nfunction countRemaining(dir: string, recursive: boolean): number {\n let count = 0;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return 0;\n }\n for (const entry of entries) {\n if (IGNORE_NAMES.has(entry.name)) continue;\n count += 1;\n if (recursive && entry.isDirectory()) count += countRemaining(path.join(dir, entry.name), true);\n }\n return count;\n}\n","/**\n * read 工具:读文本文件。\n *\n * 落地细节:\n * - offset(1 起)/ limit 分段读取;单次最多 2000 行或 50KB 先到为准,\n * 截断时在尾部附「继续读请传 offset=N」;\n * - 目录 → 报错并提示用 list;图片后缀 → 明确报错不支持(纯文本管线)。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\n\nconst MAX_LINES = 2000;\nconst MAX_BYTES = 50_000;\n\nconst IMAGE_SUFFIXES = new Set([\".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".bmp\", \".svg\"]);\n\nconst argsSchema = z.object({\n path: z.string(),\n offset: z.number().int().min(1).default(1),\n limit: z.number().int().min(1).optional(),\n});\n\nexport function makeReadTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"read\",\n description:\n \"读取文本文件内容。单次最多返回 2000 行或 50KB(先到为准),\" +\n \"大文件用 offset/limit 分段读取,直到读完为止。不支持图片。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: true, parallelSafe: true },\n handler: async (args) => {\n const { path: rawPath, offset, limit } = argsSchema.parse(args);\n const file = resolveSandboxed(workdir, rawPath, sandbox);\n if (!fs.existsSync(file)) throw new Error(`文件不存在:${rawPath}`);\n if (fs.statSync(file).isDirectory()) {\n throw new Error(`${rawPath} 是目录不是文件;查看目录内容请用 list 工具`);\n }\n if (IMAGE_SUFFIXES.has(path.extname(file).toLowerCase())) {\n throw new Error(\"暂不支持读取图片文件,只支持文本文件\");\n }\n\n const lines = fs.readFileSync(file, \"utf-8\").split(\"\\n\");\n const total = lines.length;\n if (offset > total && total > 0) {\n throw new Error(`offset 超出范围:文件共 ${total} 行,offset=${offset}`);\n }\n const cap = Math.min(limit ?? MAX_LINES, MAX_LINES);\n const window = lines.slice(offset - 1, offset - 1 + cap);\n\n // 字节上限:逐行累加,超限即停\n const picked: string[] = [];\n let size = 0;\n for (const line of window) {\n size += Buffer.byteLength(line, \"utf-8\") + 1;\n if (picked.length > 0 && size > MAX_BYTES) break;\n picked.push(line);\n }\n const end = offset - 1 + picked.length;\n\n let body = picked.join(\"\\n\");\n if (end < total) {\n body += `\\n(文件共 ${total} 行,本次返回第 ${offset}-${end} 行;继续读取请传 offset=${end + 1})`;\n }\n return body || \"(空文件)\";\n },\n };\n}\n","/** 文件内容搜索工具:有界遍历、跳过二进制与常见生成目录。 */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\n\nconst MAX_FILE_BYTES = 2 * 1024 * 1024;\nconst HARD_MAX_RESULTS = 500;\nconst IGNORE_NAMES = new Set([\n \".git\", \"node_modules\", \"dist\", \".next\", \"out\", \"coverage\", \".turbo\", \".cache\",\n \"__pycache__\", \".venv\",\n]);\n\nconst argsSchema = z.object({\n query: z.string().min(1),\n path: z.string().default(\".\"),\n glob: z.string().optional(),\n case_sensitive: z.boolean().default(false),\n max_results: z.number().int().min(1).max(HARD_MAX_RESULTS).default(100),\n});\n\nexport function makeSearchTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"search\",\n description:\n \"在工作区文本文件中搜索内容,返回 path:line:match。可用 glob 按文件路径筛选,\" +\n \"例如 **/*.ts;默认忽略 .git、node_modules、dist 等目录和二进制文件。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: true, parallelSafe: true },\n handler: async (args, context) => {\n const parsed = argsSchema.parse(args);\n const target = resolveSandboxed(workdir, parsed.path, sandbox);\n if (!fs.existsSync(target)) throw new Error(`路径不存在:${parsed.path}`);\n const matcher = parsed.glob ? globToRegExp(parsed.glob) : null;\n const needle = parsed.case_sensitive ? parsed.query : parsed.query.toLocaleLowerCase();\n const results: string[] = [];\n let truncated = false;\n\n const visit = (entryPath: string): void => {\n if (context?.signal?.aborted || results.length >= parsed.max_results) {\n truncated = results.length >= parsed.max_results;\n return;\n }\n const lstat = fs.lstatSync(entryPath);\n if (lstat.isSymbolicLink()) return;\n const stat = lstat;\n if (stat.isDirectory()) {\n for (const entry of fs.readdirSync(entryPath, { withFileTypes: true })) {\n if (IGNORE_NAMES.has(entry.name)) continue;\n visit(path.join(entryPath, entry.name));\n if (results.length >= parsed.max_results || context?.signal?.aborted) break;\n }\n return;\n }\n const relative = path.relative(workdir, entryPath) || path.basename(entryPath);\n const portable = relative.split(path.sep).join(\"/\");\n if (matcher && !matcher.test(portable)) return;\n if (stat.size > MAX_FILE_BYTES || isBinary(entryPath)) return;\n let text: string;\n try {\n text = fs.readFileSync(entryPath, \"utf-8\");\n } catch {\n return;\n }\n for (const [index, line] of text.split(\"\\n\").entries()) {\n const haystack = parsed.case_sensitive ? line : line.toLocaleLowerCase();\n if (!haystack.includes(needle)) continue;\n results.push(`${portable}:${index + 1}:${line}`);\n if (results.length >= parsed.max_results) {\n truncated = true;\n break;\n }\n }\n };\n\n visit(target);\n if (context?.signal?.aborted) throw new Error(\"搜索已取消\");\n if (results.length === 0) return `未找到匹配:${parsed.query}`;\n return results.join(\"\\n\") +\n (truncated ? `\\n(结果已截断到 ${parsed.max_results} 条;请缩小 path 或 glob)` : \"\");\n },\n };\n}\n\nfunction isBinary(file: string): boolean {\n const fd = fs.openSync(file, \"r\");\n try {\n const buffer = Buffer.alloc(4096);\n const read = fs.readSync(fd, buffer, 0, buffer.length, 0);\n return buffer.subarray(0, read).includes(0);\n } finally {\n fs.closeSync(fd);\n }\n}\n\nfunction globToRegExp(glob: string): RegExp {\n let source = \"\";\n for (let index = 0; index < glob.length; index += 1) {\n const char = glob[index]!;\n if (char === \"*\") {\n if (glob[index + 1] === \"*\") {\n if (glob[index + 2] === \"/\") {\n source += \"(?:.*/)?\";\n index += 2;\n } else {\n source += \".*\";\n index += 1;\n }\n } else {\n source += \"[^/]*\";\n }\n } else if (char === \"?\") {\n source += \"[^/]\";\n } else {\n source += char.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n }\n }\n return new RegExp(`^${source}$`);\n}\n","/**\n * write 工具:覆盖写已有文件(不存在则失败)。\n *\n * 与 create 形成对称硬闸(见 create.ts)。写入用临时文件 + rename 原子换入:\n * 写一半进程崩溃要么旧文件完好、要么新文件完整,不留残文件。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { z } from \"zod\";\nimport type { AgentTool } from \"./types.js\";\nimport { resolveSandboxed } from \"./workdir.js\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\n\nconst argsSchema = z.object({\n path: z.string(),\n content: z.string(),\n});\n\nexport function makeWriteTool(workdir: string, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"write\",\n description:\n \"整体覆盖已有文件的内容。目标不存在时失败——新建文件请用 create 工具。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: false, parallelSafe: false },\n handler: async (args) => {\n const { path: rawPath, content } = argsSchema.parse(args);\n const file = resolveSandboxed(workdir, rawPath, sandbox);\n if (!fs.existsSync(file)) {\n throw new Error(`文件不存在:${rawPath};新建文件请用 create 工具`);\n }\n if (fs.statSync(file).isDirectory()) {\n throw new Error(`${rawPath} 是目录不是文件`);\n }\n // 同目录临时文件 + rename:保证原子性(同文件系统内 rename 才原子)\n const tmp = path.join(\n path.dirname(file),\n `.xlyra-tmp-${crypto.randomUUID()}${path.extname(file)}`,\n );\n try {\n fs.writeFileSync(tmp, content);\n fs.renameSync(tmp, file);\n } catch (err) {\n fs.rmSync(tmp, { force: true });\n throw err;\n }\n return `已覆盖 ${rawPath}(${content.length} 字符,${content.split(\"\\n\").length} 行)`;\n },\n };\n}\n","import { z } from \"zod\";\nimport { COMMAND_EXECUTION_GRANT, EscalationRequiredError } from \"../agent/escalation.js\";\nimport type { SandboxOptions } from \"./sandbox-types.js\";\nimport { formatProcessResult } from \"./exec-command.js\";\nimport { ProcessManager } from \"./process-manager.js\";\nimport type { AgentTool } from \"./types.js\";\n\nconst argsSchema = z.object({\n session_id: z.string().min(1),\n chars: z.string().optional(),\n yield_time_ms: z.number().int().min(0).max(30_000).default(5_000),\n max_output_bytes: z.number().int().min(1_000).max(100_000).default(50_000),\n});\n\nexport function makeWriteStdinTool(manager: ProcessManager, sandbox: SandboxOptions = {}): AgentTool {\n return {\n definition: {\n name: \"write_stdin\",\n description:\n \"继续读取 exec_command 返回的进程会话;提供 chars 时先向进程标准输入写入内容。\" +\n \"交互式输入通常需要自行附加换行符。使用前可能需要用户授权。\",\n parameters: z.toJSONSchema(argsSchema) as Record<string, unknown>,\n },\n annotations: { readOnly: false, parallelSafe: false },\n handler: async (args) => {\n const parsed = argsSchema.parse(args);\n const commandAllowed = sandbox.commandExecutionEnabled === true\n || (sandbox.grants !== undefined && sandbox.sessionId !== undefined\n && sandbox.grants.isCapabilityGranted(sandbox.sessionId, COMMAND_EXECUTION_GRANT));\n if (!commandAllowed) {\n throw new EscalationRequiredError(\n `exec_command session ${parsed.session_id}`,\n COMMAND_EXECUTION_GRANT,\n \"继续命令会话需要用户授权\",\n \"command\",\n );\n }\n if (parsed.chars !== undefined) manager.write(parsed.session_id, parsed.chars);\n const result = await manager.poll(parsed.session_id, parsed.yield_time_ms, parsed.max_output_bytes);\n return formatProcessResult(result);\n },\n };\n}\n","/**\n * 内置工具集:文件读写、精确编辑、内容搜索,以及需要授权的本机命令会话工具。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { EscalationGrants } from \"../agent/escalation.js\";\nimport { makeApplyPatchTool } from \"./apply-patch.js\";\nimport { makeCreateTool } from \"./create.js\";\nimport { makeEditTool } from \"./edit.js\";\nimport { makeExecCommandTool } from \"./exec-command.js\";\nimport { makeListTool } from \"./list.js\";\nimport { makeReadTool } from \"./read.js\";\nimport { makeSearchTool } from \"./search.js\";\nimport { ProcessManager } from \"./process-manager.js\";\nimport type { AgentTool } from \"./types.js\";\nimport { makeWriteTool } from \"./write.js\";\nimport { makeWriteStdinTool } from \"./write-stdin.js\";\n\nexport interface BuiltinToolsOptions {\n /** 工作目录:相对路径解析基准 + 沙箱边界 */\n workdir: string;\n /** 显式放开沙箱(默认 false:全部路径限制在 workdir 内) */\n allowOutsideWorkdir?: boolean;\n /** 会话级路径授权清单(与 sessionId 一起提供时生效) */\n grants?: EscalationGrants;\n /** 当前会话 id(授权清单的查询键) */\n sessionId?: string;\n /** 预授权本机命令执行;关闭时工具仍会声明,但首次调用触发提权协商。 */\n enableCommandExecution?: boolean;\n}\n\nexport function builtinTools(opts: BuiltinToolsOptions): AgentTool[] {\n const workdir = path.resolve(opts.workdir);\n fs.mkdirSync(workdir, { recursive: true });\n const sandbox = {\n allowOutsideWorkdir: opts.allowOutsideWorkdir ?? false,\n grants: opts.grants,\n sessionId: opts.sessionId,\n };\n const tools: AgentTool[] = [\n makeListTool(workdir, sandbox),\n makeReadTool(workdir, sandbox),\n makeSearchTool(workdir, sandbox),\n makeCreateTool(workdir, sandbox),\n makeEditTool(workdir, sandbox),\n makeWriteTool(workdir, sandbox),\n makeApplyPatchTool(workdir, sandbox),\n ];\n const commandSandbox = { ...sandbox, commandExecutionEnabled: opts.enableCommandExecution ?? false };\n const processes = new ProcessManager();\n tools.push(\n makeExecCommandTool(workdir, processes, commandSandbox),\n makeWriteStdinTool(processes, commandSandbox),\n );\n return tools;\n}\n\nexport type { AgentTool, ToolAnnotations, ToolContext, ToolHandlerResult } from \"./types.js\";\nexport { makeListTool } from \"./list.js\";\nexport { makeReadTool } from \"./read.js\";\nexport { makeCreateTool } from \"./create.js\";\nexport { makeApplyPatchTool } from \"./apply-patch.js\";\nexport { makeEditTool } from \"./edit.js\";\nexport { makeSearchTool } from \"./search.js\";\nexport { makeExecCommandTool, formatProcessResult } from \"./exec-command.js\";\nexport { makeWriteStdinTool } from \"./write-stdin.js\";\nexport { ProcessManager } from \"./process-manager.js\";\nexport { makeWriteTool } from \"./write.js\";\nexport { resolveSandboxed } from \"./workdir.js\";\nexport type { SandboxOptions } from \"./sandbox-types.js\";\n","/**\n * 服务配置:~/.xlyra-agent/config.json。\n *\n * 职责:\n * - 端点配置(base_url / api_key / models / protocol 类型)统一落在这里,\n * 由 `xlyra config` 子命令管理(add/list/remove),也可手编;\n * - api_key 支持 \"${ENV_VAR}\" 环境变量插值——配置文件可以入库/共享而不泄漏\n * 凭证;\n * - 加载时经 Zod schema 校验:结构错误在启动时给出明确中文报错,\n * 而不是运行到一半才以奇怪方式失败;\n * - 保存一律 tmp + rename 原子换入。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { defaultDataDir } from \"../agent/sessions.js\";\nimport type { EndpointConfig } from \"../llm/router.js\";\n\n// ---------------------------------------------------------------------------\n// Schema(加载/保存共用同一份定义,防漂移)\n// ---------------------------------------------------------------------------\n\nconst endpointSchema = z.object({\n name: z.string().min(1, \"端点名不能为空\"),\n protocol: z.enum([\"openai-responses\", \"anthropic-messages\"]),\n base_url: z.string().min(1, \"base_url 不能为空\"),\n api_key: z.string().min(1, \"api_key 不能为空(可用 ${ENV_VAR} 引用环境变量)\"),\n models: z.record(z.string(), z.object({ context_window: z.number().positive().optional() })).optional(),\n default_model: z.string().optional(),\n});\n\nconst appConfigSchema = z.object({\n endpoints: z.array(endpointSchema).min(1, \"endpoints 为空:至少配置一个模型端点\"),\n server: z\n .object({\n port: z.number().int().positive().optional(),\n token: z.string().optional(),\n })\n .optional(),\n agent: z\n .object({\n workdir: z.string().optional(),\n agent_name: z.string().optional(),\n persona: z.string().optional(),\n /** 本机命令可访问当前用户权限范围内的系统资源,必须显式开启。 */\n enable_command_execution: z.boolean().optional(),\n })\n .optional(),\n});\n\nexport type AppConfig = z.infer<typeof appConfigSchema>;\nexport type ServerConfig = NonNullable<AppConfig[\"server\"]>;\nexport type AgentServiceConfig = NonNullable<AppConfig[\"agent\"]>;\n\n// ---------------------------------------------------------------------------\n// 路径与读写\n// ---------------------------------------------------------------------------\n\nexport function defaultConfigPath(): string {\n return path.join(defaultDataDir(), \"config.json\");\n}\n\n/** 加载并校验配置;文件不存在/结构非法时抛出明确中文错误 */\nexport function loadConfig(configPath?: string): AppConfig {\n const file = configPath ?? defaultConfigPath();\n if (!fs.existsSync(file)) {\n throw new Error(\n `配置文件不存在:${file}\\n先运行 xlyra config init 交互式创建,或参考 README 手工编写。`,\n );\n }\n let raw: unknown;\n try {\n raw = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n } catch (err) {\n throw new Error(`配置文件不是合法 JSON:${file}(${err instanceof Error ? err.message : err})`);\n }\n const parsed = appConfigSchema.safeParse(raw);\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((i) => ` - ${i.path.join(\".\") || \"(根)\"}:${i.message}`)\n .join(\"\\n\");\n throw new Error(`配置文件校验失败:${file}\\n${issues}`);\n }\n for (const endpoint of parsed.data.endpoints) {\n endpoint.api_key = interpolateEnv(endpoint.api_key, file);\n }\n return parsed.data;\n}\n\n/** 保存配置(tmp + rename 原子写入);config 须已通过 schema 校验 */\nexport function saveConfig(config: AppConfig, configPath?: string): void {\n const file = configPath ?? defaultConfigPath();\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const tmp = `${file}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify(config, null, 2) + \"\\n\");\n fs.renameSync(tmp, file);\n}\n\n/** 配置是否存在(config init 判重 / 首次运行引导用) */\nexport function configExists(configPath?: string): boolean {\n return fs.existsSync(configPath ?? defaultConfigPath());\n}\n\n// ---------------------------------------------------------------------------\n// 端点管理(config add/remove 子命令的实现)\n// ---------------------------------------------------------------------------\n\n/** 新增或更新端点(按 name 匹配,同名覆盖);返回写入后的完整配置 */\nexport function upsertEndpoint(\n endpoint: EndpointConfig,\n configPath?: string,\n): AppConfig {\n const file = configPath ?? defaultConfigPath();\n let config: AppConfig;\n if (fs.existsSync(file)) {\n // 已有配置:加载校验后合并(loadConfig 会插值 api_key,写回前需还原原始配置——\n // 因此这里读原始 JSON 而不是走 loadConfig)\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\")) as AppConfig;\n config = appConfigSchema.parse({ ...raw, endpoints: raw.endpoints ?? [] });\n } else {\n config = { endpoints: [] };\n }\n const idx = config.endpoints.findIndex((e) => e.name === endpoint.name);\n if (idx >= 0) {\n config.endpoints[idx] = endpoint;\n } else {\n config.endpoints.push(endpoint);\n }\n // 写回前整体过一遍 schema(endpoints 至少一条此时必然成立)\n const validated = appConfigSchema.parse(config);\n saveConfig(validated, file);\n return validated;\n}\n\n/** 按 name 删除端点;不存在时返回 false。不允许删除最后一条(配置必须非空) */\nexport function removeEndpoint(name: string, configPath?: string): boolean {\n const file = configPath ?? defaultConfigPath();\n if (!fs.existsSync(file)) return false;\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\")) as AppConfig;\n const endpoints = (raw.endpoints ?? []).filter((e) => e.name !== name);\n if (endpoints.length === (raw.endpoints ?? []).length) return false;\n if (endpoints.length === 0) {\n throw new Error(`不能删除最后一个端点(配置必须保留至少一个模型端点):${file}`);\n }\n saveConfig({ ...raw, endpoints }, file);\n return true;\n}\n\n/** \"${ENV_VAR}\" → 环境变量值;未设置时报出可读错误 */\nfunction interpolateEnv(value: string, file: string): string {\n return value.replace(/\\$\\{([A-Z0-9_]+)\\}/g, (whole, name: string) => {\n const v = process.env[name];\n if (v === undefined) {\n throw new Error(`配置文件 ${file} 引用了未设置的环境变量 ${name}(来自 \"${whole}\")`);\n }\n return v;\n });\n}\n","/**\n * 进程内 Agent 运行注册表:后台执行、事件回放与广播订阅。\n *\n * 设计(移植自 MovieClaw agent_runs.py):为每次运行维护一份只追加的事件\n * 日志,订阅者各自持有序号游标——不用消息队列(队列消息只会被一个消费者\n * 取走,无法同时满足多个 SSE 订阅者,也无法让断线客户端回放历史)。\n * Promise 通知链只负责在新事件到达时唤醒等待者,消息本身始终以日志为准。\n *\n * 注册表仅在单个进程内有效;若未来需要多实例部署,应把这一层替换为\n * Redis 等共享存储,而不是改变 AgentRunner 或 SSE 事件协议。\n */\nimport crypto from \"node:crypto\";\nimport type { AgentEvent, AgentEventType, AgentStartParams } from \"../agent/events.js\";\nimport { TERMINAL_EVENT_TYPES } from \"../agent/events.js\";\nimport type { AgentRunner } from \"../agent/runner.js\";\n\nexport const DEFAULT_RETENTION_MS = 24 * 60 * 60 * 1000;\n\nexport interface StoredAgentEvent {\n /** 运行内递增序号;直接用作 SSE 的 id */\n sequence: number;\n event: AgentEvent;\n}\n\ninterface Run {\n runId: string;\n sessionId: string;\n events: StoredAgentEvent[];\n terminal: boolean;\n completedAt: number | null;\n controller: AbortController;\n /** 等待新事件的唤醒回调(一次性,触发后移除) */\n waiters: Set<() => void>;\n /** 终态钩子:运行进入终态后调用一次(停心跳、补配对、清运行标记) */\n onTerminal: ((event: AgentEvent) => Promise<void>) | null;\n}\n\nexport class RunRegistry {\n private readonly retentionMs: number;\n private readonly runs = new Map<string, Run>();\n private readonly latestBySession = new Map<string, string>();\n private closing = false;\n\n constructor(opts: { retentionMs?: number } = {}) {\n this.retentionMs = opts.retentionMs ?? DEFAULT_RETENTION_MS;\n }\n\n /** 分配运行编号并把 runner 放入后台执行,立即返回编号 */\n start(\n runner: AgentRunner,\n params: AgentStartParams,\n opts: { sessionId: string; onTerminal?: (event: AgentEvent) => Promise<void> },\n ): string {\n if (this.closing) throw new Error(\"运行注册表正在关闭,无法创建新运行\");\n this.pruneExpired();\n const runId = crypto.randomUUID().replaceAll(\"-\", \"\").slice(0, 12);\n const run: Run = {\n runId,\n sessionId: opts.sessionId,\n events: [],\n terminal: false,\n completedAt: null,\n controller: new AbortController(),\n waiters: new Set(),\n onTerminal: opts.onTerminal ?? null,\n };\n this.runs.set(runId, run);\n this.latestBySession.set(opts.sessionId, runId);\n void this.execute(run, runner, params);\n return runId;\n }\n\n /** 按公开会话编号读取当前(或最近一轮)事件 */\n async getSessionEvents(\n sessionId: string,\n afterSequence: number,\n timeoutSeconds: number,\n ): Promise<{ events: StoredAgentEvent[]; terminal: boolean }> {\n return this.getEvents(this.sessionRun(sessionId).runId, afterSequence, timeoutSeconds);\n }\n\n /**\n * 返回游标后的事件;暂无事件时等待通知,超时返回空列表供 SSE 发心跳。\n * 调用方应先发送本批事件,再在 terminal=true 且批次已追平时关闭连接。\n */\n async getEvents(\n runId: string,\n afterSequence: number,\n timeoutSeconds: number,\n ): Promise<{ events: StoredAgentEvent[]; terminal: boolean }> {\n if (afterSequence < 0) throw new HttpError(400, \"SSE 事件游标不能为负数\");\n const run = this.getRun(runId);\n if (afterSequence > run.events.length) {\n throw new HttpError(400, `SSE 事件游标 ${afterSequence} 超出当前事件范围`);\n }\n if (afterSequence === run.events.length && !run.terminal && timeoutSeconds > 0) {\n await new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n run.waiters.delete(wake);\n resolve();\n }, timeoutSeconds * 1000);\n const wake = (): void => {\n clearTimeout(timer);\n run.waiters.delete(wake);\n resolve();\n };\n run.waiters.add(wake);\n });\n }\n return { events: run.events.slice(afterSequence), terminal: run.terminal };\n }\n\n /**\n * 幂等取消一次运行:**先落可回放的 agent_cancelled 终态事件,再 abort**。\n * 顺序很重要:运行刚创建、事件循环尚未开始消费时,直接 abort 会让 runner\n * 一次都不执行,订阅者会永久等待——先落终态事件保证任何情况下订阅者\n * 都能看到收尾。\n */\n async cancel(runId: string): Promise<void> {\n const run = this.getRun(runId);\n if (run.terminal) return;\n await this.publish(run, { type: \"agent_cancelled\", run_id: run.runId });\n run.controller.abort();\n }\n\n async cancelSession(sessionId: string): Promise<void> {\n await this.cancel(this.sessionRun(sessionId).runId);\n }\n\n /** 应用关闭时取消全部活动运行 */\n async close(): Promise<void> {\n this.closing = true;\n for (const run of this.runs.values()) {\n if (!run.terminal) await this.cancel(run.runId);\n }\n this.runs.clear();\n this.latestBySession.clear();\n }\n\n /** 消费 runner 事件并写入日志,兜住所有退出路径补齐终态 */\n private async execute(run: Run, runner: AgentRunner, params: AgentStartParams): Promise<void> {\n try {\n for await (const event of runner.start(params, {\n runId: run.runId,\n signal: run.controller.signal,\n })) {\n await this.publish(run, event);\n }\n if (!run.terminal) {\n await this.publish(run, {\n type: \"agent_error\",\n run_id: run.runId,\n error: \"Agent 运行异常结束,未返回终态事件\",\n });\n }\n } catch (err) {\n // runner 设计为不抛异常;这里是最后防线——后台任务必须转成可见终态\n if (!run.terminal) {\n await this.publish(run, {\n type: \"agent_error\",\n run_id: run.runId,\n error: `Agent 运行发生未知错误:${err instanceof Error ? err.message : err}`,\n });\n }\n }\n }\n\n /** 原子追加事件并广播唤醒;终态之后的迟到事件直接忽略 */\n private async publish(run: Run, event: AgentEvent): Promise<void> {\n if (run.terminal) return;\n run.events.push({ sequence: run.events.length + 1, event });\n let becameTerminal = false;\n if (TERMINAL_EVENT_TYPES.has(event.type as AgentEventType)) {\n run.terminal = true;\n run.completedAt = Date.now();\n becameTerminal = true;\n }\n for (const wake of [...run.waiters]) wake();\n // 终态钩子在事件广播之后调用:收尾涉及文件 IO,不应阻塞事件流;\n // terminal 置位保证本钩子最多触发一次\n if (becameTerminal && run.onTerminal) {\n try {\n await run.onTerminal(event);\n } catch (err) {\n console.error(`Agent 运行终态钩子执行失败 run=${run.runId}:${err instanceof Error ? err.message : err}`);\n }\n }\n }\n\n getRun(runId: string): Run {\n this.pruneExpired();\n const run = this.runs.get(runId);\n if (!run) throw new HttpError(404, \"Agent 运行不存在或事件历史已过期\");\n return run;\n }\n\n private sessionRun(sessionId: string): Run {\n this.pruneExpired();\n const runId = this.latestBySession.get(sessionId);\n const run = runId ? this.runs.get(runId) : undefined;\n if (!run) throw new HttpError(404, \"会话没有可跟随或停止的运行\");\n return run;\n }\n\n /** 惰性清理超过保留期的终态运行;活动运行永不在这里删除 */\n private pruneExpired(): void {\n const cutoff = Date.now() - this.retentionMs;\n for (const [runId, run] of [...this.runs]) {\n if (run.completedAt !== null && run.completedAt <= cutoff) {\n this.runs.delete(runId);\n if (this.latestBySession.get(run.sessionId) === runId) {\n this.latestBySession.delete(run.sessionId);\n }\n }\n }\n }\n}\n\n/** 路由层可直接转成统一错误响应的异常 */\nexport class HttpError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n ) {\n super(message);\n this.name = \"HttpError\";\n }\n}\n","/**\n * 会话记录器:把一次 Agent 运行的定稿消息接进 JSONL 存储与会话索引。\n *\n * 一次运行一个实例,由路由层创建并挂到两个钩子上:\n * - AgentRunner(onMessage / onCompaction)——定稿消息与压缩行落盘并刷新\n * 索引(先文件后索引,见 sessions.ts 的写入顺序约定);\n * - RunRegistry.start(onTerminal)——运行终态时收尾:停心跳、给未配对的\n * tool_call 补错误回执、清空运行标记(列表立即显示已结束)。\n *\n * 心跳独立于消息追加:长工具执行期间可能几十秒没有新消息,心跳任务保证\n * last_heartbeat 持续刷新,调用方才能正确区分「还在跑」和「已崩溃」。\n * 进程硬崩时心跳自然停止,超时窗过后状态自愈为已结束——这正是不持久化\n * 静态 status 字段的原因。\n */\nimport type { AgentEvent } from \"../agent/events.js\";\nimport type { CompactionResult } from \"../agent/compaction.js\";\nimport { PREVIEW_MAX_CHARS, type AgentSessionStore } from \"../agent/sessions.js\";\nimport type { ChatMessage, ChatResponse } from \"../llm/models.js\";\nimport type { SessionIndex } from \"./session-index.js\";\n\n/** 心跳间隔(毫秒);超时窗见 session-index 的 HEARTBEAT_TIMEOUT_MS(须大于本值) */\nexport const HEARTBEAT_INTERVAL_MS = 10_000;\n\nexport class AgentRunRecorder {\n private readonly store: AgentSessionStore;\n private readonly index: SessionIndex;\n private readonly sessionId: string;\n /** 运行开始时会话已有的 entry 数;之后每次落盘递增,避免反复重读文件 */\n private entryCount: number;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n /** begin 与 onTerminal 分别由路由层和后台任务并发调用:用同一根 Promise\n * 链串行化,防「极速结束的运行被误标为永远运行中」的竞态 */\n private lifecycle: Promise<void> = Promise.resolve();\n private terminated = false;\n\n constructor(store: AgentSessionStore, index: SessionIndex, sessionId: string, entryCount: number) {\n this.store = store;\n this.index = index;\n this.sessionId = sessionId;\n this.entryCount = entryCount;\n }\n\n /** 运行启动:标记 running 并开启心跳。运行已先一步终态时跳过。 */\n async begin(runId: string): Promise<void> {\n this.lifecycle = this.lifecycle.then(() => {\n if (this.terminated) return;\n this.index.markRunning(this.sessionId, runId);\n this.heartbeatTimer = setInterval(() => {\n try {\n this.index.heartbeat(this.sessionId);\n } catch (err) {\n console.warn(`会话心跳刷新失败 session=${this.sessionId}:${err instanceof Error ? err.message : err}`);\n }\n }, HEARTBEAT_INTERVAL_MS);\n this.heartbeatTimer.unref?.();\n });\n await this.lifecycle;\n }\n\n /** 落盘 user message,刷新标题(仅首条)与最后提示预览,返回 message id */\n async recordUserMessage(text: string): Promise<string> {\n const entry = this.store.append(this.sessionId, { role: \"user\", content: text });\n this.entryCount += 1;\n const preview = text.trim().slice(0, PREVIEW_MAX_CHARS);\n this.index.touchAfterAppend(this.sessionId, {\n leaf_uuid: entry.uuid,\n entry_count: this.entryCount,\n last_prompt: preview,\n title: preview,\n });\n return entry.uuid;\n }\n\n /** runner 定稿消息回调:assistant 带响应元数据,tool 结果不带 */\n onMessage = async (message: ChatMessage, response: ChatResponse | null): Promise<void> => {\n const entry = this.store.append(this.sessionId, message, {\n ...(response?.model ? { model: response.model } : {}),\n ...(response?.usage ? { usage: response.usage } : {}),\n ...(response?.finish_reason ? { finish_reason: response.finish_reason } : {}),\n });\n this.entryCount += 1;\n this.index.touchAfterAppend(this.sessionId, {\n leaf_uuid: entry.uuid,\n entry_count: this.entryCount,\n });\n };\n\n /** runner 压缩定稿回调:压缩行落盘并刷新索引(与 onMessage 同一节奏) */\n onCompaction = async (result: CompactionResult): Promise<void> => {\n const entry = this.store.appendCompaction(this.sessionId, result);\n this.entryCount += 1;\n this.index.touchAfterAppend(this.sessionId, {\n leaf_uuid: entry.uuid,\n entry_count: this.entryCount,\n });\n };\n\n /** runner 提权请求回调:提权行落盘并刷新索引(回放时前端渲染确认卡片) */\n onEscalation = async (info: {\n escalation_id: string;\n requested_path: string;\n resolved_path: string;\n tool_name: string;\n resource_type?: \"path\" | \"command\";\n requested_command?: string[];\n }): Promise<void> => {\n const entry = this.store.appendEscalation(this.sessionId, {\n escalation_id: info.escalation_id,\n requested_path: info.requested_path,\n resolved_path: info.resolved_path,\n tool_name: info.tool_name,\n resource_type: info.resource_type,\n requested_command: info.requested_command,\n });\n this.entryCount += 1;\n this.index.touchAfterAppend(this.sessionId, {\n leaf_uuid: entry.uuid,\n entry_count: this.entryCount,\n });\n };\n\n /** 运行终态收尾(done / error / cancelled 统一路径) */\n onTerminal = async (_event: AgentEvent): Promise<void> => {\n this.lifecycle = this.lifecycle.then(() => {\n this.terminated = true;\n if (this.heartbeatTimer !== null) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n // 取消/出错的运行可能留下没有回执的 tool_call,补齐保证配对完整\n let sealed = 0;\n try {\n sealed = this.store.sealPendingToolCalls(this.sessionId);\n } catch (err) {\n console.warn(`会话中断收尾失败 session=${this.sessionId}:${err instanceof Error ? err.message : err}`);\n }\n if (sealed > 0) {\n this.entryCount += sealed;\n const { entries } = this.store.read(this.sessionId);\n this.index.touchAfterAppend(this.sessionId, {\n leaf_uuid: entries[entries.length - 1]?.uuid ?? \"\",\n entry_count: this.entryCount,\n });\n }\n this.index.finishRun(this.sessionId);\n });\n await this.lifecycle;\n };\n}\n","/**\n * REST + SSE 路由(Hono)—— Agent 会话的 HTTP 面。\n *\n * 响应统一信封:成功 {success:true, code, message, data};\n * 错误 {success:false, code, message}(HTTP 状态码同步表达错误类别)。\n */\nimport { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport { buildSystemPrompt } from \"../agent/prompts.js\";\nimport { compact, type CompactionResult } from \"../agent/compaction.js\";\nimport {\n isCompactionEntry,\n isEscalationEntry,\n isMessageEntry,\n type AgentSessionStore,\n} from \"../agent/sessions.js\";\nimport { AgentRunner } from \"../agent/runner.js\";\nimport type { AgentEvent } from \"../agent/events.js\";\nimport type { EndpointResolver } from \"../llm/router.js\";\nimport type { AgentTool } from \"../tools/types.js\";\nimport { AgentRunRecorder } from \"./recorder.js\";\nimport { HttpError, RunRegistry } from \"./run-registry.js\";\nimport type { SessionIndex } from \"./session-index.js\";\n\nexport interface RoutesContext {\n resolver: EndpointResolver;\n store: AgentSessionStore;\n index: SessionIndex;\n registry: RunRegistry;\n /** 会话级路径授权登记表(提权协商的确认落点) */\n grants: import(\"../agent/escalation.js\").EscalationGrants;\n /** 工具工厂:按会话构建工具集(授权清单需要 sessionId 才能生效) */\n makeTools: (sessionId: string) => AgentTool[];\n /** 提权事件展示的工作区根 */\n workdir: string;\n agentName?: string;\n persona?: string;\n /** 可选静态 Bearer token;配置后全部端点要求鉴权 */\n token?: string;\n}\n\nfunction ok<T>(data: T, message = \"\"): { success: true; code: number; message: string; data: T } {\n return { success: true, code: 0, message, data };\n}\n\nfunction fail(status: number, message: string): never {\n throw new HttpError(status, message);\n}\n\nconst startPayloadSchema = z.object({\n content: z.string().min(1, \"消息内容不能为空\"),\n session_id: z.string().optional(),\n model: z.string().default(\"\"),\n});\n\nconst retryPayloadSchema = z.object({\n message_id: z.string().min(1),\n content: z.string().optional(),\n model: z.string().default(\"\"),\n});\n\nexport function createAgentRoutes(ctx: RoutesContext): Hono {\n const app = new Hono();\n\n // 统一错误处理:HttpError → 对应状态码;其余 → 500\n app.onError((err, c) => {\n if (err instanceof HttpError) {\n return c.json({ success: false, code: err.status, message: err.message }, err.status as 400);\n }\n console.error(`请求处理失败:${err instanceof Error ? (err.stack ?? err.message) : err}`);\n return c.json({ success: false, code: 500, message: \"服务内部错误\" }, 500);\n });\n\n // 可选 Bearer 鉴权\n if (ctx.token) {\n app.use(\"*\", async (c, next) => {\n const header = c.req.header(\"authorization\") ?? \"\";\n if (header !== `Bearer ${ctx.token}`) {\n return c.json({ success: false, code: 401, message: \"未授权:缺少或错误的 Bearer token\" }, 401);\n }\n await next();\n });\n }\n\n const buildSystem = (): string =>\n buildSystemPrompt({ agentName: ctx.agentName, persona: ctx.persona });\n\n /** 在已校验的会话链尾追加用户消息并启动后台运行(start / retry 共用) */\n async function launchUserMessage(args: {\n sessionId: string;\n content: string;\n model: string;\n history: import(\"../llm/models.js\").ChatMessage[];\n entryCount: number;\n systemPrompt?: string;\n recordUser?: boolean;\n }): Promise<{ sessionId: string; messageId: string }> {\n const recorder = new AgentRunRecorder(ctx.store, ctx.index, args.sessionId, args.entryCount);\n const messageId = args.recordUser === false ? \"\" : await recorder.recordUserMessage(args.content);\n const runner = new AgentRunner({\n resolver: ctx.resolver,\n tools: ctx.makeTools(args.sessionId),\n onMessage: recorder.onMessage,\n onCompaction: recorder.onCompaction,\n onEscalation: recorder.onEscalation,\n workdirHint: ctx.workdir,\n });\n const runId = ctx.registry.start(\n runner,\n {\n input: args.content,\n include_input: args.recordUser !== false,\n history: args.history,\n model: args.model,\n system_prompt: args.systemPrompt ?? buildSystem(),\n },\n { sessionId: args.sessionId, onTerminal: recorder.onTerminal },\n );\n await recorder.begin(runId);\n return { sessionId: args.sessionId, messageId };\n }\n\n /** 开始新会话,或向已有会话发送用户消息(202 异步) */\n app.post(\"/sessions\", async (c) => {\n const payload = startPayloadSchema.parse(await c.req.json());\n // 路由解析先行:端点未配置/模型不存在时必须在会话落盘前失败,\n // 否则磁盘上会残留一条空会话\n ctx.resolver.resolve(payload.model);\n\n let sessionId: string;\n let history: import(\"../llm/models.js\").ChatMessage[];\n let entryCount: number;\n if (payload.session_id) {\n sessionId = payload.session_id;\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n if (ctx.index.isRunning(sessionId)) {\n fail(400, \"该会话已有正在进行的运行,请先停止或等待完成\");\n }\n history = ctx.store.buildHistory(sessionId);\n entryCount = ctx.store.read(sessionId).entries.length;\n } else {\n const header = ctx.store.create();\n sessionId = header.session_id;\n ctx.index.create(sessionId);\n history = [];\n entryCount = 0;\n }\n const { messageId } = await launchUserMessage({\n sessionId,\n content: payload.content,\n model: payload.model,\n history,\n entryCount,\n });\n return c.json(ok({ session_id: sessionId, message_id: messageId }, \"用户消息已提交\"), 202);\n });\n\n /** 最近会话列表(按最后活跃时间倒序) */\n app.get(\"/sessions\", (c) => {\n const limit = Math.min(Number(c.req.query(\"limit\") ?? 50), 200);\n const offset = Math.max(Number(c.req.query(\"offset\") ?? 0), 0);\n const list = ctx.index.list(limit, offset).map((meta) => ({\n ...meta,\n running: ctx.index.isRunning(meta.session_id),\n }));\n return c.json(ok(list));\n });\n\n /** 读取会话完整轨迹(message/compaction 按写入顺序) */\n app.get(\"/sessions/:id/transcript\", (c) => {\n const sessionId = c.req.param(\"id\");\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n const { entries } = ctx.store.read(sessionId);\n return c.json(\n ok({\n session: ctx.index.get(sessionId) ?? null,\n entries: entries.map((e) =>\n isCompactionEntry(e)\n ? {\n type: \"compaction\" as const,\n compaction_id: e.uuid,\n parent_id: e.parent_uuid,\n timestamp: e.timestamp,\n summary: e.summary,\n replacement_history: e.replacement_history,\n tokens_before: e.tokens_before,\n tokens_after: e.tokens_after,\n }\n : isEscalationEntry(e)\n ? {\n type: \"escalation\" as const,\n escalation_id: e.uuid,\n parent_id: e.parent_uuid,\n timestamp: e.timestamp,\n requested_path: e.requested_path,\n resolved_path: e.resolved_path,\n tool_name: e.tool_name,\n resource_type: e.resource_type,\n requested_command: e.requested_command,\n workdir: ctx.workdir,\n granted: e.granted,\n }\n : {\n type: \"message\" as const,\n message_id: e.uuid,\n parent_id: e.parent_uuid,\n timestamp: e.timestamp,\n message: e.message,\n model: e.model,\n usage: e.usage,\n finish_reason: e.finish_reason,\n },\n ),\n }),\n );\n });\n\n /** 重命名会话 */\n app.patch(\"/sessions/:id\", async (c) => {\n const sessionId = c.req.param(\"id\");\n const { title } = z.object({ title: z.string().min(1) }).parse(await c.req.json());\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n ctx.index.rename(sessionId, title);\n return c.json(ok(ctx.index.get(sessionId), \"会话已重命名\"));\n });\n\n /** 手动压缩会话上下文(不删除完整轨迹) */\n app.post(\"/sessions/:id/compact-context\", async (c) => {\n const sessionId = c.req.param(\"id\");\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n if (ctx.index.isRunning(sessionId)) fail(400, \"该会话正在运行中,请等待完成后再压缩\");\n const history = ctx.store.buildHistory(sessionId);\n if (history.length === 0) fail(400, \"会话没有可压缩的内容\");\n\n // 沿用会话最近一次运行的模型(转录里 assistant 行带 model 元数据)\n const { entries } = ctx.store.read(sessionId);\n const lastModel = [...entries].reverse().find((e) => isMessageEntry(e) && e.model);\n const modelRef = (lastModel && isMessageEntry(lastModel) && lastModel.model) || \"\";\n const resolved = ctx.resolver.resolve(modelRef);\n\n const result: CompactionResult | null = await compact(\n resolved.protocol,\n resolved.modelId,\n [{ role: \"system\", content: buildSystem() }, ...history],\n {},\n );\n if (!result) fail(502, \"压缩失败:模型未能生成摘要,请稍后重试\");\n\n const entry = ctx.store.appendCompaction(sessionId, result);\n ctx.index.touchAfterAppend(sessionId, {\n leaf_uuid: entry.uuid,\n entry_count: entries.length + 1,\n });\n return c.json(\n ok(\n {\n summary: result.summary,\n tokens_before: result.tokens_before,\n tokens_after: result.tokens_after,\n compaction_id: entry.uuid,\n },\n \"会话上下文已压缩\",\n ),\n );\n });\n\n /** 从指定 user message 重新提问(可替换问题内容) */\n app.post(\"/sessions/:id/retry\", async (c) => {\n const sessionId = c.req.param(\"id\");\n const payload = retryPayloadSchema.parse(await c.req.json());\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n if (ctx.index.isRunning(sessionId)) fail(400, \"该会话正在运行中,请先停止运行再重试\");\n\n const { entries } = ctx.store.read(sessionId);\n const target = entries.find((e) => e.uuid === payload.message_id);\n if (!target) fail(404, \"会话中没有这条记录,可能已被改写\");\n if (!isMessageEntry(target) || target.message.role !== \"user\") {\n fail(400, \"只能重试用户消息\");\n }\n const content = payload.content ?? (target.message.content ?? \"\");\n\n // 端点校验先于不可逆的历史删除\n ctx.resolver.resolve(payload.model);\n ctx.store.discardFromUserMessage(sessionId, payload.message_id);\n const history = ctx.store.buildHistory(sessionId);\n const remaining = ctx.store.read(sessionId).entries.length;\n\n const { messageId } = await launchUserMessage({\n sessionId,\n content,\n model: payload.model,\n history,\n entryCount: remaining,\n });\n return c.json(ok({ session_id: sessionId, message_id: messageId }, \"已重新提交\"), 202);\n });\n\n /**\n * 提权确认:用户在前端确认后,把路径登记进会话级授权清单,并自动\n * 重发最近一条用户消息续跑(效果 = 授权后从中断处继续)。\n * 授权粒度是「会话 × 路径前缀」,随会话生命周期存在(进程内,不落盘)。\n */\n app.post(\"/sessions/:id/grant-access\", async (c) => {\n const sessionId = c.req.param(\"id\");\n const { escalation_id, granted, resolved_path } = z.object({\n escalation_id: z.string().min(1),\n granted: z.boolean(),\n resolved_path: z.string().min(1),\n }).parse(await c.req.json());\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n if (ctx.index.isRunning(sessionId)) fail(400, \"该会话正在运行中\");\n\n // 用 escalation_id 定位并校验目标路径,防前端传错/被篡改\n const { entries } = ctx.store.read(sessionId);\n const esc = entries.find(\n (e) => e.type === \"escalation\" && e.uuid === escalation_id,\n );\n if (!esc || esc.type !== \"escalation\") fail(404, \"提权请求不存在或已过期\");\n if (esc.resolved_path !== resolved_path) fail(400, \"授权路径与提权请求不一致\");\n if (esc.granted !== null && esc.granted !== undefined) fail(400, \"该提权请求已处理过\");\n\n // 落确认结果(回放时卡片显示已授权/已拒绝)\n ctx.store.resolveEscalation(sessionId, escalation_id, granted);\n\n if (!granted) {\n return c.json(ok({ granted: false }, \"已拒绝授权\"));\n }\n if (esc.resource_type === \"command\") {\n ctx.grants.grantCapability(sessionId, resolved_path);\n } else {\n ctx.grants.grant(sessionId, resolved_path);\n }\n\n // 自动续跑:沿用原始 user 历史,不追加新的 user 记录;\n // 提权中断的运行已由 recorder 终态收尾补配对,轨迹仍可完整回放。\n const lastUser = [...entries].reverse().find(\n (e) => isMessageEntry(e) && e.message.role === \"user\",\n );\n if (!lastUser || !isMessageEntry(lastUser)) fail(400, \"会话中没有可续跑的用户消息\");\n ctx.resolver.resolve(\"\");\n const history = ctx.store.buildHistoryBeforeEscalation(sessionId, escalation_id);\n const { messageId } = await launchUserMessage({\n sessionId,\n content: \"\",\n model: \"\",\n history,\n entryCount: entries.length,\n recordUser: false,\n });\n return c.json(\n ok({ session_id: sessionId, message_id: messageId, granted_path: resolved_path }, \"已授权并继续执行\"),\n 202,\n );\n });\n\n /** 删除会话(转录文件与索引一并删除;运行中拒绝) */\n app.delete(\"/sessions/:id\", (c) => {\n const sessionId = c.req.param(\"id\");\n if (!ctx.store.exists(sessionId)) fail(404, \"会话不存在\");\n if (ctx.index.isRunning(sessionId)) fail(400, \"该会话正在运行中,请先停止运行再删除\");\n ctx.store.delete(sessionId);\n ctx.index.remove(sessionId);\n ctx.grants.drop(sessionId); // 授权随会话生命周期\n return c.json(ok({}, \"会话已删除\"));\n });\n\n /** SSE 跟随会话当前消息的处理事件(支持 Last-Event-ID 断线续传) */\n app.get(\"/sessions/:id/events\", async (c) => {\n const sessionId = c.req.param(\"id\");\n const cursor = Number(c.req.header(\"last-event-id\") ?? 0);\n // 在响应建立前完成存在性和游标校验,404/400 仍能以标准 JSON 返回\n const initial = await ctx.registry.getSessionEvents(sessionId, cursor, 0);\n\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const encoder = new TextEncoder();\n let current = cursor;\n let { events, terminal } = initial;\n try {\n for (;;) {\n for (const stored of events) {\n current = stored.sequence;\n const { run_id: _omit, ...payload } = stored.event;\n controller.enqueue(\n encoder.encode(\n `id: ${stored.sequence}\\nevent: ${stored.event.type}\\ndata: ${JSON.stringify(payload)}\\n\\n`,\n ),\n );\n }\n if (terminal) return;\n ({ events, terminal } = await ctx.registry.getSessionEvents(sessionId, current, 15));\n if (events.length === 0 && !terminal) {\n controller.enqueue(encoder.encode(\": heartbeat\\n\\n\"));\n }\n }\n } finally {\n controller.close();\n }\n },\n });\n return new Response(stream, {\n headers: {\n \"content-type\": \"text/event-stream\",\n \"cache-control\": \"no-cache, no-transform\",\n connection: \"keep-alive\",\n \"x-accel-buffering\": \"no\",\n },\n });\n });\n\n /** 停止会话当前消息的模型处理(幂等) */\n app.post(\"/sessions/:id/stop\", async (c) => {\n await ctx.registry.cancelSession(c.req.param(\"id\"));\n return c.json(ok({}, \"已请求停止会话\"));\n });\n\n app.get(\"/health\", (c) => c.json(ok({ status: \"ok\" })));\n\n return app;\n}\n","/**\n * 会话元数据索引(index.json)—— JSONL 文件的查询索引,不是事实源。\n *\n * 设计(移植自 MovieClaw 的「文件是事实源,DB 只是索引」并去 SQLite 化):\n * - 索引随时可由 sessions/ 目录的 JSONL 文件整体重建(rebuild);\n * - 写入顺序固定「先落 JSONL 文件、后更新索引」,两步之间崩溃只会让索引\n * 落后,启动时扫描重建即自愈;\n * - 写盘一律 tmp + rename 原子换入;\n * - 运行状态不持久化静态 status:只记 last_heartbeat 时间戳,进程硬崩后\n * 心跳自然停止,超过超时窗即视为已结束(状态自愈)。\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { SessionSummary } from \"../agent/sessions.js\";\nimport { PREVIEW_MAX_CHARS } from \"../agent/sessions.js\";\n\n/** 心跳超时窗(毫秒):超过即视为运行已结束;须大于记录器的心跳间隔 */\nexport const HEARTBEAT_TIMEOUT_MS = 30_000;\n\nexport interface RunningState {\n run_id: string;\n /** 最近一次心跳的 epoch 毫秒 */\n last_heartbeat: number;\n}\n\nexport interface SessionMeta {\n session_id: string;\n created_at: string;\n title: string | null;\n last_prompt: string | null;\n entry_count: number;\n leaf_uuid: string | null;\n last_active: string;\n running: RunningState | null;\n}\n\nexport class SessionIndex {\n private readonly file: string;\n private readonly metas = new Map<string, SessionMeta>();\n\n constructor(indexFile: string) {\n this.file = indexFile;\n this.load();\n }\n\n /** 启动时加载;文件不存在/损坏则从空开始(rebuild 会补齐) */\n private load(): void {\n try {\n const raw = JSON.parse(fs.readFileSync(this.file, \"utf-8\")) as { sessions?: SessionMeta[] };\n for (const meta of raw.sessions ?? []) this.metas.set(meta.session_id, meta);\n } catch {\n this.metas.clear();\n }\n }\n\n /** 从事实源整体重建(启动自愈):扫描结果单向覆盖索引 */\n rebuild(summaries: SessionSummary[]): void {\n for (const s of summaries) {\n const existing = this.metas.get(s.session_id);\n this.metas.set(s.session_id, {\n session_id: s.session_id,\n created_at: s.created_at,\n // 已有人工标题时保留(文件里不存标题,扫描回填的是首条 user 消息)\n title: existing?.title ?? s.title,\n last_prompt: s.last_prompt,\n entry_count: s.entry_count,\n leaf_uuid: s.leaf_uuid,\n last_active: s.last_timestamp,\n running: null, // 进程刚启动,任何「运行中」都是上一世的残留\n });\n }\n this.persist();\n }\n\n create(sessionId: string): void {\n const now = new Date().toISOString();\n this.metas.set(sessionId, {\n session_id: sessionId,\n created_at: now,\n title: null,\n last_prompt: null,\n entry_count: 0,\n leaf_uuid: null,\n last_active: now,\n running: null,\n });\n this.persist();\n }\n\n get(sessionId: string): SessionMeta | undefined {\n return this.metas.get(sessionId);\n }\n\n /** 每次追加 entry 后刷新链尾/计数/预览;title 仅在传入时更新(首条消息) */\n touchAfterAppend(\n sessionId: string,\n update: { leaf_uuid: string; entry_count: number; last_prompt?: string; title?: string },\n ): void {\n const meta = this.metas.get(sessionId);\n if (!meta) return;\n meta.leaf_uuid = update.leaf_uuid;\n meta.entry_count = update.entry_count;\n meta.last_active = new Date().toISOString();\n if (update.last_prompt !== undefined) {\n meta.last_prompt = update.last_prompt.slice(0, PREVIEW_MAX_CHARS);\n }\n if (update.title !== undefined && meta.title === null) {\n meta.title = update.title.slice(0, PREVIEW_MAX_CHARS);\n }\n this.persist();\n }\n\n rename(sessionId: string, title: string): boolean {\n const meta = this.metas.get(sessionId);\n if (!meta) return false;\n meta.title = title.slice(0, PREVIEW_MAX_CHARS);\n this.persist();\n return true;\n }\n\n markRunning(sessionId: string, runId: string): void {\n const meta = this.metas.get(sessionId);\n if (!meta) return;\n meta.running = { run_id: runId, last_heartbeat: Date.now() };\n this.persist();\n }\n\n heartbeat(sessionId: string): void {\n const meta = this.metas.get(sessionId);\n if (!meta?.running) return;\n meta.running.last_heartbeat = Date.now();\n this.persist();\n }\n\n finishRun(sessionId: string): void {\n const meta = this.metas.get(sessionId);\n if (!meta) return;\n meta.running = null;\n this.persist();\n }\n\n /** 是否有正在进行的消息处理:运行标记存在且心跳未超时 */\n isRunning(sessionId: string): boolean {\n const running = this.metas.get(sessionId)?.running;\n if (!running) return false;\n return Date.now() - running.last_heartbeat < HEARTBEAT_TIMEOUT_MS;\n }\n\n /** 按最后活跃时间倒序分页 */\n list(limit: number, offset: number): SessionMeta[] {\n return [...this.metas.values()]\n .sort((a, b) => b.last_active.localeCompare(a.last_active))\n .slice(offset, offset + limit);\n }\n\n remove(sessionId: string): void {\n this.metas.delete(sessionId);\n this.persist();\n }\n\n private persist(): void {\n const dir = path.dirname(this.file);\n fs.mkdirSync(dir, { recursive: true });\n const tmp = `${this.file}.tmp`;\n fs.writeFileSync(tmp, JSON.stringify({ sessions: [...this.metas.values()] }, null, 2));\n fs.renameSync(tmp, this.file);\n }\n}\n","/**\n * 服务装配:把配置、协议路由、存储、注册表、路由组装成一个可运行的服务。\n */\nimport path from \"node:path\";\nimport { serve } from \"@hono/node-server\";\nimport type { Hono } from \"hono\";\nimport { defaultDataDir, AgentSessionStore } from \"../agent/sessions.js\";\nimport { EscalationGrants } from \"../agent/escalation.js\";\nimport { EndpointResolver } from \"../llm/router.js\";\nimport { builtinTools } from \"../tools/index.js\";\nimport { loadConfig, type AppConfig } from \"./config.js\";\nimport { createConfigRoutes } from \"./config-routes.js\";\nimport { AgentRunRecorder } from \"./recorder.js\";\nimport { createAgentRoutes } from \"./routes.js\";\nimport { RunRegistry } from \"./run-registry.js\";\nimport { SessionIndex } from \"./session-index.js\";\n\nexport interface AgentServer {\n app: Hono;\n registry: RunRegistry;\n store: AgentSessionStore;\n index: SessionIndex;\n}\n\n/** 以代码方式装配服务(嵌入用法) */\nexport function createAgentServer(\n config: AppConfig,\n opts: { configPath?: string; dataDir?: string } = {},\n): AgentServer {\n const dataDir = path.resolve(opts.dataDir ?? defaultDataDir());\n const configPath = opts.configPath ?? path.join(dataDir, \"config.json\");\n const resolver = new EndpointResolver(config.endpoints);\n const store = new AgentSessionStore(path.join(dataDir, \"sessions\"));\n const index = new SessionIndex(path.join(dataDir, \"index.json\"));\n // 启动自愈:从事实源(JSONL 文件)整体重建索引\n index.rebuild(store.scanAll());\n const registry = new RunRegistry();\n const workdir = path.resolve(config.agent?.workdir ?? path.join(dataDir, \"workspace\"));\n const grants = new EscalationGrants();\n const app = createAgentRoutes({\n resolver,\n store,\n index,\n registry,\n grants,\n makeTools: (sessionId) => builtinTools({\n workdir,\n grants,\n sessionId,\n enableCommandExecution: config.agent?.enable_command_execution ?? false,\n }),\n workdir,\n ...(config.agent?.agent_name ? { agentName: config.agent.agent_name } : {}),\n ...(config.agent?.persona ? { persona: config.agent.persona } : {}),\n ...(config.server?.token ? { token: config.server.token } : {}),\n });\n // 配置管理 API。\n const configRoutes = createConfigRoutes({ configPath });\n if (config.server?.token) {\n configRoutes.use(\"*\", async (c, next) => {\n const header = c.req.header(\"authorization\") ?? \"\";\n if (header !== `Bearer ${config.server!.token}`) {\n return c.json({ success: false, code: 401, message: \"未授权:缺少或错误的 Bearer token\" }, 401);\n }\n await next();\n });\n }\n app.route(\"/\", configRoutes);\n return { app, registry, store, index };\n}\n\n/** 以配置文件启动 HTTP 服务(CLI serve 命令) */\nexport function serveFromConfig(opts: { configPath?: string; port?: number }): void {\n const configPath = opts.configPath ?? path.join(defaultDataDir(), \"config.json\");\n const config = loadConfig(configPath);\n const { app } = createAgentServer(config, { configPath });\n const port = opts.port ?? config.server?.port ?? 3210;\n serve({ fetch: app.fetch, port }, (info) => {\n console.log(`xlyra-agent 服务已启动:http://127.0.0.1:${info.port}`);\n console.log(`数据目录:${defaultDataDir()}(sessions/ 会话转录,workspace/ 工具工作区)`);\n if (!config.server?.token) {\n console.warn(\"⚠ 未配置 server.token,接口无鉴权——请勿暴露到公网\");\n }\n });\n}\n\nexport { AgentRunRecorder, RunRegistry, SessionIndex };\nexport { createAgentRoutes } from \"./routes.js\";\nexport {\n loadConfig,\n saveConfig,\n upsertEndpoint,\n removeEndpoint,\n configExists,\n defaultConfigPath,\n} from \"./config.js\";\nexport type { AppConfig, ServerConfig, AgentServiceConfig } from \"./config.js\";\nexport { createConfigRoutes } from \"./config-routes.js\";\nexport { HttpError, type StoredAgentEvent } from \"./run-registry.js\";\n","/**\n * 配置管理 API:\n * - GET /config 读取完整配置;api_key 打码回显(头 4 + 尾 4),\n * \"${ENV_VAR}\" 引用保持原文不插值——不回显真实凭证;\n * - PUT /config 整体保存配置(经 schema 校验,原子写盘);\n * - POST /config/test 端点连通性测试(最小真实调用,返回延迟/错误)。\n *\n * 注意:PUT 只落盘——运行中的服务下一次请求才生效的部分(工具 workdir 等\n * 启动期装配的项)需要重启服务;端点列表由 EndpointResolver 惰性构建,\n * 新增端点保存后立即可用。\n */\nimport { Hono } from \"hono\";\nimport { z } from \"zod\";\nimport { AnthropicMessagesProtocol } from \"../llm/protocols/messages.js\";\nimport { OpenAIResponsesProtocol } from \"../llm/protocols/responses.js\";\nimport { loadConfig, saveConfig, type AppConfig } from \"./config.js\";\nimport { HttpError } from \"./run-registry.js\";\n\nexport interface ConfigRoutesContext {\n configPath: string;\n}\n\n/** api_key 打码:只留头 4 尾 4;\"${ENV_VAR}\" 引用原样保留(不是真实凭证) */\nfunction maskApiKey(key: string): string {\n if (key.includes(\"${\")) return key;\n if (key.length <= 8) return \"****\";\n return `${key.slice(0, 4)}…${key.slice(-4)}`;\n}\n\nfunction maskedConfig(config: AppConfig): AppConfig {\n return {\n ...config,\n endpoints: config.endpoints.map((e) => ({ ...e, api_key: maskApiKey(e.api_key) })),\n };\n}\n\nconst putPayloadSchema = z.object({\n endpoints: z.array(\n z.object({\n name: z.string().min(1),\n protocol: z.enum([\"openai-responses\", \"anthropic-messages\"]),\n base_url: z.string().min(1),\n api_key: z.string().min(1),\n models: z.record(z.string(), z.object({ context_window: z.number().positive().optional() })).optional(),\n default_model: z.string().optional(),\n }),\n ).min(1, \"endpoints 为空:至少配置一个模型端点\"),\n server: z.object({ port: z.number().int().positive().optional(), token: z.string().optional() }).optional(),\n agent: z.object({\n workdir: z.string().optional(),\n agent_name: z.string().optional(),\n persona: z.string().optional(),\n enable_command_execution: z.boolean().optional(),\n }).optional(),\n});\n\nexport function createConfigRoutes(ctx: ConfigRoutesContext): Hono {\n const app = new Hono();\n\n app.onError((err, c) => {\n if (err instanceof HttpError) {\n return c.json({ success: false, code: err.status, message: err.message }, err.status as 400);\n }\n console.error(`配置接口处理失败:${err instanceof Error ? err.message : err}`);\n return c.json({ success: false, code: 500, message: err instanceof Error ? err.message : \"服务内部错误\" }, 500);\n });\n\n /** 读取配置(api_key 打码) */\n app.get(\"/config\", (c) => {\n const config = loadConfig(ctx.configPath);\n return c.json({ success: true, code: 0, message: \"\", data: maskedConfig(config) });\n });\n\n /**\n * 整体保存配置。api_key 与打码形式一致(含 …)时视为「未修改」,\n * 保留磁盘上的原值——Web 表单回显打码值后直接提交不会把凭证冲掉。\n */\n app.put(\"/config\", async (c) => {\n const payload = putPayloadSchema.parse(await c.req.json());\n const current = loadConfig(ctx.configPath);\n const endpoints = payload.endpoints.map((incoming) => {\n const existing = current.endpoints.find((e) => e.name === incoming.name);\n if (existing && incoming.api_key === maskApiKey(existing.api_key)) {\n return { ...incoming, api_key: existing.api_key };\n }\n return incoming;\n });\n const next: AppConfig = {\n endpoints,\n ...(payload.server ? { server: payload.server } : {}),\n ...(payload.agent ? { agent: payload.agent } : {}),\n };\n saveConfig(next, ctx.configPath);\n return c.json({ success: true, code: 0, message: \"配置已保存(部分启动期装配项需重启服务后生效)\", data: maskedConfig(next) });\n });\n\n /** 端点连通性测试:一次最小真实调用(max_tokens=1),返回延迟或错误 */\n app.post(\"/config/test\", async (c) => {\n const { name } = z.object({ name: z.string().min(1) }).parse(await c.req.json());\n const config = loadConfig(ctx.configPath);\n const endpoint = config.endpoints.find((e) => e.name === name);\n if (!endpoint) throw new HttpError(404, `端点不存在:${name}`);\n const model = endpoint.default_model ?? Object.keys(endpoint.models ?? {})[0];\n if (!model) throw new HttpError(400, `端点 ${name} 未配置 default_model 或 models,无法测试`);\n const protocol =\n endpoint.protocol === \"anthropic-messages\"\n ? new AnthropicMessagesProtocol({ baseUrl: endpoint.base_url, apiKey: endpoint.api_key, providerName: endpoint.name })\n : new OpenAIResponsesProtocol({ baseUrl: endpoint.base_url, apiKey: endpoint.api_key, providerName: endpoint.name });\n\n const started = Date.now();\n for await (const event of protocol.chatStream({\n model,\n messages: [{ role: \"user\", content: \"ping\" }],\n settings: { max_tokens: endpoint.protocol === \"anthropic-messages\" ? 16 : 16 },\n })) {\n if (event.type === \"error\") {\n return c.json({ success: false, code: 502, message: `连通性测试失败:${event.error}`, data: null }, 502);\n }\n if (event.type === \"done\") {\n return c.json({\n success: true, code: 0,\n message: `端点 ${name} 连通正常(${Date.now() - started}ms)`,\n data: { elapsed_ms: Date.now() - started, model: event.response.model || model },\n });\n }\n }\n return c.json({ success: false, code: 502, message: \"连通性测试失败:流异常终止\", data: null }, 502);\n });\n\n return app;\n}\n"],"mappings":"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","names":["errMsg","safeParse","ok","z","z","z","z","crypto","truncateMiddle","crypto","truncateMiddle","fs","path","fs","path","crypto","fs","path","z","z","fs","path","crypto","fs","path","z","argsSchema","z","fs","path","crypto","fs","path","z","argsSchema","z","fs","path","crypto","crypto","session","crypto","truncateMiddle","fs","z","argsSchema","z","fs","fs","path","z","argsSchema","z","fs","path","fs","path","z","argsSchema","z","fs","path","fs","path","z","IGNORE_NAMES","argsSchema","z","fs","globToRegExp","path","fs","path","crypto","z","argsSchema","z","fs","path","crypto","z","argsSchema","z","fs","path","path","fs","fs","path","z","z","path","fs","crypto","crypto","z","z","fs","path","fs","path","path","Hono","z","z","Hono","path"]}
|