@gajae-code/coding-agent 0.17.2 → 0.17.5

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 (390) hide show
  1. package/CHANGELOG.md +267 -0
  2. package/dist/types/cli/daemon-cli.d.ts +3 -1
  3. package/dist/types/cli/github-release.d.ts +17 -0
  4. package/dist/types/cli/public-command-entry.d.ts +56 -0
  5. package/dist/types/cli/public-command-errors.d.ts +126 -0
  6. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  7. package/dist/types/cli/public-command-help.d.ts +65 -0
  8. package/dist/types/cli/public-command-registry.d.ts +69 -0
  9. package/dist/types/cli/session-picker.d.ts +1 -1
  10. package/dist/types/cli/setup-cli.d.ts +1 -0
  11. package/dist/types/cli/skills-cli.d.ts +5 -0
  12. package/dist/types/cli.d.ts +3 -0
  13. package/dist/types/commands/daemon.d.ts +4 -50
  14. package/dist/types/commands/sdk.d.ts +20 -37
  15. package/dist/types/commands/setup.d.ts +3 -0
  16. package/dist/types/commands/skills.d.ts +9 -0
  17. package/dist/types/config/autorouting-tier-map.d.ts +1049 -3
  18. package/dist/types/config/file-lock.d.ts +13 -3
  19. package/dist/types/config/model-profile-activation.d.ts +45 -1
  20. package/dist/types/config/model-registry.d.ts +14 -3
  21. package/dist/types/config/model-resolver.d.ts +1 -1
  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/daemon/operator-contract.d.ts +5 -1
  25. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  26. package/dist/types/exec/bash-executor.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/gjc-plugins/runtime-adapters.d.ts +11 -2
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  31. package/dist/types/extensibility/shared-events.d.ts +3 -1
  32. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  33. package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
  34. package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
  35. package/dist/types/harness-control-plane/finalize.d.ts +14 -3
  36. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  37. package/dist/types/internal-urls/index.d.ts +1 -0
  38. package/dist/types/internal-urls/parse.d.ts +9 -1
  39. package/dist/types/main.d.ts +23 -1
  40. package/dist/types/modes/acp/acp-agent.d.ts +55 -1
  41. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  42. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  43. package/dist/types/modes/components/session-selector.d.ts +5 -2
  44. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  45. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  46. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  47. package/dist/types/modes/interactive-mode.d.ts +1 -1
  48. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  49. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  50. package/dist/types/modes/types.d.ts +2 -2
  51. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  52. package/dist/types/runtime-mcp/loader.d.ts +2 -0
  53. package/dist/types/runtime-mcp/manager.d.ts +69 -6
  54. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  55. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  56. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  57. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  58. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  59. package/dist/types/sdk/broker/broker.d.ts +17 -4
  60. package/dist/types/sdk/broker/ensure.d.ts +3 -0
  61. package/dist/types/sdk/broker/identity.d.ts +5 -1
  62. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  63. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  64. package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
  65. package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
  66. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  67. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  68. package/dist/types/sdk/broker/spawn-authority.d.ts +12 -0
  69. package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
  70. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  71. package/dist/types/sdk/bus/index.d.ts +19 -0
  72. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +7 -1
  73. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  74. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  75. package/dist/types/sdk/cli/rows.d.ts +19 -1
  76. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  77. package/dist/types/sdk/client/client.d.ts +2 -0
  78. package/dist/types/sdk/guides/cli.d.ts +3 -4
  79. package/dist/types/sdk/guides/verify.d.ts +2 -0
  80. package/dist/types/sdk/host/host.d.ts +9 -0
  81. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  82. package/dist/types/sdk/host/types.d.ts +10 -0
  83. package/dist/types/sdk/index.d.ts +1 -0
  84. package/dist/types/sdk/prompt-deadline-flush.d.ts +85 -0
  85. package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
  86. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  87. package/dist/types/sdk/router/session-router.d.ts +2 -0
  88. package/dist/types/sdk/session.d.ts +3 -3
  89. package/dist/types/sdk/startup-capability.d.ts +2 -0
  90. package/dist/types/sdk/transport/relay.d.ts +1 -0
  91. package/dist/types/sdk/transport/serve-cli.d.ts +48 -4
  92. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  93. package/dist/types/session/agent-session.d.ts +175 -23
  94. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  95. package/dist/types/session/fold-coordinator.d.ts +17 -3
  96. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  97. package/dist/types/session/session-manager.d.ts +64 -1
  98. package/dist/types/session/session-work-lease.d.ts +14 -0
  99. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  100. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  101. package/dist/types/task/types.d.ts +2 -0
  102. package/dist/types/tools/bash-interactive.d.ts +1 -0
  103. package/dist/types/tools/bash.d.ts +37 -11
  104. package/dist/types/tools/fetch.d.ts +10 -1
  105. package/dist/types/tools/job.d.ts +1 -1
  106. package/dist/types/tools/steer-fold.d.ts +31 -0
  107. package/dist/types/tools/subagent.d.ts +8 -1
  108. package/dist/types/utils/git.d.ts +28 -2
  109. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  110. package/dist/types/utils/mupdf.d.ts +4 -0
  111. package/dist/types/utils/session-title-generation.d.ts +6 -0
  112. package/dist/types/utils/title-generator.d.ts +11 -2
  113. package/dist/types/web/scrapers/types.d.ts +3 -0
  114. package/package.json +18 -10
  115. package/scripts/build-binary.ts +9 -3
  116. package/scripts/compile-args.ts +0 -9
  117. package/scripts/embed-mupdf.ts +52 -0
  118. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  119. package/scripts/vendor-markit.ts +196 -0
  120. package/src/async/job-manager.ts +22 -1
  121. package/src/cli/daemon-cli.ts +53 -18
  122. package/src/cli/github-release.ts +87 -5
  123. package/src/cli/mcp-cli.ts +38 -4
  124. package/src/cli/public-command-entry.ts +450 -0
  125. package/src/cli/public-command-errors.ts +581 -0
  126. package/src/cli/public-command-evidence.ts +717 -0
  127. package/src/cli/public-command-help.ts +360 -0
  128. package/src/cli/public-command-registry.ts +541 -0
  129. package/src/cli/session-picker.ts +2 -1
  130. package/src/cli/setup-cli.ts +10 -1
  131. package/src/cli/skills-cli.ts +46 -2
  132. package/src/cli/stats-cli.ts +11 -1
  133. package/src/cli.ts +61 -1
  134. package/src/commands/daemon.ts +65 -69
  135. package/src/commands/sdk.ts +175 -117
  136. package/src/commands/setup.ts +2 -0
  137. package/src/commands/skills.ts +11 -0
  138. package/src/config/autorouting-tier-map.ts +543 -3
  139. package/src/config/file-lock.ts +206 -65
  140. package/src/config/model-discovery-manager.ts +4 -4
  141. package/src/config/model-profile-activation.ts +417 -66
  142. package/src/config/model-registry.ts +254 -36
  143. package/src/config/model-resolver.ts +6 -1
  144. package/src/config/settings-schema.ts +26 -2
  145. package/src/coordinator-mcp/policy.ts +10 -5
  146. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  147. package/src/coordinator-mcp/question-state.ts +179 -9
  148. package/src/coordinator-mcp/server.ts +521 -87
  149. package/src/coordinator-mcp/session-reaper.ts +6 -4
  150. package/src/crash/record-loader.ts +6 -2
  151. package/src/daemon/operator-contract.ts +26 -12
  152. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  153. package/src/eval/js/context-manager.ts +8 -8
  154. package/src/eval/js/worker-core.ts +9 -4
  155. package/src/eval/js/worker-protocol.ts +2 -0
  156. package/src/exec/bash-executor.ts +3 -0
  157. package/src/extensibility/extensions/runner.ts +52 -4
  158. package/src/extensibility/extensions/types.ts +10 -0
  159. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
  161. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  162. package/src/extensibility/shared-events.ts +3 -1
  163. package/src/gjc-runtime/session-state-lock.ts +165 -24
  164. package/src/gjc-runtime/state-writer.ts +317 -6
  165. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  166. package/src/harness-control-plane/control-endpoint.ts +24 -6
  167. package/src/harness-control-plane/finalize.ts +312 -25
  168. package/src/harness-control-plane/owner.ts +323 -89
  169. package/src/internal-urls/docs-index.generated.ts +23 -20
  170. package/src/internal-urls/embedded-protocol.ts +83 -0
  171. package/src/internal-urls/index.ts +1 -0
  172. package/src/internal-urls/parse.ts +21 -1
  173. package/src/internal-urls/router.ts +4 -2
  174. package/src/main.ts +192 -74
  175. package/src/modes/acp/acp-agent.ts +973 -56
  176. package/src/modes/acp/startup-provenance.ts +59 -0
  177. package/src/modes/components/custom-provider-wizard.ts +308 -7
  178. package/src/modes/components/gjc-bundle-settings.ts +21 -1
  179. package/src/modes/components/oauth-selector.ts +9 -0
  180. package/src/modes/components/session-selector.ts +47 -4
  181. package/src/modes/components/tool-status-header.ts +72 -6
  182. package/src/modes/components/user-message-selector.ts +57 -15
  183. package/src/modes/controllers/command-controller.ts +58 -32
  184. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  185. package/src/modes/controllers/input-controller.ts +4 -0
  186. package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
  187. package/src/modes/controllers/selector-controller.ts +161 -15
  188. package/src/modes/interactive-mode.ts +21 -7
  189. package/src/modes/runtime-init.ts +1 -0
  190. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  191. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  192. package/src/modes/types.ts +2 -2
  193. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  194. package/src/prompts/system/title-system.md +1 -1
  195. package/src/prompts/tools/bash.md +1 -1
  196. package/src/prompts/tools/job.md +1 -1
  197. package/src/prompts/tools/read.md +2 -0
  198. package/src/runtime/network-prewarm-service.test.ts +36 -1
  199. package/src/runtime/network-prewarm-service.ts +28 -3
  200. package/src/runtime/process-lifecycle.ts +22 -11
  201. package/src/runtime-mcp/config.ts +16 -1
  202. package/src/runtime-mcp/loader.ts +6 -3
  203. package/src/runtime-mcp/manager.ts +845 -109
  204. package/src/runtime-mcp/pool.test.ts +31 -0
  205. package/src/runtime-mcp/pool.ts +304 -28
  206. package/src/runtime-mcp/redaction.ts +42 -0
  207. package/src/runtime-mcp/startup-policy.ts +7 -0
  208. package/src/runtime-mcp/tool-bridge.ts +71 -0
  209. package/src/runtime-mcp/transports/http.ts +108 -25
  210. package/src/sdk/acp/adapter.ts +27 -8
  211. package/src/sdk/broker/broker.ts +1431 -198
  212. package/src/sdk/broker/ensure.ts +21 -3
  213. package/src/sdk/broker/identity.ts +22 -1
  214. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  215. package/src/sdk/broker/lifecycle.ts +690 -141
  216. package/src/sdk/broker/managed-task-dag.ts +1927 -0
  217. package/src/sdk/broker/managed-task-verification.ts +642 -0
  218. package/src/sdk/broker/runtime.ts +1 -1
  219. package/src/sdk/broker/session-index.ts +97 -4
  220. package/src/sdk/broker/spawn-authority.ts +175 -14
  221. package/src/sdk/broker/startup-failure.ts +80 -1
  222. package/src/sdk/broker/stderr-drainer.ts +59 -0
  223. package/src/sdk/broker/transport.ts +1 -0
  224. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  225. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  226. package/src/sdk/bus/index.ts +707 -81
  227. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  228. package/src/sdk/bus/telegram-daemon-contract.ts +7 -1
  229. package/src/sdk/bus/telegram-daemon.ts +10 -3
  230. package/src/sdk/cli/master-cli.ts +47 -36
  231. package/src/sdk/cli/rows.ts +30 -7
  232. package/src/sdk/cli/session-cli.ts +705 -184
  233. package/src/sdk/client/client.ts +18 -0
  234. package/src/sdk/guides/catalog.ts +2 -2
  235. package/src/sdk/guides/cli.ts +20 -62
  236. package/src/sdk/guides/verify.ts +14 -0
  237. package/src/sdk/host/host.ts +49 -5
  238. package/src/sdk/host/session-runtime.test.ts +184 -2
  239. package/src/sdk/host/session-runtime.ts +322 -101
  240. package/src/sdk/host/types.ts +12 -1
  241. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  242. package/src/sdk/host/websocket-transport.ts +40 -6
  243. package/src/sdk/index.ts +11 -0
  244. package/src/sdk/lifecycle/service.ts +2 -0
  245. package/src/sdk/prompt-deadline-flush.ts +356 -0
  246. package/src/sdk/prompt-deadline-manager.ts +133 -1
  247. package/src/sdk/prompt-tool-boundary.ts +121 -0
  248. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  249. package/src/sdk/router/session-router.ts +9 -1
  250. package/src/sdk/session.ts +763 -116
  251. package/src/sdk/startup-capability.ts +1 -1
  252. package/src/sdk/transport/relay.ts +71 -6
  253. package/src/sdk/transport/serve-cli.ts +397 -42
  254. package/src/sdk/transport/socket.ts +12 -11
  255. package/src/sdk/transport/stdio.ts +7 -3
  256. package/src/session/agent-session.ts +2472 -407
  257. package/src/session/fallback-chain-controller.ts +6 -7
  258. package/src/session/fold-coordinator.ts +24 -5
  259. package/src/session/internal/managed-session-scope.ts +68 -18
  260. package/src/session/internal/managed-session-storage.ts +334 -12
  261. package/src/session/session-manager.ts +382 -44
  262. package/src/session/session-work-lease.ts +34 -0
  263. package/src/setup/model-onboarding-guidance.ts +1 -1
  264. package/src/setup/provider-onboarding.ts +397 -24
  265. package/src/setup/provider-presets.json +2 -1
  266. package/src/slash-commands/builtin-registry.ts +259 -15
  267. package/src/task/executor.ts +46 -17
  268. package/src/task/index.ts +14 -2
  269. package/src/task/types.ts +2 -0
  270. package/src/tools/bash-interactive.ts +2 -0
  271. package/src/tools/bash.ts +118 -78
  272. package/src/tools/fetch.ts +140 -25
  273. package/src/tools/job.ts +151 -25
  274. package/src/tools/output-meta.ts +15 -2
  275. package/src/tools/path-utils.ts +27 -3
  276. package/src/tools/read.ts +3 -3
  277. package/src/tools/steer-fold.ts +107 -0
  278. package/src/tools/subagent-render.ts +24 -1
  279. package/src/tools/subagent.ts +27 -1
  280. package/src/tools/tool-catalog.generated.ts +29 -2
  281. package/src/tools/tool-errors.ts +4 -0
  282. package/src/utils/git.ts +53 -3
  283. package/src/utils/markit.ts +55 -41
  284. package/src/utils/mupdf-assets.d.ts +4 -0
  285. package/src/utils/mupdf-embedded.ts +4 -0
  286. package/src/utils/mupdf.ts +136 -0
  287. package/src/utils/session-title-generation.ts +29 -0
  288. package/src/utils/title-generator.ts +46 -2
  289. package/src/web/scrapers/types.ts +24 -3
  290. package/vendor/markit-ai/LICENSE +21 -0
  291. package/vendor/markit-ai/MANIFEST.json +412 -0
  292. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  293. package/vendor/markit-ai/dist/commands/config.js +139 -0
  294. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  295. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  296. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  297. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  298. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  299. package/vendor/markit-ai/dist/commands/init.js +29 -0
  300. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  301. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  302. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  303. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  304. package/vendor/markit-ai/dist/config.d.ts +26 -0
  305. package/vendor/markit-ai/dist/config.js +42 -0
  306. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  307. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  308. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  309. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  310. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  311. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  312. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  313. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  314. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  315. package/vendor/markit-ai/dist/converters/github.js +148 -0
  316. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  317. package/vendor/markit-ai/dist/converters/html.js +30 -0
  318. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  319. package/vendor/markit-ai/dist/converters/image.js +124 -0
  320. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  321. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  322. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  323. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  324. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  325. package/vendor/markit-ai/dist/converters/json.js +21 -0
  326. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  327. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  328. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  329. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  330. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  331. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  332. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  333. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  334. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  335. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  336. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  337. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  338. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  339. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  340. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  341. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  342. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  343. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  344. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  345. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  346. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  347. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  348. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  349. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  350. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  351. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  352. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  353. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  354. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  355. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  356. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  357. package/vendor/markit-ai/dist/index.d.ts +30 -0
  358. package/vendor/markit-ai/dist/index.js +26 -0
  359. package/vendor/markit-ai/dist/main.d.ts +2 -0
  360. package/vendor/markit-ai/dist/main.js +191 -0
  361. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  362. package/vendor/markit-ai/dist/markit.js +267 -0
  363. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  364. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  365. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  366. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  367. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  368. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  369. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  370. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  371. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  372. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  373. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  374. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  375. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  376. package/vendor/markit-ai/dist/providers/index.js +56 -0
  377. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  378. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  379. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  380. package/vendor/markit-ai/dist/providers/types.js +1 -0
  381. package/vendor/markit-ai/dist/types.d.ts +36 -0
  382. package/vendor/markit-ai/dist/types.js +1 -0
  383. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  384. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  385. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  386. package/vendor/markit-ai/dist/utils/output.js +31 -0
  387. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  388. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  389. package/vendor/markit-ai/package.json +74 -0
  390. package/vendor/markit-ai.patch +49 -0
@@ -44,6 +44,9 @@ import { fetchModelsDevPayload } from "@gajae-code/ai/provider-models/openai-com
44
44
  import { isDirectXaiReasoningEffortModel } from "@gajae-code/ai/providers/openai-completions-compat";
45
45
  import {
46
46
  detectDiscoveredApiFamily,
47
+ isSafeCatalogModelId,
48
+ MODELS_LIST_REQUEST_TIMEOUT_MS,
49
+ readBoundedModelsJson,
47
50
  resolveLoopbackOpenAIBaseUrl,
48
51
  } from "@gajae-code/ai/utils/discovery/openai-compatible";
49
52
 
@@ -80,6 +83,8 @@ import { ModelDiscoveryManager, type ProviderDiscoveryState } from "./model-disc
80
83
  import {
81
84
  loadAcceptedModelPresetProfiles,
82
85
  type ModelPresetRegistryDependencies,
86
+ type ModelPresetRegistryRefreshResult,
87
+ refreshModelPresetRegistry,
83
88
  refreshModelPresetRegistryInBackground,
84
89
  } from "./model-preset-registry";
85
90
 
@@ -144,6 +149,36 @@ function redactDiscoveryUrl(value: string | URL): string {
144
149
  }
145
150
  }
146
151
 
152
+ /**
153
+ * Scrub resolved credential material from a discovery failure before it is
154
+ * published to discovery state, cache provenance, or the logger. Mutates
155
+ * Error messages and stacks in place to preserve class/identity; wraps non-Errors.
156
+ */
157
+ export function scrubDiscoveryError(error: unknown, secrets: ReadonlyArray<string | undefined>): unknown {
158
+ const redact = (text: string): string => {
159
+ let scrubbed = text;
160
+ for (const secret of secrets) {
161
+ if (secret) scrubbed = scrubbed.split(secret).join("[redacted]");
162
+ }
163
+ return scrubbed;
164
+ };
165
+ if (error instanceof Error) {
166
+ const seen = new Set<Error>();
167
+ const scrubError = (current: Error): void => {
168
+ if (seen.has(current)) return;
169
+ seen.add(current);
170
+ current.message = redact(current.message);
171
+ if (typeof current.stack === "string") current.stack = redact(current.stack);
172
+ if (current.cause instanceof Error) scrubError(current.cause);
173
+ else if (typeof current.cause === "string") current.cause = redact(current.cause);
174
+ };
175
+ scrubError(error);
176
+ return error;
177
+ }
178
+ if (typeof error === "string") return redact(error);
179
+ return error;
180
+ }
181
+
147
182
  /** Whether a structured transport code proves that no listener accepted the connection. */
148
183
  function isConnectionRefusedDiscoveryCode(value: unknown): boolean {
149
184
  if (typeof value === "string") {
@@ -742,13 +777,26 @@ function registryModelMetadataWithoutApiSpecificFields(model: Model<Api>): Parti
742
777
  return metadata;
743
778
  }
744
779
 
745
- function registrySelectorResolvesToModel(selector: string, models: readonly Model<Api>[]): boolean {
746
- if (models.some(model => model.id === selector || `${model.provider}/${model.id}` === selector)) return true;
747
- const suffix = splitSelectorThinkingSuffix(selector);
748
- const baseSelector = suffix.thinkingLevel === undefined ? selector : suffix.selector;
780
+ export function registrySelectorResolvesToModel(selector: string, models: readonly Model<Api>[]): boolean {
781
+ const normalizedSelector = selector.trim().toLowerCase();
782
+ if (
783
+ models.some(
784
+ model =>
785
+ model.id.toLowerCase() === normalizedSelector ||
786
+ `${model.provider}/${model.id}`.toLowerCase() === normalizedSelector,
787
+ )
788
+ )
789
+ return true;
790
+ const suffix = splitSelectorThinkingSuffix(normalizedSelector);
791
+ const baseSelector = suffix.thinkingLevel === undefined ? normalizedSelector : suffix.selector;
749
792
  const parsed = parseModelString(baseSelector);
750
- if (parsed) return models.some(model => model.provider === parsed.provider && model.id === parsed.id);
751
- return models.some(model => model.id === baseSelector || model.id.endsWith(`/${baseSelector}`));
793
+ if (parsed)
794
+ return models.some(
795
+ model => model.provider.toLowerCase() === parsed.provider && model.id.toLowerCase() === parsed.id,
796
+ );
797
+ return models.some(
798
+ model => model.id.toLowerCase() === baseSelector || model.id.toLowerCase().endsWith(`/${baseSelector}`),
799
+ );
752
800
  }
753
801
 
754
802
  function filterMaterializedRegistryProfiles(
@@ -1856,6 +1904,17 @@ export class ModelRegistry {
1856
1904
  });
1857
1905
  }
1858
1906
 
1907
+ /** Refresh the signed profile catalog online, then publish its accepted snapshot. */
1908
+ async refreshModelPresetProfilesFromRegistry(): Promise<ModelPresetRegistryRefreshResult> {
1909
+ const result = await refreshModelPresetRegistry({
1910
+ ...this.#modelPresetRegistryDependencies,
1911
+ agentDir: this.#modelPresetRegistryAgentDir,
1912
+ knownManifestSha256: this.#loadedModelPresetRegistryManifestSha256,
1913
+ });
1914
+ await this.refreshStatic();
1915
+ return result;
1916
+ }
1917
+
1859
1918
  /**
1860
1919
  * Reload models from disk and refresh runtime provider discovery state.
1861
1920
  */
@@ -2501,12 +2560,20 @@ export class ModelRegistry {
2501
2560
  for (const providerConfig of this.#discoveryManager.providers) {
2502
2561
  if (providerId && providerConfig.provider !== providerId) continue;
2503
2562
  let expectedProvenance: string | undefined;
2563
+ let effectiveConfig: DiscoveryProviderConfig | undefined;
2564
+ let expectedAuthGeneration: string | undefined;
2565
+ let expectedEndpoint: string | undefined;
2504
2566
  try {
2505
- const effectiveConfig = this.#effectiveDiscoveryProviderConfig(providerConfig);
2567
+ effectiveConfig = this.#effectiveDiscoveryProviderConfig(providerConfig);
2568
+ const effectiveAuthGeneration =
2569
+ authEvidence ?? this.#getProviderEvidenceGeneration(effectiveConfig.provider);
2570
+ const effectiveEndpoint = this.#normalizeDiscoveryEvidenceEndpoint(effectiveConfig.baseUrl ?? "");
2571
+ expectedAuthGeneration = effectiveAuthGeneration;
2572
+ expectedEndpoint = effectiveEndpoint;
2506
2573
  expectedProvenance = fingerprintConfiguredDiscoveryRequestShape(
2507
2574
  effectiveConfig,
2508
- authEvidence ?? this.#getProviderEvidenceGeneration(effectiveConfig.provider),
2509
- this.#normalizeDiscoveryEvidenceEndpoint(effectiveConfig.baseUrl ?? ""),
2575
+ effectiveAuthGeneration,
2576
+ effectiveEndpoint,
2510
2577
  );
2511
2578
  } catch {
2512
2579
  // A context that cannot be fully derived cannot vouch for a cache row.
@@ -2515,6 +2582,30 @@ export class ModelRegistry {
2515
2582
  const models = publishDiscoveryState
2516
2583
  ? this.#discoveryManager.loadCached(providerConfig, this.#cacheDbPath, expectedProvenance)
2517
2584
  : this.#readCachedDiscoverableModels(providerConfig, expectedProvenance);
2585
+ if (publishDiscoveryState) {
2586
+ const cache =
2587
+ effectiveConfig !== undefined
2588
+ ? readModelCache<Api>(effectiveConfig.provider, 24 * 60 * 60 * 1000, Date.now, this.#cacheDbPath)
2589
+ : null;
2590
+ if (
2591
+ effectiveConfig !== undefined &&
2592
+ expectedAuthGeneration !== undefined &&
2593
+ expectedEndpoint !== undefined &&
2594
+ expectedProvenance !== undefined &&
2595
+ cache?.fresh === true &&
2596
+ cache.authoritative === true &&
2597
+ cache.dynamicModelIds !== undefined &&
2598
+ cache.dynamicModelProvenance === expectedProvenance
2599
+ ) {
2600
+ this.#configuredDiscoveryEvidence.set(effectiveConfig.provider, {
2601
+ authGeneration: expectedAuthGeneration,
2602
+ endpoint: expectedEndpoint,
2603
+ modelIds: new Set(cache.dynamicModelIds),
2604
+ });
2605
+ } else {
2606
+ this.#configuredDiscoveryEvidence.delete(providerConfig.provider);
2607
+ }
2608
+ }
2518
2609
  // Cache rows persist sanitized transport metadata (no headers), so a
2519
2610
  // rebooted registry re-derives the provider transport override from the
2520
2611
  // same source the live publish path uses — mirroring the cached
@@ -3247,16 +3338,24 @@ export class ModelRegistry {
3247
3338
  const currentEndpoint = this.#normalizeDiscoveryEvidenceEndpoint(
3248
3339
  this.#effectiveDiscoveryProviderConfig(provider).baseUrl ?? "",
3249
3340
  );
3341
+ const authoritativeState =
3342
+ state !== undefined &&
3343
+ state.error === undefined &&
3344
+ !state.stale &&
3345
+ ((state.status === "ok" && discovery.fetched) ||
3346
+ state.status === "empty" ||
3347
+ (state.status === "ok" && !discovery.fetched));
3250
3348
  if (
3251
3349
  evidence !== undefined &&
3252
- state?.status === "ok" &&
3253
- discovery.fetched &&
3350
+ authoritativeState &&
3254
3351
  currentAuthGeneration === evidence.authGeneration &&
3255
3352
  currentEndpoint === evidence.endpoint
3256
3353
  ) {
3257
3354
  this.#configuredDiscoveryEvidence.set(provider.provider, evidence);
3258
3355
  } else if (
3259
- (state?.status !== "cached" && !(state?.status === "ok" && !discovery.fetched)) ||
3356
+ (state?.status !== "cached" &&
3357
+ state?.status !== "empty" &&
3358
+ !(state?.status === "ok" && !discovery.fetched)) ||
3260
3359
  state.error !== undefined ||
3261
3360
  this.#configuredDiscoveryEvidence.get(provider.provider)?.authGeneration !== currentAuthGeneration ||
3262
3361
  this.#configuredDiscoveryEvidence.get(provider.provider)?.endpoint !== currentEndpoint
@@ -3287,8 +3386,8 @@ export class ModelRegistry {
3287
3386
  }
3288
3387
 
3289
3388
  #profileAvailabilityEvidenceFingerprint(): string {
3290
- return JSON.stringify(
3291
- [...this.#descriptorDiscoveryEvidence.entries()]
3389
+ return JSON.stringify({
3390
+ descriptor: [...this.#descriptorDiscoveryEvidence.entries()]
3292
3391
  .sort(([left], [right]) => left.localeCompare(right))
3293
3392
  .map(([provider, evidence]) => [
3294
3393
  provider,
@@ -3300,7 +3399,15 @@ export class ModelRegistry {
3300
3399
  [...evidence.modelIds].sort(),
3301
3400
  evidence.profileModelIds === undefined ? undefined : [...evidence.profileModelIds].sort(),
3302
3401
  ]),
3303
- );
3402
+ configured: [...this.#configuredDiscoveryEvidence.entries()]
3403
+ .sort(([left], [right]) => left.localeCompare(right))
3404
+ .map(([provider, evidence]) => [
3405
+ provider,
3406
+ evidence.authGeneration,
3407
+ evidence.endpoint,
3408
+ [...evidence.modelIds].sort(),
3409
+ ]),
3410
+ });
3304
3411
  }
3305
3412
 
3306
3413
  #mergeDiscoveredModels(discovered: readonly Model<Api>[]): void {
@@ -3496,8 +3603,14 @@ export class ModelRegistry {
3496
3603
  await this.#discoverModelsByProviderType(provider, apiKey),
3497
3604
  );
3498
3605
  } catch (error) {
3499
- discoveryFailureEvidence = error;
3500
- throw error;
3606
+ // ONE credential-safe discovery error boundary: transport
3607
+ // layers may echo request details (including the bearer)
3608
+ // in failure text. Scrub resolved credential material
3609
+ // before the error reaches discovery state, cache
3610
+ // provenance, or the logger below.
3611
+ const scrubbedError = scrubDiscoveryError(error, [apiKey, preflightApiKey]);
3612
+ discoveryFailureEvidence = scrubbedError;
3613
+ throw scrubbedError;
3501
3614
  }
3502
3615
  },
3503
3616
  getEvidenceGeneration: provider => this.#getProviderEvidenceGeneration(provider.provider, preflightApiKey),
@@ -3569,24 +3682,35 @@ export class ModelRegistry {
3569
3682
  };
3570
3683
  }
3571
3684
 
3572
- #discoverModelsByProviderType(
3685
+ async #discoverModelsByProviderType(
3573
3686
  providerConfig: DiscoveryProviderConfig,
3574
3687
  apiKey: string | undefined,
3575
3688
  ): Promise<Model<Api>[]> {
3689
+ let models: Model<Api>[];
3576
3690
  switch (providerConfig.discovery.type) {
3577
3691
  case "ollama":
3578
- return this.#discoverOllamaModels(providerConfig, apiKey);
3692
+ models = await this.#discoverOllamaModels(providerConfig, apiKey);
3693
+ break;
3579
3694
  case "llama.cpp":
3580
- return this.#discoverLlamaCppModels(providerConfig, apiKey);
3695
+ models = await this.#discoverLlamaCppModels(providerConfig, apiKey);
3696
+ break;
3581
3697
  case "lm-studio":
3582
3698
  case "omlx":
3583
3699
  case "vllm":
3584
3700
  case "sglang":
3585
3701
  case "openai-models-list":
3586
- return this.#discoverOpenAIModelsList(providerConfig, apiKey);
3702
+ models = await this.#discoverOpenAIModelsList(providerConfig, apiKey);
3703
+ break;
3587
3704
  case "models-dev":
3588
- return this.#discoverModelsDevProvider(providerConfig);
3705
+ models = await this.#discoverModelsDevProvider(providerConfig);
3706
+ break;
3589
3707
  }
3708
+ if (providerConfig.discovery.type === "openai-models-list" && models.length === 0) {
3709
+ throw new Error(
3710
+ `Model discovery for ${redactDiscoveryUrl(providerConfig.baseUrl ?? "")} returned no models; add --model <id> or fix the endpoint catalog.`,
3711
+ );
3712
+ }
3713
+ return models;
3590
3714
  }
3591
3715
 
3592
3716
  async #discoverBuiltInProviderModels(
@@ -4222,7 +4346,7 @@ export class ModelRegistry {
4222
4346
  ...(providerConfig.discovery.type === "vllm" || providerConfig.discovery.type === "sglang"
4223
4347
  ? { redirect: "error" as const }
4224
4348
  : {}),
4225
- signal: AbortSignal.timeout(hardenedLocalDiscovery ? 500 : 5_000),
4349
+ signal: AbortSignal.timeout(hardenedLocalDiscovery ? 500 : MODELS_LIST_REQUEST_TIMEOUT_MS),
4226
4350
  });
4227
4351
  if (!response.ok) {
4228
4352
  if (response.status === 401 || response.status === 403) {
@@ -4234,16 +4358,31 @@ export class ModelRegistry {
4234
4358
  }
4235
4359
  throw new Error(`HTTP ${response.status} from ${redactDiscoveryUrl(modelsUrl)}`);
4236
4360
  }
4237
- const payload: unknown = await response.json();
4361
+ // Shared 1MB bounded reader (same as the setup probe): a timeout
4362
+ // bounds wall clock, not bytes buffered.
4363
+ let payload: unknown;
4364
+ try {
4365
+ payload = await readBoundedModelsJson(response);
4366
+ } catch {
4367
+ throw new Error(`Malformed OpenAI models-list response from ${redactDiscoveryUrl(modelsUrl)}`);
4368
+ }
4238
4369
  if (!isRecord(payload) || !Array.isArray(payload.data)) {
4239
4370
  throw new Error(`Malformed OpenAI models-list response from ${redactDiscoveryUrl(modelsUrl)}`);
4240
4371
  }
4241
4372
  const models = payload.data;
4242
4373
  const discovered: Model<Api>[] = [];
4243
4374
  for (const item of models) {
4244
- if (!isRecord(item) || typeof item.id !== "string" || !item.id.trim()) continue;
4245
- const id = item.id;
4375
+ // Shared catalog admission: the setup probe applies the same
4376
+ // check, so IDs that appear only between requests cannot enter
4377
+ // the live catalog or cache unsanitized.
4378
+ if (!isRecord(item) || !isSafeCatalogModelId(item.id)) continue;
4379
+ const id = item.id.trim();
4246
4380
  const referenceModel = resolveCustomModelReference(id);
4381
+ // Names render directly in the model selector: apply the same
4382
+ // text-safety admission, falling back to the reference name or
4383
+ // the safe ID.
4384
+ const rawName = typeof item.name === "string" ? item.name.trim() : "";
4385
+ const name = rawName && isSafeCatalogModelId(rawName) ? rawName : (referenceModel?.name ?? id);
4247
4386
  const discoveredMaxTokens = firstPositiveDiscoveryNumber(
4248
4387
  item.max_completion_tokens,
4249
4388
  item.max_tokens,
@@ -4253,7 +4392,7 @@ export class ModelRegistry {
4253
4392
  discovered.push(
4254
4393
  enrichModelThinking({
4255
4394
  id,
4256
- name: typeof item.name === "string" ? item.name : (referenceModel?.name ?? id),
4395
+ name,
4257
4396
  api,
4258
4397
  provider: providerConfig.provider,
4259
4398
  baseUrl: requestBaseUrl,
@@ -5226,8 +5365,10 @@ export class ModelRegistry {
5226
5365
  }
5227
5366
 
5228
5367
  /**
5229
- * Get only models that have auth configured.
5230
- * This is a fast check that doesn't refresh OAuth tokens.
5368
+ * Get selectable models with auth configured.
5369
+ * This is a fast check that doesn't refresh OAuth tokens. A current,
5370
+ * authoritative live catalog also limits each provider to its enrolled ids;
5371
+ * bundled entries remain the fallback until that evidence exists.
5231
5372
  */
5232
5373
  getAvailable(): Model<Api>[] {
5233
5374
  this.#synchronizeEnvironmentCredentials();
@@ -5241,12 +5382,82 @@ export class ModelRegistry {
5241
5382
  ) {
5242
5383
  return this.#availableModelsCache;
5243
5384
  }
5244
- this.#availableModelsCache = this.#models.filter(model => this.#isModelAvailable(model, disabledProviders));
5385
+ const authoritativeDiscoveryIds = new Map<string, ReadonlySet<string> | undefined>();
5386
+ const bundledIdsByProvider = new Map<string, Set<string>>();
5387
+ this.#availableModelsCache = this.#models.filter(model => {
5388
+ if (!this.#isModelAvailable(model, disabledProviders)) return false;
5389
+
5390
+ let liveIds = authoritativeDiscoveryIds.get(model.provider);
5391
+ if (!authoritativeDiscoveryIds.has(model.provider)) {
5392
+ liveIds = this.#getAuthoritativeDiscoveredModelIds(model.provider);
5393
+ authoritativeDiscoveryIds.set(model.provider, liveIds);
5394
+ }
5395
+ // Undefined means discovery has not run successfully for the current
5396
+ // provider context. Keep the bundled catalog as the explicit fallback.
5397
+ if (liveIds === undefined) return true;
5398
+ if (this.#hasCustomModelOverlay(model.provider, model.id)) return true;
5399
+
5400
+ const activity = this.#providerActivity.get(model.provider);
5401
+ if (!activity?.staticModelIds.has(model.id)) return liveIds.has(model.id);
5402
+
5403
+ let bundledIds = bundledIdsByProvider.get(model.provider);
5404
+ if (!bundledIds) {
5405
+ bundledIds = new Set(
5406
+ (getBundledModels(model.provider as Parameters<typeof getBundledModels>[0]) as Model<Api>[]).map(
5407
+ candidate => candidate.id,
5408
+ ),
5409
+ );
5410
+ bundledIdsByProvider.set(model.provider, bundledIds);
5411
+ }
5412
+ return !bundledIds.has(model.id) || liveIds.has(model.id);
5413
+ });
5245
5414
  this.#availableModelsDisabledProviders = disabledProviderKey;
5246
5415
  this.#availableModelsEnvFingerprint = envFingerprint;
5247
5416
  return this.#availableModelsCache;
5248
5417
  }
5249
5418
 
5419
+ /**
5420
+ * Return the current live model ids only when discovery produced an
5421
+ * authoritative catalog for the provider and endpoint. An unavailable or
5422
+ * failed discovery returns undefined so callers retain the bundled fallback.
5423
+ */
5424
+ #getAuthoritativeDiscoveredModelIds(provider: string): ReadonlySet<string> | undefined {
5425
+ const descriptorEvidence = this.#descriptorDiscoveryEvidence.get(provider);
5426
+ if (descriptorEvidence?.profileFresh && descriptorEvidence.profileModelIds !== undefined) {
5427
+ try {
5428
+ if (
5429
+ descriptorEvidence.authGeneration === this.#getProviderEvidenceGeneration(provider) &&
5430
+ descriptorEvidence.profileEndpoint ===
5431
+ this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(provider) ?? "")
5432
+ ) {
5433
+ return descriptorEvidence.profileModelIds;
5434
+ }
5435
+ } catch {
5436
+ // A provider context that can no longer be verified must use its fallback.
5437
+ }
5438
+ }
5439
+
5440
+ const configuredEvidence = this.#configuredDiscoveryEvidence.get(provider);
5441
+ if (!configuredEvidence) return undefined;
5442
+ const discoveryState = this.#discoveryManager.getState(provider);
5443
+ if (
5444
+ discoveryState?.status !== "ok" &&
5445
+ discoveryState?.status !== "cached" &&
5446
+ discoveryState?.status !== "empty"
5447
+ ) {
5448
+ return undefined;
5449
+ }
5450
+ try {
5451
+ return configuredEvidence.authGeneration === this.#getProviderEvidenceGeneration(provider) &&
5452
+ configuredEvidence.endpoint ===
5453
+ this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(provider) ?? "")
5454
+ ? configuredEvidence.modelIds
5455
+ : undefined;
5456
+ } catch {
5457
+ return undefined;
5458
+ }
5459
+ }
5460
+
5250
5461
  #synchronizeEnvironmentCredentials(): void {
5251
5462
  // Runtime registrations own a provider while their credential is present.
5252
5463
  // Refresh them first so a missing runtime env key can hand ownership back to
@@ -5267,6 +5478,10 @@ export class ModelRegistry {
5267
5478
  */
5268
5479
  getAvailableForProfileActivation(): Model<Api>[] {
5269
5480
  const bundledIdsByProvider = new Map<string, Set<string>>();
5481
+ // Evidence staleness depends only on the provider, and resolving it scans the
5482
+ // catalog for the provider base URL. Decide it once per provider per call so a
5483
+ // multi-thousand-model catalog is not rescanned for every model.
5484
+ const staleEvidenceByProvider = new Map<string, boolean>();
5270
5485
  return this.getAvailable().filter(model => {
5271
5486
  const evidence = this.#descriptorDiscoveryEvidence.get(model.provider);
5272
5487
  if (!evidence?.profileFresh || evidence.profileModelIds === undefined) return true;
@@ -5281,12 +5496,15 @@ export class ModelRegistry {
5281
5496
  bundledIdsByProvider.set(model.provider, bundledModelIds);
5282
5497
  }
5283
5498
  if (!bundledModelIds.has(model.id)) return true;
5284
- if (
5285
- evidence.authGeneration !== this.#getProviderEvidenceGeneration(model.provider) ||
5286
- evidence.profileEndpoint !==
5287
- this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(model.provider) ?? "")
5288
- )
5289
- return true;
5499
+ let staleEvidence = staleEvidenceByProvider.get(model.provider);
5500
+ if (staleEvidence === undefined) {
5501
+ staleEvidence =
5502
+ evidence.authGeneration !== this.#getProviderEvidenceGeneration(model.provider) ||
5503
+ evidence.profileEndpoint !==
5504
+ this.#normalizeDiscoveryEvidenceEndpoint(this.#getProviderBaseUrlForDiscovery(model.provider) ?? "");
5505
+ staleEvidenceByProvider.set(model.provider, staleEvidence);
5506
+ }
5507
+ if (staleEvidence) return true;
5290
5508
  return evidence.profileModelIds.has(model.id);
5291
5509
  });
5292
5510
  }
@@ -87,6 +87,7 @@ export function resolveStartupModelRefreshSelectors(
87
87
  export async function refreshMissingQualifiedModelProviders(
88
88
  selectors: ModelSelectorValue | undefined,
89
89
  modelRegistry: Pick<ModelRegistry, "getAvailable" | "getRefreshableProviders" | "refreshProvider">,
90
+ credentialSessionId?: string,
90
91
  ): Promise<boolean> {
91
92
  const refreshedProviders = new Set<string>();
92
93
  for (const selector of normalizeModelSelectorValue(selectors)) {
@@ -104,7 +105,11 @@ export async function refreshMissingQualifiedModelProviders(
104
105
  )
105
106
  continue;
106
107
 
107
- await modelRegistry.refreshProvider(provider, "online-if-uncached");
108
+ if (credentialSessionId === undefined) {
109
+ await modelRegistry.refreshProvider(provider, "online-if-uncached");
110
+ } else {
111
+ await modelRegistry.refreshProvider(provider, "online-if-uncached", credentialSessionId);
112
+ }
108
113
  refreshedProviders.add(provider);
109
114
  }
110
115
  return refreshedProviders.size > 0;
@@ -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
  {