@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
@@ -10,6 +10,7 @@ import {
10
10
  formatModelProfileDisplayLabel,
11
11
  type ModelProfileDefinition,
12
12
  PROXY_ROUTABLE_PROVIDER_IDS,
13
+ type ResolvedProfileBinding,
13
14
  resolveProfileBindings,
14
15
  } from "./model-profiles";
15
16
 
@@ -21,11 +22,13 @@ import {
21
22
  isAuthenticated,
22
23
  kNoAuth,
23
24
  type ModelRegistry,
25
+ registrySelectorResolvesToModel,
24
26
  } from "./model-registry";
25
27
  import {
26
28
  formatModelSelectorValue,
27
29
  formatModelString,
28
30
  parseModelString,
31
+ resolveConfiguredModelPatterns,
29
32
  resolveModelChainWithAuth,
30
33
  resolveModelRoleValue,
31
34
  splitSelectorThinkingSuffix,
@@ -69,7 +72,8 @@ type ModelProfileActivationSession = Pick<
69
72
  | "resolveModelByLookupAlias"
70
73
  | "authStorage"
71
74
  | "isCredentiallessProvider"
72
- >;
75
+ > &
76
+ Partial<Pick<ModelRegistry, "getAvailableForProfileActivation">>;
73
77
  getConfiguredModelChainState?: (role: string) => ConfiguredModelChainState | undefined;
74
78
  };
75
79
 
@@ -249,7 +253,12 @@ function concretizeMaterializedAssignmentValues(
249
253
  const sessionId = (options.session as { sessionId?: string }).sessionId;
250
254
  const credentialSessionId = options.session.credentialSessionId ?? sessionId;
251
255
  if (!modelRegistry || !sessionId) return assignments;
252
- const availableModels = modelRegistry.getAvailable();
256
+ // Materialized assignments are persisted into `modelRoles` and
257
+ // `task.agentModelOverrides` and later consumed by profile execution, so they
258
+ // must resolve against the descriptor-backed profile-activation catalog, not
259
+ // the broadened general one: otherwise a bare assignment can persist a
260
+ // bundled model that fresh live profile evidence excludes.
261
+ const availableModels = modelRegistry.getAvailableForProfileActivation?.() ?? modelRegistry.getAvailable();
253
262
  const authenticatedModels = availableModels.filter(model => {
254
263
  const isCredentiallessProvider = modelRegistry.isCredentiallessProvider?.bind(modelRegistry);
255
264
  const hasUsableAuth = modelRegistry.authStorage?.hasUsableAuth?.bind(modelRegistry.authStorage);
@@ -639,6 +648,245 @@ export function requiresQualifiedModelProfileRoleResolution(profile: Pick<ModelP
639
648
  return profile.source === "user" || profile.source === "registry";
640
649
  }
641
650
 
651
+ /** Resolve a removed saved-session default through the durable profile without mutating persistent state. */
652
+ export async function resolveMissingSessionModelRecovery(options: {
653
+ modelRegistry: PrepareModelProfileActivationOptions["modelRegistry"];
654
+ settings: Pick<Settings, "get" | "getModelRole">;
655
+ defaultEntries: readonly string[];
656
+ skips: Array<{ selector: string; reason: string }>;
657
+ savedDefault: string | undefined;
658
+ credentialSessionId: string;
659
+ aliasIntent?: "preset-equivalent";
660
+ }): Promise<
661
+ | {
662
+ profileName: string;
663
+ entries: string[];
664
+ model?: Model<Api>;
665
+ thinkingLevel?: ThinkingLevel;
666
+ explicitThinkingLevel: boolean;
667
+ activeIndex: number;
668
+ skips: Array<{ selector: string; reason: string }>;
669
+ }
670
+ | undefined
671
+ > {
672
+ const allSelectorsUnknown =
673
+ options.skips.length === options.defaultEntries.length &&
674
+ options.skips.every(skip => skip.reason === "unknown_model");
675
+ if (!allSelectorsUnknown) return undefined;
676
+ const fullCatalog = options.modelRegistry.getAll();
677
+ const savedSelectorsMissingFromCatalog = resolveConfiguredModelPatterns(
678
+ options.defaultEntries,
679
+ options.settings,
680
+ ).every(selector => {
681
+ if (
682
+ resolveModelRoleValue(selector, fullCatalog, {
683
+ settings: options.settings,
684
+ modelRegistry: options.modelRegistry,
685
+ credentialSessionId: options.credentialSessionId,
686
+ ...(options.aliasIntent ? { aliasIntent: options.aliasIntent } : {}),
687
+ }).model
688
+ )
689
+ return false;
690
+ return !registrySelectorResolvesToModel(selector, fullCatalog);
691
+ });
692
+ const savedConcreteDefault = options.savedDefault ? parseModelString(options.savedDefault) : undefined;
693
+ const savedConcreteDefaultMissingFromCatalog =
694
+ savedConcreteDefault === undefined ||
695
+ !fullCatalog.some(
696
+ model =>
697
+ model.provider.toLowerCase() === savedConcreteDefault.provider.toLowerCase() &&
698
+ model.id.toLowerCase() === savedConcreteDefault.id.toLowerCase(),
699
+ );
700
+ const durableProfile = options.settings.get("modelProfile.default");
701
+ if (!savedSelectorsMissingFromCatalog || !savedConcreteDefaultMissingFromCatalog || !durableProfile)
702
+ return undefined;
703
+ return resolveModelProfileDefaultChain({
704
+ modelRegistry: options.modelRegistry,
705
+ settings: options.settings,
706
+ profileName: durableProfile,
707
+ credentialSessionId: options.credentialSessionId,
708
+ });
709
+ }
710
+
711
+ /** Resolve a durable profile's effective default chain without mutating session or settings state. */
712
+ export async function resolveModelProfileDefaultChain(options: {
713
+ modelRegistry: PrepareModelProfileActivationOptions["modelRegistry"];
714
+ settings: Pick<Settings, "get">;
715
+ profileName: string;
716
+ credentialSessionId: string;
717
+ }): Promise<{
718
+ profileName: string;
719
+ entries: string[];
720
+ model?: Model<Api>;
721
+ thinkingLevel?: ThinkingLevel;
722
+ explicitThinkingLevel: boolean;
723
+ activeIndex: number;
724
+ skips: Array<{ selector: string; reason: string }>;
725
+ }> {
726
+ const profiles = options.modelRegistry.getModelProfiles();
727
+ const profileName = validateModelProfileName(options.profileName, profiles, options.modelRegistry.getError?.());
728
+ const profile = profiles.get(profileName) ?? options.modelRegistry.getModelProfile(profileName)!;
729
+ const profileLabel = formatModelProfileDisplayLabel(profile);
730
+ const requiredProviders = aggregateModelProfileRequiredProviders(profile.requiredProviders, profile);
731
+ const alternativeGroups = profile.alternativeProviderGroups ?? [];
732
+ const alternativeSet = new Set(alternativeGroups.flat());
733
+ const requiredProviderSet = new Set(requiredProviders);
734
+ const authenticatedProviders = new Set<string>();
735
+ const missingProviders: string[] = [];
736
+ const configuredProviderIds = options.modelRegistry.getConfiguredProviderIds?.();
737
+ if (configuredProviderIds !== undefined || options.modelRegistry.isKnownProvider !== undefined) {
738
+ const isProviderKnown = (provider: string): boolean =>
739
+ (options.modelRegistry.isKnownProvider?.(provider) ?? false) ||
740
+ isKnownProvider(provider) ||
741
+ configuredProviderIds?.includes(provider) === true;
742
+ const unknownProviderIds = new Set<string>();
743
+ for (const provider of requiredProviders) {
744
+ if (!alternativeSet.has(provider) && !isProviderKnown(provider)) unknownProviderIds.add(provider);
745
+ }
746
+ for (const group of alternativeGroups) {
747
+ if (group.some(isProviderKnown)) continue;
748
+ for (const provider of group) {
749
+ if (!isProviderKnown(provider)) unknownProviderIds.add(provider);
750
+ }
751
+ }
752
+ const unknownProviders = [...unknownProviderIds].sort();
753
+ if (unknownProviders.length > 0) throw new ModelProfileUnknownProviderError(profileLabel, unknownProviders);
754
+ }
755
+ for (const provider of new Set([
756
+ ...requiredProviders,
757
+ ...alternativeSet,
758
+ ...deriveModelProfileMappedProviders(profile),
759
+ ])) {
760
+ let apiKey: string | undefined;
761
+ try {
762
+ apiKey = await options.modelRegistry.getApiKeyForProvider(provider, options.credentialSessionId);
763
+ } catch (error) {
764
+ if (requiredProviderSet.has(provider) && !alternativeSet.has(provider)) throw error;
765
+ continue;
766
+ }
767
+ if (apiKey === kNoAuth || isAuthenticated(apiKey)) authenticatedProviders.add(provider);
768
+ else if (requiredProviderSet.has(provider)) missingProviders.push(provider);
769
+ }
770
+ const proxyProvider = profile.source !== "user" ? resolveProxyProviderId(options.settings) : undefined;
771
+ const proxyMode = profile.source !== "user" ? resolveProxyMode(options.settings) : "fallback";
772
+ const proxyRoutableProviders =
773
+ profile.source === "user"
774
+ ? new Set<string>()
775
+ : profile.source === "registry"
776
+ ? new Set([
777
+ ...PROXY_ROUTABLE_PROVIDER_IDS,
778
+ ...profile.requiredProviders,
779
+ ...deriveModelProfileMappedProviders(profile),
780
+ ])
781
+ : PROXY_ROUTABLE_PROVIDER_IDS;
782
+ if (proxyMode === "always" && proxyProvider === undefined)
783
+ throw new Error('modelProfile.proxyMode "always" requires modelProfile.proxyProvider');
784
+ const proxyApiKey =
785
+ proxyProvider === undefined
786
+ ? undefined
787
+ : await options.modelRegistry.getApiKeyForProvider(proxyProvider, options.credentialSessionId);
788
+ if (
789
+ proxyProvider !== undefined &&
790
+ !isModelProfileProxyConfigured(proxyProvider, configuredProviderIds, proxyApiKey === kNoAuth)
791
+ ) {
792
+ throw new Error(
793
+ `modelProfile.proxyProvider "${proxyProvider}" is not configured. Configure it with \`gjc setup provider\` before activating a preset.`,
794
+ );
795
+ }
796
+ const proxyAuthenticated = proxyApiKey !== undefined && (proxyApiKey === kNoAuth || isAuthenticated(proxyApiKey));
797
+ if (proxyMode === "always" && !proxyAuthenticated)
798
+ throw new ModelProfileCredentialError(profileLabel, [proxyProvider!]);
799
+ const strictMissing = missingProviders.filter(
800
+ provider => !proxyRoutableProviders.has(provider) && !alternativeSet.has(provider),
801
+ );
802
+ if (strictMissing.length > 0) throw new ModelProfileCredentialError(profileLabel, strictMissing);
803
+ const strictRoutableMissing = missingProviders.filter(
804
+ provider => proxyRoutableProviders.has(provider) && !alternativeSet.has(provider),
805
+ );
806
+ if (strictRoutableMissing.length > 0 && !proxyAuthenticated) {
807
+ throw new ModelProfileCredentialError(
808
+ profileLabel,
809
+ proxyProvider === undefined ? strictRoutableMissing : [proxyProvider],
810
+ );
811
+ }
812
+ for (const group of alternativeGroups) {
813
+ if (group.some(provider => authenticatedProviders.has(provider))) continue;
814
+ const allRoutable = group.every(provider => proxyRoutableProviders.has(provider));
815
+ if (allRoutable && proxyAuthenticated) continue;
816
+ throw new ModelProfileCredentialError(
817
+ profileLabel,
818
+ allRoutable && proxyProvider !== undefined ? [proxyProvider] : [...group],
819
+ );
820
+ }
821
+ const availableModels =
822
+ options.modelRegistry.getAvailableForProfileActivation?.() ??
823
+ options.modelRegistry.getAvailable?.() ??
824
+ options.modelRegistry.getAll();
825
+ let bindings = resolveProfileBindings(profile);
826
+ if (alternativeGroups.length > 0)
827
+ bindings = rewriteBindingsProviders(bindings, authenticatedProviders, alternativeGroups);
828
+ if (proxyProvider !== undefined && proxyAuthenticated && profile.source !== "user") {
829
+ bindings = rewriteBindingsForProxy(
830
+ bindings,
831
+ proxyProvider,
832
+ proxyMode,
833
+ availableModels,
834
+ authenticatedProviders,
835
+ proxyRoutableProviders,
836
+ );
837
+ }
838
+ await preflightModelProfileRoleBindings({
839
+ profile,
840
+ bindings,
841
+ roleCatalogModels: options.modelRegistry.getAll(),
842
+ settings: options.settings as Settings,
843
+ modelRegistry: options.modelRegistry as ModelRegistry,
844
+ sessionId: "",
845
+ credentialSessionId: options.credentialSessionId,
846
+ profileLabel,
847
+ });
848
+ if (!bindings.defaultSelector)
849
+ return { profileName, entries: [], explicitThinkingLevel: false, activeIndex: 0, skips: [] };
850
+ const defaultChain = normalizeModelSelectorValue(
851
+ await resolveAndClampSelectorValue(
852
+ bindings.defaultSelector,
853
+ availableModels,
854
+ {
855
+ settings: options.settings as Settings,
856
+ modelRegistry: options.modelRegistry as ModelRegistry,
857
+ sessionId: "",
858
+ credentialSessionId: options.credentialSessionId,
859
+ aliasIntent: "preset-equivalent",
860
+ },
861
+ profileLabel,
862
+ "default",
863
+ ),
864
+ );
865
+ const resolution = await resolveModelChainWithAuth(
866
+ defaultChain,
867
+ {
868
+ getAvailable: () => availableModels,
869
+ getApiKey: (model, sessionId) =>
870
+ options.modelRegistry.getApiKeyForProvider(model.provider, sessionId, model.baseUrl),
871
+ resolveCanonicalModel: options.modelRegistry.resolveCanonicalModel?.bind(options.modelRegistry),
872
+ getCanonicalVariants: options.modelRegistry.getCanonicalVariants?.bind(options.modelRegistry),
873
+ getCanonicalId: options.modelRegistry.getCanonicalId?.bind(options.modelRegistry),
874
+ resolveModelByLookupAlias: options.modelRegistry.resolveModelByLookupAlias?.bind(options.modelRegistry),
875
+ lookupAliasExists: options.modelRegistry.lookupAliasExists?.bind(options.modelRegistry),
876
+ clearCanonicalVariant: options.modelRegistry.clearCanonicalVariant?.bind(options.modelRegistry),
877
+ } as ModelRegistry,
878
+ options.settings as Settings,
879
+ options.credentialSessionId,
880
+ {
881
+ managedFallback: true,
882
+ aliasIntent: "preset-equivalent",
883
+ canonicalSessionId: null,
884
+ credentialSessionId: options.credentialSessionId,
885
+ },
886
+ );
887
+ return { profileName, entries: defaultChain, ...resolution };
888
+ }
889
+
642
890
  export function rewriteSelectorForProxy(
643
891
  selector: string,
644
892
  proxyProvider: string,
@@ -886,6 +1134,49 @@ async function resolveAndClampSelectorValue(
886
1134
  return clamped.length === 1 && typeof selectorValue === "string" ? clamped[0] : clamped;
887
1135
  }
888
1136
 
1137
+ /** Resolve every non-default binding under the profile activation contract without installing it. */
1138
+ async function preflightModelProfileRoleBindings(options: {
1139
+ profile: ModelProfileDefinition;
1140
+ bindings: ResolvedProfileBinding;
1141
+ roleCatalogModels: Model<Api>[];
1142
+ settings: Settings;
1143
+ modelRegistry: ModelRegistry;
1144
+ sessionId: string;
1145
+ credentialSessionId: string;
1146
+ profileLabel: string;
1147
+ }): Promise<{
1148
+ modelRoles: Record<string, ModelSelectorValue>;
1149
+ agentModelOverrides: Record<string, ModelSelectorValue>;
1150
+ }> {
1151
+ const resolveBindings = async (bindings: Record<string, ModelSelectorValue>) => {
1152
+ const resolved: Record<string, ModelSelectorValue> = {};
1153
+ for (const [role, selectorValue] of Object.entries(bindings) as [
1154
+ GjcModelAssignmentTargetId,
1155
+ ModelSelectorValue,
1156
+ ][]) {
1157
+ resolved[role] = await resolveAndClampSelectorValue(
1158
+ selectorValue,
1159
+ options.roleCatalogModels,
1160
+ {
1161
+ settings: options.settings,
1162
+ modelRegistry: options.modelRegistry,
1163
+ sessionId: options.sessionId,
1164
+ credentialSessionId: options.credentialSessionId,
1165
+ aliasIntent: "preset-equivalent",
1166
+ requireQualifiedResolution: requiresQualifiedModelProfileRoleResolution(options.profile),
1167
+ },
1168
+ options.profileLabel,
1169
+ role,
1170
+ );
1171
+ }
1172
+ return resolved;
1173
+ };
1174
+ return {
1175
+ modelRoles: await resolveBindings(options.bindings.modelRoles),
1176
+ agentModelOverrides: await resolveBindings(options.bindings.agentModelOverrides),
1177
+ };
1178
+ }
1179
+
889
1180
  async function concretizeProfileSelectorValue(
890
1181
  selectorValue: ModelSelectorValue,
891
1182
  prepared: PreparedModelProfileActivation,
@@ -1180,47 +1471,16 @@ export async function prepareModelProfileActivation(
1180
1471
  throw new Error(`Model profile "${profileLabel}" default selectors did not resolve to an authenticated model`);
1181
1472
  }
1182
1473
 
1183
- const modelRoles: Record<string, ModelSelectorValue> = {};
1184
- for (const [role, selectorValue] of Object.entries(bindings.modelRoles) as [
1185
- GjcModelAssignmentTargetId,
1186
- ModelSelectorValue,
1187
- ][]) {
1188
- modelRoles[role] = await resolveAndClampSelectorValue(
1189
- selectorValue,
1190
- roleCatalogModels,
1191
- {
1192
- settings: options.settings as Settings,
1193
- modelRegistry: options.modelRegistry as ModelRegistry,
1194
- sessionId: options.session.sessionId,
1195
- credentialSessionId,
1196
- aliasIntent: "preset-equivalent",
1197
- requireQualifiedResolution: requiresQualifiedModelProfileRoleResolution(profile),
1198
- },
1199
- profileLabel,
1200
- role,
1201
- );
1202
- }
1203
-
1204
- const agentModelOverrides: Record<string, ModelSelectorValue> = {};
1205
- for (const [role, selectorValue] of Object.entries(bindings.agentModelOverrides) as [
1206
- GjcModelAssignmentTargetId,
1207
- ModelSelectorValue,
1208
- ][]) {
1209
- agentModelOverrides[role] = await resolveAndClampSelectorValue(
1210
- selectorValue,
1211
- roleCatalogModels,
1212
- {
1213
- settings: options.settings as Settings,
1214
- modelRegistry: options.modelRegistry as ModelRegistry,
1215
- sessionId: options.session.sessionId,
1216
- credentialSessionId,
1217
- aliasIntent: "preset-equivalent",
1218
- requireQualifiedResolution: requiresQualifiedModelProfileRoleResolution(profile),
1219
- },
1220
- profileLabel,
1221
- role,
1222
- );
1223
- }
1474
+ const { modelRoles, agentModelOverrides } = await preflightModelProfileRoleBindings({
1475
+ profile,
1476
+ bindings,
1477
+ roleCatalogModels,
1478
+ settings: options.settings as Settings,
1479
+ modelRegistry: options.modelRegistry as ModelRegistry,
1480
+ sessionId: options.session.sessionId,
1481
+ credentialSessionId,
1482
+ profileLabel,
1483
+ });
1224
1484
 
1225
1485
  return {
1226
1486
  profileName,
@@ -1268,15 +1528,58 @@ export async function prepareModelProfileActivation(
1268
1528
  previousDefaultFallbackRuntimeState: options.session.getDefaultFallbackRuntimeState?.(),
1269
1529
  };
1270
1530
  } catch (error) {
1271
- restoreCanonicalVariant(options.modelRegistry, options.session.sessionId, previousCanonicalVariant);
1531
+ try {
1532
+ restoreCanonicalVariant(options.modelRegistry, options.session.sessionId, previousCanonicalVariant);
1533
+ } catch (rollbackError) {
1534
+ throw incompleteModelProfileRollbackError("preparation", "profile preflight", error, [
1535
+ { stage: "restore canonical model variant", error: rollbackError },
1536
+ ]);
1537
+ }
1272
1538
  throw error;
1273
1539
  }
1274
1540
  }
1275
1541
 
1542
+ function modelProfileFailureReason(error: unknown, stage: string): string {
1543
+ try {
1544
+ if (error instanceof ModelProfileCredentialError) return "required credentials unavailable";
1545
+ if (error instanceof Error && error.message.startsWith("No API key for ")) return "credentials unavailable";
1546
+ } catch {
1547
+ // An exotic error getter must not replace the activation failure.
1548
+ }
1549
+ return stage.includes("settings") || stage.startsWith("persist ") || stage.endsWith(" setting")
1550
+ ? "settings write failed"
1551
+ : "operation failed";
1552
+ }
1553
+
1554
+ class ModelProfileActivationStageError extends Error {
1555
+ readonly stage: string;
1556
+
1557
+ constructor(stage: string, error: unknown) {
1558
+ super(`${stage} (${modelProfileFailureReason(error, stage)})`, { cause: error });
1559
+ this.name = "ModelProfileActivationStageError";
1560
+ this.stage = stage;
1561
+ }
1562
+ }
1563
+
1564
+ function incompleteModelProfileRollbackError(
1565
+ phase: "preparation" | "activation",
1566
+ stage: string,
1567
+ error: unknown,
1568
+ rollbackErrors: readonly { stage: string; error: unknown }[],
1569
+ ): AggregateError {
1570
+ const primary = new ModelProfileActivationStageError(stage, error);
1571
+ const incomplete = rollbackErrors.map(failure => new ModelProfileActivationStageError(failure.stage, failure.error));
1572
+ return new AggregateError(
1573
+ [primary, ...incomplete],
1574
+ `Model profile ${phase} failed at ${primary.message}; rollback incomplete: ${incomplete.map(failure => failure.message).join("; ")}. Prior state may be unverified.`,
1575
+ );
1576
+ }
1577
+
1276
1578
  export async function applyPreparedModelProfileActivation(
1277
1579
  prepared: PreparedModelProfileActivation,
1278
1580
  options: ApplyModelProfileActivationOptions = {},
1279
1581
  ): Promise<void> {
1582
+ let activationStage = "default chain";
1280
1583
  let modelMutationStarted = false;
1281
1584
  let overridesChanged = false;
1282
1585
  let modelRolesChanged = false;
@@ -1307,15 +1610,21 @@ export async function applyPreparedModelProfileActivation(
1307
1610
  }
1308
1611
  }
1309
1612
  if (prepared.defaultModel) {
1310
- modelMutationStarted = true;
1613
+ activationStage = "model selection";
1311
1614
  await prepared.session.setModelTemporary(
1312
1615
  prepared.defaultModel,
1313
1616
  options.thinkingLevelOverride ?? prepared.defaultThinkingLevel,
1314
- { cause: "profile-activation" },
1617
+ {
1618
+ cause: "profile-activation",
1619
+ onMutationStarted: () => {
1620
+ modelMutationStarted = true;
1621
+ },
1622
+ },
1315
1623
  );
1316
1624
  }
1317
1625
  // Always reinstall the model role layer from the durable base plus the
1318
1626
  // new profile's roles so omitted roles from the previous profile are dropped.
1627
+ activationStage = "model role overrides";
1319
1628
  prepared.settings.override("modelRoles", {
1320
1629
  ...prepared.baseModelRoles,
1321
1630
  ...prepared.modelRoles,
@@ -1324,6 +1633,7 @@ export async function applyPreparedModelProfileActivation(
1324
1633
  // Always reinstall the agent role layer from the durable base plus the
1325
1634
  // new profile's roles: a default-only or role-free successor must drop
1326
1635
  // the previous profile's role-agent mappings rather than inheriting them.
1636
+ activationStage = "agent role overrides";
1327
1637
  prepared.settings.override("task.agentModelOverrides", {
1328
1638
  ...prepared.baseAgentModelOverrides,
1329
1639
  ...prepared.agentModelOverrides,
@@ -1331,65 +1641,74 @@ export async function applyPreparedModelProfileActivation(
1331
1641
  overridesChanged = true;
1332
1642
  if (options.persistDefault) {
1333
1643
  persistentMutationStarted = true;
1644
+ activationStage = "persist model roles";
1334
1645
  prepared.settings.set("modelRoles", {});
1646
+ activationStage = "persist agent roles";
1335
1647
  prepared.settings.set("task.agentModelOverrides", {});
1336
1648
  if (prepared.defaultThinkingLevel !== undefined && prepared.defaultThinkingLevel !== ThinkingLevel.Inherit) {
1649
+ activationStage = "persist thinking level";
1337
1650
  prepared.settings.set("defaultThinkingLevel", prepared.defaultThinkingLevel);
1338
1651
  }
1652
+ activationStage = "persist default profile";
1339
1653
  prepared.settings.set("modelProfile.default", prepared.profileName);
1654
+ activationStage = "forward settings flush";
1340
1655
  await prepared.settings.flushOrThrow();
1341
1656
  }
1657
+ activationStage = "active profile marker";
1342
1658
  prepared.session.setActiveModelProfile?.(prepared.profileName);
1343
1659
  if (prepared.defaultModel) {
1660
+ activationStage = "canonical model variant";
1344
1661
  prepared.modelRegistry.seedCanonicalVariant?.(prepared.session.sessionId, prepared.defaultModel);
1345
1662
  resumeDefaultChanged = true;
1663
+ activationStage = "resume default model";
1346
1664
  prepared.session.recordResumeDefaultModel?.(`${prepared.defaultModel.provider}/${prepared.defaultModel.id}`);
1347
1665
  }
1666
+ activationStage = "installed role tracking";
1348
1667
  prepared.session.noteProfileInstalledOverrides?.(
1349
1668
  Object.keys(prepared.modelRoles),
1350
1669
  Object.keys(prepared.agentModelOverrides),
1351
1670
  prepared.previousModel,
1352
1671
  );
1353
1672
  } catch (error) {
1354
- const rollbackErrors: unknown[] = [];
1355
- const restore = (action: () => void): void => {
1673
+ const rollbackErrors: Array<{ stage: string; error: unknown }> = [];
1674
+ const restore = (stage: string, action: () => void): void => {
1356
1675
  try {
1357
1676
  action();
1358
1677
  } catch (rollbackError) {
1359
- rollbackErrors.push(rollbackError);
1678
+ rollbackErrors.push({ stage, error: rollbackError });
1360
1679
  }
1361
1680
  };
1362
1681
  if (persistentMutationStarted) {
1363
- restore(() =>
1682
+ restore("restore default profile setting", () =>
1364
1683
  prepared.previousPersistedDefaultProfile === undefined
1365
1684
  ? prepared.settings.unset("modelProfile.default")
1366
1685
  : prepared.settings.set("modelProfile.default", prepared.previousPersistedDefaultProfile),
1367
1686
  );
1368
- restore(() =>
1687
+ restore("restore model role setting", () =>
1369
1688
  prepared.previousPersistedModelRoles === undefined
1370
1689
  ? prepared.settings.unset("modelRoles")
1371
1690
  : prepared.settings.set("modelRoles", prepared.previousPersistedModelRoles),
1372
1691
  );
1373
- restore(() =>
1692
+ restore("restore agent role setting", () =>
1374
1693
  prepared.previousPersistedAgentModelOverrides === undefined
1375
1694
  ? prepared.settings.unset("task.agentModelOverrides")
1376
1695
  : prepared.settings.set("task.agentModelOverrides", prepared.previousPersistedAgentModelOverrides),
1377
1696
  );
1378
- restore(() =>
1697
+ restore("restore thinking level setting", () =>
1379
1698
  prepared.previousPersistedDefaultThinkingLevel === undefined
1380
1699
  ? prepared.settings.unset("defaultThinkingLevel")
1381
1700
  : prepared.settings.set("defaultThinkingLevel", prepared.previousPersistedDefaultThinkingLevel),
1382
1701
  );
1383
1702
  }
1384
1703
  if (modelRolesChanged) {
1385
- restore(() =>
1704
+ restore("restore model role overrides", () =>
1386
1705
  prepared.previousModelRolesOverride === undefined
1387
1706
  ? prepared.settings.clearOverride("modelRoles")
1388
1707
  : prepared.settings.override("modelRoles", prepared.previousModelRolesOverride),
1389
1708
  );
1390
1709
  }
1391
1710
  if (overridesChanged) {
1392
- restore(() =>
1711
+ restore("restore agent role overrides", () =>
1393
1712
  prepared.previousAgentModelOverridesOverride === undefined
1394
1713
  ? prepared.settings.clearOverride("task.agentModelOverrides")
1395
1714
  : prepared.settings.override("task.agentModelOverrides", prepared.previousAgentModelOverridesOverride),
@@ -1410,15 +1729,17 @@ export async function applyPreparedModelProfileActivation(
1410
1729
  throw new Error("Model-less profile activation rollback is unavailable");
1411
1730
  }
1412
1731
  } catch (rollbackError) {
1413
- rollbackErrors.push(rollbackError);
1732
+ rollbackErrors.push({ stage: "restore live model", error: rollbackError });
1414
1733
  }
1415
1734
  }
1416
1735
  if (resumeDefaultChanged) {
1417
- restore(() => prepared.session.recordResumeDefaultModel?.(prepared.previousSessionDefaultModel));
1736
+ restore("restore resume default", () =>
1737
+ prepared.session.recordResumeDefaultModel?.(prepared.previousSessionDefaultModel),
1738
+ );
1418
1739
  }
1419
1740
  if (defaultChainChanged) {
1420
1741
  const previousChain = prepared.previousDefaultChainState;
1421
- restore(() =>
1742
+ restore("restore default chain", () =>
1422
1743
  prepared.session.setConfiguredModelChain(
1423
1744
  "default",
1424
1745
  previousChain?.entries ??
@@ -1431,26 +1752,25 @@ export async function applyPreparedModelProfileActivation(
1431
1752
  );
1432
1753
  }
1433
1754
  if (prepared.previousDefaultFallbackRuntimeState) {
1434
- restore(() =>
1755
+ restore("restore fallback runtime", () =>
1435
1756
  prepared.session.restoreDefaultFallbackRuntimeState?.(prepared.previousDefaultFallbackRuntimeState!),
1436
1757
  );
1437
1758
  }
1438
- restore(() => prepared.session.setActiveModelProfile?.(prepared.previousActiveModelProfile));
1439
- restore(() =>
1759
+ restore("restore active profile", () =>
1760
+ prepared.session.setActiveModelProfile?.(prepared.previousActiveModelProfile),
1761
+ );
1762
+ restore("restore canonical model variant", () =>
1440
1763
  restoreCanonicalVariant(prepared.modelRegistry, prepared.session.sessionId, prepared.previousCanonicalVariant),
1441
1764
  );
1442
1765
  if (persistentMutationStarted) {
1443
1766
  try {
1444
1767
  await prepared.settings.flushOrThrow();
1445
1768
  } catch (rollbackError) {
1446
- rollbackErrors.push(rollbackError);
1769
+ rollbackErrors.push({ stage: "restore settings flush", error: rollbackError });
1447
1770
  }
1448
1771
  }
1449
1772
  if (rollbackErrors.length > 0) {
1450
- throw new AggregateError(
1451
- [error, ...rollbackErrors],
1452
- "Model profile activation failed and rollback was incomplete",
1453
- );
1773
+ throw incompleteModelProfileRollbackError("activation", activationStage, error, rollbackErrors);
1454
1774
  }
1455
1775
  throw error;
1456
1776
  }
@@ -1722,3 +2042,34 @@ export async function activateModelProfile(
1722
2042
  const prepared = await prepareModelProfileActivation(options);
1723
2043
  await applyPreparedModelProfileActivation(prepared, applyOptions);
1724
2044
  }
2045
+
2046
+ /** Install only a profile's runtime role layer, preserving session model and configured-chain intent. */
2047
+ export async function applyModelProfileRuntimeBindings(options: PrepareModelProfileActivationOptions): Promise<void> {
2048
+ const prepared = await prepareModelProfileActivation(options);
2049
+ try {
2050
+ prepared.settings.override("modelRoles", {
2051
+ ...prepared.baseModelRoles,
2052
+ ...prepared.modelRoles,
2053
+ });
2054
+ prepared.settings.override("task.agentModelOverrides", {
2055
+ ...prepared.baseAgentModelOverrides,
2056
+ ...prepared.agentModelOverrides,
2057
+ });
2058
+ prepared.session.setActiveModelProfile?.(prepared.profileName);
2059
+ prepared.session.noteProfileInstalledOverrides?.(
2060
+ Object.keys(prepared.modelRoles),
2061
+ Object.keys(prepared.agentModelOverrides),
2062
+ prepared.previousModel,
2063
+ );
2064
+ try {
2065
+ await prepared.session.syncEagerDelegation?.();
2066
+ } catch (error) {
2067
+ logger.warn("Failed to sync eager delegation after recovered profile runtime bindings", {
2068
+ profile: prepared.profileName,
2069
+ error: error instanceof Error ? error.message : String(error),
2070
+ });
2071
+ }
2072
+ } finally {
2073
+ restoreCanonicalVariant(prepared.modelRegistry, prepared.session.sessionId, prepared.previousCanonicalVariant);
2074
+ }
2075
+ }