@zqagent/core 0.2.20 → 0.3.6

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.
Files changed (238) hide show
  1. package/README.md +1 -1
  2. package/README.oss.en.md +3 -3
  3. package/README.oss.md +8 -3
  4. package/README.oss.zh-TW.md +3 -3
  5. package/dist/McpClient-CEQBUPuC.d.cts +145 -0
  6. package/dist/McpClient-CEQBUPuC.d.ts +145 -0
  7. package/dist/{ToolRegistry-C3pTFiaJ.d.cts → ToolRegistry-Cy0fQxrb.d.ts} +2 -111
  8. package/dist/{ToolRegistry-C3pTFiaJ.d.ts → ToolRegistry-DouDvn9E.d.cts} +2 -111
  9. package/dist/{explore-RtZtb-V6.d.ts → TurnEngine-BPKhWuSI.d.cts} +108 -73
  10. package/dist/{explore-BgRhj6SP.d.cts → TurnEngine-DtGEuVLT.d.ts} +108 -73
  11. package/dist/conflictGuard-BBOOIxxK.d.cts +42 -0
  12. package/dist/conflictGuard-BBOOIxxK.d.ts +42 -0
  13. package/dist/index.cjs +5418 -1096
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +577 -195
  16. package/dist/index.d.ts +577 -195
  17. package/dist/index.js +5299 -1011
  18. package/dist/index.js.map +1 -1
  19. package/dist/internal/crypto/secrets.cjs +25 -0
  20. package/dist/internal/crypto/secrets.cjs.map +1 -0
  21. package/dist/internal/crypto/secrets.d.cts +2 -0
  22. package/dist/internal/crypto/secrets.d.ts +2 -0
  23. package/dist/internal/crypto/secrets.js +3 -0
  24. package/dist/internal/crypto/secrets.js.map +1 -0
  25. package/dist/internal/engine/FileLogHook.cjs +179 -0
  26. package/dist/internal/engine/FileLogHook.cjs.map +1 -0
  27. package/dist/internal/engine/FileLogHook.d.cts +67 -0
  28. package/dist/internal/engine/FileLogHook.d.ts +67 -0
  29. package/dist/internal/engine/FileLogHook.js +144 -0
  30. package/dist/internal/engine/FileLogHook.js.map +1 -0
  31. package/dist/internal/engine/approvalView.cjs +25 -0
  32. package/dist/internal/engine/approvalView.cjs.map +1 -0
  33. package/dist/internal/engine/approvalView.d.cts +1 -0
  34. package/dist/internal/engine/approvalView.d.ts +1 -0
  35. package/dist/internal/engine/approvalView.js +3 -0
  36. package/dist/internal/engine/approvalView.js.map +1 -0
  37. package/dist/internal/engine/limits.cjs +59 -0
  38. package/dist/internal/engine/limits.cjs.map +1 -0
  39. package/dist/internal/engine/limits.d.cts +32 -0
  40. package/dist/internal/engine/limits.d.ts +32 -0
  41. package/dist/internal/engine/limits.js +31 -0
  42. package/dist/internal/engine/limits.js.map +1 -0
  43. package/dist/internal/engine/sessionNaming.cjs +47 -0
  44. package/dist/internal/engine/sessionNaming.cjs.map +1 -0
  45. package/dist/internal/engine/sessionNaming.d.cts +25 -0
  46. package/dist/internal/engine/sessionNaming.d.ts +25 -0
  47. package/dist/internal/engine/sessionNaming.js +20 -0
  48. package/dist/internal/engine/sessionNaming.js.map +1 -0
  49. package/dist/internal/llmConfig.cjs +561 -0
  50. package/dist/internal/llmConfig.cjs.map +1 -0
  51. package/dist/internal/llmConfig.d.cts +75 -0
  52. package/dist/internal/llmConfig.d.ts +75 -0
  53. package/dist/internal/llmConfig.js +535 -0
  54. package/dist/internal/llmConfig.js.map +1 -0
  55. package/dist/internal/mcp/builtin/index.cjs +685 -0
  56. package/dist/internal/mcp/builtin/index.cjs.map +1 -0
  57. package/dist/internal/mcp/builtin/index.d.cts +21 -0
  58. package/dist/internal/mcp/builtin/index.d.ts +21 -0
  59. package/dist/internal/mcp/builtin/index.js +652 -0
  60. package/dist/internal/mcp/builtin/index.js.map +1 -0
  61. package/dist/internal/mcp/config.cjs +278 -0
  62. package/dist/internal/mcp/config.cjs.map +1 -0
  63. package/dist/internal/mcp/config.d.cts +61 -0
  64. package/dist/internal/mcp/config.d.ts +61 -0
  65. package/dist/internal/mcp/config.js +235 -0
  66. package/dist/internal/mcp/config.js.map +1 -0
  67. package/dist/internal/mcp/presets.cjs +184 -0
  68. package/dist/internal/mcp/presets.cjs.map +1 -0
  69. package/dist/internal/mcp/presets.d.cts +39 -0
  70. package/dist/internal/mcp/presets.d.ts +39 -0
  71. package/dist/internal/mcp/presets.js +158 -0
  72. package/dist/internal/mcp/presets.js.map +1 -0
  73. package/dist/internal/node-name.cjs +45 -0
  74. package/dist/internal/node-name.cjs.map +1 -0
  75. package/dist/internal/node-name.d.cts +3 -0
  76. package/dist/internal/node-name.d.ts +3 -0
  77. package/dist/internal/node-name.js +10 -0
  78. package/dist/internal/node-name.js.map +1 -0
  79. package/dist/internal/paths.cjs +63 -0
  80. package/dist/internal/paths.cjs.map +1 -0
  81. package/dist/internal/paths.d.cts +17 -0
  82. package/dist/internal/paths.d.ts +17 -0
  83. package/dist/internal/paths.js +25 -0
  84. package/dist/internal/paths.js.map +1 -0
  85. package/dist/internal/providers/diagnostics.cjs +288 -0
  86. package/dist/internal/providers/diagnostics.cjs.map +1 -0
  87. package/dist/internal/providers/diagnostics.d.cts +103 -0
  88. package/dist/internal/providers/diagnostics.d.ts +103 -0
  89. package/dist/internal/providers/diagnostics.js +250 -0
  90. package/dist/internal/providers/diagnostics.js.map +1 -0
  91. package/dist/internal/providers/models.cjs +699 -0
  92. package/dist/internal/providers/models.cjs.map +1 -0
  93. package/dist/internal/providers/models.d.cts +136 -0
  94. package/dist/internal/providers/models.d.ts +136 -0
  95. package/dist/internal/providers/models.js +654 -0
  96. package/dist/internal/providers/models.js.map +1 -0
  97. package/dist/internal/terminal.cjs +161 -0
  98. package/dist/internal/terminal.cjs.map +1 -0
  99. package/dist/internal/terminal.d.cts +58 -0
  100. package/dist/internal/terminal.d.ts +58 -0
  101. package/dist/internal/terminal.js +128 -0
  102. package/dist/internal/terminal.js.map +1 -0
  103. package/dist/internal/tools/execAsync.cjs +187 -0
  104. package/dist/internal/tools/execAsync.cjs.map +1 -0
  105. package/dist/internal/tools/execAsync.d.cts +30 -0
  106. package/dist/internal/tools/execAsync.d.ts +30 -0
  107. package/dist/internal/tools/execAsync.js +162 -0
  108. package/dist/internal/tools/execAsync.js.map +1 -0
  109. package/dist/internal/tools/git.cjs +935 -0
  110. package/dist/internal/tools/git.cjs.map +1 -0
  111. package/dist/internal/tools/git.d.cts +206 -0
  112. package/dist/internal/tools/git.d.ts +206 -0
  113. package/dist/internal/tools/git.js +883 -0
  114. package/dist/internal/tools/git.js.map +1 -0
  115. package/dist/internal/tools/pathSafety.cjs +99 -0
  116. package/dist/internal/tools/pathSafety.cjs.map +1 -0
  117. package/dist/internal/tools/pathSafety.d.cts +44 -0
  118. package/dist/internal/tools/pathSafety.d.ts +44 -0
  119. package/dist/internal/tools/pathSafety.js +61 -0
  120. package/dist/internal/tools/pathSafety.js.map +1 -0
  121. package/dist/internal/tools/plan.cjs +146 -0
  122. package/dist/internal/tools/plan.cjs.map +1 -0
  123. package/dist/internal/tools/plan.d.cts +48 -0
  124. package/dist/internal/tools/plan.d.ts +48 -0
  125. package/dist/internal/tools/plan.js +117 -0
  126. package/dist/internal/tools/plan.js.map +1 -0
  127. package/dist/internal/tools/ripgrep.cjs +118 -0
  128. package/dist/internal/tools/ripgrep.cjs.map +1 -0
  129. package/dist/internal/tools/ripgrep.d.cts +6 -0
  130. package/dist/internal/tools/ripgrep.d.ts +6 -0
  131. package/dist/internal/tools/ripgrep.js +89 -0
  132. package/dist/internal/tools/ripgrep.js.map +1 -0
  133. package/dist/internal/tools/sandbox.cjs +253 -0
  134. package/dist/internal/tools/sandbox.cjs.map +1 -0
  135. package/dist/internal/tools/sandbox.d.cts +67 -0
  136. package/dist/internal/tools/sandbox.d.ts +67 -0
  137. package/dist/internal/tools/sandbox.js +213 -0
  138. package/dist/internal/tools/sandbox.js.map +1 -0
  139. package/dist/internal/tools/shell.cjs +771 -0
  140. package/dist/internal/tools/shell.cjs.map +1 -0
  141. package/dist/internal/tools/shell.d.cts +47 -0
  142. package/dist/internal/tools/shell.d.ts +47 -0
  143. package/dist/internal/tools/shell.js +731 -0
  144. package/dist/internal/tools/shell.js.map +1 -0
  145. package/dist/internal/tools/shellRuntime.cjs +220 -0
  146. package/dist/internal/tools/shellRuntime.cjs.map +1 -0
  147. package/dist/internal/tools/shellRuntime.d.cts +67 -0
  148. package/dist/internal/tools/shellRuntime.d.ts +67 -0
  149. package/dist/internal/tools/shellRuntime.js +181 -0
  150. package/dist/internal/tools/shellRuntime.js.map +1 -0
  151. package/dist/internal/update/controller.cjs +1035 -0
  152. package/dist/internal/update/controller.cjs.map +1 -0
  153. package/dist/internal/update/controller.d.cts +150 -0
  154. package/dist/internal/update/controller.d.ts +150 -0
  155. package/dist/internal/update/controller.js +991 -0
  156. package/dist/internal/update/controller.js.map +1 -0
  157. package/dist/internal/update/platform.cjs +234 -0
  158. package/dist/internal/update/platform.cjs.map +1 -0
  159. package/dist/internal/update/platform.d.cts +77 -0
  160. package/dist/internal/update/platform.d.ts +77 -0
  161. package/dist/internal/update/platform.js +184 -0
  162. package/dist/internal/update/platform.js.map +1 -0
  163. package/dist/tools/ask.d.cts +3 -1
  164. package/dist/tools/ask.d.ts +3 -1
  165. package/dist/tools/diff.cjs +17 -6
  166. package/dist/tools/diff.cjs.map +1 -1
  167. package/dist/tools/diff.d.cts +5 -2
  168. package/dist/tools/diff.d.ts +5 -2
  169. package/dist/tools/diff.js +17 -6
  170. package/dist/tools/diff.js.map +1 -1
  171. package/dist/tools/directories.d.cts +3 -1
  172. package/dist/tools/directories.d.ts +3 -1
  173. package/dist/tools/explore.cjs +1778 -204
  174. package/dist/tools/explore.cjs.map +1 -1
  175. package/dist/tools/explore.d.cts +82 -2
  176. package/dist/tools/explore.d.ts +82 -2
  177. package/dist/tools/explore.js +1780 -204
  178. package/dist/tools/explore.js.map +1 -1
  179. package/dist/tools/files.cjs +56 -21
  180. package/dist/tools/files.cjs.map +1 -1
  181. package/dist/tools/files.d.cts +6 -3
  182. package/dist/tools/files.d.ts +6 -3
  183. package/dist/tools/files.js +56 -21
  184. package/dist/tools/files.js.map +1 -1
  185. package/dist/tools/git.cjs +34 -25
  186. package/dist/tools/git.cjs.map +1 -1
  187. package/dist/tools/git.d.cts +4 -204
  188. package/dist/tools/git.d.ts +4 -204
  189. package/dist/tools/git.js +34 -25
  190. package/dist/tools/git.js.map +1 -1
  191. package/dist/tools/media.cjs +280 -3
  192. package/dist/tools/media.cjs.map +1 -1
  193. package/dist/tools/media.d.cts +3 -1
  194. package/dist/tools/media.d.ts +3 -1
  195. package/dist/tools/media.js +278 -1
  196. package/dist/tools/media.js.map +1 -1
  197. package/dist/tools/plan.cjs +62 -0
  198. package/dist/tools/plan.cjs.map +1 -1
  199. package/dist/tools/plan.d.cts +4 -17
  200. package/dist/tools/plan.d.ts +4 -17
  201. package/dist/tools/plan.js +59 -0
  202. package/dist/tools/plan.js.map +1 -1
  203. package/dist/tools/search.cjs +3 -0
  204. package/dist/tools/search.cjs.map +1 -1
  205. package/dist/tools/search.d.cts +3 -1
  206. package/dist/tools/search.d.ts +3 -1
  207. package/dist/tools/search.js +3 -0
  208. package/dist/tools/search.js.map +1 -1
  209. package/dist/tools/shell.cjs +76 -11
  210. package/dist/tools/shell.cjs.map +1 -1
  211. package/dist/tools/shell.d.cts +5 -39
  212. package/dist/tools/shell.d.ts +5 -39
  213. package/dist/tools/shell.js +75 -11
  214. package/dist/tools/shell.js.map +1 -1
  215. package/dist/tools/todo.d.cts +3 -1
  216. package/dist/tools/todo.d.ts +3 -1
  217. package/dist/tools/web.cjs +279 -5
  218. package/dist/tools/web.cjs.map +1 -1
  219. package/dist/tools/web.d.cts +3 -1
  220. package/dist/tools/web.d.ts +3 -1
  221. package/dist/tools/web.js +275 -3
  222. package/dist/tools/web.js.map +1 -1
  223. package/dist/types-BYyXWWPW.d.cts +237 -0
  224. package/dist/types-BYyXWWPW.d.ts +237 -0
  225. package/package.json +26 -37
  226. package/bin/zqagent +0 -2
  227. package/dist/cli/index.cjs +0 -25218
  228. package/dist/cli/index.cjs.map +0 -1
  229. package/dist/cli/index.d.cts +0 -2
  230. package/dist/cli/index.d.ts +0 -2
  231. package/dist/cli/index.js +0 -25201
  232. package/dist/cli/index.js.map +0 -1
  233. package/dist/server/index.cjs +0 -20510
  234. package/dist/server/index.cjs.map +0 -1
  235. package/dist/server/index.d.cts +0 -2
  236. package/dist/server/index.d.ts +0 -2
  237. package/dist/server/index.js +0 -20493
  238. package/dist/server/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/mcp/builtin/index.ts","../../../../src/mcp/builtin/ocr.ts","../../../../src/mcp/builtin/ocrEngine.ts","../../../../src/tools/shellRuntime.ts"],"sourcesContent":["/**\n * 内置 MCP 服务器注册表与进程内传输\n *\n * 内置服务器通过 InMemoryTransport 与客户端通信:无需子进程、跨平台、\n * 对 SEA 单文件打包友好。新增内置能力时只需在此登记工厂。\n */\n\nimport type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { InMemoryTransport } from \"@modelcontextprotocol/sdk/inMemory.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { McpServerConfig } from \"../McpClient.js\";\nimport { createOcrServer } from \"./ocr.js\";\nimport type { McpBuiltinContext } from \"./types.js\";\n\nexport type BuiltinMcpFactory = (ctx: McpBuiltinContext) => Server;\n\nconst FACTORIES: Record<string, BuiltinMcpFactory> = {\n ocr: createOcrServer,\n};\n\n/** 已注册的内置服务器标识 */\nexport function listBuiltinServers(): string[] {\n return Object.keys(FACTORIES);\n}\n\n/**\n * 创建内置服务器的客户端侧传输(已建立连接)。\n * 服务端实例与客户端共享进程,随传输关闭而释放。\n */\nexport async function createBuiltinTransport(\n config: McpServerConfig,\n ctx: McpBuiltinContext,\n): Promise<Transport> {\n const id = config.builtin ?? config.name;\n const factory = FACTORIES[id];\n if (!factory) {\n throw new Error(\n `未知的内置 MCP server \"${id}\"(可用: ${listBuiltinServers().join(\", \")})`,\n );\n }\n const [clientTransport, serverTransport] =\n InMemoryTransport.createLinkedPair();\n const server = factory(ctx);\n await server.connect(serverTransport);\n return clientTransport;\n}\n\nexport type { McpBuiltinContext } from \"./types.js\";\n","/**\n * 内置 OCR MCP 服务器\n *\n * 以标准 MCP server 形式暴露 recognize 工具,经 InMemoryTransport 与\n * McpClient 通信,因此与外部 MCP 服务器共享同一套注入/审批/懒加载逻辑。\n * 工具名固定为 recognize,配合默认 server 名 ocr 得到 `mcp__ocr__recognize`。\n */\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { recognizeOcr, type OcrInput } from \"./ocrEngine.js\";\nimport type { McpBuiltinContext } from \"./types.js\";\n\nconst TOOL_NAME = \"recognize\";\n\nconst TOOL_DESCRIPTION = [\n \"从图片、扫描件或 PDF 中提取文字(OCR)。\",\n \"优先传 imagePath(工作区内的文件路径),也支持 imageBase64(可带 data URL 前缀)或 imageUrl。\",\n \"传入 PDF 会逐页识别(maxPages 默认 5,dpi 默认 150)。\",\n \"识别引擎自动选择:macOS Vision / tesseract+pdftoppm / 已配置的多模态模型。\",\n].join(\"\\n\");\n\nconst INPUT_SCHEMA = {\n type: \"object\",\n properties: {\n imagePath: {\n type: \"string\",\n description: \"本地图片或 PDF 路径(相对路径按工作区解析)\",\n },\n imageBase64: {\n type: \"string\",\n description: \"图片的 base64 编码(可带 data URL 前缀)\",\n },\n imageUrl: {\n type: \"string\",\n description: \"远程图片或 PDF 的 URL\",\n },\n maxPages: {\n type: \"number\",\n description: \"PDF 最多识别页数(默认 5,上限 50)\",\n },\n dpi: {\n type: \"number\",\n description: \"PDF 渲染 DPI(默认 150,上限 400)\",\n },\n lang: {\n type: \"string\",\n description: \"tesseract 语言包(默认 chi_sim+eng)\",\n },\n },\n} as const;\n\n/** 创建内置 OCR MCP 服务器 */\nexport function createOcrServer(ctx: McpBuiltinContext = {}): Server {\n const server = new Server(\n { name: \"zqagent-ocr\", version: \"0.1.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: TOOL_NAME,\n description: TOOL_DESCRIPTION,\n inputSchema: INPUT_SCHEMA,\n },\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n if (request.params.name !== TOOL_NAME) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: `未知工具 \"${request.params.name}\",可用工具:${TOOL_NAME}`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const args = (request.params.arguments ?? {}) as OcrInput;\n const result = await recognizeOcr(args, ctx);\n if (!result.ok) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n error: result.error,\n how_to_fix: result.how_to_fix,\n attempts: result.attempts,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n return {\n content: [{ type: \"text\", text: result.text }],\n };\n });\n\n return server;\n}\n","/**\n * 内置 OCR 引擎\n *\n * 识别后端按优先级降级(本机引擎优先,多模态模型兜底):\n * 1. macOS Vision(Swift + PDFKit,免安装,支持 PDF 逐页)\n * 2. tesseract + pdftoppm(Linux/Windows 或非 macOS 环境)\n * 3. 已配置的多模态 LLM(OpenAI 兼容接口,图片走 data URL)\n * 4. 全部不可用 → 返回 error + how_to_fix(不抛异常,模型可读)\n *\n * 所有外部依赖均可通过 OcrRuntimeOverrides 注入,便于单测。\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { execFile } from \"node:child_process\";\nimport OpenAI from \"openai\";\nimport { findExecutable } from \"../../tools/shellRuntime.js\";\nimport type {\n McpBuiltinContext,\n OcrLlmConfig,\n OcrRuntimeOverrides,\n} from \"./types.js\";\n\n/** OCR 输入参数(MCP 工具 recognize 的入参) */\nexport interface OcrInput {\n /** 本地图片/PDF 路径(相对路径按工作区解析) */\n imagePath?: string;\n /** base64(可带 data URL 前缀) */\n imageBase64?: string;\n /** 远程图片/PDF URL */\n imageUrl?: string;\n /** PDF 最多处理页数(默认 5,上限 50) */\n maxPages?: number;\n /** PDF 渲染 DPI(默认 150,上限 400) */\n dpi?: number;\n /** Tesseract 语言(默认 chi_sim+eng) */\n lang?: string;\n}\n\nexport type OcrEngineName = \"vision\" | \"tesseract\" | \"llm\";\n\nexport interface OcrPage {\n page: number;\n text: string;\n}\n\nexport type OcrResult =\n | {\n ok: true;\n text: string;\n engine: OcrEngineName;\n pages: OcrPage[];\n }\n | {\n ok: false;\n error: string;\n how_to_fix: string;\n attempts: { engine: string; error: string }[];\n };\n\nconst DEFAULT_MAX_PAGES = 5;\nconst MAX_MAX_PAGES = 50;\nconst DEFAULT_DPI = 150;\nconst MAX_DPI = 400;\nconst CMD_TIMEOUT_MS = 120_000;\nconst COMPILE_TIMEOUT_MS = 180_000;\nconst MAX_BUFFER = 32 * 1024 * 1024;\n\n/** Vision 引擎 Swift 源码(首次使用时编译并缓存到 .agent/bin) */\nconst VISION_SOURCE = `import Foundation\nimport Vision\nimport AppKit\nimport PDFKit\nimport CoreGraphics\n\nstruct PageResult: Codable { let page: Int; let text: String }\nstruct Output: Codable { let pages: [PageResult] }\n\nfunc recognize(_ image: CGImage) -> String {\n func run(_ langs: [String]?) throws -> [VNRecognizedTextObservation] {\n let request = VNRecognizeTextRequest()\n request.recognitionLevel = .accurate\n request.usesLanguageCorrection = true\n if let langs = langs { request.recognitionLanguages = langs }\n let handler = VNImageRequestHandler(cgImage: image, options: [:])\n try handler.perform([request])\n return request.results ?? []\n }\n let observations = (try? run([\"zh-Hans\", \"zh-Hant\", \"en-US\"])) ?? (try? run(nil)) ?? []\n let lines = observations.compactMap { $0.topCandidates(1).first?.string }\n return lines.joined(separator: \"\\\\n\")\n}\n\nfunc imageFromFile(_ p: String) -> CGImage? {\n guard let src = CGImageSourceCreateWithURL(URL(fileURLWithPath: p) as CFURL, nil) else { return nil }\n return CGImageSourceCreateImageAtIndex(src, 0, nil)\n}\n\nlet args = CommandLine.arguments\nguard args.count >= 2 else {\n FileHandle.standardError.write(\"usage: ocr-vision <file> [maxPages] [dpi]\\\\n\".data(using: .utf8)!)\n exit(2)\n}\nlet file = args[1]\nlet maxPages = args.count > 2 ? (Int(args[2]) ?? 5) : 5\nlet dpi = args.count > 3 ? (Int(args[3]) ?? 150) : 150\n\nvar pages: [PageResult] = []\nif file.lowercased().hasSuffix(\".pdf\"), let doc = PDFDocument(url: URL(fileURLWithPath: file)) {\n let count = min(doc.pageCount, max(1, maxPages))\n let scale = CGFloat(dpi) / 72.0\n for i in 0..<count {\n guard let page = doc.page(at: i) else { continue }\n let bounds = page.bounds(for: .mediaBox)\n let w = Int(bounds.width * scale)\n let h = Int(bounds.height * scale)\n guard w > 0, h > 0 else { continue }\n guard let ctx = CGContext(\n data: nil, width: w, height: h, bitsPerComponent: 8, bytesPerRow: 0,\n space: CGColorSpaceCreateDeviceRGB(),\n bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue\n ) else { continue }\n ctx.setFillColor(CGColor(red: 1, green: 1, blue: 1, alpha: 1))\n ctx.fill(CGRect(x: 0, y: 0, width: w, height: h))\n ctx.scaleBy(x: scale, y: scale)\n page.draw(with: .mediaBox, to: ctx)\n guard let image = ctx.makeImage() else { continue }\n pages.append(PageResult(page: i + 1, text: recognize(image)))\n }\n} else if let image = imageFromFile(file) {\n pages.append(PageResult(page: 1, text: recognize(image)))\n} else {\n FileHandle.standardError.write(\"unsupported or unreadable image: \\\\(file)\\\\n\".data(using: .utf8)!)\n exit(3)\n}\n\nlet encoder = JSONEncoder()\nencoder.outputFormatting = [.withoutEscapingSlashes]\nif let data = try? encoder.encode(Output(pages: pages)) {\n FileHandle.standardOutput.write(data)\n} else {\n exit(4)\n}\n`;\n\n/** 默认命令执行器 */\nfunction defaultRun(\n command: string,\n args: string[],\n opts: { timeoutMs?: number; cwd?: string } = {},\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n execFile(\n command,\n args,\n {\n timeout: opts.timeoutMs ?? CMD_TIMEOUT_MS,\n cwd: opts.cwd,\n maxBuffer: MAX_BUFFER,\n encoding: \"utf8\",\n },\n (err, stdout, stderr) => {\n if (err) {\n const e = err as Error;\n e.message = `${path.basename(command)} 执行失败: ${e.message}${\n stderr ? `\\n${stderr.trim()}` : \"\"\n }`;\n reject(e);\n } else {\n resolve({ stdout, stderr });\n }\n },\n );\n });\n}\n\ninterface Runtime {\n platform: NodeJS.Platform;\n env: NodeJS.ProcessEnv;\n workspace: string;\n llm?: OcrLlmConfig;\n overrides: OcrRuntimeOverrides;\n which(name: string): string | null;\n run(\n command: string,\n args: string[],\n opts?: { timeoutMs?: number; cwd?: string },\n ): Promise<{ stdout: string; stderr: string }>;\n fileExists(p: string): boolean;\n}\n\nfunction makeRuntime(ctx: McpBuiltinContext): Runtime {\n const overrides = ctx.ocr ?? {};\n const platform = overrides.platform ?? process.platform;\n const env = overrides.env ?? ctx.env ?? process.env;\n const workspace = ctx.workspace ?? env.WORKSPACE ?? process.cwd();\n const fileExists =\n overrides.fileExists ??\n ((p: string): boolean => {\n try {\n return fs.statSync(p).isFile();\n } catch {\n return false;\n }\n });\n const which =\n overrides.which ??\n ((name: string): string | null =>\n findExecutable(name, { platform, env, fileExists }));\n return {\n platform,\n env,\n workspace,\n llm: ctx.llm,\n overrides,\n which,\n run: overrides.run ?? defaultRun,\n fileExists,\n };\n}\n\nfunction clampInt(\n value: unknown,\n fallback: number,\n min: number,\n max: number,\n): number {\n const n = typeof value === \"number\" ? value : Number(value);\n if (!Number.isFinite(n)) return fallback;\n return Math.min(max, Math.max(min, Math.trunc(n)));\n}\n\nfunction isPdfFile(file: string): boolean {\n if (file.toLowerCase().endsWith(\".pdf\")) return true;\n try {\n const fd = fs.openSync(file, \"r\");\n try {\n const buf = Buffer.alloc(5);\n const read = fs.readSync(fd, buf, 0, 5, 0);\n return read >= 5 && buf.toString(\"latin1\") === \"%PDF-\";\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n return false;\n }\n}\n\nfunction detectMime(file: string): string {\n try {\n const fd = fs.openSync(file, \"r\");\n try {\n const buf = Buffer.alloc(12);\n fs.readSync(fd, buf, 0, 12, 0);\n if (buf[0] === 0x89 && buf[1] === 0x50) return \"image/png\";\n if (buf[0] === 0xff && buf[1] === 0xd8) return \"image/jpeg\";\n if (buf.toString(\"latin1\", 0, 4) === \"RIFF\") return \"image/webp\";\n if (buf.toString(\"latin1\", 0, 4) === \"GIF8\") return \"image/gif\";\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n // 忽略:按扩展名兜底\n }\n const ext = path.extname(file).toLowerCase();\n if (ext === \".jpg\" || ext === \".jpeg\") return \"image/jpeg\";\n if (ext === \".webp\") return \"image/webp\";\n if (ext === \".gif\") return \"image/gif\";\n return \"image/png\";\n}\n\nfunction toDataUrl(file: string): string {\n return `data:${detectMime(file)};base64,${fs.readFileSync(file).toString(\"base64\")}`;\n}\n\nfunction dataUrlToBuffer(value: string): { buffer: Buffer; ext: string } {\n const m = /^data:([^;,]+);base64,([\\s\\S]*)$/.exec(value.trim());\n const mime = m?.[1] ?? \"image/png\";\n const b64 = m?.[2] ?? value.trim();\n const ext =\n mime === \"image/jpeg\"\n ? \".jpg\"\n : mime === \"image/webp\"\n ? \".webp\"\n : mime === \"image/gif\"\n ? \".gif\"\n : mime === \"application/pdf\"\n ? \".pdf\"\n : \".png\";\n return { buffer: Buffer.from(b64, \"base64\"), ext };\n}\n\nfunction naturalCompare(a: string, b: string): number {\n return a.localeCompare(b, undefined, { numeric: true });\n}\n\n/** 把图片 URL 下载到临时文件 */\nasync function downloadToFile(\n url: string,\n dest: string,\n runtime: Runtime,\n): Promise<void> {\n const fetchImpl =\n runtime.overrides.fetchImpl ??\n (globalThis.fetch as unknown as OcrRuntimeOverrides[\"fetchImpl\"]);\n if (!fetchImpl) throw new Error(\"当前运行时不支持 fetch,无法下载 imageUrl\");\n const res = await fetchImpl(url);\n if (!res.ok) throw new Error(`下载图片失败:HTTP ${res.status}`);\n fs.writeFileSync(dest, Buffer.from(await res.arrayBuffer()));\n}\n\ninterface MaterializedInput {\n file: string;\n isPdf: boolean;\n tmpDir: string;\n cleanup(): void;\n}\n\n/** 把三种输入形式统一落成临时文件 */\nasync function materializeInput(\n input: OcrInput,\n runtime: Runtime,\n): Promise<MaterializedInput> {\n const root = runtime.overrides.tmpDir ?? os.tmpdir();\n const tmpDir = fs.mkdtempSync(path.join(root, \"zqagent-ocr-\"));\n const cleanup = (): void => {\n try {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n // 忽略清理失败\n }\n };\n try {\n if (typeof input.imagePath === \"string\" && input.imagePath.trim()) {\n const file = path.isAbsolute(input.imagePath)\n ? input.imagePath\n : path.resolve(runtime.workspace, input.imagePath);\n if (!runtime.fileExists(file) && !fs.existsSync(file))\n throw new Error(`图片不存在:${file}`);\n return { file, isPdf: isPdfFile(file), tmpDir, cleanup };\n }\n if (typeof input.imageBase64 === \"string\" && input.imageBase64.trim()) {\n const { buffer, ext } = dataUrlToBuffer(input.imageBase64);\n const file = path.join(tmpDir, `input${ext}`);\n fs.writeFileSync(file, buffer);\n return { file, isPdf: isPdfFile(file), tmpDir, cleanup };\n }\n if (typeof input.imageUrl === \"string\" && input.imageUrl.trim()) {\n const url = input.imageUrl.trim();\n const ext = path.extname(new URL(url).pathname).toLowerCase() || \".png\";\n const file = path.join(tmpDir, `input${ext}`);\n await downloadToFile(url, file, runtime);\n return { file, isPdf: isPdfFile(file), tmpDir, cleanup };\n }\n throw new Error(\"缺少输入:请提供 imagePath / imageBase64 / imageUrl 之一\");\n } catch (err) {\n cleanup();\n throw err;\n }\n}\n\n/** PDF 转 PNG(依赖 poppler 的 pdftoppm) */\nasync function pdfToImages(\n file: string,\n tmpDir: string,\n input: OcrInput,\n runtime: Runtime,\n): Promise<string[]> {\n const pdftoppm = runtime.which(\"pdftoppm\");\n if (!pdftoppm) {\n throw new Error(\n \"PDF 需要 poppler 的 pdftoppm(macOS 可使用内置 Vision 引擎,无需该依赖)\",\n );\n }\n const pagesDir = path.join(tmpDir, \"pages\");\n fs.mkdirSync(pagesDir, { recursive: true });\n const maxPages = clampInt(\n input.maxPages,\n DEFAULT_MAX_PAGES,\n 1,\n MAX_MAX_PAGES,\n );\n const dpi = clampInt(input.dpi, DEFAULT_DPI, 36, MAX_DPI);\n await runtime.run(\n pdftoppm,\n [\n \"-r\",\n String(dpi),\n \"-png\",\n \"-f\",\n \"1\",\n \"-l\",\n String(maxPages),\n file,\n path.join(pagesDir, \"page\"),\n ],\n { timeoutMs: CMD_TIMEOUT_MS },\n );\n const images = fs\n .readdirSync(pagesDir)\n .filter((f) => /^page.*\\.png$/i.test(f))\n .sort(naturalCompare)\n .map((f) => path.join(pagesDir, f));\n if (images.length === 0) throw new Error(\"PDF 转图片失败(未生成页面)\");\n return images;\n}\n\ninterface VisionBuild {\n binary: string | null;\n error?: string;\n}\n\n// Vision 编译任务按 workspace 缓存:并发 OCR 只编译一次,\n// 失败结果同样缓存,避免长驻进程内每次 OCR 都重复等待编译。\nconst visionBuilds = new Map<string, Promise<VisionBuild>>();\n\n/** 从编译器输出中提取一行可读错误(避免把整页 modulemap 灌给模型) */\nfunction conciseError(err: Error): string {\n const lines = err.message\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => /error:|fatal error:/i.test(l));\n const pick = lines.length > 0 ? lines[lines.length - 1]! : err.message;\n return pick.slice(0, 500);\n}\n\n/** 确保 Vision 二进制已编译;不可用时返回原因 */\nasync function ensureVisionBinary(runtime: Runtime): Promise<VisionBuild> {\n if (runtime.platform !== \"darwin\")\n return { binary: null, error: \"仅 macOS 可用\" };\n const swiftc = runtime.which(\"swiftc\");\n if (!swiftc)\n return {\n binary: null,\n error: \"未找到 swiftc(需要 Xcode Command Line Tools)\",\n };\n\n const dir = path.join(runtime.workspace, \".agent\", \"bin\");\n const srcPath = path.join(dir, \"ocr-vision.swift\");\n const binPath = path.join(dir, \"ocr-vision\");\n const cacheKey = binPath;\n const cached = visionBuilds.get(cacheKey);\n if (cached) return cached;\n\n const build = (async (): Promise<VisionBuild> => {\n try {\n fs.mkdirSync(dir, { recursive: true });\n let changed = true;\n try {\n changed = fs.readFileSync(srcPath, \"utf8\") !== VISION_SOURCE;\n } catch {\n changed = true;\n }\n if (changed) fs.writeFileSync(srcPath, VISION_SOURCE, \"utf8\");\n if (changed || !runtime.fileExists(binPath)) {\n await runtime.run(swiftc, [\"-O\", \"-o\", binPath, srcPath], {\n timeoutMs: COMPILE_TIMEOUT_MS,\n });\n }\n return runtime.fileExists(binPath)\n ? { binary: binPath }\n : { binary: null, error: \"Vision 编译未生成可执行文件\" };\n } catch (err) {\n // 编译失败(如 CLT 与 SDK 版本不匹配):降级到其它引擎\n return { binary: null, error: `Vision 编译失败: ${conciseError(err as Error)}` };\n }\n })();\n visionBuilds.set(cacheKey, build);\n return build;\n}\n\nasync function runVision(\n binary: string,\n file: string,\n input: OcrInput,\n runtime: Runtime,\n): Promise<OcrPage[]> {\n const maxPages = clampInt(\n input.maxPages,\n DEFAULT_MAX_PAGES,\n 1,\n MAX_MAX_PAGES,\n );\n const dpi = clampInt(input.dpi, DEFAULT_DPI, 36, MAX_DPI);\n const { stdout } = await runtime.run(\n binary,\n [file, String(maxPages), String(dpi)],\n { timeoutMs: CMD_TIMEOUT_MS },\n );\n const parsed = JSON.parse(stdout) as { pages?: OcrPage[] };\n const pages = Array.isArray(parsed.pages) ? parsed.pages : [];\n if (pages.length === 0) throw new Error(\"Vision 未返回识别结果\");\n return pages.map((p) => ({\n page: Number(p.page) || 1,\n text: typeof p.text === \"string\" ? p.text : \"\",\n }));\n}\n\nasync function runTesseract(\n file: string,\n isPdf: boolean,\n input: OcrInput,\n runtime: Runtime,\n tmpDir: string,\n): Promise<OcrPage[]> {\n const tesseract = runtime.which(\"tesseract\");\n if (!tesseract) throw new Error(\"未找到 tesseract\");\n const lang = input.lang ?? runtime.env.OCR_LANG ?? \"chi_sim+eng\";\n const images = isPdf\n ? await pdfToImages(file, tmpDir, input, runtime)\n : [file];\n const pages: OcrPage[] = [];\n for (let i = 0; i < images.length; i += 1) {\n const { stdout } = await runtime.run(\n tesseract,\n [images[i]!, \"stdout\", \"-l\", lang, \"--psm\", \"3\"],\n { timeoutMs: CMD_TIMEOUT_MS },\n );\n pages.push({ page: i + 1, text: stdout.trim() });\n }\n return pages;\n}\n\nfunction resolveLlmConfig(runtime: Runtime): {\n apiKey: string;\n model: string;\n baseURL?: string;\n} | null {\n const llm = runtime.llm;\n const apiKey =\n llm?.apiKey ??\n runtime.env.OPENAI_API_KEY ??\n runtime.env.OCR_API_KEY ??\n \"\";\n const model =\n llm?.model ?? runtime.env.OCR_MODEL ?? runtime.env.OPENAI_MODEL ?? \"\";\n const baseURL =\n llm?.baseURL ?? runtime.env.OPENAI_BASE_URL ?? runtime.env.OCR_BASE_URL;\n if (!apiKey || !model) return null;\n return { apiKey, model, baseURL };\n}\n\nasync function defaultLlmComplete(req: {\n model: string;\n prompt: string;\n imageDataUrl: string;\n baseURL?: string;\n apiKey?: string;\n}): Promise<string> {\n const client = new OpenAI({\n apiKey: req.apiKey ?? \"\",\n ...(req.baseURL ? { baseURL: req.baseURL } : {}),\n });\n const res = await client.chat.completions.create({\n model: req.model,\n messages: [\n {\n role: \"user\",\n content: [\n { type: \"text\", text: req.prompt },\n { type: \"image_url\", image_url: { url: req.imageDataUrl } },\n ],\n },\n ],\n });\n return res.choices?.[0]?.message?.content ?? \"\";\n}\n\nasync function runLlm(\n file: string,\n isPdf: boolean,\n input: OcrInput,\n runtime: Runtime,\n tmpDir: string,\n): Promise<OcrPage[]> {\n const cfg = resolveLlmConfig(runtime);\n if (!cfg) {\n throw new Error(\"未配置多模态模型(缺少 API key 或 model)\");\n }\n const images = isPdf\n ? await pdfToImages(file, tmpDir, input, runtime)\n : [file];\n const prompt =\n \"请逐字提取这张图片中的全部文字,保持原有换行与顺序。只输出文字,不要解释。\";\n const complete = runtime.overrides.llmComplete ?? defaultLlmComplete;\n const pages: OcrPage[] = [];\n for (let i = 0; i < images.length; i += 1) {\n const text = await complete({\n model: cfg.model,\n prompt,\n imageDataUrl: toDataUrl(images[i]!),\n baseURL: cfg.baseURL,\n apiKey: cfg.apiKey,\n });\n pages.push({ page: i + 1, text: text.trim() });\n }\n return pages;\n}\n\nfunction joinPages(pages: OcrPage[]): string {\n if (pages.length === 1) return pages[0]!.text;\n return pages\n .map((p) => `--- page ${p.page} ---\\n${p.text}`)\n .join(\"\\n\\n\");\n}\n\nfunction howToFix(platform: NodeJS.Platform): string {\n if (platform === \"darwin\")\n return [\n \"macOS 可任选其一:\",\n \"1) 安装 Xcode Command Line Tools 以启用内置 Vision:xcode-select --install\",\n \"2) 安装 tesseract 与 poppler:brew install tesseract tesseract-lang poppler\",\n \"3) 用 /connect 配置支持图片输入的多模态模型后重试\",\n ].join(\"\\n\");\n if (platform === \"win32\")\n return [\n \"Windows 可任选其一:\",\n \"1) 安装 tesseract:winget install UB-Mannheim.TesseractOCR\",\n \"2) 安装 poppler(PDF 需要)并加入 PATH\",\n \"3) 用 /connect 配置支持图片输入的多模态模型后重试\",\n ].join(\"\\n\");\n return [\n \"Linux 可任选其一:\",\n \"1) apt-get install -y tesseract-ocr tesseract-ocr-chi-sim poppler-utils\",\n \"2) 用 /connect 配置支持图片输入的多模态模型后重试\",\n ].join(\"\\n\");\n}\n\n/** 引擎探测顺序(OCR_ENGINE 可强制指定) */\nfunction engineOrder(runtime: Runtime): OcrEngineName[] {\n const forced = (runtime.env.OCR_ENGINE ?? \"\").toLowerCase();\n if (forced === \"vision\" || forced === \"tesseract\" || forced === \"llm\")\n return [forced];\n return [\"vision\", \"tesseract\", \"llm\"];\n}\n\n/**\n * 识别图片或 PDF。\n * 不抛异常:失败时返回 { ok:false, error, how_to_fix, attempts }。\n */\nexport async function recognizeOcr(\n input: OcrInput,\n ctx: McpBuiltinContext = {},\n): Promise<OcrResult> {\n const runtime = makeRuntime(ctx);\n let materialized: MaterializedInput;\n try {\n materialized = await materializeInput(input, runtime);\n } catch (err) {\n return {\n ok: false,\n error: (err as Error).message,\n how_to_fix: howToFix(runtime.platform),\n attempts: [],\n };\n }\n\n const attempts: { engine: string; error: string }[] = [];\n try {\n for (const engine of engineOrder(runtime)) {\n try {\n let pages: OcrPage[];\n if (engine === \"vision\") {\n const build = await ensureVisionBinary(runtime);\n if (!build.binary) {\n attempts.push({ engine, error: build.error ?? \"不可用\" });\n continue;\n }\n pages = await runVision(\n build.binary,\n materialized.file,\n input,\n runtime,\n );\n } else if (engine === \"tesseract\") {\n pages = await runTesseract(\n materialized.file,\n materialized.isPdf,\n input,\n runtime,\n materialized.tmpDir,\n );\n } else {\n pages = await runLlm(\n materialized.file,\n materialized.isPdf,\n input,\n runtime,\n materialized.tmpDir,\n );\n }\n if (pages.length === 0) throw new Error(\"未识别到任何页面\");\n return {\n ok: true,\n text: joinPages(pages),\n engine,\n pages,\n };\n } catch (err) {\n attempts.push({ engine, error: (err as Error).message });\n }\n }\n return {\n ok: false,\n error:\n attempts.length > 0\n ? `没有可用的 OCR 引擎: ${attempts\n .map((a) => `${a.engine}: ${a.error}`)\n .join(\"; \")}`\n : \"没有可用的 OCR 引擎\",\n how_to_fix: howToFix(runtime.platform),\n attempts,\n };\n } finally {\n materialized.cleanup();\n }\n}\n","/**\n * shell 运行时探测\n *\n * 决定 run_shell 用哪个 shell 执行命令,解决三件事:\n * - POSIX:沿用 Node 默认 /bin/sh,不改变既有语义;\n * - Windows:cmd.exe 没有 ls/grep/rm/cat,优先挑一个 POSIX 风格的 shell\n * (BusyBox-w32 / Git Bash / PowerShell),都没有时才回退到 %ComSpec%;\n * - 允许用 ZQAGENT_SHELL / ZQAGENT_BUSYBOX 显式覆盖,便于在装了非常规\n * shell(如内网自带的 busybox)的机器上接入。\n *\n * 本模块只做解析,不执行命令;platform / env / 文件探测均可注入,\n * 便于在 CI(Linux)上覆盖 Windows 分支。\n */\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n/** shell 家族,决定命令行参数怎么拼 */\nexport type ShellKind = \"sh\" | \"busybox\" | \"powershell\" | \"cmd\" | \"default\";\n\nexport interface ShellSpec {\n kind: ShellKind;\n /** 人类可读标签,用于工具描述 */\n label: string;\n /** 可执行文件路径;null 表示交给 Node 默认(POSIX /bin/sh 或 %ComSpec%) */\n file: string | null;\n /** 拼出实际 argv(含命令本身) */\n buildArgs: (command: string) => string[];\n}\n\nexport interface ResolveShellOptions {\n platform?: NodeJS.Platform;\n env?: NodeJS.ProcessEnv;\n /** 判断文件是否存在,便于测试注入 */\n fileExists?: (p: string) => boolean;\n /** 用于定位「产物同目录」的 busybox,默认 process.execPath */\n execPath?: string;\n}\n\nexport interface ProbeContext {\n platform: NodeJS.Platform;\n env: NodeJS.ProcessEnv;\n fileExists: (p: string) => boolean;\n}\n\n/** Windows 可执行文件后缀(按优先级) */\nconst WINDOWS_SUFFIXES = [\".exe\", \".cmd\", \".bat\", \".com\", \"\"];\n\nfunction pathApi(platform: NodeJS.Platform) {\n return platform === \"win32\" ? path.win32 : path.posix;\n}\n\nfunction defaultFileExists(p: string): boolean {\n try {\n return fs.statSync(p).isFile();\n } catch {\n return false;\n }\n}\n\n/** 按目标平台(而非宿主)拼路径 */\nfunction joinPath(platform: NodeJS.Platform, ...parts: string[]): string {\n return pathApi(platform).join(...parts);\n}\n\n/**\n * 在 PATH 上查找可执行文件(同步,不 spawn 进程)。\n * name 含路径分隔符时按路径直接判定。Windows 会按 WINDOWS_SUFFIXES 补后缀。\n */\nexport function findExecutable(name: string, ctx: ProbeContext): string | null {\n if (name.includes(\"/\") || name.includes(\"\\\\\")) {\n return ctx.fileExists(name) ? name : null;\n }\n const suffixes = ctx.platform === \"win32\" ? WINDOWS_SUFFIXES : [\"\"];\n const delimiter = ctx.platform === \"win32\" ? \";\" : \":\";\n const dirs = (ctx.env.PATH ?? \"\").split(delimiter).filter((d) => d.length > 0);\n for (const dir of dirs) {\n for (const suffix of suffixes) {\n const candidate = joinPath(ctx.platform, dir, name + suffix);\n if (ctx.fileExists(candidate)) return candidate;\n }\n }\n return null;\n}\n\n/** 按文件名推断 shell 家族 */\nfunction kindFromBasename(base: string): ShellKind {\n const b = base.toLowerCase().replace(/\\.(exe|cmd|bat|com)$/, \"\");\n if (b === \"busybox\") return \"busybox\";\n if (b === \"powershell\" || b === \"pwsh\") return \"powershell\";\n if (b === \"cmd\") return \"cmd\";\n // sh/bash/dash/zsh/ash 以及不认识的名字(如 busybox 的 sh.exe 符号链接)都按 sh 处理\n return \"sh\";\n}\n\n/**\n * busybox 按 argv[0] 决定 applet:`busybox.exe` 需要显式给 applet 名\n * (`busybox.exe sh -c \"...\"`),而重命名/硬链接出来的 `sh.exe` 本身就是 ash,\n * 多传一个 \"sh\" 会被当成脚本文件名。\n */\nfunction busyboxArgs(file: string | null, command: string): string[] {\n const base = (file ? path.win32.basename(file) : \"busybox\")\n .toLowerCase()\n .replace(/\\.(exe|cmd|bat|com)$/, \"\");\n return base === \"busybox\" ? [\"sh\", \"-c\", command] : [\"-c\", command];\n}\n\nfunction argsFor(kind: ShellKind, command: string): string[] {\n switch (kind) {\n case \"busybox\":\n return [\"sh\", \"-c\", command];\n case \"powershell\":\n return [\"-NoProfile\", \"-NonInteractive\", \"-Command\", command];\n case \"cmd\":\n return [\"/d\", \"/s\", \"/c\", command];\n default:\n return [\"-c\", command];\n }\n}\n\nfunction makeSpec(kind: ShellKind, file: string | null, label: string): ShellSpec {\n return {\n kind,\n file,\n label,\n buildArgs: (command) =>\n kind === \"busybox\" ? busyboxArgs(file, command) : argsFor(kind, command),\n };\n}\n\nfunction defaultLabelFor(kind: ShellKind): string {\n switch (kind) {\n case \"busybox\":\n return \"busybox ash\";\n case \"powershell\":\n return \"PowerShell\";\n case \"cmd\":\n return \"cmd.exe\";\n case \"default\":\n return \"系统默认 shell\";\n default:\n return \"sh\";\n }\n}\n\n/**\n * 查找 BusyBox-w32。\n * 显式 ZQAGENT_BUSYBOX 优先;否则看 CLI 产物同目录及其 bin/ 子目录\n * (兼容 SEA 单文件、npm 安装与桌面 sidecar 三种布局,其中 sh.exe 是\n * busybox.exe 的重命名副本 —— busybox 按 argv[0] 决定 applet)。\n */\nfunction findBusybox(\n ctx: ProbeContext,\n execPath: string,\n): string | null {\n const explicit = (ctx.env.ZQAGENT_BUSYBOX ?? \"\").trim();\n if (explicit) return ctx.fileExists(explicit) ? explicit : null;\n\n const exeDir = pathApi(ctx.platform).dirname(execPath);\n const candidates = [\n joinPath(ctx.platform, exeDir, \"busybox.exe\"),\n joinPath(ctx.platform, exeDir, \"sh.exe\"),\n joinPath(ctx.platform, exeDir, \"bin\", \"busybox.exe\"),\n joinPath(ctx.platform, exeDir, \"bin\", \"sh.exe\"),\n ];\n for (const candidate of candidates) {\n if (ctx.fileExists(candidate)) return candidate;\n }\n return null;\n}\n\n/** 解析 ZQAGENT_SHELL 的显式取值(关键字或路径) */\nfunction resolveRequested(requested: string, ctx: ProbeContext, execPath: string): ShellSpec {\n const lower = requested.toLowerCase();\n\n if (lower === \"cmd\") {\n const file =\n findExecutable(\"cmd\", ctx) ?? ctx.env.ComSpec ?? ctx.env.COMSPEC ?? \"cmd.exe\";\n return makeSpec(\"cmd\", file, \"cmd.exe\");\n }\n if (lower === \"powershell\" || lower === \"pwsh\") {\n const file =\n findExecutable(lower, ctx) ?? findExecutable(\"powershell\", ctx) ?? `${lower}.exe`;\n return makeSpec(\"powershell\", file, \"PowerShell\");\n }\n if (lower === \"busybox\") {\n const found = findBusybox(ctx, execPath) ?? findExecutable(\"busybox\", ctx);\n return makeSpec(\"busybox\", found ?? requested, \"busybox ash\");\n }\n if ([\"sh\", \"bash\", \"dash\", \"zsh\", \"ash\"].includes(lower)) {\n return makeSpec(\"sh\", findExecutable(lower, ctx) ?? lower, lower);\n }\n\n // 视为路径(可能含空格,如 C:\\Program Files\\Git\\bin\\bash.exe)\n const base = pathApi(ctx.platform).basename(requested);\n const kind = kindFromBasename(base);\n return makeSpec(kind, requested, base || defaultLabelFor(kind));\n}\n\n/**\n * 解析当前应使用的 shell。\n * 返回值 file === null 时表示「不显式指定」,由 Node 走平台默认 shell\n * (POSIX /bin/sh / Windows %ComSpec%),即改造前的行为。\n */\nexport function resolveShellSpec(opts: ResolveShellOptions = {}): ShellSpec {\n const platform = opts.platform ?? process.platform;\n const env = opts.env ?? process.env;\n const execPath = opts.execPath ?? process.execPath;\n const ctx: ProbeContext = {\n platform,\n env,\n fileExists: opts.fileExists ?? defaultFileExists,\n };\n\n const requested = (env.ZQAGENT_SHELL ?? \"\").trim();\n if (requested && requested.toLowerCase() !== \"auto\") {\n return resolveRequested(requested, ctx, execPath);\n }\n\n // 非 Windows:保持 Node 默认(不改变既有行为)\n if (platform !== \"win32\") {\n return makeSpec(\"default\", null, \"/bin/sh\");\n }\n\n // Windows:优先 POSIX 风格 shell —— cmd.exe 缺 ls/grep/rm/cat,模型产出的\n // POSIX 命令在它下面几乎全废。\n const busybox = findBusybox(ctx, execPath);\n if (busybox) return makeSpec(\"busybox\", busybox, \"busybox ash (POSIX)\");\n\n const bash = findExecutable(\"bash\", ctx);\n if (bash) return makeSpec(\"sh\", bash, \"bash (Git for Windows)\");\n\n // PowerShell 排在 cmd 之前:它有 ls/cat/rm/cp/mv/pwd 别名,更接近模型习惯\n const shell = findExecutable(\"pwsh\", ctx) ?? findExecutable(\"powershell\", ctx);\n if (shell) return makeSpec(\"powershell\", shell, \"PowerShell\");\n\n return makeSpec(\"default\", null, env.ComSpec ?? env.COMSPEC ?? \"cmd.exe\");\n}\n\n/**\n * 为命令套上「编码设置 + 退出码传播」外壳,按 shell 家族区分。\n *\n * - PowerShell:先设置控制台输出编码为 UTF-8(同一次调用内即对后续命令生效,\n * 规避 `chcp 65001` 要等下一次调用才生效的问题),命令结束后若存在\n * `$LASTEXITCODE` 就以它作为进程退出码 —— 否则 PowerShell 对 `cmd /c ...`\n * 这类原生命令一律返回 0,工具拿到的 exit_code 不可信。\n * - cmd.exe(含 Windows 下未探测到其它 shell 时的 default):`chcp 65001` 切换\n * 代码页,避免中文被压成 `?`。\n * - POSIX sh / busybox:现代环境默认 UTF-8,不改动。\n */\nexport function wrapCommand(\n kind: ShellKind,\n command: string,\n platform: NodeJS.Platform = process.platform,\n): string {\n if (kind === \"powershell\") {\n return (\n \"$OutputEncoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8; \" +\n command +\n \"\\nif ($null -ne $LASTEXITCODE) { exit $LASTEXITCODE }\"\n );\n }\n if (kind === \"cmd\" || (kind === \"default\" && platform === \"win32\")) {\n return `chcp 65001>nul & ${command}`;\n }\n return command;\n}\n\n/** 生成给模型的运行环境提示,追加到 run_shell 描述里 */\nexport function describeShell(spec: ShellSpec, platform: NodeJS.Platform): string {\n if (spec.kind === \"sh\" || spec.kind === \"busybox\") {\n return `当前平台 ${platform},shell=${spec.label}:请使用 POSIX 风格命令。`;\n }\n if (spec.kind === \"powershell\") {\n return (\n `当前平台 ${platform},shell=PowerShell:ls/cat/rm/cp/mv/pwd 等别名可用,` +\n `也可用 cmdlet;路径分隔符为 \"\\\\\"。`\n );\n }\n if (spec.kind === \"default\" && platform !== \"win32\") {\n return `当前平台 ${platform},shell=${spec.label}:请使用 POSIX 风格命令。`;\n }\n return (\n `当前平台 ${platform},shell=${spec.label}:请使用 Windows 命令` +\n `(dir/type/del/copy/move/findstr),多条命令用 & 或 && 连接;` +\n `不要使用 ls/cat/rm/grep 等 POSIX 命令。`\n );\n}\n\n/**\n * 解析命令里的「切目录」意图,返回目录与剩余命令。\n *\n * 识别 POSIX 的 `cd dir`、PowerShell 的 `Set-Location`/`sl`、cmd 的 `cd /d dir`,\n * 以及 `pushd`/`Push-Location`(只跟踪目标目录;popd 的栈语义不在此处理)。\n * 带 `&&` 时(如 `cd /d D:\\x && dir`)只把切目录部分交给 cwd 跟踪,剩余命令\n * 在新目录下执行 —— 否则目录变更只影响那一个子 shell,无法跨调用保持。\n *\n * target 为 null 时调用方应原样执行命令(未识别到切目录意图)。\n */\nexport function parseCdChain(\n command: string,\n opts: { platform?: NodeJS.Platform } = {},\n): { target: string | null; rest: string | null } {\n const platform = opts.platform ?? process.platform;\n const trimmed = command.trim();\n\n const chain = /^([\\s\\S]*?)\\s*&&\\s*([\\s\\S]+)$/.exec(trimmed);\n const head = (chain ? chain[1] : trimmed).trim();\n const rest = chain ? chain[2].trim() : null;\n\n const m = /^(?:cd|set-location|sl|pushd|push-location)\\b\\s*([\\s\\S]*)$/i.exec(head);\n if (!m) return { target: null, rest: null };\n\n let target = m[1].trim();\n // PowerShell 显式参数与 cmd 的盘符切换\n target = target.replace(/^-(?:path|literalpath)\\s+/i, \"\");\n if (platform === \"win32\") target = target.replace(/^\\/d\\s+/i, \"\");\n // 去引号\n target = target.replace(/^\"(.*)\"$/, \"$1\").replace(/^'(.*)'$/, \"$1\").trim();\n\n // 裸 `cd` / `cd -` 不跟踪(无法确定目标目录)\n if (!target || target === \"-\") return { target: null, rest: null };\n return { target, rest };\n}\n"],"mappings":"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","names":["path","fs","os","OpenAI"]}
@@ -0,0 +1,21 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
3
+ import { M as McpBuiltinContext, a as McpServerConfig } from '../../../McpClient-CEQBUPuC.cjs';
4
+
5
+ /**
6
+ * 内置 MCP 服务器注册表与进程内传输
7
+ *
8
+ * 内置服务器通过 InMemoryTransport 与客户端通信:无需子进程、跨平台、
9
+ * 对 SEA 单文件打包友好。新增内置能力时只需在此登记工厂。
10
+ */
11
+
12
+ type BuiltinMcpFactory = (ctx: McpBuiltinContext) => Server;
13
+ /** 已注册的内置服务器标识 */
14
+ declare function listBuiltinServers(): string[];
15
+ /**
16
+ * 创建内置服务器的客户端侧传输(已建立连接)。
17
+ * 服务端实例与客户端共享进程,随传输关闭而释放。
18
+ */
19
+ declare function createBuiltinTransport(config: McpServerConfig, ctx: McpBuiltinContext): Promise<Transport>;
20
+
21
+ export { type BuiltinMcpFactory, McpBuiltinContext, createBuiltinTransport, listBuiltinServers };
@@ -0,0 +1,21 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
3
+ import { M as McpBuiltinContext, a as McpServerConfig } from '../../../McpClient-CEQBUPuC.js';
4
+
5
+ /**
6
+ * 内置 MCP 服务器注册表与进程内传输
7
+ *
8
+ * 内置服务器通过 InMemoryTransport 与客户端通信:无需子进程、跨平台、
9
+ * 对 SEA 单文件打包友好。新增内置能力时只需在此登记工厂。
10
+ */
11
+
12
+ type BuiltinMcpFactory = (ctx: McpBuiltinContext) => Server;
13
+ /** 已注册的内置服务器标识 */
14
+ declare function listBuiltinServers(): string[];
15
+ /**
16
+ * 创建内置服务器的客户端侧传输(已建立连接)。
17
+ * 服务端实例与客户端共享进程,随传输关闭而释放。
18
+ */
19
+ declare function createBuiltinTransport(config: McpServerConfig, ctx: McpBuiltinContext): Promise<Transport>;
20
+
21
+ export { type BuiltinMcpFactory, McpBuiltinContext, createBuiltinTransport, listBuiltinServers };