reasonix 0.40.0 → 0.43.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.
Files changed (194) hide show
  1. package/README.md +47 -16
  2. package/README.zh-CN.md +19 -13
  3. package/dashboard/app.css +8 -4
  4. package/dashboard/dist/app.js +377 -227
  5. package/dashboard/dist/app.js.map +1 -1
  6. package/dist/cli/acp-DAGPCVFZ.js +713 -0
  7. package/dist/cli/acp-DAGPCVFZ.js.map +1 -0
  8. package/dist/cli/chat-7ES4IBNH.js +50 -0
  9. package/dist/cli/{chunk-E46ECXJD.js → chunk-2425HK6U.js} +2 -1
  10. package/dist/cli/{chunk-E46ECXJD.js.map → chunk-2425HK6U.js.map} +1 -1
  11. package/dist/cli/chunk-25T6CVUP.js +172 -0
  12. package/dist/cli/chunk-25T6CVUP.js.map +1 -0
  13. package/dist/cli/{chunk-7DLHHBGN.js → chunk-2K65GZBT.js} +16 -5
  14. package/dist/cli/chunk-2K65GZBT.js.map +1 -0
  15. package/dist/cli/{chunk-KMWKGPFZ.js → chunk-2KDUS647.js} +14 -4
  16. package/dist/cli/chunk-2KDUS647.js.map +1 -0
  17. package/dist/cli/chunk-2R4QCDOZ.js +11392 -0
  18. package/dist/cli/chunk-2R4QCDOZ.js.map +1 -0
  19. package/dist/cli/{chunk-3Q3C4W66.js → chunk-2UQP6H6T.js} +2 -1
  20. package/dist/cli/{chunk-3Q3C4W66.js.map → chunk-2UQP6H6T.js.map} +1 -1
  21. package/dist/cli/chunk-2Z35JOA4.js +96 -0
  22. package/dist/cli/chunk-2Z35JOA4.js.map +1 -0
  23. package/dist/cli/chunk-32TIKD5U.js +54 -0
  24. package/dist/cli/{chunk-JWCTX5S4.js.map → chunk-32TIKD5U.js.map} +1 -1
  25. package/dist/cli/{chunk-UVRXTSK3.js → chunk-3BXRZFWS.js} +65 -3
  26. package/dist/cli/chunk-3BXRZFWS.js.map +1 -0
  27. package/dist/cli/chunk-3Z6IBU3D.js +249 -0
  28. package/dist/cli/chunk-3Z6IBU3D.js.map +1 -0
  29. package/dist/cli/{chunk-VLNRQMCI.js → chunk-45U62RI3.js} +12 -5
  30. package/dist/cli/chunk-45U62RI3.js.map +1 -0
  31. package/dist/cli/{chunk-5GKJLNP2.js → chunk-4QUNBQQ2.js} +3 -2
  32. package/dist/cli/{chunk-5GKJLNP2.js.map → chunk-4QUNBQQ2.js.map} +1 -1
  33. package/dist/cli/{chunk-R4YTW7PR.js → chunk-5JJRUIPA.js} +57 -12
  34. package/dist/cli/chunk-5JJRUIPA.js.map +1 -0
  35. package/dist/cli/{chunk-HCC42PEI.js → chunk-6AK4EY3D.js} +12 -6
  36. package/dist/cli/chunk-6AK4EY3D.js.map +1 -0
  37. package/dist/cli/chunk-6G3CUUFG.js +34320 -0
  38. package/dist/cli/chunk-6G3CUUFG.js.map +1 -0
  39. package/dist/cli/{chunk-XST7BSZJ.js → chunk-6PBZN4VI.js} +21 -3
  40. package/dist/cli/chunk-6PBZN4VI.js.map +1 -0
  41. package/dist/cli/{chunk-A5LSGEEK.js → chunk-6PZ3CXBP.js} +88 -66
  42. package/dist/cli/chunk-6PZ3CXBP.js.map +1 -0
  43. package/dist/cli/chunk-74EX7SUH.js +25293 -0
  44. package/dist/cli/chunk-74EX7SUH.js.map +1 -0
  45. package/dist/cli/{chunk-FFNOMR32.js → chunk-7O5ALB4C.js} +3 -2
  46. package/dist/cli/{chunk-FFNOMR32.js.map → chunk-7O5ALB4C.js.map} +1 -1
  47. package/dist/cli/{chunk-UCMTWZKU.js → chunk-DOYHN4KB.js} +3 -2
  48. package/dist/cli/{chunk-UCMTWZKU.js.map → chunk-DOYHN4KB.js.map} +1 -1
  49. package/dist/cli/{chunk-XJLZ4HKU.js → chunk-F3PXYSNN.js} +3 -2
  50. package/dist/cli/{chunk-XJLZ4HKU.js.map → chunk-F3PXYSNN.js.map} +1 -1
  51. package/dist/cli/{chunk-XHQIK7B6.js → chunk-FHOGSSCH.js} +4 -3
  52. package/dist/cli/{chunk-XHQIK7B6.js.map → chunk-FHOGSSCH.js.map} +1 -1
  53. package/dist/cli/{chunk-IYF36OCJ.js → chunk-H6PS7IUE.js} +3 -2
  54. package/dist/cli/{chunk-IYF36OCJ.js.map → chunk-H6PS7IUE.js.map} +1 -1
  55. package/dist/cli/{chunk-ZTLZO42A.js → chunk-HFEAY5DT.js} +3 -2
  56. package/dist/cli/{chunk-ZTLZO42A.js.map → chunk-HFEAY5DT.js.map} +1 -1
  57. package/dist/cli/{chunk-FWGEHRB7.js → chunk-J5XJHLWM.js} +2 -1
  58. package/dist/cli/{chunk-FWGEHRB7.js.map → chunk-J5XJHLWM.js.map} +1 -1
  59. package/dist/cli/chunk-JMBMLOBP.js +26 -0
  60. package/dist/cli/chunk-JMBMLOBP.js.map +1 -0
  61. package/dist/cli/{chunk-SZH34P45.js → chunk-O52OLQL3.js} +52 -18
  62. package/dist/cli/chunk-O52OLQL3.js.map +1 -0
  63. package/dist/cli/{chunk-4DCHFFEY.js → chunk-OSZC7C6F.js} +3 -2
  64. package/dist/cli/{chunk-4DCHFFEY.js.map → chunk-OSZC7C6F.js.map} +1 -1
  65. package/dist/cli/chunk-P7EKE5ZQ.js +60641 -0
  66. package/dist/cli/chunk-P7EKE5ZQ.js.map +1 -0
  67. package/dist/cli/{chunk-FM57FNPJ.js → chunk-PLHAZOLZ.js} +2 -1
  68. package/dist/cli/{chunk-FM57FNPJ.js.map → chunk-PLHAZOLZ.js.map} +1 -1
  69. package/dist/cli/{chunk-RFX7TYVV.js → chunk-PQXPXJBJ.js} +16 -2
  70. package/dist/cli/chunk-PQXPXJBJ.js.map +1 -0
  71. package/dist/cli/{chunk-DAEAAVDF.js → chunk-PV55UMTO.js} +2 -1
  72. package/dist/cli/{chunk-DAEAAVDF.js.map → chunk-PV55UMTO.js.map} +1 -1
  73. package/dist/cli/{chunk-H7PHYVPM.js → chunk-RE4RAVFF.js} +85 -14
  74. package/dist/cli/chunk-RE4RAVFF.js.map +1 -0
  75. package/dist/cli/chunk-S4XVGLRW.js +499 -0
  76. package/dist/cli/chunk-S4XVGLRW.js.map +1 -0
  77. package/dist/cli/{chunk-WJ3YX4PZ.js → chunk-SZ5XES2N.js} +3 -2
  78. package/dist/cli/{chunk-WJ3YX4PZ.js.map → chunk-SZ5XES2N.js.map} +1 -1
  79. package/dist/cli/{chunk-4X3NY5ZM.js → chunk-TJX6BFZZ.js} +16 -9
  80. package/dist/cli/{chunk-4X3NY5ZM.js.map → chunk-TJX6BFZZ.js.map} +1 -1
  81. package/dist/cli/chunk-TUK7OWJA.js +51 -0
  82. package/dist/cli/{chunk-WKOMCPXP.js → chunk-VK5HG73G.js} +26 -17
  83. package/dist/cli/chunk-VK5HG73G.js.map +1 -0
  84. package/dist/cli/{chunk-CLAN6PVH.js → chunk-XCGGEJTI.js} +21 -8
  85. package/dist/cli/chunk-XCGGEJTI.js.map +1 -0
  86. package/dist/cli/{chunk-SOZE7V7V.js → chunk-XJXDHAES.js} +3 -2
  87. package/dist/cli/{chunk-SOZE7V7V.js.map → chunk-XJXDHAES.js.map} +1 -1
  88. package/dist/cli/chunk-XPDVG52A.js +2648 -0
  89. package/dist/cli/chunk-XPDVG52A.js.map +1 -0
  90. package/dist/cli/{chunk-CRPQUBP6.js → chunk-XXC2BYTV.js} +2 -1
  91. package/dist/cli/{chunk-CRPQUBP6.js.map → chunk-XXC2BYTV.js.map} +1 -1
  92. package/dist/cli/{chunk-AVB3WZWU.js → chunk-YFGF5NKA.js} +17 -14
  93. package/dist/cli/{chunk-AVB3WZWU.js.map → chunk-YFGF5NKA.js.map} +1 -1
  94. package/dist/cli/{chunk-ORM6PK57.js → chunk-YQ6NTIIE.js} +2 -1
  95. package/dist/cli/{chunk-ORM6PK57.js.map → chunk-YQ6NTIIE.js.map} +1 -1
  96. package/dist/cli/{chunk-ULBW7DYL.js → chunk-YYQAUTTN.js} +3 -2
  97. package/dist/cli/{chunk-ULBW7DYL.js.map → chunk-YYQAUTTN.js.map} +1 -1
  98. package/dist/cli/chunk-ZZM6QJ4W.js +109 -0
  99. package/dist/cli/chunk-ZZM6QJ4W.js.map +1 -0
  100. package/dist/cli/code-SMKEW6CD.js +154 -0
  101. package/dist/cli/code-SMKEW6CD.js.map +1 -0
  102. package/dist/cli/{commands-FQZOBLLZ.js → commands-FVVB5FZF.js} +7 -5
  103. package/dist/cli/{commands-FQZOBLLZ.js.map → commands-FVVB5FZF.js.map} +1 -1
  104. package/dist/cli/{commit-ZS24SHPG.js → commit-HE4VSPZ7.js} +7 -4
  105. package/dist/cli/{commit-ZS24SHPG.js.map → commit-HE4VSPZ7.js.map} +1 -1
  106. package/dist/cli/{desktop-6OLENOOO.js → desktop-Q7NDXCON.js} +379 -72
  107. package/dist/cli/desktop-Q7NDXCON.js.map +1 -0
  108. package/dist/cli/devtools-YECO25QO.js +3719 -0
  109. package/dist/cli/devtools-YECO25QO.js.map +1 -0
  110. package/dist/cli/diff-435UTPC5.js +165 -0
  111. package/dist/cli/{diff-2VUKNGEI.js.map → diff-435UTPC5.js.map} +1 -1
  112. package/dist/cli/doctor-OT7KH75K.js +27 -0
  113. package/dist/cli/{events-APSVNROZ.js → events-XEFAD5VX.js} +6 -4
  114. package/dist/cli/{events-APSVNROZ.js.map → events-XEFAD5VX.js.map} +1 -1
  115. package/dist/cli/index.js +3233 -123
  116. package/dist/cli/index.js.map +1 -1
  117. package/dist/cli/{mcp-DCKOE5RF.js → mcp-WUL2WO75.js} +6 -4
  118. package/dist/cli/{mcp-DCKOE5RF.js.map → mcp-WUL2WO75.js.map} +1 -1
  119. package/dist/cli/{mcp-browse-D6GBP5RQ.js → mcp-browse-RR7R4XET.js} +34 -19
  120. package/dist/cli/mcp-browse-RR7R4XET.js.map +1 -0
  121. package/dist/cli/{mcp-inspect-KFGFPJ3E.js → mcp-inspect-REGLYBWT.js} +9 -8
  122. package/dist/cli/{mcp-inspect-KFGFPJ3E.js.map → mcp-inspect-REGLYBWT.js.map} +1 -1
  123. package/dist/cli/package.json +3 -0
  124. package/dist/cli/prompt-UW6EFLVR.js +16 -0
  125. package/dist/cli/{prune-sessions-LV33R47N.js → prune-sessions-3RWUBYRS.js} +4 -2
  126. package/dist/cli/{prune-sessions-LV33R47N.js.map → prune-sessions-3RWUBYRS.js.map} +1 -1
  127. package/dist/cli/{replay-WFCYX7XF.js → replay-YOURXV4C.js} +42 -30
  128. package/dist/cli/{replay-WFCYX7XF.js.map → replay-YOURXV4C.js.map} +1 -1
  129. package/dist/cli/{run-IUJYEPMT.js → run-Q6BUXV66.js} +28 -27
  130. package/dist/cli/{run-IUJYEPMT.js.map → run-Q6BUXV66.js.map} +1 -1
  131. package/dist/cli/{server-CN4QPPVJ.js → server-XGDBRWMB.js} +44 -43
  132. package/dist/cli/server-XGDBRWMB.js.map +1 -0
  133. package/dist/cli/{sessions-F5GPGTJN.js → sessions-FH7QVYSY.js} +22 -19
  134. package/dist/cli/{sessions-F5GPGTJN.js.map → sessions-FH7QVYSY.js.map} +1 -1
  135. package/dist/cli/setup-VDS6SVEP.js +618 -0
  136. package/dist/cli/setup-VDS6SVEP.js.map +1 -0
  137. package/dist/cli/stats-MQVI2XQH.js +14 -0
  138. package/dist/cli/update-6ITLPRDV.js +15 -0
  139. package/dist/cli/update-6ITLPRDV.js.map +1 -0
  140. package/dist/cli/version-DAHGZY5N.js +33 -0
  141. package/dist/cli/{version-KQUPV6T5.js.map → version-DAHGZY5N.js.map} +1 -1
  142. package/dist/index.d.ts +157 -103
  143. package/dist/index.js +597 -178
  144. package/dist/index.js.map +1 -1
  145. package/package.json +2 -1
  146. package/dist/cli/chat-G7CUW4ZI.js +0 -45
  147. package/dist/cli/chunk-26UDIXLD.js +0 -16481
  148. package/dist/cli/chunk-26UDIXLD.js.map +0 -1
  149. package/dist/cli/chunk-4YV2GBYG.js +0 -5237
  150. package/dist/cli/chunk-4YV2GBYG.js.map +0 -1
  151. package/dist/cli/chunk-5X7LZJDE.js +0 -36
  152. package/dist/cli/chunk-5X7LZJDE.js.map +0 -1
  153. package/dist/cli/chunk-7DLHHBGN.js.map +0 -1
  154. package/dist/cli/chunk-A5LSGEEK.js.map +0 -1
  155. package/dist/cli/chunk-AFFZF3MW.js +0 -36
  156. package/dist/cli/chunk-AFFZF3MW.js.map +0 -1
  157. package/dist/cli/chunk-CLAN6PVH.js.map +0 -1
  158. package/dist/cli/chunk-CPOV2O73.js +0 -39
  159. package/dist/cli/chunk-CPOV2O73.js.map +0 -1
  160. package/dist/cli/chunk-CPTZ5OHX.js +0 -18
  161. package/dist/cli/chunk-CPTZ5OHX.js.map +0 -1
  162. package/dist/cli/chunk-CZSJILQP.js +0 -854
  163. package/dist/cli/chunk-CZSJILQP.js.map +0 -1
  164. package/dist/cli/chunk-H7PHYVPM.js.map +0 -1
  165. package/dist/cli/chunk-HCC42PEI.js.map +0 -1
  166. package/dist/cli/chunk-JWCTX5S4.js +0 -46
  167. package/dist/cli/chunk-KMWKGPFZ.js.map +0 -1
  168. package/dist/cli/chunk-MRLXEMZ7.js +0 -26
  169. package/dist/cli/chunk-MRLXEMZ7.js.map +0 -1
  170. package/dist/cli/chunk-R4YTW7PR.js.map +0 -1
  171. package/dist/cli/chunk-RFX7TYVV.js.map +0 -1
  172. package/dist/cli/chunk-SZH34P45.js.map +0 -1
  173. package/dist/cli/chunk-UVRXTSK3.js.map +0 -1
  174. package/dist/cli/chunk-VLNRQMCI.js.map +0 -1
  175. package/dist/cli/chunk-WKOMCPXP.js.map +0 -1
  176. package/dist/cli/chunk-XST7BSZJ.js.map +0 -1
  177. package/dist/cli/code-YQGVLIT2.js +0 -147
  178. package/dist/cli/code-YQGVLIT2.js.map +0 -1
  179. package/dist/cli/desktop-6OLENOOO.js.map +0 -1
  180. package/dist/cli/diff-2VUKNGEI.js +0 -153
  181. package/dist/cli/doctor-JO2WNN6C.js +0 -24
  182. package/dist/cli/mcp-browse-D6GBP5RQ.js.map +0 -1
  183. package/dist/cli/prompt-PKCCLLAD.js +0 -13
  184. package/dist/cli/server-CN4QPPVJ.js.map +0 -1
  185. package/dist/cli/setup-WWMDBPSB.js +0 -516
  186. package/dist/cli/setup-WWMDBPSB.js.map +0 -1
  187. package/dist/cli/stats-5RJCATCE.js +0 -12
  188. package/dist/cli/update-GUCWB4UN.js +0 -13
  189. package/dist/cli/version-KQUPV6T5.js +0 -30
  190. /package/dist/cli/{chat-G7CUW4ZI.js.map → chat-7ES4IBNH.js.map} +0 -0
  191. /package/dist/cli/{doctor-JO2WNN6C.js.map → chunk-TUK7OWJA.js.map} +0 -0
  192. /package/dist/cli/{prompt-PKCCLLAD.js.map → doctor-OT7KH75K.js.map} +0 -0
  193. /package/dist/cli/{stats-5RJCATCE.js.map → prompt-UW6EFLVR.js.map} +0 -0
  194. /package/dist/cli/{update-GUCWB4UN.js.map → stats-MQVI2XQH.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/commands/acp.ts","../../src/acp/dispatch.ts","../../src/acp/gates.ts","../../src/acp/protocol.ts","../../src/acp/server.ts"],"sourcesContent":["/** ACP (Agent Client Protocol) agent — drives the cache-first loop over stdio NDJSON JSON-RPC. */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { type WriteStream, existsSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { dispatchKernelEvent } from \"../../acp/dispatch.js\";\nimport { requestPermissionForGate } from \"../../acp/gates.js\";\nimport {\n ACP_PROTOCOL_VERSION,\n type ContentBlock,\n ERR_INVALID_PARAMS,\n type InitializeParams,\n type InitializeResult,\n type SessionCancelParams,\n type SessionNewParams,\n type SessionNewResult,\n type SessionPromptParams,\n type SessionPromptResult,\n type SessionUpdateParams,\n type StopReason,\n flattenPrompt,\n} from \"../../acp/protocol.js\";\nimport { AcpServer } from \"../../acp/server.js\";\nimport { codeSystemPrompt } from \"../../code/prompt.js\";\nimport { buildCodeToolset } from \"../../code/setup.js\";\nimport {\n loadApiKey,\n loadBaseUrl,\n loadPreset,\n loadReasoningEffort,\n mcpEnvFor,\n readConfig,\n} from \"../../config.js\";\nimport { loadEditMode } from \"../../config.js\";\nimport { Eventizer } from \"../../core/eventize.js\";\nimport { pauseGate } from \"../../core/pause-gate.js\";\nimport { autoResolveVerdict } from \"../../core/pause-policy.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { t } from \"../../i18n/index.js\";\nimport { CacheFirstLoop, DeepSeekClient, ImmutablePrefix } from \"../../index.js\";\nimport { McpClient } from \"../../mcp/client.js\";\nimport { preflightStdioSpec } from \"../../mcp/preflight.js\";\nimport { bridgeMcpTools } from \"../../mcp/registry.js\";\nimport { parseMcpSpec } from \"../../mcp/spec.js\";\nimport { buildTransportFromSpec } from \"../../mcp/transport-from-spec.js\";\nimport { timestampSuffix } from \"../../memory/session.js\";\nimport { openTranscriptFile, recordFromLoopEvent, writeRecord } from \"../../transcript/log.js\";\nimport { VERSION } from \"../../version.js\";\nimport { formatMcpLifecycleEvent } from \"../ui/mcp-lifecycle.js\";\nimport { formatMcpSlowToast } from \"../ui/mcp-toast.js\";\nimport { canonicalPresetName, resolvePreset } from \"../ui/presets.js\";\n\nexport interface AcpOptions {\n model?: string;\n dir?: string;\n budgetUsd?: number;\n transcript?: string;\n yolo?: boolean;\n /** Zero or more MCP server specs. Each: `\"name=cmd args...\"` or `\"cmd args...\"`. */\n mcpSpecs?: string[];\n /** Global prefix — only honored when a single anonymous server is given. */\n mcpPrefix?: string;\n}\n\ninterface Session {\n id: string;\n rootDir: string;\n model: string;\n toolset: Awaited<ReturnType<typeof buildCodeToolset>>;\n mcpClients: McpClient[];\n loop: CacheFirstLoop;\n eventizer: Eventizer;\n ctx: { model: string; prefixHash: string; reasoningEffort: \"high\" | \"max\" };\n aborter: AbortController | null;\n}\n\nfunction resolveMcpPrefix(\n specName: string | null | undefined,\n specCount: number,\n globalPrefix: string | undefined,\n): string {\n if (specName) return `${specName}_`;\n if (specCount === 1 && globalPrefix) return globalPrefix;\n return \"\";\n}\n\n// Mirrors run.ts:81-142.\nexport async function loadMcpServers(\n tools: import(\"../../tools.js\").ToolRegistry,\n specs: string[],\n globalPrefix: string | undefined,\n): Promise<McpClient[]> {\n const clients: McpClient[] = [];\n if (specs.length === 0) return clients;\n const cfg = readConfig();\n const disabledNames = new Set(cfg.mcpDisabled ?? []);\n for (const raw of specs) {\n let label = \"anon\";\n let mcp: McpClient | undefined;\n try {\n const spec = parseMcpSpec(raw);\n label = spec.name ?? \"anon\";\n if (spec.name && disabledNames.has(spec.name)) {\n process.stderr.write(`${formatMcpLifecycleEvent({ state: \"disabled\", name: label })}\\n`);\n continue;\n }\n process.stderr.write(`${formatMcpLifecycleEvent({ state: \"handshake\", name: label })}\\n`);\n const t0 = Date.now();\n const prefix = resolveMcpPrefix(spec.name, specs.length, globalPrefix);\n if (spec.transport === \"stdio\") preflightStdioSpec(spec);\n const transport = buildTransportFromSpec(spec, { env: mcpEnvFor(spec.name, cfg) });\n mcp = new McpClient({ transport });\n await mcp.initialize();\n const bridge = await bridgeMcpTools(mcp, {\n registry: tools,\n namePrefix: prefix,\n serverName: label,\n onSlow: (info) =>\n process.stderr.write(\n `${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}\\n`,\n ),\n });\n process.stderr.write(\n `${formatMcpLifecycleEvent({\n state: \"connected\",\n name: label,\n tools: bridge.registeredNames.length,\n ms: Date.now() - t0,\n })}\\n`,\n );\n clients.push(mcp);\n } catch (err) {\n await mcp?.close().catch(() => undefined);\n process.stderr.write(\n `${formatMcpLifecycleEvent({ state: \"failed\", name: label, reason: (err as Error).message })}\\n → ${t(\"mcpLifecycle.failedSetupConfigHint\")}\\n`,\n );\n }\n }\n return clients;\n}\n\nfunction resolveDir(raw: string | undefined, fallback: string): string {\n if (!raw) return fallback;\n const abs = resolve(raw);\n if (!existsSync(abs) || !statSync(abs).isDirectory()) {\n throw new Error(`workspace directory not found: ${abs}`);\n }\n return abs;\n}\n\nasync function buildSession(opts: {\n rootDir: string;\n modelOverride?: string;\n budgetUsd?: number;\n mcpSpecs?: string[];\n mcpPrefix?: string;\n}): Promise<Session> {\n const preset = canonicalPresetName(loadPreset());\n const resolved = resolvePreset(preset);\n const model = opts.modelOverride || resolved.model;\n const toolset = await buildCodeToolset({ rootDir: opts.rootDir });\n // Bridge MCP tools BEFORE building the prefix so their specs make it into the cache key.\n const mcpClients = await loadMcpServers(toolset.tools, opts.mcpSpecs ?? [], opts.mcpPrefix);\n const system = codeSystemPrompt(opts.rootDir, {\n hasSemanticSearch: toolset.semantic.enabled,\n modelId: model,\n });\n const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });\n const prefix = new ImmutablePrefix({ system, toolSpecs: toolset.tools.specs() });\n const loop = new CacheFirstLoop({\n client,\n prefix,\n tools: toolset.tools,\n model,\n budgetUsd: opts.budgetUsd,\n session: `acp-${timestampSuffix()}`,\n });\n return {\n id: `sess_${timestampSuffix()}-${Math.random().toString(36).slice(2, 8)}`,\n rootDir: opts.rootDir,\n model,\n toolset,\n mcpClients,\n loop,\n eventizer: new Eventizer(),\n ctx: {\n model,\n prefixHash: prefix.fingerprint,\n reasoningEffort: loadReasoningEffort(),\n },\n aborter: null,\n };\n}\n\nexport async function acpCommand(opts: AcpOptions): Promise<void> {\n loadDotenv();\n if (loadApiKey()) {\n process.env.DEEPSEEK_API_KEY = loadApiKey();\n }\n\n const defaultDir = resolveDir(opts.dir, process.cwd());\n const sessions = new Map<string, Session>();\n const sessionContext = new AsyncLocalStorage<string>();\n const server = new AcpServer();\n\n let transcriptStream: WriteStream | null = null;\n if (opts.transcript) {\n const defaultModel = opts.model || resolvePreset(canonicalPresetName(loadPreset())).model;\n transcriptStream = openTranscriptFile(opts.transcript, {\n version: 1,\n source: \"reasonix acp\",\n model: defaultModel,\n startedAt: new Date().toISOString(),\n });\n }\n\n pauseGate.on((req) => {\n const editMode = opts.yolo ? \"yolo\" : loadEditMode();\n const auto = autoResolveVerdict(req, editMode);\n if (auto !== null) {\n pauseGate.resolve(req.id, auto);\n return;\n }\n const activeSessionId = sessionContext.getStore();\n if (!activeSessionId || !sessions.has(activeSessionId)) {\n pauseGate.cancel(req.id);\n return;\n }\n void (async () => {\n const verdict = await requestPermissionForGate(server, activeSessionId, req);\n pauseGate.resolve(req.id, verdict);\n })();\n });\n\n server.onRequest<InitializeParams, InitializeResult>(\"initialize\", (params) => {\n if (!params || typeof params !== \"object\") {\n throw Object.assign(new Error(\"initialize: missing params\"), { code: ERR_INVALID_PARAMS });\n }\n return {\n protocolVersion: ACP_PROTOCOL_VERSION,\n agentCapabilities: {\n loadSession: false,\n promptCapabilities: { image: false, audio: false, embeddedContext: true },\n mcpCapabilities: { http: false, sse: false },\n },\n agentInfo: { name: \"reasonix\", title: \"Reasonix\", version: VERSION },\n authMethods: [],\n };\n });\n\n server.onRequest<SessionNewParams, SessionNewResult>(\"session/new\", async (params) => {\n const rootDir = resolveDir(params?.cwd, defaultDir);\n const session = await buildSession({\n rootDir,\n modelOverride: opts.model,\n budgetUsd: opts.budgetUsd,\n mcpSpecs: opts.mcpSpecs,\n mcpPrefix: opts.mcpPrefix,\n });\n sessions.set(session.id, session);\n return { sessionId: session.id };\n });\n\n server.onRequest<SessionPromptParams, SessionPromptResult>(\"session/prompt\", async (params) => {\n if (!params?.sessionId) {\n throw Object.assign(new Error(\"session/prompt: missing sessionId\"), {\n code: ERR_INVALID_PARAMS,\n });\n }\n const session = sessions.get(params.sessionId);\n if (!session) {\n throw Object.assign(new Error(`session/prompt: unknown session ${params.sessionId}`), {\n code: ERR_INVALID_PARAMS,\n });\n }\n const text = flattenPrompt(params.prompt as ContentBlock[]);\n if (!text) {\n throw Object.assign(new Error(\"session/prompt: empty prompt\"), { code: ERR_INVALID_PARAMS });\n }\n session.aborter = new AbortController();\n let stopReason: StopReason = \"end_turn\";\n try {\n await sessionContext.run(session.id, async () => {\n for await (const ev of session.loop.step(text)) {\n if (session.aborter?.signal.aborted) {\n stopReason = \"cancelled\";\n break;\n }\n // transcript needs raw LoopEvent (usage/cost/stats); kernel events lose those fields\n if (transcriptStream) {\n writeRecord(\n transcriptStream,\n recordFromLoopEvent(ev, {\n model: session.ctx.model,\n prefixHash: session.ctx.prefixHash,\n }),\n );\n }\n for (const kev of session.eventizer.consume(ev, session.ctx)) {\n dispatchKernelEvent(server, session.id, kev);\n if (kev.type === \"error\") stopReason = \"error\";\n }\n }\n });\n } catch (err) {\n const message = (err as Error).message;\n server.sendNotification(\"session/update\", {\n sessionId: session.id,\n update: {\n sessionUpdate: \"agent_message_chunk\",\n content: { type: \"text\", text: `\\n\\n[error] ${message}` },\n },\n } satisfies SessionUpdateParams);\n stopReason = \"error\";\n } finally {\n session.aborter = null;\n }\n return { stopReason };\n });\n\n server.onNotification<SessionCancelParams>(\"session/cancel\", (params) => {\n const session = params?.sessionId ? sessions.get(params.sessionId) : undefined;\n session?.aborter?.abort();\n });\n\n try {\n await server.done();\n } finally {\n transcriptStream?.end();\n // Tear down MCP children so spawned servers don't outlive the agent.\n const closes: Promise<unknown>[] = [];\n for (const session of sessions.values()) {\n for (const mcp of session.mcpClients) {\n closes.push(mcp.close().catch(() => undefined));\n }\n }\n await Promise.all(closes);\n }\n}\n","/** Map kernel events (model.delta / tool.preparing|intent|result) to ACP session/update notifications. */\n\nimport type { Event as KernelEvent } from \"../core/events.js\";\nimport type { SessionUpdateParams } from \"./protocol.js\";\nimport type { AcpServer } from \"./server.js\";\n\nconst READ_TOOLS = new Set([\n \"read_file\",\n \"list_directory\",\n \"directory_tree\",\n \"get_file_info\",\n \"glob\",\n]);\nconst EDIT_TOOLS = new Set([\n \"write_file\",\n \"edit_file\",\n \"multi_edit\",\n \"create_directory\",\n \"delete_file\",\n \"delete_directory\",\n \"move_file\",\n \"copy_file\",\n]);\nconst SEARCH_TOOLS = new Set([\"search_content\", \"search_files\"]);\nconst EXECUTE_TOOLS = new Set([\"run_command\", \"run_background\"]);\n\nexport type AcpToolKind = \"read\" | \"edit\" | \"search\" | \"execute\" | \"other\";\n\nexport function toolKindFor(name: string): AcpToolKind {\n if (READ_TOOLS.has(name)) return \"read\";\n if (EDIT_TOOLS.has(name)) return \"edit\";\n if (SEARCH_TOOLS.has(name)) return \"search\";\n if (EXECUTE_TOOLS.has(name)) return \"execute\";\n return \"other\";\n}\n\nfunction tryParseJson(raw: string): unknown {\n if (!raw) return undefined;\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/** Stateless mapping from one kernel event to (zero or more) ACP session/update notifications. */\nexport function dispatchKernelEvent(server: AcpServer, sessionId: string, ev: KernelEvent): void {\n switch (ev.type) {\n case \"model.delta\": {\n if (!ev.text) return;\n const variant = ev.channel === \"reasoning\" ? \"agent_thought_chunk\" : \"agent_message_chunk\";\n emit(server, {\n sessionId,\n update: { sessionUpdate: variant, content: { type: \"text\", text: ev.text } },\n });\n return;\n }\n case \"tool.preparing\": {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call\",\n toolCallId: ev.callId,\n title: ev.name,\n kind: toolKindFor(ev.name),\n status: \"pending\",\n },\n });\n return;\n }\n case \"tool.intent\": {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call_update\",\n toolCallId: ev.callId,\n status: \"in_progress\",\n },\n });\n const rawInput = tryParseJson(ev.args);\n if (rawInput !== undefined) {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call\",\n toolCallId: ev.callId,\n title: ev.name,\n kind: toolKindFor(ev.name),\n status: \"in_progress\",\n rawInput,\n },\n });\n }\n return;\n }\n case \"tool.result\": {\n emit(server, {\n sessionId,\n update: {\n sessionUpdate: \"tool_call_update\",\n toolCallId: ev.callId,\n status: ev.ok ? \"completed\" : \"failed\",\n content: [\n {\n type: \"content\",\n content: { type: \"text\", text: clip(ev.output) },\n },\n ],\n },\n });\n return;\n }\n default:\n return;\n }\n}\n\nconst MAX_RESULT_CHARS = 8000;\nfunction clip(text: string): string {\n if (text.length <= MAX_RESULT_CHARS) return text;\n return `${text.slice(0, MAX_RESULT_CHARS)}\\n…(${text.length - MAX_RESULT_CHARS} more chars truncated)`;\n}\n\nfunction emit(server: AcpServer, params: SessionUpdateParams): void {\n server.sendNotification(\"session/update\", params);\n}\n","/** Bridges Reasonix's internal `PauseGate` requests onto ACP `session/request_permission` round-trips. */\n\nimport type {\n CheckpointVerdict,\n ChoiceVerdict,\n ConfirmationChoice,\n PauseRequest,\n PlanVerdict,\n RevisionVerdict,\n} from \"../core/pause-gate.js\";\nimport type {\n PermissionOption,\n PermissionRequestParams,\n PermissionRequestResult,\n} from \"./protocol.js\";\nimport type { AcpServer } from \"./server.js\";\n\nconst ID_ALLOW_ONCE = \"allow_once\";\nconst ID_ALLOW_ALWAYS = \"allow_always\";\nconst ID_REJECT = \"reject\";\nconst ID_REFINE = \"refine\";\nconst ID_REVISE = \"revise\";\nconst ID_STOP = \"stop\";\nconst ID_CANCEL = \"cancel\";\nconst ID_ACCEPT = \"accept\";\n\n/** Build the `options` list shown to the host for a given gate kind. The IDs are what the host echoes back in the response. */\nexport function permissionOptionsFor(req: PauseRequest): PermissionOption[] {\n switch (req.kind) {\n case \"run_command\":\n case \"run_background\":\n case \"path_access\":\n return [\n { optionId: ID_ALLOW_ONCE, name: \"Allow once\", kind: \"allow_once\" },\n { optionId: ID_ALLOW_ALWAYS, name: \"Allow always\", kind: \"allow_always\" },\n { optionId: ID_REJECT, name: \"Reject\", kind: \"reject_once\" },\n ];\n case \"plan_proposed\":\n return [\n { optionId: ID_ALLOW_ONCE, name: \"Approve plan\", kind: \"allow_once\" },\n { optionId: ID_REFINE, name: \"Refine\", kind: \"allow_once\" },\n { optionId: ID_CANCEL, name: \"Cancel\", kind: \"reject_once\" },\n ];\n case \"plan_checkpoint\":\n return [\n { optionId: ID_ALLOW_ONCE, name: \"Continue\", kind: \"allow_once\" },\n { optionId: ID_REVISE, name: \"Revise\", kind: \"allow_once\" },\n { optionId: ID_STOP, name: \"Stop\", kind: \"reject_once\" },\n ];\n case \"plan_revision\":\n return [\n { optionId: ID_ACCEPT, name: \"Accept revision\", kind: \"allow_once\" },\n { optionId: ID_REJECT, name: \"Keep original plan\", kind: \"reject_once\" },\n ];\n case \"choice\": {\n const payload = req.payload as { options: { id: string; title?: string }[] };\n const opts: PermissionOption[] = (payload.options ?? []).map((o) => ({\n optionId: o.id,\n name: o.title ?? o.id,\n kind: \"allow_once\",\n }));\n opts.push({ optionId: ID_CANCEL, name: \"Cancel\", kind: \"reject_once\" });\n return opts;\n }\n }\n}\n\nfunction commandPrefix(command: string): string {\n const first = command.trim().split(/\\s+/)[0] ?? command.trim();\n return `${first} *`;\n}\n\nfunction pathPrefix(p: string): string {\n return p;\n}\n\n/** Map an ACP permission response back into the internal verdict shape PauseGate.resolve expects. */\nexport function verdictFor(\n req: PauseRequest,\n result: PermissionRequestResult,\n): ConfirmationChoice | PlanVerdict | CheckpointVerdict | RevisionVerdict | ChoiceVerdict {\n const cancelled = result.outcome.outcome === \"cancelled\";\n const optionId = result.outcome.outcome === \"selected\" ? result.outcome.optionId : null;\n switch (req.kind) {\n case \"run_command\":\n case \"run_background\": {\n if (cancelled || optionId === ID_REJECT) return { type: \"deny\" };\n if (optionId === ID_ALLOW_ALWAYS) {\n const payload = req.payload as { command?: string };\n return { type: \"always_allow\", prefix: commandPrefix(payload.command ?? \"\") };\n }\n return { type: \"run_once\" };\n }\n case \"path_access\": {\n if (cancelled || optionId === ID_REJECT) return { type: \"deny\" };\n if (optionId === ID_ALLOW_ALWAYS) {\n const payload = req.payload as { allowPrefix: string };\n return { type: \"always_allow\", prefix: pathPrefix(payload.allowPrefix) };\n }\n return { type: \"run_once\" };\n }\n case \"plan_proposed\": {\n if (cancelled || optionId === ID_CANCEL) return { type: \"cancel\" };\n if (optionId === ID_REFINE) return { type: \"refine\" };\n return { type: \"approve\" };\n }\n case \"plan_checkpoint\": {\n if (cancelled || optionId === ID_STOP) return { type: \"stop\" };\n if (optionId === ID_REVISE) return { type: \"revise\" };\n return { type: \"continue\" };\n }\n case \"plan_revision\": {\n if (cancelled) return { type: \"cancelled\" };\n if (optionId === ID_ACCEPT) return { type: \"accepted\" };\n return { type: \"rejected\" };\n }\n case \"choice\": {\n if (cancelled || optionId === ID_CANCEL || !optionId) return { type: \"cancel\" };\n return { type: \"pick\", optionId };\n }\n }\n}\n\nfunction permissionTitleFor(req: PauseRequest): string {\n switch (req.kind) {\n case \"run_command\":\n case \"run_background\":\n return `Run command — ${((req.payload as { command?: string }).command ?? \"\").slice(0, 80)}`;\n case \"path_access\":\n return `Access path — ${(req.payload as { path: string }).path}`;\n case \"plan_proposed\":\n return \"Approve plan\";\n case \"plan_checkpoint\":\n return `Checkpoint — ${(req.payload as { title?: string }).title ?? \"step complete\"}`;\n case \"plan_revision\":\n return \"Approve plan revision\";\n case \"choice\":\n return (req.payload as { question?: string }).question ?? \"Choose an option\";\n }\n}\n\nfunction permissionKindFor(req: PauseRequest): \"execute\" | \"edit\" | \"other\" {\n if (req.kind === \"run_command\" || req.kind === \"run_background\") return \"execute\";\n if (req.kind === \"path_access\") {\n return (req.payload as { intent?: string }).intent === \"write\" ? \"edit\" : \"other\";\n }\n return \"other\";\n}\n\n/** Forward a PauseGate request as an ACP session/request_permission outbound call. Returns the verdict to pass into pauseGate.resolve. */\nexport async function requestPermissionForGate(\n server: AcpServer,\n sessionId: string,\n req: PauseRequest,\n): Promise<ConfirmationChoice | PlanVerdict | CheckpointVerdict | RevisionVerdict | ChoiceVerdict> {\n const params: PermissionRequestParams = {\n sessionId,\n toolCall: {\n toolCallId: `gate-${req.id}`,\n title: permissionTitleFor(req),\n kind: permissionKindFor(req),\n status: \"pending\",\n rawInput: req.payload,\n },\n options: permissionOptionsFor(req),\n };\n let result: PermissionRequestResult;\n try {\n result = await server.sendRequest<PermissionRequestResult>(\n \"session/request_permission\",\n params,\n );\n } catch {\n result = { outcome: { outcome: \"cancelled\" } };\n }\n return verdictFor(req, result);\n}\n","/** Wire types for the Agent Client Protocol — https://agentclientprotocol.com */\n\nexport const ACP_PROTOCOL_VERSION = 1;\n\nexport type JsonRpcId = string | number;\n\nexport interface JsonRpcRequest<P = unknown> {\n jsonrpc: \"2.0\";\n id: JsonRpcId;\n method: string;\n params?: P;\n}\n\nexport interface JsonRpcNotification<P = unknown> {\n jsonrpc: \"2.0\";\n method: string;\n params?: P;\n}\n\nexport interface JsonRpcError {\n code: number;\n message: string;\n data?: unknown;\n}\n\nexport interface JsonRpcResponse<R = unknown> {\n jsonrpc: \"2.0\";\n id: JsonRpcId | null;\n result?: R;\n error?: JsonRpcError;\n}\n\nexport interface InitializeParams {\n protocolVersion: number;\n clientCapabilities?: {\n fs?: { readTextFile?: boolean; writeTextFile?: boolean };\n terminal?: boolean;\n };\n clientInfo?: { name: string; title?: string; version?: string };\n}\n\nexport interface InitializeResult {\n protocolVersion: number;\n agentCapabilities: {\n loadSession?: boolean;\n promptCapabilities?: { image?: boolean; audio?: boolean; embeddedContext?: boolean };\n mcpCapabilities?: { http?: boolean; sse?: boolean };\n };\n agentInfo: { name: string; title?: string; version: string };\n authMethods: never[];\n}\n\nexport interface SessionNewParams {\n cwd?: string;\n mcpServers?: Array<{\n name: string;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n }>;\n}\n\nexport interface SessionNewResult {\n sessionId: string;\n}\n\nexport type ContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"resource\"; resource: { uri: string; mimeType?: string; text?: string } }\n | { type: \"image\"; mimeType: string; data: string }\n | { type: \"audio\"; mimeType: string; data: string };\n\nexport interface SessionPromptParams {\n sessionId: string;\n prompt: ContentBlock[];\n}\n\nexport type StopReason = \"end_turn\" | \"tool_use_complete\" | \"cancelled\" | \"error\";\n\nexport interface SessionPromptResult {\n stopReason: StopReason;\n}\n\nexport type SessionUpdate =\n | {\n sessionUpdate: \"agent_message_chunk\";\n content: { type: \"text\"; text: string };\n }\n | {\n sessionUpdate: \"agent_thought_chunk\";\n content: { type: \"text\"; text: string };\n }\n | {\n sessionUpdate: \"tool_call\";\n toolCallId: string;\n title?: string;\n kind?: \"read\" | \"edit\" | \"search\" | \"execute\" | \"other\";\n status?: \"pending\" | \"in_progress\" | \"completed\" | \"failed\";\n rawInput?: unknown;\n }\n | {\n sessionUpdate: \"tool_call_update\";\n toolCallId: string;\n status?: \"pending\" | \"in_progress\" | \"completed\" | \"failed\";\n content?: Array<{ type: \"content\"; content: { type: \"text\"; text: string } }>;\n }\n | {\n sessionUpdate: \"plan\";\n entries: Array<{\n content: string;\n priority: \"high\" | \"medium\" | \"low\";\n status: \"pending\" | \"in_progress\" | \"completed\";\n }>;\n };\n\nexport interface SessionUpdateParams {\n sessionId: string;\n update: SessionUpdate;\n}\n\nexport interface SessionCancelParams {\n sessionId: string;\n}\n\nexport type PermissionOptionKind = \"allow_once\" | \"allow_always\" | \"reject_once\" | \"reject_always\";\n\nexport interface PermissionOption {\n optionId: string;\n name: string;\n kind: PermissionOptionKind;\n}\n\nexport interface PermissionRequestParams {\n sessionId: string;\n toolCall: {\n toolCallId: string;\n title?: string;\n kind?: \"read\" | \"edit\" | \"search\" | \"execute\" | \"other\";\n status?: \"pending\";\n rawInput?: unknown;\n };\n options: PermissionOption[];\n}\n\nexport type PermissionOutcome =\n | { outcome: \"selected\"; optionId: string }\n | { outcome: \"cancelled\" };\n\nexport interface PermissionRequestResult {\n outcome: PermissionOutcome;\n}\n\nexport const ERR_PARSE = -32700;\nexport const ERR_INVALID_REQUEST = -32600;\nexport const ERR_METHOD_NOT_FOUND = -32601;\nexport const ERR_INVALID_PARAMS = -32602;\nexport const ERR_INTERNAL = -32603;\n\n/** Extract the user prompt text out of ACP content blocks. Resource blocks contribute their inline `text` if present. */\nexport function flattenPrompt(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const b of blocks) {\n if (b.type === \"text\") parts.push(b.text);\n else if (b.type === \"resource\" && b.resource.text) parts.push(b.resource.text);\n }\n return parts.join(\"\\n\\n\").trim();\n}\n","/** NDJSON JSON-RPC 2.0 server — per the ACP transport spec, one JSON object per line, no embedded newlines. */\n\nimport { type Interface, createInterface } from \"node:readline\";\nimport type { Readable, Writable } from \"node:stream\";\nimport {\n ERR_INTERNAL,\n ERR_METHOD_NOT_FOUND,\n ERR_PARSE,\n type JsonRpcId,\n type JsonRpcNotification,\n type JsonRpcRequest,\n type JsonRpcResponse,\n} from \"./protocol.js\";\n\nexport type RequestHandler<P = unknown, R = unknown> = (params: P) => Promise<R> | R;\nexport type NotificationHandler<P = unknown> = (params: P) => Promise<void> | void;\n\nexport interface AcpServerOptions {\n input?: Readable;\n output?: Writable;\n}\n\ninterface PendingOutbound {\n resolve: (value: unknown) => void;\n reject: (err: Error) => void;\n}\n\nexport class AcpServer {\n private requestHandlers = new Map<string, RequestHandler>();\n private notificationHandlers = new Map<string, NotificationHandler>();\n private pending = new Map<JsonRpcId, PendingOutbound>();\n private nextOutboundId = 1;\n private readonly output: Writable;\n private readonly rl: Interface;\n private closed = false;\n\n constructor(opts: AcpServerOptions = {}) {\n this.output = opts.output ?? process.stdout;\n const input = opts.input ?? process.stdin;\n this.rl = createInterface({ input });\n this.rl.on(\"line\", (line) => {\n void this.handleLine(line);\n });\n }\n\n onRequest<P, R>(method: string, handler: RequestHandler<P, R>): void {\n this.requestHandlers.set(method, handler as RequestHandler);\n }\n\n onNotification<P>(method: string, handler: NotificationHandler<P>): void {\n this.notificationHandlers.set(method, handler as NotificationHandler);\n }\n\n sendNotification(method: string, params: unknown): void {\n this.write({ jsonrpc: \"2.0\", method, params });\n }\n\n /** Send an outbound JSON-RPC request and resolve when the peer responds. */\n sendRequest<R = unknown>(method: string, params: unknown): Promise<R> {\n const id = this.nextOutboundId++;\n return new Promise<R>((resolve, reject) => {\n this.pending.set(id, {\n resolve: resolve as (v: unknown) => void,\n reject,\n });\n this.write({ jsonrpc: \"2.0\", id, method, params });\n });\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n for (const p of this.pending.values()) p.reject(new Error(\"server closed\"));\n this.pending.clear();\n this.rl.close();\n }\n\n /** Wait for the input stream to end. */\n done(): Promise<void> {\n return new Promise((resolve) => this.rl.once(\"close\", () => resolve()));\n }\n\n private write(msg: JsonRpcRequest | JsonRpcNotification | JsonRpcResponse): void {\n this.output.write(`${JSON.stringify(msg)}\\n`);\n }\n\n private writeError(id: JsonRpcId | null, code: number, message: string): void {\n this.write({ jsonrpc: \"2.0\", id, error: { code, message } });\n }\n\n private async handleLine(raw: string): Promise<void> {\n const line = raw.trim();\n if (!line) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n this.writeError(null, ERR_PARSE, \"parse error\");\n return;\n }\n if (!parsed || typeof parsed !== \"object\") {\n this.writeError(null, ERR_PARSE, \"expected JSON object\");\n return;\n }\n const msg = parsed as Partial<JsonRpcRequest>;\n if (typeof msg.method === \"string\" && msg.id !== undefined) {\n const id = msg.id as JsonRpcId;\n const handler = this.requestHandlers.get(msg.method);\n if (!handler) {\n this.writeError(id, ERR_METHOD_NOT_FOUND, `method not found: ${msg.method}`);\n return;\n }\n try {\n const result = await handler(msg.params);\n this.write({ jsonrpc: \"2.0\", id, result });\n } catch (err) {\n this.writeError(id, ERR_INTERNAL, (err as Error).message);\n }\n return;\n }\n if (typeof msg.method === \"string\" && msg.id === undefined) {\n const handler = this.notificationHandlers.get(msg.method);\n if (!handler) return;\n try {\n await handler(msg.params);\n } catch {\n // notifications can't be replied to — log channel would help, but stderr would pollute the wire\n }\n return;\n }\n if (msg.id !== undefined && msg.method === undefined) {\n const response = parsed as JsonRpcResponse;\n const pending = this.pending.get(response.id as JsonRpcId);\n if (!pending) return;\n this.pending.delete(response.id as JsonRpcId);\n if (response.error) {\n pending.reject(new Error(response.error.message));\n } else {\n pending.resolve(response.result);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,SAAS,yBAAyB;AAClC,SAA2B,YAAY,gBAAgB;AACvD,SAAS,eAAe;;;ACExB,IAAM,aAAa,oBAAI,IAAI;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,aAAa,oBAAI,IAAI;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,eAAe,oBAAI,IAAI,CAAC,kBAAkB,cAAc,CAAC;AAC/D,IAAM,gBAAgB,oBAAI,IAAI,CAAC,eAAe,gBAAgB,CAAC;AAIxD,SAAS,YAAY,MAA2B;AACrD,MAAI,WAAW,IAAI,IAAI,EAAG,QAAO;AACjC,MAAI,WAAW,IAAI,IAAI,EAAG,QAAO;AACjC,MAAI,aAAa,IAAI,IAAI,EAAG,QAAO;AACnC,MAAI,cAAc,IAAI,IAAI,EAAG,QAAO;AACpC,SAAO;AACT;AAEA,SAAS,aAAa,KAAsB;AAC1C,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,oBAAoB,QAAmB,WAAmB,IAAuB;AAC/F,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK,eAAe;AAClB,UAAI,CAAC,GAAG,KAAM;AACd,YAAM,UAAU,GAAG,YAAY,cAAc,wBAAwB;AACrE,WAAK,QAAQ;AAAA,QACX;AAAA,QACA,QAAQ,EAAE,eAAe,SAAS,SAAS,EAAE,MAAM,QAAQ,MAAM,GAAG,KAAK,EAAE;AAAA,MAC7E,CAAC;AACD;AAAA,IACF;AAAA,IACA,KAAK,kBAAkB;AACrB,WAAK,QAAQ;AAAA,QACX;AAAA,QACA,QAAQ;AAAA,UACN,eAAe;AAAA,UACf,YAAY,GAAG;AAAA,UACf,OAAO,GAAG;AAAA,UACV,MAAM,YAAY,GAAG,IAAI;AAAA,UACzB,QAAQ;AAAA,QACV;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IACA,KAAK,eAAe;AAClB,WAAK,QAAQ;AAAA,QACX;AAAA,QACA,QAAQ;AAAA,UACN,eAAe;AAAA,UACf,YAAY,GAAG;AAAA,UACf,QAAQ;AAAA,QACV;AAAA,MACF,CAAC;AACD,YAAM,WAAW,aAAa,GAAG,IAAI;AACrC,UAAI,aAAa,QAAW;AAC1B,aAAK,QAAQ;AAAA,UACX;AAAA,UACA,QAAQ;AAAA,YACN,eAAe;AAAA,YACf,YAAY,GAAG;AAAA,YACf,OAAO,GAAG;AAAA,YACV,MAAM,YAAY,GAAG,IAAI;AAAA,YACzB,QAAQ;AAAA,YACR;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IACA,KAAK,eAAe;AAClB,WAAK,QAAQ;AAAA,QACX;AAAA,QACA,QAAQ;AAAA,UACN,eAAe;AAAA,UACf,YAAY,GAAG;AAAA,UACf,QAAQ,GAAG,KAAK,cAAc;AAAA,UAC9B,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,SAAS,EAAE,MAAM,QAAQ,MAAM,KAAK,GAAG,MAAM,EAAE;AAAA,YACjD;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAAA,IACA;AACE;AAAA,EACJ;AACF;AAEA,IAAM,mBAAmB;AACzB,SAAS,KAAK,MAAsB;AAClC,MAAI,KAAK,UAAU,iBAAkB,QAAO;AAC5C,SAAO,GAAG,KAAK,MAAM,GAAG,gBAAgB,CAAC;AAAA,SAAO,KAAK,SAAS,gBAAgB;AAChF;AAEA,SAAS,KAAK,QAAmB,QAAmC;AAClE,SAAO,iBAAiB,kBAAkB,MAAM;AAClD;;;AC5GA,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AACxB,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAM,UAAU;AAChB,IAAM,YAAY;AAClB,IAAM,YAAY;AAGX,SAAS,qBAAqB,KAAuC;AAC1E,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,EAAE,UAAU,eAAe,MAAM,cAAc,MAAM,aAAa;AAAA,QAClE,EAAE,UAAU,iBAAiB,MAAM,gBAAgB,MAAM,eAAe;AAAA,QACxE,EAAE,UAAU,WAAW,MAAM,UAAU,MAAM,cAAc;AAAA,MAC7D;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,EAAE,UAAU,eAAe,MAAM,gBAAgB,MAAM,aAAa;AAAA,QACpE,EAAE,UAAU,WAAW,MAAM,UAAU,MAAM,aAAa;AAAA,QAC1D,EAAE,UAAU,WAAW,MAAM,UAAU,MAAM,cAAc;AAAA,MAC7D;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,EAAE,UAAU,eAAe,MAAM,YAAY,MAAM,aAAa;AAAA,QAChE,EAAE,UAAU,WAAW,MAAM,UAAU,MAAM,aAAa;AAAA,QAC1D,EAAE,UAAU,SAAS,MAAM,QAAQ,MAAM,cAAc;AAAA,MACzD;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,EAAE,UAAU,WAAW,MAAM,mBAAmB,MAAM,aAAa;AAAA,QACnE,EAAE,UAAU,WAAW,MAAM,sBAAsB,MAAM,cAAc;AAAA,MACzE;AAAA,IACF,KAAK,UAAU;AACb,YAAM,UAAU,IAAI;AACpB,YAAM,QAA4B,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,QACnE,UAAU,EAAE;AAAA,QACZ,MAAM,EAAE,SAAS,EAAE;AAAA,QACnB,MAAM;AAAA,MACR,EAAE;AACF,WAAK,KAAK,EAAE,UAAU,WAAW,MAAM,UAAU,MAAM,cAAc,CAAC;AACtE,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,cAAc,SAAyB;AAC9C,QAAM,QAAQ,QAAQ,KAAK,EAAE,MAAM,KAAK,EAAE,CAAC,KAAK,QAAQ,KAAK;AAC7D,SAAO,GAAG,KAAK;AACjB;AAEA,SAAS,WAAW,GAAmB;AACrC,SAAO;AACT;AAGO,SAAS,WACd,KACA,QACwF;AACxF,QAAM,YAAY,OAAO,QAAQ,YAAY;AAC7C,QAAM,WAAW,OAAO,QAAQ,YAAY,aAAa,OAAO,QAAQ,WAAW;AACnF,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK;AAAA,IACL,KAAK,kBAAkB;AACrB,UAAI,aAAa,aAAa,UAAW,QAAO,EAAE,MAAM,OAAO;AAC/D,UAAI,aAAa,iBAAiB;AAChC,cAAM,UAAU,IAAI;AACpB,eAAO,EAAE,MAAM,gBAAgB,QAAQ,cAAc,QAAQ,WAAW,EAAE,EAAE;AAAA,MAC9E;AACA,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B;AAAA,IACA,KAAK,eAAe;AAClB,UAAI,aAAa,aAAa,UAAW,QAAO,EAAE,MAAM,OAAO;AAC/D,UAAI,aAAa,iBAAiB;AAChC,cAAM,UAAU,IAAI;AACpB,eAAO,EAAE,MAAM,gBAAgB,QAAQ,WAAW,QAAQ,WAAW,EAAE;AAAA,MACzE;AACA,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B;AAAA,IACA,KAAK,iBAAiB;AACpB,UAAI,aAAa,aAAa,UAAW,QAAO,EAAE,MAAM,SAAS;AACjE,UAAI,aAAa,UAAW,QAAO,EAAE,MAAM,SAAS;AACpD,aAAO,EAAE,MAAM,UAAU;AAAA,IAC3B;AAAA,IACA,KAAK,mBAAmB;AACtB,UAAI,aAAa,aAAa,QAAS,QAAO,EAAE,MAAM,OAAO;AAC7D,UAAI,aAAa,UAAW,QAAO,EAAE,MAAM,SAAS;AACpD,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B;AAAA,IACA,KAAK,iBAAiB;AACpB,UAAI,UAAW,QAAO,EAAE,MAAM,YAAY;AAC1C,UAAI,aAAa,UAAW,QAAO,EAAE,MAAM,WAAW;AACtD,aAAO,EAAE,MAAM,WAAW;AAAA,IAC5B;AAAA,IACA,KAAK,UAAU;AACb,UAAI,aAAa,aAAa,aAAa,CAAC,SAAU,QAAO,EAAE,MAAM,SAAS;AAC9E,aAAO,EAAE,MAAM,QAAQ,SAAS;AAAA,IAClC;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,KAA2B;AACrD,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,uBAAmB,IAAI,QAAiC,WAAW,IAAI,MAAM,GAAG,EAAE,CAAC;AAAA,IAC5F,KAAK;AACH,aAAO,sBAAkB,IAAI,QAA6B,IAAI;AAAA,IAChE,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,qBAAiB,IAAI,QAA+B,SAAS,eAAe;AAAA,IACrF,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAQ,IAAI,QAAkC,YAAY;AAAA,EAC9D;AACF;AAEA,SAAS,kBAAkB,KAAiD;AAC1E,MAAI,IAAI,SAAS,iBAAiB,IAAI,SAAS,iBAAkB,QAAO;AACxE,MAAI,IAAI,SAAS,eAAe;AAC9B,WAAQ,IAAI,QAAgC,WAAW,UAAU,SAAS;AAAA,EAC5E;AACA,SAAO;AACT;AAGA,eAAsB,yBACpB,QACA,WACA,KACiG;AACjG,QAAM,SAAkC;AAAA,IACtC;AAAA,IACA,UAAU;AAAA,MACR,YAAY,QAAQ,IAAI,EAAE;AAAA,MAC1B,OAAO,mBAAmB,GAAG;AAAA,MAC7B,MAAM,kBAAkB,GAAG;AAAA,MAC3B,QAAQ;AAAA,MACR,UAAU,IAAI;AAAA,IAChB;AAAA,IACA,SAAS,qBAAqB,GAAG;AAAA,EACnC;AACA,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,OAAO;AAAA,MACpB;AAAA,MACA;AAAA,IACF;AAAA,EACF,QAAQ;AACN,aAAS,EAAE,SAAS,EAAE,SAAS,YAAY,EAAE;AAAA,EAC/C;AACA,SAAO,WAAW,KAAK,MAAM;AAC/B;;;AC9KO,IAAM,uBAAuB;AAsJ7B,IAAM,YAAY;AAElB,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAC3B,IAAM,eAAe;AAGrB,SAAS,cAAc,QAAgC;AAC5D,QAAM,QAAkB,CAAC;AACzB,aAAW,KAAK,QAAQ;AACtB,QAAI,EAAE,SAAS,OAAQ,OAAM,KAAK,EAAE,IAAI;AAAA,aAC/B,EAAE,SAAS,cAAc,EAAE,SAAS,KAAM,OAAM,KAAK,EAAE,SAAS,IAAI;AAAA,EAC/E;AACA,SAAO,MAAM,KAAK,MAAM,EAAE,KAAK;AACjC;;;ACpKA,SAAyB,uBAAuB;AAyBzC,IAAM,YAAN,MAAgB;AAAA,EACb,kBAAkB,oBAAI,IAA4B;AAAA,EAClD,uBAAuB,oBAAI,IAAiC;AAAA,EAC5D,UAAU,oBAAI,IAAgC;AAAA,EAC9C,iBAAiB;AAAA,EACR;AAAA,EACA;AAAA,EACT,SAAS;AAAA,EAEjB,YAAY,OAAyB,CAAC,GAAG;AACvC,SAAK,SAAS,KAAK,UAAU,QAAQ;AACrC,UAAM,QAAQ,KAAK,SAAS,QAAQ;AACpC,SAAK,KAAK,gBAAgB,EAAE,MAAM,CAAC;AACnC,SAAK,GAAG,GAAG,QAAQ,CAAC,SAAS;AAC3B,WAAK,KAAK,WAAW,IAAI;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,UAAgB,QAAgB,SAAqC;AACnE,SAAK,gBAAgB,IAAI,QAAQ,OAAyB;AAAA,EAC5D;AAAA,EAEA,eAAkB,QAAgB,SAAuC;AACvE,SAAK,qBAAqB,IAAI,QAAQ,OAA8B;AAAA,EACtE;AAAA,EAEA,iBAAiB,QAAgB,QAAuB;AACtD,SAAK,MAAM,EAAE,SAAS,OAAO,QAAQ,OAAO,CAAC;AAAA,EAC/C;AAAA;AAAA,EAGA,YAAyB,QAAgB,QAA6B;AACpE,UAAM,KAAK,KAAK;AAChB,WAAO,IAAI,QAAW,CAACA,UAAS,WAAW;AACzC,WAAK,QAAQ,IAAI,IAAI;AAAA,QACnB,SAASA;AAAA,QACT;AAAA,MACF,CAAC;AACD,WAAK,MAAM,EAAE,SAAS,OAAO,IAAI,QAAQ,OAAO,CAAC;AAAA,IACnD,CAAC;AAAA,EACH;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,OAAQ;AACjB,SAAK,SAAS;AACd,eAAW,KAAK,KAAK,QAAQ,OAAO,EAAG,GAAE,OAAO,IAAI,MAAM,eAAe,CAAC;AAC1E,SAAK,QAAQ,MAAM;AACnB,SAAK,GAAG,MAAM;AAAA,EAChB;AAAA;AAAA,EAGA,OAAsB;AACpB,WAAO,IAAI,QAAQ,CAACA,aAAY,KAAK,GAAG,KAAK,SAAS,MAAMA,SAAQ,CAAC,CAAC;AAAA,EACxE;AAAA,EAEQ,MAAM,KAAmE;AAC/E,SAAK,OAAO,MAAM,GAAG,KAAK,UAAU,GAAG,CAAC;AAAA,CAAI;AAAA,EAC9C;AAAA,EAEQ,WAAW,IAAsB,MAAc,SAAuB;AAC5E,SAAK,MAAM,EAAE,SAAS,OAAO,IAAI,OAAO,EAAE,MAAM,QAAQ,EAAE,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAc,WAAW,KAA4B;AACnD,UAAM,OAAO,IAAI,KAAK;AACtB,QAAI,CAAC,KAAM;AACX,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,WAAK,WAAW,MAAM,WAAW,aAAa;AAC9C;AAAA,IACF;AACA,QAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAK,WAAW,MAAM,WAAW,sBAAsB;AACvD;AAAA,IACF;AACA,UAAM,MAAM;AACZ,QAAI,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,QAAW;AAC1D,YAAM,KAAK,IAAI;AACf,YAAM,UAAU,KAAK,gBAAgB,IAAI,IAAI,MAAM;AACnD,UAAI,CAAC,SAAS;AACZ,aAAK,WAAW,IAAI,sBAAsB,qBAAqB,IAAI,MAAM,EAAE;AAC3E;AAAA,MACF;AACA,UAAI;AACF,cAAM,SAAS,MAAM,QAAQ,IAAI,MAAM;AACvC,aAAK,MAAM,EAAE,SAAS,OAAO,IAAI,OAAO,CAAC;AAAA,MAC3C,SAAS,KAAK;AACZ,aAAK,WAAW,IAAI,cAAe,IAAc,OAAO;AAAA,MAC1D;AACA;AAAA,IACF;AACA,QAAI,OAAO,IAAI,WAAW,YAAY,IAAI,OAAO,QAAW;AAC1D,YAAM,UAAU,KAAK,qBAAqB,IAAI,IAAI,MAAM;AACxD,UAAI,CAAC,QAAS;AACd,UAAI;AACF,cAAM,QAAQ,IAAI,MAAM;AAAA,MAC1B,QAAQ;AAAA,MAER;AACA;AAAA,IACF;AACA,QAAI,IAAI,OAAO,UAAa,IAAI,WAAW,QAAW;AACpD,YAAM,WAAW;AACjB,YAAM,UAAU,KAAK,QAAQ,IAAI,SAAS,EAAe;AACzD,UAAI,CAAC,QAAS;AACd,WAAK,QAAQ,OAAO,SAAS,EAAe;AAC5C,UAAI,SAAS,OAAO;AAClB,gBAAQ,OAAO,IAAI,MAAM,SAAS,MAAM,OAAO,CAAC;AAAA,MAClD,OAAO;AACL,gBAAQ,QAAQ,SAAS,MAAM;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;;;AJlEA,SAAS,iBACP,UACA,WACA,cACQ;AACR,MAAI,SAAU,QAAO,GAAG,QAAQ;AAChC,MAAI,cAAc,KAAK,aAAc,QAAO;AAC5C,SAAO;AACT;AAGA,eAAsB,eACpB,OACA,OACA,cACsB;AACtB,QAAM,UAAuB,CAAC;AAC9B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,MAAM,WAAW;AACvB,QAAM,gBAAgB,IAAI,IAAI,IAAI,eAAe,CAAC,CAAC;AACnD,aAAW,OAAO,OAAO;AACvB,QAAI,QAAQ;AACZ,QAAI;AACJ,QAAI;AACF,YAAM,OAAO,aAAa,GAAG;AAC7B,cAAQ,KAAK,QAAQ;AACrB,UAAI,KAAK,QAAQ,cAAc,IAAI,KAAK,IAAI,GAAG;AAC7C,gBAAQ,OAAO,MAAM,GAAG,wBAAwB,EAAE,OAAO,YAAY,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AACvF;AAAA,MACF;AACA,cAAQ,OAAO,MAAM,GAAG,wBAAwB,EAAE,OAAO,aAAa,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AACxF,YAAM,KAAK,KAAK,IAAI;AACpB,YAAM,SAAS,iBAAiB,KAAK,MAAM,MAAM,QAAQ,YAAY;AACrE,UAAI,KAAK,cAAc,QAAS,oBAAmB,IAAI;AACvD,YAAM,YAAY,uBAAuB,MAAM,EAAE,KAAK,UAAU,KAAK,MAAM,GAAG,EAAE,CAAC;AACjF,YAAM,IAAI,UAAU,EAAE,UAAU,CAAC;AACjC,YAAM,IAAI,WAAW;AACrB,YAAM,SAAS,MAAM,eAAe,KAAK;AAAA,QACvC,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ,CAAC,SACP,QAAQ,OAAO;AAAA,UACb,GAAG,mBAAmB,EAAE,MAAM,KAAK,YAAY,OAAO,KAAK,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC;AAAA;AAAA,QAClG;AAAA,MACJ,CAAC;AACD,cAAQ,OAAO;AAAA,QACb,GAAG,wBAAwB;AAAA,UACzB,OAAO;AAAA,UACP,MAAM;AAAA,UACN,OAAO,OAAO,gBAAgB;AAAA,UAC9B,IAAI,KAAK,IAAI,IAAI;AAAA,QACnB,CAAC,CAAC;AAAA;AAAA,MACJ;AACA,cAAQ,KAAK,GAAG;AAAA,IAClB,SAAS,KAAK;AACZ,YAAM,KAAK,MAAM,EAAE,MAAM,MAAM,MAAS;AACxC,cAAQ,OAAO;AAAA,QACb,GAAG,wBAAwB,EAAE,OAAO,UAAU,MAAM,OAAO,QAAS,IAAc,QAAQ,CAAC,CAAC;AAAA,WAAS,EAAE,oCAAoC,CAAC;AAAA;AAAA,MAC9I;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,KAAyB,UAA0B;AACrE,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,QAAQ,GAAG;AACvB,MAAI,CAAC,WAAW,GAAG,KAAK,CAAC,SAAS,GAAG,EAAE,YAAY,GAAG;AACpD,UAAM,IAAI,MAAM,kCAAkC,GAAG,EAAE;AAAA,EACzD;AACA,SAAO;AACT;AAEA,eAAe,aAAa,MAMP;AACnB,QAAM,SAAS,oBAAoB,WAAW,CAAC;AAC/C,QAAM,WAAW,cAAc,MAAM;AACrC,QAAM,QAAQ,KAAK,iBAAiB,SAAS;AAC7C,QAAM,UAAU,MAAM,iBAAiB,EAAE,SAAS,KAAK,QAAQ,CAAC;AAEhE,QAAM,aAAa,MAAM,eAAe,QAAQ,OAAO,KAAK,YAAY,CAAC,GAAG,KAAK,SAAS;AAC1F,QAAM,SAAS,iBAAiB,KAAK,SAAS;AAAA,IAC5C,mBAAmB,QAAQ,SAAS;AAAA,IACpC,SAAS;AAAA,EACX,CAAC;AACD,QAAM,SAAS,IAAI,eAAe,EAAE,SAAS,YAAY,EAAE,CAAC;AAC5D,QAAM,SAAS,IAAI,gBAAgB,EAAE,QAAQ,WAAW,QAAQ,MAAM,MAAM,EAAE,CAAC;AAC/E,QAAM,OAAO,IAAI,eAAe;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,OAAO,QAAQ;AAAA,IACf;AAAA,IACA,WAAW,KAAK;AAAA,IAChB,SAAS,OAAO,gBAAgB,CAAC;AAAA,EACnC,CAAC;AACD,SAAO;AAAA,IACL,IAAI,QAAQ,gBAAgB,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IACvE,SAAS,KAAK;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,IAAI,UAAU;AAAA,IACzB,KAAK;AAAA,MACH;AAAA,MACA,YAAY,OAAO;AAAA,MACnB,iBAAiB,oBAAoB;AAAA,IACvC;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAEA,eAAsB,WAAW,MAAiC;AAChE,aAAW;AACX,MAAI,WAAW,GAAG;AAChB,YAAQ,IAAI,mBAAmB,WAAW;AAAA,EAC5C;AAEA,QAAM,aAAa,WAAW,KAAK,KAAK,QAAQ,IAAI,CAAC;AACrD,QAAM,WAAW,oBAAI,IAAqB;AAC1C,QAAM,iBAAiB,IAAI,kBAA0B;AACrD,QAAM,SAAS,IAAI,UAAU;AAE7B,MAAI,mBAAuC;AAC3C,MAAI,KAAK,YAAY;AACnB,UAAM,eAAe,KAAK,SAAS,cAAc,oBAAoB,WAAW,CAAC,CAAC,EAAE;AACpF,uBAAmB,mBAAmB,KAAK,YAAY;AAAA,MACrD,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,CAAC;AAAA,EACH;AAEA,YAAU,GAAG,CAAC,QAAQ;AACpB,UAAM,WAAW,KAAK,OAAO,SAAS,aAAa;AACnD,UAAM,OAAO,mBAAmB,KAAK,QAAQ;AAC7C,QAAI,SAAS,MAAM;AACjB,gBAAU,QAAQ,IAAI,IAAI,IAAI;AAC9B;AAAA,IACF;AACA,UAAM,kBAAkB,eAAe,SAAS;AAChD,QAAI,CAAC,mBAAmB,CAAC,SAAS,IAAI,eAAe,GAAG;AACtD,gBAAU,OAAO,IAAI,EAAE;AACvB;AAAA,IACF;AACA,UAAM,YAAY;AAChB,YAAM,UAAU,MAAM,yBAAyB,QAAQ,iBAAiB,GAAG;AAC3E,gBAAU,QAAQ,IAAI,IAAI,OAAO;AAAA,IACnC,GAAG;AAAA,EACL,CAAC;AAED,SAAO,UAA8C,cAAc,CAAC,WAAW;AAC7E,QAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,YAAM,OAAO,OAAO,IAAI,MAAM,4BAA4B,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAAA,IAC3F;AACA,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,QACjB,aAAa;AAAA,QACb,oBAAoB,EAAE,OAAO,OAAO,OAAO,OAAO,iBAAiB,KAAK;AAAA,QACxE,iBAAiB,EAAE,MAAM,OAAO,KAAK,MAAM;AAAA,MAC7C;AAAA,MACA,WAAW,EAAE,MAAM,YAAY,OAAO,YAAY,SAAS,QAAQ;AAAA,MACnE,aAAa,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAO,UAA8C,eAAe,OAAO,WAAW;AACpF,UAAM,UAAU,WAAW,QAAQ,KAAK,UAAU;AAClD,UAAM,UAAU,MAAM,aAAa;AAAA,MACjC;AAAA,MACA,eAAe,KAAK;AAAA,MACpB,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,IAClB,CAAC;AACD,aAAS,IAAI,QAAQ,IAAI,OAAO;AAChC,WAAO,EAAE,WAAW,QAAQ,GAAG;AAAA,EACjC,CAAC;AAED,SAAO,UAAoD,kBAAkB,OAAO,WAAW;AAC7F,QAAI,CAAC,QAAQ,WAAW;AACtB,YAAM,OAAO,OAAO,IAAI,MAAM,mCAAmC,GAAG;AAAA,QAClE,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,UAAM,UAAU,SAAS,IAAI,OAAO,SAAS;AAC7C,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,OAAO,IAAI,MAAM,mCAAmC,OAAO,SAAS,EAAE,GAAG;AAAA,QACpF,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,UAAM,OAAO,cAAc,OAAO,MAAwB;AAC1D,QAAI,CAAC,MAAM;AACT,YAAM,OAAO,OAAO,IAAI,MAAM,8BAA8B,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAAA,IAC7F;AACA,YAAQ,UAAU,IAAI,gBAAgB;AACtC,QAAI,aAAyB;AAC7B,QAAI;AACF,YAAM,eAAe,IAAI,QAAQ,IAAI,YAAY;AAC/C,yBAAiB,MAAM,QAAQ,KAAK,KAAK,IAAI,GAAG;AAC9C,cAAI,QAAQ,SAAS,OAAO,SAAS;AACnC,yBAAa;AACb;AAAA,UACF;AAEA,cAAI,kBAAkB;AACpB;AAAA,cACE;AAAA,cACA,oBAAoB,IAAI;AAAA,gBACtB,OAAO,QAAQ,IAAI;AAAA,gBACnB,YAAY,QAAQ,IAAI;AAAA,cAC1B,CAAC;AAAA,YACH;AAAA,UACF;AACA,qBAAW,OAAO,QAAQ,UAAU,QAAQ,IAAI,QAAQ,GAAG,GAAG;AAC5D,gCAAoB,QAAQ,QAAQ,IAAI,GAAG;AAC3C,gBAAI,IAAI,SAAS,QAAS,cAAa;AAAA,UACzC;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,UAAW,IAAc;AAC/B,aAAO,iBAAiB,kBAAkB;AAAA,QACxC,WAAW,QAAQ;AAAA,QACnB,QAAQ;AAAA,UACN,eAAe;AAAA,UACf,SAAS,EAAE,MAAM,QAAQ,MAAM;AAAA;AAAA,UAAe,OAAO,GAAG;AAAA,QAC1D;AAAA,MACF,CAA+B;AAC/B,mBAAa;AAAA,IACf,UAAE;AACA,cAAQ,UAAU;AAAA,IACpB;AACA,WAAO,EAAE,WAAW;AAAA,EACtB,CAAC;AAED,SAAO,eAAoC,kBAAkB,CAAC,WAAW;AACvE,UAAM,UAAU,QAAQ,YAAY,SAAS,IAAI,OAAO,SAAS,IAAI;AACrE,aAAS,SAAS,MAAM;AAAA,EAC1B,CAAC;AAED,MAAI;AACF,UAAM,OAAO,KAAK;AAAA,EACpB,UAAE;AACA,sBAAkB,IAAI;AAEtB,UAAM,SAA6B,CAAC;AACpC,eAAW,WAAW,SAAS,OAAO,GAAG;AACvC,iBAAW,OAAO,QAAQ,YAAY;AACpC,eAAO,KAAK,IAAI,MAAM,EAAE,MAAM,MAAM,MAAS,CAAC;AAAA,MAChD;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,MAAM;AAAA,EAC1B;AACF;","names":["resolve"]}
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+ import {
4
+ chatCommand
5
+ } from "./chunk-P7EKE5ZQ.js";
6
+ import "./chunk-2Z35JOA4.js";
7
+ import "./chunk-JMBMLOBP.js";
8
+ import "./chunk-3Z6IBU3D.js";
9
+ import "./chunk-45U62RI3.js";
10
+ import "./chunk-H6PS7IUE.js";
11
+ import "./chunk-PQXPXJBJ.js";
12
+ import "./chunk-ZZM6QJ4W.js";
13
+ import "./chunk-2R4QCDOZ.js";
14
+ import "./chunk-F3PXYSNN.js";
15
+ import "./chunk-FHOGSSCH.js";
16
+ import "./chunk-6AK4EY3D.js";
17
+ import "./chunk-5JJRUIPA.js";
18
+ import "./chunk-6PZ3CXBP.js";
19
+ import "./chunk-TJX6BFZZ.js";
20
+ import "./chunk-6G3CUUFG.js";
21
+ import "./chunk-2425HK6U.js";
22
+ import "./chunk-VK5HG73G.js";
23
+ import "./chunk-74EX7SUH.js";
24
+ import "./chunk-PV55UMTO.js";
25
+ import "./chunk-2KDUS647.js";
26
+ import "./chunk-25T6CVUP.js";
27
+ import "./chunk-2UQP6H6T.js";
28
+ import "./chunk-OSZC7C6F.js";
29
+ import "./chunk-SZ5XES2N.js";
30
+ import "./chunk-3BXRZFWS.js";
31
+ import "./chunk-4QUNBQQ2.js";
32
+ import "./chunk-XJXDHAES.js";
33
+ import "./chunk-O52OLQL3.js";
34
+ import "./chunk-2K65GZBT.js";
35
+ import "./chunk-PLHAZOLZ.js";
36
+ import "./chunk-DOYHN4KB.js";
37
+ import "./chunk-XCGGEJTI.js";
38
+ import "./chunk-7O5ALB4C.js";
39
+ import "./chunk-S4XVGLRW.js";
40
+ import "./chunk-6PBZN4VI.js";
41
+ import "./chunk-RE4RAVFF.js";
42
+ import "./chunk-XPDVG52A.js";
43
+ import "./chunk-HFEAY5DT.js";
44
+ import "./chunk-YQ6NTIIE.js";
45
+ import "./chunk-XXC2BYTV.js";
46
+ import "./chunk-TUK7OWJA.js";
47
+ export {
48
+ chatCommand
49
+ };
50
+ //# sourceMappingURL=chat-7ES4IBNH.js.map
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
2
3
 
3
4
  // src/cli/ui/presets.ts
4
5
  var PRESETS = {
@@ -50,4 +51,4 @@ export {
50
51
  resolvePreset,
51
52
  canonicalPresetName
52
53
  };
53
- //# sourceMappingURL=chunk-E46ECXJD.js.map
54
+ //# sourceMappingURL=chunk-2425HK6U.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/ui/presets.ts"],"sourcesContent":["import type { PresetName } from \"../../config.js\";\n\nexport interface PresetSettings {\n model: string;\n reasoningEffort: \"high\" | \"max\";\n autoEscalate: boolean;\n}\n\n/** Old names `fast`/`smart`/`max` aliased via `resolvePreset` so legacy configs still load. */\nexport const PRESETS: Record<\"auto\" | \"flash\" | \"pro\", PresetSettings> = {\n auto: {\n model: \"deepseek-v4-flash\",\n reasoningEffort: \"max\",\n autoEscalate: true,\n },\n flash: {\n model: \"deepseek-v4-flash\",\n reasoningEffort: \"max\",\n autoEscalate: false,\n },\n pro: {\n model: \"deepseek-v4-pro\",\n reasoningEffort: \"max\",\n autoEscalate: false,\n },\n};\n\nexport const PRESET_DESCRIPTIONS: Record<\n \"auto\" | \"flash\" | \"pro\",\n { headline: string; cost: string }\n> = {\n auto: {\n headline: \"flash → pro on hard turns\",\n cost: \"default · ~96% turns stay on flash · pro kicks in only when needed\",\n },\n flash: {\n headline: \"v4-flash always\",\n cost: \"cheapest · predictable · /pro still works for a one-turn bump\",\n },\n pro: {\n headline: \"v4-pro always\",\n cost: \"~3× flash (5/31 discount) / ~12× full price · for hard multi-turn work\",\n },\n};\n\n/** Legacy aliases: fast→flash+high, smart→auto, max→pro. Unknown names fall through to auto. */\nexport function resolvePreset(name: PresetName | undefined): PresetSettings {\n if (name === \"auto\" || name === \"flash\" || name === \"pro\") return PRESETS[name];\n if (name === \"fast\") return { ...PRESETS.flash, reasoningEffort: \"high\" };\n if (name === \"smart\") return PRESETS.auto;\n if (name === \"max\") return PRESETS.pro;\n return PRESETS.auto;\n}\n\n/** Canonical name for storage / display — unknown values become auto. */\nexport function canonicalPresetName(name: PresetName | undefined): \"auto\" | \"flash\" | \"pro\" {\n if (name === \"auto\" || name === \"flash\" || name === \"pro\") return name;\n return \"auto\";\n}\n"],"mappings":";;;AASO,IAAM,UAA4D;AAAA,EACvE,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AACF;AAEO,IAAM,sBAGT;AAAA,EACF,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,OAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,KAAK;AAAA,IACH,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AACF;AAGO,SAAS,cAAc,MAA8C;AAC1E,MAAI,SAAS,UAAU,SAAS,WAAW,SAAS,MAAO,QAAO,QAAQ,IAAI;AAC9E,MAAI,SAAS,OAAQ,QAAO,EAAE,GAAG,QAAQ,OAAO,iBAAiB,OAAO;AACxE,MAAI,SAAS,QAAS,QAAO,QAAQ;AACrC,MAAI,SAAS,MAAO,QAAO,QAAQ;AACnC,SAAO,QAAQ;AACjB;AAGO,SAAS,oBAAoB,MAAwD;AAC1F,MAAI,SAAS,UAAU,SAAS,WAAW,SAAS,MAAO,QAAO;AAClE,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/cli/ui/presets.ts"],"sourcesContent":["import type { PresetName } from \"../../config.js\";\n\nexport interface PresetSettings {\n model: string;\n reasoningEffort: \"high\" | \"max\";\n autoEscalate: boolean;\n}\n\n/** Old names `fast`/`smart`/`max` aliased via `resolvePreset` so legacy configs still load. */\nexport const PRESETS: Record<\"auto\" | \"flash\" | \"pro\", PresetSettings> = {\n auto: {\n model: \"deepseek-v4-flash\",\n reasoningEffort: \"max\",\n autoEscalate: true,\n },\n flash: {\n model: \"deepseek-v4-flash\",\n reasoningEffort: \"max\",\n autoEscalate: false,\n },\n pro: {\n model: \"deepseek-v4-pro\",\n reasoningEffort: \"max\",\n autoEscalate: false,\n },\n};\n\nexport const PRESET_DESCRIPTIONS: Record<\n \"auto\" | \"flash\" | \"pro\",\n { headline: string; cost: string }\n> = {\n auto: {\n headline: \"flash → pro on hard turns\",\n cost: \"default · ~96% turns stay on flash · pro kicks in only when needed\",\n },\n flash: {\n headline: \"v4-flash always\",\n cost: \"cheapest · predictable · /pro still works for a one-turn bump\",\n },\n pro: {\n headline: \"v4-pro always\",\n cost: \"~3× flash (5/31 discount) / ~12× full price · for hard multi-turn work\",\n },\n};\n\n/** Legacy aliases: fast→flash+high, smart→auto, max→pro. Unknown names fall through to auto. */\nexport function resolvePreset(name: PresetName | undefined): PresetSettings {\n if (name === \"auto\" || name === \"flash\" || name === \"pro\") return PRESETS[name];\n if (name === \"fast\") return { ...PRESETS.flash, reasoningEffort: \"high\" };\n if (name === \"smart\") return PRESETS.auto;\n if (name === \"max\") return PRESETS.pro;\n return PRESETS.auto;\n}\n\n/** Canonical name for storage / display — unknown values become auto. */\nexport function canonicalPresetName(name: PresetName | undefined): \"auto\" | \"flash\" | \"pro\" {\n if (name === \"auto\" || name === \"flash\" || name === \"pro\") return name;\n return \"auto\";\n}\n"],"mappings":";;;;AASO,IAAM,UAA4D;AAAA,EACvE,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,cAAc;AAAA,EAChB;AACF;AAEO,IAAM,sBAGT;AAAA,EACF,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,OAAO;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAAA,EACA,KAAK;AAAA,IACH,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AACF;AAGO,SAAS,cAAc,MAA8C;AAC1E,MAAI,SAAS,UAAU,SAAS,WAAW,SAAS,MAAO,QAAO,QAAQ,IAAI;AAC9E,MAAI,SAAS,OAAQ,QAAO,EAAE,GAAG,QAAQ,OAAO,iBAAiB,OAAO;AACxE,MAAI,SAAS,QAAS,QAAO,QAAQ;AACrC,MAAI,SAAS,MAAO,QAAO,QAAQ;AACnC,SAAO,QAAQ;AACjB;AAGO,SAAS,oBAAoB,MAAwD;AAC1F,MAAI,SAAS,UAAU,SAAS,WAAW,SAAS,MAAO,QAAO;AAClE,SAAO;AACT;","names":[]}
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+
4
+ // node_modules/eventsource-parser/dist/index.js
5
+ var ParseError = class extends Error {
6
+ constructor(message, options) {
7
+ super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
8
+ }
9
+ };
10
+ var LF = 10;
11
+ var CR = 13;
12
+ var SPACE = 32;
13
+ function noop(_arg) {
14
+ }
15
+ function createParser(callbacks) {
16
+ if (typeof callbacks == "function")
17
+ throw new TypeError(
18
+ "`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
19
+ );
20
+ const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks, pendingFragments = [];
21
+ let isFirstChunk = true, id, data = "", dataLines = 0, eventType;
22
+ function feed(chunk) {
23
+ if (isFirstChunk && (isFirstChunk = false, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
24
+ const trailing2 = processLines(chunk);
25
+ trailing2 !== "" && pendingFragments.push(trailing2);
26
+ return;
27
+ }
28
+ if (chunk.indexOf(`
29
+ `) === -1 && chunk.indexOf("\r") === -1) {
30
+ pendingFragments.push(chunk);
31
+ return;
32
+ }
33
+ pendingFragments.push(chunk);
34
+ const input = pendingFragments.join("");
35
+ pendingFragments.length = 0;
36
+ const trailing = processLines(input);
37
+ trailing !== "" && pendingFragments.push(trailing);
38
+ }
39
+ function processLines(chunk) {
40
+ let searchIndex = 0;
41
+ if (chunk.indexOf("\r") === -1) {
42
+ let lfIndex = chunk.indexOf(`
43
+ `, searchIndex);
44
+ for (; lfIndex !== -1; ) {
45
+ if (searchIndex === lfIndex) {
46
+ dataLines > 0 && onEvent({ id, event: eventType, data }), id = void 0, data = "", dataLines = 0, eventType = void 0, searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
47
+ `, searchIndex);
48
+ continue;
49
+ }
50
+ const firstCharCode = chunk.charCodeAt(searchIndex);
51
+ if (isDataPrefix(chunk, searchIndex, firstCharCode)) {
52
+ const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5, value = chunk.slice(valueStart, lfIndex);
53
+ if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {
54
+ onEvent({ id, event: eventType, data: value }), id = void 0, data = "", eventType = void 0, searchIndex = lfIndex + 2, lfIndex = chunk.indexOf(`
55
+ `, searchIndex);
56
+ continue;
57
+ }
58
+ data = dataLines === 0 ? value : `${data}
59
+ ${value}`, dataLines++;
60
+ } else isEventPrefix(chunk, searchIndex, firstCharCode) ? eventType = chunk.slice(
61
+ chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,
62
+ lfIndex
63
+ ) || void 0 : parseLine(chunk, searchIndex, lfIndex);
64
+ searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
65
+ `, searchIndex);
66
+ }
67
+ return chunk.slice(searchIndex);
68
+ }
69
+ for (; searchIndex < chunk.length; ) {
70
+ const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
71
+ `, searchIndex);
72
+ let lineEnd = -1;
73
+ if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = crIndex < lfIndex ? crIndex : lfIndex : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1)
74
+ break;
75
+ parseLine(chunk, searchIndex, lineEnd), searchIndex = lineEnd + 1, chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF && searchIndex++;
76
+ }
77
+ return chunk.slice(searchIndex);
78
+ }
79
+ function parseLine(chunk, start, end) {
80
+ if (start === end) {
81
+ dispatchEvent();
82
+ return;
83
+ }
84
+ const firstCharCode = chunk.charCodeAt(start);
85
+ if (isDataPrefix(chunk, start, firstCharCode)) {
86
+ const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end);
87
+ data = dataLines === 0 ? value2 : `${data}
88
+ ${value2}`, dataLines++;
89
+ return;
90
+ }
91
+ if (isEventPrefix(chunk, start, firstCharCode)) {
92
+ eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || void 0;
93
+ return;
94
+ }
95
+ if (firstCharCode === 105 && chunk.charCodeAt(start + 1) === 100 && chunk.charCodeAt(start + 2) === 58) {
96
+ const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);
97
+ id = value2.includes("\0") ? void 0 : value2;
98
+ return;
99
+ }
100
+ if (firstCharCode === 58) {
101
+ if (onComment) {
102
+ const line2 = chunk.slice(start, end);
103
+ onComment(line2.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));
104
+ }
105
+ return;
106
+ }
107
+ const line = chunk.slice(start, end), fieldSeparatorIndex = line.indexOf(":");
108
+ if (fieldSeparatorIndex === -1) {
109
+ processField(line, "", line);
110
+ return;
111
+ }
112
+ const field = line.slice(0, fieldSeparatorIndex), offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
113
+ processField(field, value, line);
114
+ }
115
+ function processField(field, value, line) {
116
+ switch (field) {
117
+ case "event":
118
+ eventType = value || void 0;
119
+ break;
120
+ case "data":
121
+ data = dataLines === 0 ? value : `${data}
122
+ ${value}`, dataLines++;
123
+ break;
124
+ case "id":
125
+ id = value.includes("\0") ? void 0 : value;
126
+ break;
127
+ case "retry":
128
+ /^\d+$/.test(value) ? onRetry(parseInt(value, 10)) : onError(
129
+ new ParseError(`Invalid \`retry\` value: "${value}"`, {
130
+ type: "invalid-retry",
131
+ value,
132
+ line
133
+ })
134
+ );
135
+ break;
136
+ default:
137
+ onError(
138
+ new ParseError(
139
+ `Unknown field "${field.length > 20 ? `${field.slice(0, 20)}\u2026` : field}"`,
140
+ { type: "unknown-field", field, value, line }
141
+ )
142
+ );
143
+ break;
144
+ }
145
+ }
146
+ function dispatchEvent() {
147
+ dataLines > 0 && onEvent({
148
+ id,
149
+ event: eventType,
150
+ data
151
+ }), id = void 0, data = "", dataLines = 0, eventType = void 0;
152
+ }
153
+ function reset(options = {}) {
154
+ if (options.consume && pendingFragments.length > 0) {
155
+ const incompleteLine = pendingFragments.join("");
156
+ parseLine(incompleteLine, 0, incompleteLine.length);
157
+ }
158
+ isFirstChunk = true, id = void 0, data = "", dataLines = 0, eventType = void 0, pendingFragments.length = 0;
159
+ }
160
+ return { feed, reset };
161
+ }
162
+ function isDataPrefix(chunk, i, firstCharCode) {
163
+ return firstCharCode === 100 && chunk.charCodeAt(i + 1) === 97 && chunk.charCodeAt(i + 2) === 116 && chunk.charCodeAt(i + 3) === 97 && chunk.charCodeAt(i + 4) === 58;
164
+ }
165
+ function isEventPrefix(chunk, i, firstCharCode) {
166
+ return firstCharCode === 101 && chunk.charCodeAt(i + 1) === 118 && chunk.charCodeAt(i + 2) === 101 && chunk.charCodeAt(i + 3) === 110 && chunk.charCodeAt(i + 4) === 116 && chunk.charCodeAt(i + 5) === 58;
167
+ }
168
+
169
+ export {
170
+ createParser
171
+ };
172
+ //# sourceMappingURL=chunk-25T6CVUP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../node_modules/eventsource-parser/src/errors.ts","../../node_modules/eventsource-parser/src/parse.ts"],"sourcesContent":["/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of an unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of an unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserCallbacks} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\n\n// oxlint-disable-next-line no-unused-vars\nfunction noop(_arg: unknown) {\n // intentional noop\n}\n\n/**\n * Creates a new EventSource parser.\n *\n * @param callbacks - Callbacks to invoke on different parsing events:\n * - `onEvent` when a new event is parsed\n * - `onError` when an error occurs\n * - `onRetry` when a new reconnection interval has been sent from the server\n * - `onComment` when a comment is encountered in the stream\n *\n * @returns A new EventSource parser, with `parse` and `reset` methods.\n * @public\n */\nexport function createParser(callbacks: ParserCallbacks): EventSourceParser {\n if (typeof callbacks === 'function') {\n throw new TypeError(\n '`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?',\n )\n }\n\n const {onEvent = noop, onError = noop, onRetry = noop, onComment} = callbacks\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, a UTF-8 BOM (0xEF 0xBB 0xBF) at the start of the very\n * first chunk is stripped before parsing.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (isFirstChunk) {\n isFirstChunk = false\n // Match and strip UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream)\n if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (pendingFragments.length === 0) {\n const trailing = processLines(chunk)\n if (trailing !== '') pendingFragments.push(trailing)\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n pendingFragments.push(chunk)\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n const trailing = processLines(input)\n if (trailing !== '') pendingFragments.push(trailing)\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (dataLines > 0) {\n onEvent({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n onEvent({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n id = value.includes('\\0') ? undefined : value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n id = value.includes('\\0') ? undefined : value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry(parseInt(value, 10))\n } else {\n onError(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (dataLines > 0) {\n onEvent({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n"],"mappings":"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","names":["trailing","value","line"]}
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
2
3
 
3
4
  // src/memory/project.ts
4
5
  import { existsSync, readFileSync, statSync } from "fs";
@@ -103,6 +104,11 @@ If you have a search tool (\`search_content\`, \`grep\`, web search), call it FI
103
104
 
104
105
  If you have no search tool, qualify hard: "I haven't verified \u2014 this is a guess." Never assert absence with fake authority.`;
105
106
 
107
+ // src/skills.ts
108
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync, statSync as statSync2, writeFileSync } from "fs";
109
+ import { homedir } from "os";
110
+ import { dirname, join as join2, resolve } from "path";
111
+
106
112
  // src/frontmatter.ts
107
113
  var KEY_RE = /^([a-zA-Z_][a-zA-Z0-9_-]*):\s*(.*)$/;
108
114
  var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
@@ -151,9 +157,6 @@ function parseFrontmatter(raw) {
151
157
  }
152
158
 
153
159
  // src/skills.ts
154
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, readdirSync, statSync as statSync2, writeFileSync } from "fs";
155
- import { homedir } from "os";
156
- import { dirname, join as join2, resolve } from "path";
157
160
  var SKILLS_DIRNAME = "skills";
158
161
  var SKILL_FILE = "SKILL.md";
159
162
  var SKILLS_INDEX_MAX_CHARS = 4e3;
@@ -176,6 +179,12 @@ function parseAllowedTools(raw) {
176
179
  const names = raw.split(",").map((s) => s.trim()).filter(Boolean);
177
180
  return names.length > 0 ? Object.freeze(names) : void 0;
178
181
  }
182
+ function parseMaxToolIters(raw) {
183
+ if (raw === void 0) return void 0;
184
+ const n = Number.parseInt(raw.trim(), 10);
185
+ if (!Number.isFinite(n) || n < 1) return void 0;
186
+ return n;
187
+ }
179
188
  var SkillStore = class {
180
189
  homeDir;
181
190
  projectRoot;
@@ -306,7 +315,8 @@ var SkillStore = class {
306
315
  path,
307
316
  allowedTools: parseAllowedTools(data["allowed-tools"]),
308
317
  runAs: parseRunAs(data.runAs),
309
- model: data.model?.startsWith("deepseek-") ? data.model : void 0
318
+ model: data.model?.startsWith("deepseek-") ? data.model : void 0,
319
+ maxToolIters: parseMaxToolIters(data["max-iters"])
310
320
  };
311
321
  }
312
322
  };
@@ -327,6 +337,7 @@ Tips:
327
337
  - Reference tools by name (run_command, edit_file, search_content, ...)
328
338
  - Add \`runAs: subagent\` to frontmatter to spawn an isolated subagent loop
329
339
  - Add \`allowed-tools: read_file, search_content\` to scope a subagent's tools
340
+ - Add \`max-iters: N\` to change the subagent's pause cadence (default 16). This isn't a budget \u2014 the parent resumes on pause, so N is how often the parent gets a checkpoint, not how much total work the subagent gets.
330
341
  `;
331
342
  }
332
343
  function skillIndexLine(s) {
@@ -564,4 +575,4 @@ export {
564
575
  SkillStore,
565
576
  applySkillsIndex
566
577
  };
567
- //# sourceMappingURL=chunk-7DLHHBGN.js.map
578
+ //# sourceMappingURL=chunk-2K65GZBT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/memory/project.ts","../../src/prompt-fragments.ts","../../src/skills.ts","../../src/frontmatter.ts"],"sourcesContent":["/** Reads REASONIX.md → AGENTS.md → AGENT.md (first that exists); writes prefer the file already on disk. */\n\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\n\n/** Default WRITE target — created when no candidate exists yet. */\nexport const PROJECT_MEMORY_FILE = \"REASONIX.md\";\n\n/** READ candidates, in priority order. AGENTS.md is the open spec at agents.md (Linux Foundation). */\nexport const PROJECT_MEMORY_FILES = [\"REASONIX.md\", \"AGENTS.md\", \"AGENT.md\"] as const;\n\nexport const PROJECT_MEMORY_MAX_CHARS = 8000;\n\nconst FOREIGN_PLATFORM_FILE_MARKERS = [\"SOUL.md\", \"PERSONA.md\"] as const;\n\n/** Returns the marker(s) that flagged rootDir as a foreign agent-platform data dir; null on a normal coding project. */\nexport function detectForeignAgentPlatform(rootDir: string): string[] | null {\n const hits: string[] = [];\n for (const name of FOREIGN_PLATFORM_FILE_MARKERS) {\n if (existsSync(join(rootDir, name))) hits.push(name);\n }\n if (isDir(join(rootDir, \"skills\")) && isDir(join(rootDir, \"memories\"))) {\n hits.push(\"skills/ + memories/\");\n }\n return hits.length > 0 ? hits : null;\n}\n\nfunction isDir(path: string): boolean {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n\n/** Absolute path of the first PROJECT_MEMORY_FILES candidate that exists at rootDir, or null. */\nexport function findProjectMemoryPath(rootDir: string): string | null {\n for (const name of PROJECT_MEMORY_FILES) {\n const path = join(rootDir, name);\n if (existsSync(path)) return path;\n }\n return null;\n}\n\n/** Path callers should write to: an existing candidate wins, otherwise rootDir/REASONIX.md. */\nexport function resolveProjectMemoryWritePath(rootDir: string): string {\n return findProjectMemoryPath(rootDir) ?? join(rootDir, PROJECT_MEMORY_FILE);\n}\n\nexport interface ProjectMemory {\n /** Absolute path the memory was read from. */\n path: string;\n /** Post-truncation content (may include a \"… (truncated N chars)\" marker). */\n content: string;\n /** Original byte length before truncation. */\n originalChars: number;\n /** True iff `originalChars > PROJECT_MEMORY_MAX_CHARS`. */\n truncated: boolean;\n}\n\n/** Empty / whitespace-only files return null so they don't perturb the cache prefix. */\nexport function readProjectMemory(rootDir: string): ProjectMemory | null {\n const path = findProjectMemoryPath(rootDir);\n if (!path) return null;\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return null;\n }\n const trimmed = raw.trim();\n if (!trimmed) return null;\n const originalChars = trimmed.length;\n const truncated = originalChars > PROJECT_MEMORY_MAX_CHARS;\n const content = truncated\n ? `${trimmed.slice(0, PROJECT_MEMORY_MAX_CHARS)}\\n… (truncated ${\n originalChars - PROJECT_MEMORY_MAX_CHARS\n } chars)`\n : trimmed;\n return { path, content, originalChars, truncated };\n}\n\nexport function memoryEnabled(): boolean {\n const env = process.env.REASONIX_MEMORY;\n if (env === \"off\" || env === \"false\" || env === \"0\") return false;\n return true;\n}\n\n/** Deterministic — same memory file always yields the same prefix hash. */\nexport function applyProjectMemory(basePrompt: string, rootDir: string): string {\n if (!memoryEnabled()) return basePrompt;\n const mem = readProjectMemory(rootDir);\n if (!mem) return basePrompt;\n const filename = basename(mem.path);\n return `${basePrompt}\n\n# Project memory (${filename})\n\nThe user pinned these notes about this project — treat them as authoritative context for every turn:\n\n\\`\\`\\`\n${mem.content}\n\\`\\`\\`\n`;\n}\n","/** Shared prompt fragments — single source so house-style rules can't drift across agent/subagent/skill prompts. */\n\n/** Embedded literally — no interpolation, so prefix-cache hash stays stable across sessions. */\nexport const TUI_FORMATTING_RULES = `Formatting (rendered in a TUI with a real markdown renderer):\n- Tabular data → GitHub-Flavored Markdown tables with ASCII pipes (\\`| col | col |\\` header + \\`| --- | --- |\\` separator). Never use Unicode box-drawing characters (│ ─ ┼ ┌ ┐ └ ┘ ├ ┤) — they look intentional but break terminal word-wrap and render as garbled columns at narrow widths.\n- Keep table cells short (one phrase each). If a cell needs a paragraph, use bullets below the table instead.\n- Code, file paths with line ranges, and shell commands → fenced code blocks (\\`\\`\\`).\n- Do NOT draw decorative frames around content with \\`┌──┐ │ └──┘\\` characters. The renderer adds its own borders; extra ASCII art adds noise and shatters at narrow widths.\n- For flow charts and diagrams: a plain bullet list with \\`→\\` or \\`↓\\` between steps. Don't try to draw boxes-and-arrows in ASCII; it never survives word-wrap.`;\n\n/** Pro is the top tier — escalation is a no-op for it; flash + others get the full ladder. */\nexport function escalationContract(modelId: string): string {\n if (modelId === \"deepseek-v4-pro\") {\n return `Cost-aware escalation note: you are running on \\`${modelId}\\` — the escalation tier. There is no higher tier to escalate to, so the \\`<<<NEEDS_PRO>>>\\` marker is a no-op for you; deliver the strongest answer you can directly. If asked which model you are, answer \\`${modelId}\\`.`;\n }\n return `Cost-aware escalation (you are running on \\`${modelId}\\`):\n\nIf a task CLEARLY exceeds what this tier can do well — complex cross-file architecture refactors, subtle concurrency / security / correctness invariants you can't resolve with confidence, or a design trade-off you'd be guessing at — output the marker as the FIRST line of your response (nothing before it, not even whitespace on a separate line). This aborts the current call and retries this turn on deepseek-v4-pro, one shot.\n\nTwo accepted forms:\n- \\`<<<NEEDS_PRO>>>\\` — bare marker, no rationale.\n- \\`<<<NEEDS_PRO: <one-sentence reason>>>>\\` — preferred. The reason text appears in the user-visible warning (\"⇧ flash requested escalation — <your reason>\"), so they understand WHY a more expensive call is happening. Keep it under ~150 chars, no newlines, no nested \\`>\\` characters. Examples: \\`<<<NEEDS_PRO: cross-file refactor across 6 modules with circular imports>>>\\` or \\`<<<NEEDS_PRO: subtle session-token race; flash would likely miss the locking invariant>>>\\`.\n\nDo NOT emit any other content in the same response when you request escalation. Use this sparingly: normal tasks — reading files, small edits, clear bug fixes, straightforward feature additions — stay on this tier. Request escalation ONLY when you would otherwise produce a guess or a visibly-mediocre answer. If in doubt, attempt the task here first; the system also escalates automatically if you hit 3+ repair / SEARCH-mismatch errors in a single turn (the user sees a typed breakdown). If asked which model you are, answer \\`${modelId}\\`.`;\n}\n\n/** Backward-compat — pre-#582 callers (and the `CODE_SYSTEM_PROMPT` public-API const) keep the historical flash phrasing. */\nexport const ESCALATION_CONTRACT = escalationContract(\"deepseek-v4-flash\");\n\nexport const NEGATIVE_CLAIM_RULE = `Negative claims (\"X is missing\", \"Y isn't implemented\", \"there's no Z\") are the #1 hallucination shape. They feel safe to write because no citation seems possible — but that's exactly why you must NOT write them on instinct.\n\nIf you have a search tool (\\`search_content\\`, \\`grep\\`, web search), call it FIRST before asserting absence:\n- Returns matches → you were wrong; correct yourself and cite the matches.\n- Returns nothing → state the absence WITH the search query as evidence: \\`No callers of \\\\\\`foo()\\\\\\` found (search_content \"foo\").\\`\n\nIf you have no search tool, qualify hard: \"I haven't verified — this is a guess.\" Never assert absence with fake authority.`;\n","/** Project scope wins over global. Only names+descriptions enter the prefix; bodies load lazily into the append-only log. */\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { parseFrontmatter } from \"./frontmatter.js\";\nimport { NEGATIVE_CLAIM_RULE, TUI_FORMATTING_RULES } from \"./prompt-fragments.js\";\n\nexport const SKILLS_DIRNAME = \"skills\";\nexport const SKILL_FILE = \"SKILL.md\";\n/** Cap on the pinned skills-index block, mirrors memory-index cap. */\nexport const SKILLS_INDEX_MAX_CHARS = 4000;\n/** Skill identifier shape — alnum + `_` + `-` + interior `.`, 1-64 chars. */\nconst VALID_SKILL_NAME = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/;\n\nexport type SkillScope = \"project\" | \"global\" | \"builtin\";\n\n/** inline = body enters parent log; subagent = isolated child loop, only final answer returns. */\nexport type SkillRunAs = \"inline\" | \"subagent\";\n\nexport interface Skill {\n /** Canonical name — sanitized, matches the directory / filename stem. */\n name: string;\n /** One-line description shown in the pinned index. */\n description: string;\n /** Full markdown body (post-frontmatter). Loaded on demand. */\n body: string;\n /** Which scope this skill was loaded from. */\n scope: SkillScope;\n /** Absolute path to the SKILL.md (or {name}.md) file, or \"(builtin)\" for shipped defaults. */\n path: string;\n /** Parsed `allowed-tools` frontmatter — when present, the spawned subagent's registry is scoped to these literal tool names. */\n allowedTools?: readonly string[];\n runAs: SkillRunAs;\n /** Subagent model override; only meaningful when `runAs === \"subagent\"`. */\n model?: string;\n /** Subagent tool-call budget; only meaningful when `runAs === \"subagent\"`. Clamped to [1, 32]. */\n maxToolIters?: number;\n}\n\nexport interface SkillStoreOptions {\n /** Override `$HOME` — tests point this at a tmpdir. */\n homeDir?: string;\n /** Required for project-scope skills; omit to read only the global scope. */\n projectRoot?: string;\n /** Suppress bundled built-ins — for tests asserting exact list contents. */\n disableBuiltins?: boolean;\n}\n\n/** Reject skill files that would silently disappear from the prefix index — `description:` is what `applySkillsIndex` keys on. */\nexport function validateSkillFrontmatter(raw: string): { ok: true } | { error: string } {\n const { data } = parseFrontmatter(raw);\n const desc = (data.description ?? \"\").trim();\n if (!desc) {\n return {\n error:\n 'skill frontmatter is missing a non-empty \"description:\" line — without it the skill will not appear in the model\\'s skills index',\n };\n }\n return { ok: true };\n}\n\nfunction isValidSkillName(name: string): boolean {\n return VALID_SKILL_NAME.test(name);\n}\n\nfunction parseAllowedTools(raw: string | undefined): readonly string[] | undefined {\n if (raw === undefined) return undefined;\n const names = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return names.length > 0 ? Object.freeze(names) : undefined;\n}\n\n/** `max-iters` is checkpoint cadence, not a budget — work continues across pauses via resume_session. No upper bound; values below 1 fall back to the subagent default. */\nfunction parseMaxToolIters(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined;\n const n = Number.parseInt(raw.trim(), 10);\n if (!Number.isFinite(n) || n < 1) return undefined;\n return n;\n}\n\nexport class SkillStore {\n private readonly homeDir: string;\n private readonly projectRoot: string | undefined;\n private readonly disableBuiltins: boolean;\n\n constructor(opts: SkillStoreOptions = {}) {\n this.homeDir = opts.homeDir ?? homedir();\n this.projectRoot = opts.projectRoot ? resolve(opts.projectRoot) : undefined;\n this.disableBuiltins = opts.disableBuiltins === true;\n }\n\n /** True iff this store was configured with a project root. */\n hasProjectScope(): boolean {\n return this.projectRoot !== undefined;\n }\n\n /** Project scope first so per-repo skill overrides a global with the same name. */\n roots(): Array<{ dir: string; scope: SkillScope }> {\n const out: Array<{ dir: string; scope: SkillScope }> = [];\n if (this.projectRoot) {\n out.push({\n dir: join(this.projectRoot, \".reasonix\", SKILLS_DIRNAME),\n scope: \"project\",\n });\n }\n out.push({ dir: join(this.homeDir, \".reasonix\", SKILLS_DIRNAME), scope: \"global\" });\n return out;\n }\n\n /** Higher-priority root wins on collision (project > global > builtin); sorted for stable prefix hash. */\n list(): Skill[] {\n const byName = new Map<string, Skill>();\n for (const { dir, scope } of this.roots()) {\n if (!existsSync(dir)) continue;\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n continue;\n }\n for (const entry of entries) {\n const skill = this.readEntry(dir, scope, entry);\n if (!skill) continue;\n if (!byName.has(skill.name)) byName.set(skill.name, skill);\n }\n }\n // Builtins last so user/project files override on name collision.\n if (!this.disableBuiltins) {\n for (const skill of BUILTIN_SKILLS) {\n if (!byName.has(skill.name)) byName.set(skill.name, skill);\n }\n }\n return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));\n }\n\n /** Scaffold a new skill stub at the chosen scope. Refuses to overwrite. */\n create(name: string, scope: \"project\" | \"global\"): { path: string } | { error: string } {\n return this.createWithContent(name, scope, skillStubBody(name));\n }\n\n /** Like `create` but writes caller-supplied file contents instead of the stub — used by the scaffold tool. */\n createWithContent(\n name: string,\n scope: \"project\" | \"global\",\n content: string,\n ): { path: string } | { error: string } {\n if (!isValidSkillName(name)) {\n return { error: `invalid skill name: \"${name}\" — use letters, digits, _, -, .` };\n }\n if (scope === \"project\" && !this.projectRoot) {\n return { error: \"project scope requires a workspace — run from `reasonix code`\" };\n }\n const root =\n scope === \"project\"\n ? join(this.projectRoot ?? \"\", \".reasonix\", SKILLS_DIRNAME)\n : join(this.homeDir, \".reasonix\", SKILLS_DIRNAME);\n const flat = join(root, `${name}.md`);\n const folder = join(root, name, SKILL_FILE);\n if (existsSync(folder)) {\n return { error: `skill \"${name}\" already exists at ${folder}` };\n }\n mkdirSync(dirname(flat), { recursive: true });\n try {\n writeFileSync(flat, content, { encoding: \"utf8\", flag: \"wx\" });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"EEXIST\") {\n return { error: `skill \"${name}\" already exists at ${flat}` };\n }\n throw err;\n }\n return { path: flat };\n }\n\n /** Resolve one skill by name. Returns `null` if not found or malformed. */\n read(name: string): Skill | null {\n if (!isValidSkillName(name)) return null;\n for (const { dir, scope } of this.roots()) {\n if (!existsSync(dir)) continue;\n const dirCandidate = join(dir, name, SKILL_FILE);\n if (existsSync(dirCandidate) && statSync(dirCandidate).isFile()) {\n return this.parse(dirCandidate, name, scope);\n }\n const flatCandidate = join(dir, `${name}.md`);\n if (existsSync(flatCandidate) && statSync(flatCandidate).isFile()) {\n return this.parse(flatCandidate, name, scope);\n }\n }\n if (!this.disableBuiltins) {\n for (const skill of BUILTIN_SKILLS) {\n if (skill.name === name) return skill;\n }\n }\n return null;\n }\n\n private readEntry(dir: string, scope: SkillScope, entry: import(\"node:fs\").Dirent): Skill | null {\n if (entry.isDirectory()) {\n if (!isValidSkillName(entry.name)) return null;\n const file = join(dir, entry.name, SKILL_FILE);\n if (!existsSync(file)) return null;\n return this.parse(file, entry.name, scope);\n }\n if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const stem = entry.name.slice(0, -3);\n if (!isValidSkillName(stem)) return null;\n return this.parse(join(dir, entry.name), stem, scope);\n }\n return null;\n }\n\n private parse(path: string, stem: string, scope: SkillScope): Skill | null {\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch {\n return null;\n }\n const { data, body } = parseFrontmatter(raw);\n const name = data.name && isValidSkillName(data.name) ? data.name : stem;\n return {\n name,\n description: (data.description ?? \"\").trim(),\n body: body.trim(),\n scope,\n path,\n allowedTools: parseAllowedTools(data[\"allowed-tools\"]),\n runAs: parseRunAs(data.runAs),\n model: data.model?.startsWith(\"deepseek-\") ? data.model : undefined,\n maxToolIters: parseMaxToolIters(data[\"max-iters\"]),\n };\n }\n}\n\n/** Unknown values default to the safe (non-spawning) `inline` mode. */\nfunction parseRunAs(raw: string | undefined): SkillRunAs {\n return raw?.trim() === \"subagent\" ? \"subagent\" : \"inline\";\n}\n\n/** Stub markdown for `/skill new` — minimal frontmatter + scaffolding the user fills in. */\nfunction skillStubBody(name: string): string {\n return `---\nname: ${name}\ndescription: One-liner — what does this skill do?\n---\n\n# ${name}\n\nReplace this body with the playbook the model should follow when this skill is invoked.\n\nTips:\n- Reference tools by name (run_command, edit_file, search_content, ...)\n- Add \\`runAs: subagent\\` to frontmatter to spawn an isolated subagent loop\n- Add \\`allowed-tools: read_file, search_content\\` to scope a subagent's tools\n- Add \\`max-iters: N\\` to change the subagent's pause cadence (default 16). This isn't a budget — the parent resumes on pause, so N is how often the parent gets a checkpoint, not how much total work the subagent gets.\n`;\n}\n\n/** Subagent tag goes AFTER the name in brackets — leading-marker tags get copied into `name` arg verbatim. */\nfunction skillIndexLine(s: Pick<Skill, \"name\" | \"description\" | \"runAs\">): string {\n const safeDesc = s.description.replace(/\\n/g, \" \").trim();\n const tag = s.runAs === \"subagent\" ? \" [🧬 subagent]\" : \"\";\n const max = 130 - s.name.length - tag.length;\n const clipped = safeDesc.length > max ? `${safeDesc.slice(0, Math.max(1, max - 1))}…` : safeDesc;\n return clipped ? `- ${s.name}${tag} — ${clipped}` : `- ${s.name}${tag}`;\n}\n\nconst MISSING_DESCRIPTION_PLACEHOLDER =\n '(no description — frontmatter is missing a \"description:\" line; tell the user to add one)';\n\n/** Bodies stay out — prefix must stay short + cacheable; bodies load on demand. */\nexport function applySkillsIndex(basePrompt: string, opts: SkillStoreOptions = {}): string {\n const store = new SkillStore(opts);\n const skills = store.list();\n if (skills.length === 0) return basePrompt;\n const lines = skills.map((s) =>\n skillIndexLine(s.description ? s : { ...s, description: MISSING_DESCRIPTION_PLACEHOLDER }),\n );\n const joined = lines.join(\"\\n\");\n const truncated =\n joined.length > SKILLS_INDEX_MAX_CHARS\n ? `${joined.slice(0, SKILLS_INDEX_MAX_CHARS)}\\n… (truncated ${\n joined.length - SKILLS_INDEX_MAX_CHARS\n } chars)`\n : joined;\n return [\n basePrompt,\n \"\",\n \"# Skills — playbooks you can invoke\",\n \"\",\n 'One-liner index. Each entry is either a built-in or a user-authored playbook. Call `run_skill({ name: \"<skill-name>\", arguments: \"<task>\" })` — the `name` is JUST the skill identifier (e.g. `\"explore\"`), NOT the `[🧬 subagent]` tag that appears after it. Entries tagged `[🧬 subagent]` spawn an **isolated subagent** — its tool calls and reasoning never enter your context, only its final answer does. Use subagent skills for tasks that would otherwise flood your context (deep exploration, multi-step research, anything where you only need the conclusion). Plain skills are inlined: their body becomes a tool result you read and act on directly. The user can also invoke a skill via `/skill <name>`.',\n \"\",\n \"```\",\n truncated,\n \"```\",\n ].join(\"\\n\");\n}\n\nconst BUILTIN_EXPLORE_BODY = `You are running as an exploration subagent. Your job is to investigate the codebase the parent agent pointed you at, then return one focused, distilled answer.\n\nHow to operate:\n- Use read_file, search_files, search_content, directory_tree, list_directory, get_file_info as your primary tools. Stay read-only.\n- For \"find all places that call / reference / use X\" questions, use \\`search_content\\` (content grep) — NOT \\`search_files\\` (which only matches file names). This is the most common subagent mistake; using the wrong tool gives empty results and you waste your iter budget chasing a phantom.\n- Cast a wide net first (search_content for symbol references, directory_tree for structure) to map the territory; then read the 3-10 most relevant files in full.\n- Don't read every file — be selective. Aim for breadth on the first pass, depth only where the question demands it.\n- Stop exploring as soon as you can answer the question. The parent doesn't see your tool calls, so over-exploration is pure waste.\n\nYour final answer:\n- One paragraph (or a few short bullets). Lead with the conclusion.\n- Cite specific file paths + line ranges when they support the answer.\n- If the question can't be answered from what you found, say so plainly and suggest where to look next.\n- No follow-up offers, no \"let me know if you need more.\" The parent will ask again if they need more.\n\n${NEGATIVE_CLAIM_RULE}\n\n${TUI_FORMATTING_RULES}\n\nThe 'task' the parent gave you is the question you must answer. Treat any other reading of it as scope creep.`;\n\nconst BUILTIN_RESEARCH_BODY = `You are running as a research subagent. Your job is to gather information from code AND the web, synthesize it, and return one focused conclusion.\n\nHow to operate:\n- Combine code reading (read_file, search_files) with web tools (web_search, web_fetch) as appropriate to the question.\n- For \"how does X work\" / \"is Y supported\" questions: web first to find the canonical reference, then verify against the local code.\n- For \"what's our policy on Z\" / \"where do we use Q\": local code first, web only if you need to compare against external standards.\n- Cap yourself at ~10 tool calls. If you can't converge in 10, return what you have plus a note about what's missing.\n\nYour final answer:\n- One paragraph (or short bullets). Lead with the conclusion.\n- Cite both code (file:line) AND web sources (URL) when they back the answer.\n- Distinguish \"I verified this in code\" from \"I read this on a docs page\" — the parent will trust the former more.\n- If the answer is uncertain, say so. Don't invent confidence.\n\n${NEGATIVE_CLAIM_RULE}\n\n${TUI_FORMATTING_RULES}\n\nThe 'task' the parent gave you is the research question. Stay on it.`;\n\nconst BUILTIN_REVIEW_BODY = `You are running as a code-review subagent. Your job is to inspect the changes the user is about to ship — usually the current git branch vs its upstream — and produce a focused review the parent can hand back to the user.\n\nHow to operate:\n- Default scope: the current branch's diff vs the default branch. If the user's task names a specific commit range or files, honor that instead.\n- Discover scope first: \\`run_command git status\\`, \\`git diff --stat\\`, \\`git log --oneline\\` to see what changed. Then \\`git diff\\` (or \\`git diff <base>...HEAD\\`) for the actual hunks.\n- Read the touched files (\\`read_file\\`) when the diff alone doesn't carry enough context — function signatures, surrounding invariants, callers.\n- For \"any callers depending on this?\" questions: \\`search_content\\` against the symbol BEFORE asserting impact.\n- Stay read-only. Never \\`run_command git commit\\`, never write files, never propose SEARCH/REPLACE blocks. The parent decides whether to act on your findings.\n- Cap yourself at ~12 tool calls. If the diff is too big to review in one pass, pick the riskiest 2-3 files and say so explicitly.\n\nWhat to look for, in priority order:\n1. **Correctness bugs** — off-by-one, null/undefined handling, race conditions, wrong sign / wrong operator, edge cases the code doesn't handle.\n2. **Security** — injection (SQL, shell, path traversal), secrets in code, missing authz checks, unsafe deserialization.\n3. **Behavior changes the diff hides** — renames that miss callers, removed branches that were load-bearing, error-handling that now swallows what used to surface.\n4. **Tests** — does the change have tests for the new behavior? Are existing tests still meaningful, or did the change make them tautological?\n5. **Style + consistency** — only flag deviations that matter (unsafe \\`any\\`, missing types in TypeScript, inconsistent error shape). Don't pile on cosmetic nits if the substance is clean.\n\nYour final answer:\n- Lead with a one-sentence verdict: \"ship as-is\" / \"minor nits, OK to ship after\" / \"blocking issues, do not ship\".\n- Then a short bulleted list of issues, each with: file:line citation + the problem in one sentence + what to change.\n- Group by severity if you have more than 4 items: **Blocking**, **Should-fix**, **Nits**.\n- If everything looks clean, say so plainly. Don't manufacture concerns.\n\n${NEGATIVE_CLAIM_RULE}\n\n${TUI_FORMATTING_RULES}\n\nThe 'task' the parent gave you describes WHAT to review (a branch, a file set, or \"the pending changes\"). Stay on it; don't redesign the feature.`;\n\nconst BUILTIN_SECURITY_REVIEW_BODY = `You are running as a security-review subagent. Your job is to inspect the changes the user is about to ship — usually the current git branch vs its upstream — through a security lens specifically, and report exploitable issues.\n\nHow to operate:\n- Default scope: the current branch's diff vs the default branch. If the user names a different range or a directory, honor that.\n- Discover scope first: \\`git status\\`, \\`git diff --stat\\`, \\`git diff <base>...HEAD\\`. Read touched files (\\`read_file\\`) when the diff alone doesn't carry security context — auth checks, input validation, the actual handler that calls into the changed function.\n- Use \\`search_content\\` to verify \"is this user-controlled input ever sanitized later?\" / \"are there other call sites that depend on this validation?\" before asserting impact.\n- Stay read-only. Never write, never run destructive commands, never propose SEARCH/REPLACE blocks. The parent decides what to act on.\n- Cap yourself at ~12 tool calls. If the diff is too big, focus on the riskiest 2-3 files and say so explicitly.\n\nThreat model — flag with severity:\n\n**CRITICAL** (do-not-ship):\n- SQL / NoSQL / shell / template injection — user input concatenated into a query, command, or template without parameterization.\n- Path traversal — user-controlled filenames touching the filesystem without canonicalization + sandbox check.\n- Authentication / authorization missing — endpoints / actions that should require a session check but don't.\n- Hardcoded secrets — API keys, passwords, signing tokens visible in the diff.\n- Deserialization of untrusted input — \\`pickle.loads\\`, \\`yaml.load\\` (non-safe), \\`eval\\`, \\`Function()\\`, \\`unserialize()\\`.\n- Cryptographic mistakes — homemade crypto, weak hashes (MD5/SHA-1) for passwords, missing IVs, ECB mode, predictable nonces.\n\n**HIGH**:\n- XSS — user input rendered into HTML without escaping (or wrong escaping context).\n- SSRF — fetching URLs from user input without an allowlist.\n- Race conditions in security-relevant code — TOCTOU on auth/file checks.\n- Open redirects — user-controlled URL passed to a redirect helper.\n- Insufficient logging on security events (login failure, permission denial) — only flag if the codebase clearly DOES log elsewhere.\n\n**MEDIUM**:\n- Verbose error messages leaking internal paths / stack traces / SQL.\n- Missing rate limiting on a credential / token endpoint.\n- Cross-origin / cookie-flag issues (missing \\`Secure\\` / \\`HttpOnly\\` / \\`SameSite\\`).\n\nThings to NOT pile on (out of scope here — the regular /review covers them):\n- Style, formatting, naming.\n- Performance, refactor opportunities, test coverage gaps that aren't security-relevant.\n- \"Should be a constant\" / \"extract this helper\" — irrelevant to ship-blocking.\n\nYour final answer:\n- Lead with a one-sentence verdict: \"no security issues found\", \"minor concerns\", or \"blocking issues\".\n- Then a list grouped by severity. Each item: file:line + 1-sentence threat + 1-sentence fix direction (no full SEARCH/REPLACE — the user / parent agent will write that).\n- If clean, say so plainly. Don't manufacture findings.\n\n${NEGATIVE_CLAIM_RULE}\n\n${TUI_FORMATTING_RULES}\n\nThe 'task' the parent gave you names what to review. Stay on it; don't redesign the feature.`;\n\nconst BUILTIN_TEST_BODY = `You are running as the parent agent — this skill is INLINED, not a subagent. The user invoked /test (or asked you to \"run the tests and fix failures\"). Your job: run the project's test suite, diagnose any failure, propose fixes as SEARCH/REPLACE edit blocks, then re-run. Repeat until green or you hit a wall you should escalate.\n\nHow to operate:\n\n1. **Detect the test command**.\n - Look for \\`package.json\\` → \\`scripts.test\\` first (most common: \\`npm test\\`, \\`pnpm test\\`, \\`yarn test\\`).\n - If no package.json or no test script: try \\`pytest\\`, \\`go test ./...\\`, \\`cargo test\\` based on what files exist (pyproject.toml/requirements.txt → pytest; go.mod → go test; Cargo.toml → cargo test).\n - If you can't tell, ASK the user for the command — don't guess. One question, one tool call to confirm.\n\n2. **Run it via run_command** (typical timeout 120s, bigger if the suite is large). Capture stdout + stderr.\n\n3. **Read the failures**. Pull out: which test names failed, the actual error/traceback, the file + line that threw. Don't just paraphrase — locate the exact assertion or stack frame.\n\n4. **Propose fixes**. For each distinct failure:\n - If the failure is in PRODUCTION code (test catches a real bug) → propose a SEARCH/REPLACE that fixes the production code.\n - If the failure is in TEST code (test is wrong, codebase is right) → propose a SEARCH/REPLACE that updates the test, AND say so explicitly: \"This is a test bug, not a production bug — updating the assertion.\"\n - If the failure is environmental (missing dep, wrong node version, missing fixture file) → say so and stop. Don't try to install packages or change config without checking with the user.\n\n5. **Apply + re-run**. After the user accepts the edit blocks, run the test command again. Iterate.\n\n6. **Stop conditions**:\n - All tests pass → report green, summarize what changed.\n - Same test still failing after 2 fix attempts on the same line → STOP. Tell the user \"I've tried twice, it's still failing — here's what I think is happening, want me to try a different angle?\". Don't loop indefinitely.\n - 3+ unrelated failures → fix one at a time, smallest first, so each pass narrows the surface.\n\nDon't:\n- Run \\`npm install\\` / \\`pip install\\` / \\`cargo update\\` without asking — those mutate lockfiles and have global effects.\n- Disable, skip, or delete failing tests to \"make it green\". If a test seems wrong, update its assertion with a one-sentence explanation, but never add \\`.skip\\` / \\`it.skip\\` / \\`@pytest.mark.skip\\`.\n- Modify the test runner config (vitest.config, jest.config, etc.) to silence failures.\n\nLead each turn with a one-line status: \"▸ running \\`npm test\\` ...\" → \"▸ 2 failures in tests/foo.test.ts — first is …\" → so the user always knows where you are without scrolling tool output.`;\n\nconst BUILTIN_SKILLS: readonly Skill[] = Object.freeze([\n Object.freeze<Skill>({\n name: \"explore\",\n description:\n \"Explore the codebase in an isolated subagent — wide-net read-only investigation that returns one distilled answer. Best for: 'find all places that...', 'how does X work across the project', 'survey the code for Y'.\",\n body: BUILTIN_EXPLORE_BODY,\n scope: \"builtin\",\n path: \"(builtin)\",\n runAs: \"subagent\",\n }),\n Object.freeze<Skill>({\n name: \"research\",\n description:\n \"Research a question by combining web search + code reading in an isolated subagent. Best for: 'is X feature supported by lib Y', 'what's the canonical way to do Z', 'compare our impl against the spec'.\",\n body: BUILTIN_RESEARCH_BODY,\n scope: \"builtin\",\n path: \"(builtin)\",\n runAs: \"subagent\",\n }),\n Object.freeze<Skill>({\n name: \"review\",\n description:\n \"Review the pending changes (current branch diff by default) in an isolated subagent — flags correctness, security, missing tests, hidden behavior changes; reports verdict + per-issue file:line. Read-only; the parent decides what to act on.\",\n body: BUILTIN_REVIEW_BODY,\n scope: \"builtin\",\n path: \"(builtin)\",\n runAs: \"subagent\",\n }),\n Object.freeze<Skill>({\n name: \"security-review\",\n description:\n \"Security-focused review of the current branch diff in an isolated subagent — flags injection/authz/secrets/deserialization/path-traversal/crypto issues, severity-tagged. Read-only. Use when shipping changes that touch auth, input parsing, file IO, or external requests.\",\n body: BUILTIN_SECURITY_REVIEW_BODY,\n scope: \"builtin\",\n path: \"(builtin)\",\n runAs: \"subagent\",\n }),\n Object.freeze<Skill>({\n name: \"test\",\n description:\n \"Run the project's test suite, diagnose failures, propose SEARCH/REPLACE fixes, re-run until green (or stop after 2 fix attempts on the same failure). Inlined — runs in the parent loop so you see the edit blocks and can /apply them. Detects npm/pnpm/yarn/pytest/go/cargo.\",\n body: BUILTIN_TEST_BODY,\n scope: \"builtin\",\n path: \"(builtin)\",\n runAs: \"inline\",\n }),\n]);\n","/** Tiny YAML-frontmatter parser shared by skills / memory loaders. Single source so BOM + folded + quoted handling stay consistent. */\n\nconst KEY_RE = /^([a-zA-Z_][a-zA-Z0-9_-]*):\\s*(.*)$/;\n/** Bracket-write guard — regex permits these as identifiers, but writing them would mutate Object.prototype. */\nconst FORBIDDEN_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction stripQuotes(s: string): string {\n if (s.length < 2) return s;\n const first = s[0];\n const last = s[s.length - 1];\n if ((first === '\"' && last === '\"') || (first === \"'\" && last === \"'\")) {\n return s.slice(1, -1);\n }\n return s;\n}\n\nexport function parseFrontmatter(raw: string): { data: Record<string, string>; body: string } {\n const stripped = raw.charCodeAt(0) === 0xfeff ? raw.slice(1) : raw;\n const lines = stripped.split(/\\r?\\n/);\n if (lines[0] !== \"---\") return { data: {}, body: stripped };\n const end = lines.indexOf(\"---\", 1);\n if (end < 0) return { data: {}, body: stripped };\n const entries = new Map<string, string>();\n let currentKey: string | null = null;\n for (let i = 1; i < end; i++) {\n const line = lines[i] ?? \"\";\n if (line.trim() === \"\") {\n currentKey = null;\n continue;\n }\n const m = line.match(KEY_RE);\n if (m?.[1] && !FORBIDDEN_KEYS.has(m[1])) {\n currentKey = m[1];\n entries.set(currentKey, (m[2] ?? \"\").trim());\n } else if (currentKey) {\n const cont = line.trim();\n const prev = entries.get(currentKey) ?? \"\";\n entries.set(currentKey, prev ? `${prev} ${cont}` : cont);\n }\n }\n const data: Record<string, string> = Object.create(null);\n for (const [k, v] of entries) {\n if (FORBIDDEN_KEYS.has(k)) continue;\n data[k] = stripQuotes(v);\n }\n return {\n data,\n body: lines\n .slice(end + 1)\n .join(\"\\n\")\n .replace(/^\\n+/, \"\"),\n };\n}\n"],"mappings":"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","names":["existsSync","readFileSync","statSync","join","join","existsSync","statSync","readFileSync"]}