@gajae-code/coding-agent 0.17.1 → 0.17.4

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 (375) hide show
  1. package/CHANGELOG.md +266 -0
  2. package/dist/types/async/job-manager.d.ts +7 -6
  3. package/dist/types/cli/daemon-cli.d.ts +3 -1
  4. package/dist/types/cli/github-release.d.ts +17 -0
  5. package/dist/types/cli/public-command-entry.d.ts +56 -0
  6. package/dist/types/cli/public-command-errors.d.ts +126 -0
  7. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  8. package/dist/types/cli/public-command-help.d.ts +65 -0
  9. package/dist/types/cli/public-command-registry.d.ts +69 -0
  10. package/dist/types/cli/session-picker.d.ts +1 -1
  11. package/dist/types/cli/setup-cli.d.ts +1 -0
  12. package/dist/types/cli/skills-cli.d.ts +5 -0
  13. package/dist/types/cli.d.ts +3 -0
  14. package/dist/types/commands/daemon.d.ts +4 -50
  15. package/dist/types/commands/sdk.d.ts +20 -37
  16. package/dist/types/commands/setup.d.ts +3 -0
  17. package/dist/types/commands/skills.d.ts +9 -0
  18. package/dist/types/config/autorouting-tier-map.d.ts +24 -0
  19. package/dist/types/config/file-lock.d.ts +10 -1
  20. package/dist/types/config/model-profile-activation.d.ts +63 -4
  21. package/dist/types/config/model-registry.d.ts +20 -2
  22. package/dist/types/config/settings-schema.d.ts +11 -0
  23. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  24. package/dist/types/coordinator-mcp/server.d.ts +3 -0
  25. package/dist/types/daemon/operator-contract.d.ts +5 -1
  26. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  28. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  29. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  30. package/dist/types/extensibility/shared-events.d.ts +3 -1
  31. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  32. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  33. package/dist/types/internal-urls/index.d.ts +1 -0
  34. package/dist/types/internal-urls/parse.d.ts +9 -1
  35. package/dist/types/main.d.ts +22 -0
  36. package/dist/types/modes/acp/acp-agent.d.ts +94 -1
  37. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  38. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  39. package/dist/types/modes/components/session-selector.d.ts +5 -2
  40. package/dist/types/modes/components/thinking-selector.d.ts +2 -1
  41. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  42. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  43. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  44. package/dist/types/modes/interactive-mode.d.ts +1 -1
  45. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  46. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  47. package/dist/types/modes/types.d.ts +2 -2
  48. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  49. package/dist/types/runtime-mcp/manager.d.ts +56 -0
  50. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  51. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  52. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  53. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  54. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  55. package/dist/types/sdk/acp/adapter.d.ts +27 -0
  56. package/dist/types/sdk/acp/final-text.d.ts +8 -0
  57. package/dist/types/sdk/broker/broker.d.ts +13 -2
  58. package/dist/types/sdk/broker/ensure.d.ts +46 -1
  59. package/dist/types/sdk/broker/identity.d.ts +3 -1
  60. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  61. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  62. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  63. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  64. package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
  65. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  66. package/dist/types/sdk/bus/index.d.ts +19 -0
  67. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  68. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  69. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  70. package/dist/types/sdk/cli/rows.d.ts +19 -1
  71. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/guides/cli.d.ts +3 -4
  74. package/dist/types/sdk/guides/verify.d.ts +2 -0
  75. package/dist/types/sdk/host/host.d.ts +9 -0
  76. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  77. package/dist/types/sdk/host/types.d.ts +10 -0
  78. package/dist/types/sdk/index.d.ts +1 -0
  79. package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
  80. package/dist/types/sdk/prompt-deadline-manager.d.ts +38 -1
  81. package/dist/types/sdk/prompt-failure.d.ts +30 -1
  82. package/dist/types/sdk/prompt-status.d.ts +8 -0
  83. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  84. package/dist/types/sdk/router/replay-retention-gap-cache.d.ts +13 -0
  85. package/dist/types/sdk/router/session-router.d.ts +2 -0
  86. package/dist/types/sdk/startup-capability.d.ts +2 -0
  87. package/dist/types/sdk/transport/relay.d.ts +1 -0
  88. package/dist/types/sdk/transport/serve-cli.d.ts +73 -2
  89. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  90. package/dist/types/session/agent-session.d.ts +168 -21
  91. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  92. package/dist/types/session/fold-coordinator.d.ts +17 -3
  93. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  94. package/dist/types/session/session-manager.d.ts +64 -1
  95. package/dist/types/session/session-work-lease.d.ts +14 -0
  96. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  97. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  98. package/dist/types/thinking.d.ts +3 -1
  99. package/dist/types/tools/bash.d.ts +37 -11
  100. package/dist/types/tools/job.d.ts +1 -1
  101. package/dist/types/tools/steer-fold.d.ts +31 -0
  102. package/dist/types/utils/git.d.ts +28 -2
  103. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  104. package/dist/types/utils/mupdf-wasm-embedded.d.ts +2 -0
  105. package/dist/types/utils/mupdf.d.ts +4 -0
  106. package/dist/types/utils/session-title-generation.d.ts +6 -0
  107. package/dist/types/utils/title-generator.d.ts +11 -2
  108. package/dist/types/web/scrapers/types.d.ts +3 -0
  109. package/package.json +18 -10
  110. package/scripts/build-binary.ts +9 -3
  111. package/scripts/compile-args.ts +0 -9
  112. package/scripts/embed-mupdf.ts +52 -0
  113. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  114. package/scripts/vendor-markit.ts +196 -0
  115. package/src/async/job-manager.ts +60 -9
  116. package/src/cli/daemon-cli.ts +53 -18
  117. package/src/cli/github-release.ts +87 -5
  118. package/src/cli/mcp-cli.ts +38 -4
  119. package/src/cli/public-command-entry.ts +450 -0
  120. package/src/cli/public-command-errors.ts +581 -0
  121. package/src/cli/public-command-evidence.ts +717 -0
  122. package/src/cli/public-command-help.ts +360 -0
  123. package/src/cli/public-command-registry.ts +535 -0
  124. package/src/cli/session-picker.ts +2 -1
  125. package/src/cli/setup-cli.ts +9 -1
  126. package/src/cli/skills-cli.ts +46 -2
  127. package/src/cli.ts +61 -1
  128. package/src/commands/daemon.ts +65 -69
  129. package/src/commands/sdk.ts +232 -100
  130. package/src/commands/setup.ts +2 -0
  131. package/src/commands/skills.ts +11 -0
  132. package/src/config/autorouting-tier-map.ts +16 -0
  133. package/src/config/file-lock.ts +199 -68
  134. package/src/config/model-profile-activation.ts +406 -53
  135. package/src/config/model-registry.ts +204 -25
  136. package/src/config/settings-schema.ts +26 -2
  137. package/src/coordinator-mcp/policy.ts +10 -5
  138. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  139. package/src/coordinator-mcp/question-state.ts +175 -8
  140. package/src/coordinator-mcp/server.ts +528 -87
  141. package/src/coordinator-mcp/session-reaper.ts +6 -4
  142. package/src/crash/record-loader.ts +6 -2
  143. package/src/daemon/operator-contract.ts +26 -12
  144. package/src/debug/report-bundle.ts +114 -24
  145. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  146. package/src/eval/js/context-manager.ts +8 -8
  147. package/src/eval/js/worker-core.ts +9 -4
  148. package/src/eval/js/worker-protocol.ts +2 -0
  149. package/src/extensibility/extensions/runner.ts +52 -4
  150. package/src/extensibility/extensions/types.ts +10 -0
  151. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  152. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  153. package/src/extensibility/shared-events.ts +3 -1
  154. package/src/gjc-runtime/managed-owner-admission.ts +67 -50
  155. package/src/gjc-runtime/session-state-lock.ts +165 -24
  156. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  157. package/src/internal-urls/docs-index.generated.ts +21 -19
  158. package/src/internal-urls/embedded-protocol.ts +83 -0
  159. package/src/internal-urls/index.ts +1 -0
  160. package/src/internal-urls/parse.ts +21 -1
  161. package/src/internal-urls/router.ts +4 -2
  162. package/src/main.ts +123 -55
  163. package/src/modes/acp/acp-agent.ts +593 -47
  164. package/src/modes/acp/acp-event-mapper.ts +9 -0
  165. package/src/modes/acp/startup-provenance.ts +59 -0
  166. package/src/modes/components/custom-provider-wizard.ts +308 -7
  167. package/src/modes/components/model-selector.ts +31 -15
  168. package/src/modes/components/oauth-selector.ts +9 -0
  169. package/src/modes/components/session-selector.ts +47 -4
  170. package/src/modes/components/status-line/segments.ts +6 -1
  171. package/src/modes/components/thinking-selector.ts +7 -3
  172. package/src/modes/components/user-message-selector.ts +57 -15
  173. package/src/modes/controllers/command-controller.ts +58 -32
  174. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  175. package/src/modes/controllers/input-controller.ts +4 -0
  176. package/src/modes/controllers/selector-controller.ts +177 -18
  177. package/src/modes/interactive-mode.ts +21 -7
  178. package/src/modes/runtime-init.ts +1 -0
  179. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  180. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  181. package/src/modes/types.ts +2 -2
  182. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  183. package/src/prompts/system/title-system.md +1 -1
  184. package/src/prompts/tools/bash.md +1 -1
  185. package/src/prompts/tools/job.md +1 -1
  186. package/src/prompts/tools/read.md +2 -0
  187. package/src/runtime/network-prewarm-service.test.ts +36 -1
  188. package/src/runtime/network-prewarm-service.ts +28 -3
  189. package/src/runtime/process-lifecycle.ts +22 -11
  190. package/src/runtime-mcp/config.ts +16 -1
  191. package/src/runtime-mcp/manager.ts +689 -55
  192. package/src/runtime-mcp/pool.test.ts +31 -0
  193. package/src/runtime-mcp/pool.ts +304 -28
  194. package/src/runtime-mcp/redaction.ts +42 -0
  195. package/src/runtime-mcp/startup-policy.ts +7 -0
  196. package/src/runtime-mcp/tool-bridge.ts +71 -0
  197. package/src/runtime-mcp/transports/http.ts +108 -25
  198. package/src/sdk/acp/adapter.ts +90 -9
  199. package/src/sdk/acp/final-text.ts +19 -2
  200. package/src/sdk/broker/broker.ts +378 -52
  201. package/src/sdk/broker/ensure.ts +97 -19
  202. package/src/sdk/broker/identity.ts +9 -1
  203. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  204. package/src/sdk/broker/lifecycle.ts +690 -141
  205. package/src/sdk/broker/runtime.ts +1 -1
  206. package/src/sdk/broker/session-index.ts +97 -4
  207. package/src/sdk/broker/spawn-authority.ts +35 -7
  208. package/src/sdk/broker/stderr-drainer.ts +59 -0
  209. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  210. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  211. package/src/sdk/bus/index.ts +721 -84
  212. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  213. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  214. package/src/sdk/bus/telegram-daemon.ts +10 -3
  215. package/src/sdk/cli/master-cli.ts +47 -36
  216. package/src/sdk/cli/rows.ts +30 -7
  217. package/src/sdk/cli/session-cli.ts +687 -184
  218. package/src/sdk/client/client.ts +18 -0
  219. package/src/sdk/guides/catalog.ts +2 -2
  220. package/src/sdk/guides/cli.ts +20 -62
  221. package/src/sdk/guides/verify.ts +14 -0
  222. package/src/sdk/host/host.ts +49 -5
  223. package/src/sdk/host/session-runtime.test.ts +636 -9
  224. package/src/sdk/host/session-runtime.ts +499 -118
  225. package/src/sdk/host/types.ts +12 -1
  226. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  227. package/src/sdk/host/websocket-transport.ts +40 -6
  228. package/src/sdk/index.ts +11 -0
  229. package/src/sdk/prompt-deadline-flush.ts +334 -0
  230. package/src/sdk/prompt-deadline-manager.ts +136 -4
  231. package/src/sdk/prompt-failure.ts +43 -1
  232. package/src/sdk/prompt-status.ts +8 -0
  233. package/src/sdk/prompt-tool-boundary.ts +121 -0
  234. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  235. package/src/sdk/router/replay-retention-gap-cache.ts +27 -0
  236. package/src/sdk/router/session-router.ts +31 -4
  237. package/src/sdk/session.ts +194 -16
  238. package/src/sdk/startup-capability.ts +1 -1
  239. package/src/sdk/transport/relay.ts +71 -6
  240. package/src/sdk/transport/serve-cli.ts +494 -49
  241. package/src/sdk/transport/socket.ts +12 -11
  242. package/src/sdk/transport/stdio.ts +7 -3
  243. package/src/session/agent-session.ts +2437 -400
  244. package/src/session/fallback-chain-controller.ts +6 -7
  245. package/src/session/fold-coordinator.ts +24 -5
  246. package/src/session/internal/managed-session-scope.ts +58 -18
  247. package/src/session/internal/managed-session-storage.ts +304 -11
  248. package/src/session/session-manager.ts +382 -44
  249. package/src/session/session-work-lease.ts +34 -0
  250. package/src/session-import/codex.ts +12 -3
  251. package/src/setup/model-onboarding-guidance.ts +1 -1
  252. package/src/setup/provider-onboarding.ts +397 -24
  253. package/src/slash-commands/builtin-registry.ts +258 -14
  254. package/src/task/index.ts +14 -2
  255. package/src/thinking.ts +21 -2
  256. package/src/tools/bash.ts +98 -78
  257. package/src/tools/fetch.ts +119 -20
  258. package/src/tools/job.ts +151 -25
  259. package/src/tools/output-meta.ts +15 -2
  260. package/src/tools/path-utils.ts +27 -3
  261. package/src/tools/read.ts +3 -3
  262. package/src/tools/steer-fold.ts +107 -0
  263. package/src/tools/tool-catalog.generated.ts +29 -2
  264. package/src/tools/tool-errors.ts +4 -0
  265. package/src/utils/git.ts +53 -3
  266. package/src/utils/markit.ts +55 -41
  267. package/src/utils/mupdf-assets.d.ts +4 -0
  268. package/src/utils/mupdf-embedded.ts +4 -0
  269. package/src/utils/mupdf-wasm-embedded.ts +3 -0
  270. package/src/utils/mupdf-wasm.ts +24 -2
  271. package/src/utils/mupdf.ts +129 -0
  272. package/src/utils/session-title-generation.ts +29 -0
  273. package/src/utils/title-generator.ts +46 -2
  274. package/src/web/scrapers/types.ts +24 -3
  275. package/vendor/markit-ai/LICENSE +21 -0
  276. package/vendor/markit-ai/MANIFEST.json +412 -0
  277. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  278. package/vendor/markit-ai/dist/commands/config.js +139 -0
  279. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  280. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  281. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  282. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  283. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  284. package/vendor/markit-ai/dist/commands/init.js +29 -0
  285. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  286. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  287. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  288. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  289. package/vendor/markit-ai/dist/config.d.ts +26 -0
  290. package/vendor/markit-ai/dist/config.js +42 -0
  291. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  292. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  293. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  294. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  295. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  296. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  297. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  298. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  299. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  300. package/vendor/markit-ai/dist/converters/github.js +148 -0
  301. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  302. package/vendor/markit-ai/dist/converters/html.js +30 -0
  303. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  304. package/vendor/markit-ai/dist/converters/image.js +124 -0
  305. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  306. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  307. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  308. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  309. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  310. package/vendor/markit-ai/dist/converters/json.js +21 -0
  311. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  312. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  313. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  314. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  315. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  316. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  317. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  318. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  319. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  320. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  321. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  322. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  323. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  324. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  325. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  326. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  327. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  328. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  329. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  330. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  331. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  332. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  333. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  334. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  335. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  336. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  337. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  338. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  339. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  340. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  341. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  342. package/vendor/markit-ai/dist/index.d.ts +30 -0
  343. package/vendor/markit-ai/dist/index.js +26 -0
  344. package/vendor/markit-ai/dist/main.d.ts +2 -0
  345. package/vendor/markit-ai/dist/main.js +191 -0
  346. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  347. package/vendor/markit-ai/dist/markit.js +267 -0
  348. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  349. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  350. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  351. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  352. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  353. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  354. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  355. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  356. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  357. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  358. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  359. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  360. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  361. package/vendor/markit-ai/dist/providers/index.js +56 -0
  362. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  363. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  364. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  365. package/vendor/markit-ai/dist/providers/types.js +1 -0
  366. package/vendor/markit-ai/dist/types.d.ts +36 -0
  367. package/vendor/markit-ai/dist/types.js +1 -0
  368. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  369. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  370. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  371. package/vendor/markit-ai/dist/utils/output.js +31 -0
  372. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  373. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  374. package/vendor/markit-ai/package.json +74 -0
  375. package/vendor/markit-ai.patch +49 -0
@@ -18,6 +18,7 @@ import {
18
18
  getBundledModels,
19
19
  getBundledProviders,
20
20
  getEnvApiKey,
21
+ getMiniMaxThinkingMode,
21
22
  googleAntigravityModelManagerOptions,
22
23
  googleGeminiCliModelManagerOptions,
23
24
  isCodexGpt56Tier,
@@ -43,6 +44,9 @@ import { fetchModelsDevPayload } from "@gajae-code/ai/provider-models/openai-com
43
44
  import { isDirectXaiReasoningEffortModel } from "@gajae-code/ai/providers/openai-completions-compat";
44
45
  import {
45
46
  detectDiscoveredApiFamily,
47
+ isSafeCatalogModelId,
48
+ MODELS_LIST_REQUEST_TIMEOUT_MS,
49
+ readBoundedModelsJson,
46
50
  resolveLoopbackOpenAIBaseUrl,
47
51
  } from "@gajae-code/ai/utils/discovery/openai-compatible";
48
52
 
@@ -143,6 +147,36 @@ function redactDiscoveryUrl(value: string | URL): string {
143
147
  }
144
148
  }
145
149
 
150
+ /**
151
+ * Scrub resolved credential material from a discovery failure before it is
152
+ * published to discovery state, cache provenance, or the logger. Mutates
153
+ * Error messages and stacks in place to preserve class/identity; wraps non-Errors.
154
+ */
155
+ export function scrubDiscoveryError(error: unknown, secrets: ReadonlyArray<string | undefined>): unknown {
156
+ const redact = (text: string): string => {
157
+ let scrubbed = text;
158
+ for (const secret of secrets) {
159
+ if (secret) scrubbed = scrubbed.split(secret).join("[redacted]");
160
+ }
161
+ return scrubbed;
162
+ };
163
+ if (error instanceof Error) {
164
+ const seen = new Set<Error>();
165
+ const scrubError = (current: Error): void => {
166
+ if (seen.has(current)) return;
167
+ seen.add(current);
168
+ current.message = redact(current.message);
169
+ if (typeof current.stack === "string") current.stack = redact(current.stack);
170
+ if (current.cause instanceof Error) scrubError(current.cause);
171
+ else if (typeof current.cause === "string") current.cause = redact(current.cause);
172
+ };
173
+ scrubError(error);
174
+ return error;
175
+ }
176
+ if (typeof error === "string") return redact(error);
177
+ return error;
178
+ }
179
+
146
180
  /** Whether a structured transport code proves that no listener accepted the connection. */
147
181
  function isConnectionRefusedDiscoveryCode(value: unknown): boolean {
148
182
  if (typeof value === "string") {
@@ -280,6 +314,7 @@ export const GJC_MODEL_ASSIGNMENT_TARGETS: Record<GjcModelAssignmentTargetId, Gj
280
314
 
281
315
  export function requiresExplicitThinkingChoice(model: Model, role: GjcModelAssignmentTargetId | null): boolean {
282
316
  if (!modelSupportsReasoningControl(model)) return false;
317
+ if (getMiniMaxThinkingMode(model) === "toggle") return true;
283
318
  if (model.provider === "openai" || model.provider === "openai-codex" || isDirectXaiReasoningEffortModel(model))
284
319
  return true;
285
320
  if (role === null) return false;
@@ -740,13 +775,26 @@ function registryModelMetadataWithoutApiSpecificFields(model: Model<Api>): Parti
740
775
  return metadata;
741
776
  }
742
777
 
743
- function registrySelectorResolvesToModel(selector: string, models: readonly Model<Api>[]): boolean {
744
- if (models.some(model => model.id === selector || `${model.provider}/${model.id}` === selector)) return true;
745
- const suffix = splitSelectorThinkingSuffix(selector);
746
- const baseSelector = suffix.thinkingLevel === undefined ? selector : suffix.selector;
778
+ export function registrySelectorResolvesToModel(selector: string, models: readonly Model<Api>[]): boolean {
779
+ const normalizedSelector = selector.trim().toLowerCase();
780
+ if (
781
+ models.some(
782
+ model =>
783
+ model.id.toLowerCase() === normalizedSelector ||
784
+ `${model.provider}/${model.id}`.toLowerCase() === normalizedSelector,
785
+ )
786
+ )
787
+ return true;
788
+ const suffix = splitSelectorThinkingSuffix(normalizedSelector);
789
+ const baseSelector = suffix.thinkingLevel === undefined ? normalizedSelector : suffix.selector;
747
790
  const parsed = parseModelString(baseSelector);
748
- if (parsed) return models.some(model => model.provider === parsed.provider && model.id === parsed.id);
749
- return models.some(model => model.id === baseSelector || model.id.endsWith(`/${baseSelector}`));
791
+ if (parsed)
792
+ return models.some(
793
+ model => model.provider.toLowerCase() === parsed.provider && model.id.toLowerCase() === parsed.id,
794
+ );
795
+ return models.some(
796
+ model => model.id.toLowerCase() === baseSelector || model.id.toLowerCase().endsWith(`/${baseSelector}`),
797
+ );
750
798
  }
751
799
 
752
800
  function filterMaterializedRegistryProfiles(
@@ -3247,7 +3295,7 @@ export class ModelRegistry {
3247
3295
  );
3248
3296
  if (
3249
3297
  evidence !== undefined &&
3250
- state?.status === "ok" &&
3298
+ (state?.status === "ok" || state?.status === "empty") &&
3251
3299
  discovery.fetched &&
3252
3300
  currentAuthGeneration === evidence.authGeneration &&
3253
3301
  currentEndpoint === evidence.endpoint
@@ -3285,8 +3333,8 @@ export class ModelRegistry {
3285
3333
  }
3286
3334
 
3287
3335
  #profileAvailabilityEvidenceFingerprint(): string {
3288
- return JSON.stringify(
3289
- [...this.#descriptorDiscoveryEvidence.entries()]
3336
+ return JSON.stringify({
3337
+ descriptor: [...this.#descriptorDiscoveryEvidence.entries()]
3290
3338
  .sort(([left], [right]) => left.localeCompare(right))
3291
3339
  .map(([provider, evidence]) => [
3292
3340
  provider,
@@ -3298,7 +3346,15 @@ export class ModelRegistry {
3298
3346
  [...evidence.modelIds].sort(),
3299
3347
  evidence.profileModelIds === undefined ? undefined : [...evidence.profileModelIds].sort(),
3300
3348
  ]),
3301
- );
3349
+ configured: [...this.#configuredDiscoveryEvidence.entries()]
3350
+ .sort(([left], [right]) => left.localeCompare(right))
3351
+ .map(([provider, evidence]) => [
3352
+ provider,
3353
+ evidence.authGeneration,
3354
+ evidence.endpoint,
3355
+ [...evidence.modelIds].sort(),
3356
+ ]),
3357
+ });
3302
3358
  }
3303
3359
 
3304
3360
  #mergeDiscoveredModels(discovered: readonly Model<Api>[]): void {
@@ -3494,8 +3550,14 @@ export class ModelRegistry {
3494
3550
  await this.#discoverModelsByProviderType(provider, apiKey),
3495
3551
  );
3496
3552
  } catch (error) {
3497
- discoveryFailureEvidence = error;
3498
- throw error;
3553
+ // ONE credential-safe discovery error boundary: transport
3554
+ // layers may echo request details (including the bearer)
3555
+ // in failure text. Scrub resolved credential material
3556
+ // before the error reaches discovery state, cache
3557
+ // provenance, or the logger below.
3558
+ const scrubbedError = scrubDiscoveryError(error, [apiKey, preflightApiKey]);
3559
+ discoveryFailureEvidence = scrubbedError;
3560
+ throw scrubbedError;
3499
3561
  }
3500
3562
  },
3501
3563
  getEvidenceGeneration: provider => this.#getProviderEvidenceGeneration(provider.provider, preflightApiKey),
@@ -3567,24 +3629,35 @@ export class ModelRegistry {
3567
3629
  };
3568
3630
  }
3569
3631
 
3570
- #discoverModelsByProviderType(
3632
+ async #discoverModelsByProviderType(
3571
3633
  providerConfig: DiscoveryProviderConfig,
3572
3634
  apiKey: string | undefined,
3573
3635
  ): Promise<Model<Api>[]> {
3636
+ let models: Model<Api>[];
3574
3637
  switch (providerConfig.discovery.type) {
3575
3638
  case "ollama":
3576
- return this.#discoverOllamaModels(providerConfig, apiKey);
3639
+ models = await this.#discoverOllamaModels(providerConfig, apiKey);
3640
+ break;
3577
3641
  case "llama.cpp":
3578
- return this.#discoverLlamaCppModels(providerConfig, apiKey);
3642
+ models = await this.#discoverLlamaCppModels(providerConfig, apiKey);
3643
+ break;
3579
3644
  case "lm-studio":
3580
3645
  case "omlx":
3581
3646
  case "vllm":
3582
3647
  case "sglang":
3583
3648
  case "openai-models-list":
3584
- return this.#discoverOpenAIModelsList(providerConfig, apiKey);
3649
+ models = await this.#discoverOpenAIModelsList(providerConfig, apiKey);
3650
+ break;
3585
3651
  case "models-dev":
3586
- return this.#discoverModelsDevProvider(providerConfig);
3652
+ models = await this.#discoverModelsDevProvider(providerConfig);
3653
+ break;
3587
3654
  }
3655
+ if (providerConfig.discovery.type === "openai-models-list" && models.length === 0) {
3656
+ throw new Error(
3657
+ `Model discovery for ${redactDiscoveryUrl(providerConfig.baseUrl ?? "")} returned no models; add --model <id> or fix the endpoint catalog.`,
3658
+ );
3659
+ }
3660
+ return models;
3588
3661
  }
3589
3662
 
3590
3663
  async #discoverBuiltInProviderModels(
@@ -4220,7 +4293,7 @@ export class ModelRegistry {
4220
4293
  ...(providerConfig.discovery.type === "vllm" || providerConfig.discovery.type === "sglang"
4221
4294
  ? { redirect: "error" as const }
4222
4295
  : {}),
4223
- signal: AbortSignal.timeout(hardenedLocalDiscovery ? 500 : 5_000),
4296
+ signal: AbortSignal.timeout(hardenedLocalDiscovery ? 500 : MODELS_LIST_REQUEST_TIMEOUT_MS),
4224
4297
  });
4225
4298
  if (!response.ok) {
4226
4299
  if (response.status === 401 || response.status === 403) {
@@ -4232,16 +4305,31 @@ export class ModelRegistry {
4232
4305
  }
4233
4306
  throw new Error(`HTTP ${response.status} from ${redactDiscoveryUrl(modelsUrl)}`);
4234
4307
  }
4235
- const payload: unknown = await response.json();
4308
+ // Shared 1MB bounded reader (same as the setup probe): a timeout
4309
+ // bounds wall clock, not bytes buffered.
4310
+ let payload: unknown;
4311
+ try {
4312
+ payload = await readBoundedModelsJson(response);
4313
+ } catch {
4314
+ throw new Error(`Malformed OpenAI models-list response from ${redactDiscoveryUrl(modelsUrl)}`);
4315
+ }
4236
4316
  if (!isRecord(payload) || !Array.isArray(payload.data)) {
4237
4317
  throw new Error(`Malformed OpenAI models-list response from ${redactDiscoveryUrl(modelsUrl)}`);
4238
4318
  }
4239
4319
  const models = payload.data;
4240
4320
  const discovered: Model<Api>[] = [];
4241
4321
  for (const item of models) {
4242
- if (!isRecord(item) || typeof item.id !== "string" || !item.id.trim()) continue;
4243
- const id = item.id;
4322
+ // Shared catalog admission: the setup probe applies the same
4323
+ // check, so IDs that appear only between requests cannot enter
4324
+ // the live catalog or cache unsanitized.
4325
+ if (!isRecord(item) || !isSafeCatalogModelId(item.id)) continue;
4326
+ const id = item.id.trim();
4244
4327
  const referenceModel = resolveCustomModelReference(id);
4328
+ // Names render directly in the model selector: apply the same
4329
+ // text-safety admission, falling back to the reference name or
4330
+ // the safe ID.
4331
+ const rawName = typeof item.name === "string" ? item.name.trim() : "";
4332
+ const name = rawName && isSafeCatalogModelId(rawName) ? rawName : (referenceModel?.name ?? id);
4245
4333
  const discoveredMaxTokens = firstPositiveDiscoveryNumber(
4246
4334
  item.max_completion_tokens,
4247
4335
  item.max_tokens,
@@ -4251,7 +4339,7 @@ export class ModelRegistry {
4251
4339
  discovered.push(
4252
4340
  enrichModelThinking({
4253
4341
  id,
4254
- name: typeof item.name === "string" ? item.name : (referenceModel?.name ?? id),
4342
+ name,
4255
4343
  api,
4256
4344
  provider: providerConfig.provider,
4257
4345
  baseUrl: requestBaseUrl,
@@ -4770,6 +4858,25 @@ export class ModelRegistry {
4770
4858
  return [...this.#configuredProviderIds];
4771
4859
  }
4772
4860
 
4861
+ /**
4862
+ * Whether this registry can serve a provider id from any active source.
4863
+ *
4864
+ * Built-in providers are backed by the bundled AI catalog, configured
4865
+ * providers come from models.yml, and extension registrations are retained
4866
+ * in the runtime provider stores below. Runtime model/override state is
4867
+ * included for direct registrations that do not have an extension source id.
4868
+ */
4869
+ isKnownProvider(provider: string): boolean {
4870
+ return (
4871
+ isKnownProvider(provider) ||
4872
+ this.#configuredProviderIds.has(provider) ||
4873
+ this.#runtimeProviderSourceByName.has(provider) ||
4874
+ this.#runtimeModelOverlays.some(model => model.provider === provider) ||
4875
+ this.#runtimeProviderApiKeys.has(provider) ||
4876
+ this.#runtimeProviderOverrides.has(provider)
4877
+ );
4878
+ }
4879
+
4773
4880
  #isModelAvailable(model: Model<Api>, disabledProviders?: ReadonlySet<string>): boolean {
4774
4881
  const disabled = disabledProviders ?? getDisabledProviderIdsFromSettings(this.#settings);
4775
4882
  return (
@@ -5205,8 +5312,10 @@ export class ModelRegistry {
5205
5312
  }
5206
5313
 
5207
5314
  /**
5208
- * Get only models that have auth configured.
5209
- * This is a fast check that doesn't refresh OAuth tokens.
5315
+ * Get selectable models with auth configured.
5316
+ * This is a fast check that doesn't refresh OAuth tokens. A current,
5317
+ * authoritative live catalog also limits each provider to its enrolled ids;
5318
+ * bundled entries remain the fallback until that evidence exists.
5210
5319
  */
5211
5320
  getAvailable(): Model<Api>[] {
5212
5321
  this.#synchronizeEnvironmentCredentials();
@@ -5220,12 +5329,82 @@ export class ModelRegistry {
5220
5329
  ) {
5221
5330
  return this.#availableModelsCache;
5222
5331
  }
5223
- this.#availableModelsCache = this.#models.filter(model => this.#isModelAvailable(model, disabledProviders));
5332
+ const authoritativeDiscoveryIds = new Map<string, ReadonlySet<string> | undefined>();
5333
+ const bundledIdsByProvider = new Map<string, Set<string>>();
5334
+ this.#availableModelsCache = this.#models.filter(model => {
5335
+ if (!this.#isModelAvailable(model, disabledProviders)) return false;
5336
+
5337
+ let liveIds = authoritativeDiscoveryIds.get(model.provider);
5338
+ if (!authoritativeDiscoveryIds.has(model.provider)) {
5339
+ liveIds = this.#getAuthoritativeDiscoveredModelIds(model.provider);
5340
+ authoritativeDiscoveryIds.set(model.provider, liveIds);
5341
+ }
5342
+ // Undefined means discovery has not run successfully for the current
5343
+ // provider context. Keep the bundled catalog as the explicit fallback.
5344
+ if (liveIds === undefined) return true;
5345
+ if (this.#hasCustomModelOverlay(model.provider, model.id)) return true;
5346
+
5347
+ const activity = this.#providerActivity.get(model.provider);
5348
+ if (!activity?.staticModelIds.has(model.id)) return liveIds.has(model.id);
5349
+
5350
+ let bundledIds = bundledIdsByProvider.get(model.provider);
5351
+ if (!bundledIds) {
5352
+ bundledIds = new Set(
5353
+ (getBundledModels(model.provider as Parameters<typeof getBundledModels>[0]) as Model<Api>[]).map(
5354
+ candidate => candidate.id,
5355
+ ),
5356
+ );
5357
+ bundledIdsByProvider.set(model.provider, bundledIds);
5358
+ }
5359
+ return !bundledIds.has(model.id) || liveIds.has(model.id);
5360
+ });
5224
5361
  this.#availableModelsDisabledProviders = disabledProviderKey;
5225
5362
  this.#availableModelsEnvFingerprint = envFingerprint;
5226
5363
  return this.#availableModelsCache;
5227
5364
  }
5228
5365
 
5366
+ /**
5367
+ * Return the current live model ids only when discovery produced an
5368
+ * authoritative catalog for the provider and endpoint. An unavailable or
5369
+ * failed discovery returns undefined so callers retain the bundled fallback.
5370
+ */
5371
+ #getAuthoritativeDiscoveredModelIds(provider: string): ReadonlySet<string> | undefined {
5372
+ const descriptorEvidence = this.#descriptorDiscoveryEvidence.get(provider);
5373
+ if (descriptorEvidence?.profileFresh && descriptorEvidence.profileModelIds !== undefined) {
5374
+ try {
5375
+ if (
5376
+ descriptorEvidence.authGeneration === this.#getProviderEvidenceGeneration(provider) &&
5377
+ descriptorEvidence.profileEndpoint ===
5378
+ this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(provider) ?? "")
5379
+ ) {
5380
+ return descriptorEvidence.profileModelIds;
5381
+ }
5382
+ } catch {
5383
+ // A provider context that can no longer be verified must use its fallback.
5384
+ }
5385
+ }
5386
+
5387
+ const configuredEvidence = this.#configuredDiscoveryEvidence.get(provider);
5388
+ if (!configuredEvidence) return undefined;
5389
+ const discoveryState = this.#discoveryManager.getState(provider);
5390
+ if (
5391
+ discoveryState?.status !== "ok" &&
5392
+ discoveryState?.status !== "cached" &&
5393
+ discoveryState?.status !== "empty"
5394
+ ) {
5395
+ return undefined;
5396
+ }
5397
+ try {
5398
+ return configuredEvidence.authGeneration === this.#getProviderEvidenceGeneration(provider) &&
5399
+ configuredEvidence.endpoint ===
5400
+ this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(provider) ?? "")
5401
+ ? configuredEvidence.modelIds
5402
+ : undefined;
5403
+ } catch {
5404
+ return undefined;
5405
+ }
5406
+ }
5407
+
5229
5408
  #synchronizeEnvironmentCredentials(): void {
5230
5409
  // Runtime registrations own a provider while their credential is present.
5231
5410
  // Refresh them first so a missing runtime env key can hand ownership back to
@@ -369,6 +369,24 @@ const AUTOROUTING_PROVENANCE_JSON_SCHEMA: JsonSchemaObject = {
369
369
  required: ["schema", "source", "declarationFingerprint", "tiersFingerprint"],
370
370
  };
371
371
 
372
+ // SDK prompt deadline defaults. The `sdk.promptDeadlineMs` /
373
+ // `sdk.promptMaxRuntimeMs` schema entries below and the SDK bus/host lease
374
+ // fallbacks read these same constants, so a Settings lookup that misses — no
375
+ // settings object, an unwritten key, a non-finite value — cannot arm a deadline
376
+ // that disagrees with the declared default (#5583).
377
+ export const DEFAULT_SDK_PROMPT_DEADLINE_MS = 3_600_000;
378
+ export const DEFAULT_SDK_PROMPT_MAX_RUNTIME_MS = 21_600_000;
379
+
380
+ /** Resolve a `sdk.promptDeadlineMs` lookup, falling back on any non-finite value. */
381
+ export function resolveSdkPromptDeadlineMs(value: unknown): number {
382
+ return typeof value === "number" && Number.isFinite(value) ? value : DEFAULT_SDK_PROMPT_DEADLINE_MS;
383
+ }
384
+
385
+ /** Resolve a `sdk.promptMaxRuntimeMs` lookup, falling back on any non-finite value. */
386
+ export function resolveSdkPromptMaxRuntimeMs(value: unknown): number {
387
+ return typeof value === "number" && Number.isFinite(value) ? value : DEFAULT_SDK_PROMPT_MAX_RUNTIME_MS;
388
+ }
389
+
372
390
  export const SETTINGS_SCHEMA = {
373
391
  // ────────────────────────────────────────────────────────────────────────
374
392
  // General settings (no UI)
@@ -416,16 +434,22 @@ export const SETTINGS_SCHEMA = {
416
434
  // SDK-owned prompt deadline. Hidden from the UI; ACP has no separate timeout.
417
435
  "sdk.promptDeadlineMs": {
418
436
  type: "number",
419
- default: 3_600_000,
437
+ default: DEFAULT_SDK_PROMPT_DEADLINE_MS,
420
438
  description: "SDK-owned prompt deadline; ACP has no separate timeout.",
421
439
  validate: (value: number) => Number.isSafeInteger(value) && value >= 60_000 && value <= 86_400_000,
422
440
  },
423
441
  "sdk.promptMaxRuntimeMs": {
424
442
  type: "number",
425
- default: 21_600_000,
443
+ default: DEFAULT_SDK_PROMPT_MAX_RUNTIME_MS,
426
444
  description: "Hard maximum runtime for an SDK prompt from acceptance, bounding progress-aware renewals.",
427
445
  validate: (value: number) => Number.isSafeInteger(value) && value >= 60_000 && value <= 86_400_000,
428
446
  },
447
+ "sdk.flushWorktreeOnDeadline": {
448
+ type: "boolean",
449
+ default: true,
450
+ description:
451
+ "Autosave uncommitted changes in the session's linked worktree by default as a WIP commit when a prompt deadline retires a prompt; primary checkouts require an explicit true opt-in.",
452
+ },
429
453
  "sdk.masterOrphanGraceMs": {
430
454
  type: "number",
431
455
  default: 120_000,
@@ -275,11 +275,16 @@ export async function assertCoordinatorSessionLocations(
275
275
  ]);
276
276
  // Reauthorize both persisted locations independently. A managed worktree may
277
277
  // differ from the requested cwd, but neither may escape the current roots.
278
- if (
279
- !roots.some(root => isInsideCanonicalRoot(canonicalCwd, root, platform)) ||
280
- !roots.some(root => isInsideCanonicalRoot(canonicalWorkspace, root, platform))
281
- )
282
- throw new Error("coordinator_workdir_outside_allowed_roots");
278
+ const escaped: string[] = [];
279
+ if (!roots.some(root => isInsideCanonicalRoot(canonicalCwd, root, platform))) escaped.push(`cwd ${canonicalCwd}`);
280
+ if (!roots.some(root => isInsideCanonicalRoot(canonicalWorkspace, root, platform)))
281
+ escaped.push(`workspace ${canonicalWorkspace}`);
282
+ if (escaped.length > 0)
283
+ // The message stays exact because isSessionAuthorityError() in server.ts matches it
284
+ // verbatim; the escaping location rides in `cause` so a caller that logs can name it.
285
+ throw new Error("coordinator_workdir_outside_allowed_roots", {
286
+ cause: new Error(`outside allowed roots: ${escaped.join(", ")}`),
287
+ });
283
288
  }
284
289
 
285
290
  export async function assertCoordinatorArtifactPath(
@@ -184,6 +184,23 @@ export function buildCoordinatorAskAnswerSchema(
184
184
  return {
185
185
  title: "CoordinatorQuestionAnswerV1",
186
186
  type: "object",
187
+ // `additionalProperties: false` is scoped by the SIBLING `properties` map, not by
188
+ // the `oneOf` branches: a standards-compliant validator evaluates the keyword
189
+ // against this node alone. Without this map every answer field was "additional",
190
+ // so selection, custom-answer, and clarification payloads were all rejected
191
+ // client-side before the server saw them (#5801). Each branch stays closed too,
192
+ // so the union still rejects field combinations this map alone would allow.
193
+ properties: {
194
+ selected: selectedBase,
195
+ other: { type: "boolean", description: "set true to provide a free-text answer in `custom`" },
196
+ custom: boundedAnswerText("free-text answer; required when `other` is true"),
197
+ action: {
198
+ type: "string",
199
+ enum: ["answer", "clarify"],
200
+ description: "set to `clarify` to ask about the choices without answering the round",
201
+ },
202
+ question: boundedAnswerText("clarification question; required when action is `clarify`"),
203
+ },
187
204
  additionalProperties: false,
188
205
  oneOf: [
189
206
  {