@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
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Protocol handler for `embedded:` URLs.
3
+ *
4
+ * Bundled GJC skills and skill fragments have no filesystem home: the skill
5
+ * tool, skill discovery, and the skill registry all report the stable
6
+ * identifier `embedded:gjc/<catalog relative path>` (for example
7
+ * `embedded:gjc/skills/ultragoal/SKILL.md`). This handler resolves exactly
8
+ * those identifiers back to the bundled catalog content so the path a tool
9
+ * prints is a path `read` can open.
10
+ *
11
+ * URL forms (the `embedded:` and `embedded://` spellings are equivalent):
12
+ * - `embedded:gjc/skills/<name>/SKILL.md` — bundled skill body
13
+ * - `embedded:gjc/skills/<name>` — skill baseDir, resolves to its SKILL.md
14
+ * - `embedded:gjc/skill-fragments/<parent>/<fragment>.md` — bundled fragment
15
+ */
16
+ import { BUNDLED_GJC_SKILL_CATALOG, type BundledGjcSkillCatalogEntry } from "../defaults/gjc-skills.generated";
17
+ import type { InternalResource, InternalUrl, ProtocolHandler } from "./types";
18
+
19
+ const GJC_NAMESPACE = "gjc";
20
+
21
+ function normalizeRelativePath(relativePath: string): string {
22
+ return relativePath.replace(/^\/+/, "").replace(/\/+$/, "");
23
+ }
24
+
25
+ function findCatalogEntry(relativePath: string): BundledGjcSkillCatalogEntry | undefined {
26
+ const direct = BUNDLED_GJC_SKILL_CATALOG.find(entry => entry.relativePath === relativePath);
27
+ if (direct) return direct;
28
+ // `baseDir` identifiers point at the skill directory, not the body file.
29
+ return BUNDLED_GJC_SKILL_CATALOG.find(entry => entry.relativePath === `${relativePath}/SKILL.md`);
30
+ }
31
+
32
+ function availablePaths(): string {
33
+ return BUNDLED_GJC_SKILL_CATALOG.map(entry => `embedded:${GJC_NAMESPACE}/${entry.relativePath}`).join(", ");
34
+ }
35
+
36
+ /**
37
+ * Handler for `embedded:` URLs.
38
+ */
39
+ export class EmbeddedProtocolHandler implements ProtocolHandler {
40
+ readonly scheme = "embedded";
41
+ readonly immutable = true;
42
+
43
+ async resolve(url: InternalUrl): Promise<InternalResource> {
44
+ const namespace = (url.rawHost || url.hostname || "").toLowerCase();
45
+ if (namespace !== GJC_NAMESPACE) {
46
+ throw new Error(
47
+ `Unknown embedded namespace: ${namespace || "(empty)"}\nOnly embedded:${GJC_NAMESPACE}/... is resolvable.`,
48
+ );
49
+ }
50
+
51
+ let rawRelativePath = url.rawPathname ?? url.pathname ?? "";
52
+ try {
53
+ rawRelativePath = decodeURIComponent(rawRelativePath);
54
+ } catch {
55
+ // Leave the raw form in place; the lookup below reports it verbatim.
56
+ }
57
+ const relativePath = normalizeRelativePath(rawRelativePath);
58
+ if (!relativePath) {
59
+ throw new Error(
60
+ `embedded:${GJC_NAMESPACE}/ URL requires a bundled resource path, e.g. embedded:${GJC_NAMESPACE}/skills/ultragoal/SKILL.md`,
61
+ );
62
+ }
63
+ if (relativePath.split("/").includes("..")) {
64
+ throw new Error("Path traversal (..) is not allowed in embedded: URLs");
65
+ }
66
+
67
+ const entry = findCatalogEntry(relativePath);
68
+ if (!entry) {
69
+ throw new Error(
70
+ `Unknown embedded resource: embedded:${GJC_NAMESPACE}/${relativePath}\nAvailable: ${availablePaths()}`,
71
+ );
72
+ }
73
+
74
+ const content = await entry.loadContent();
75
+ return {
76
+ url: url.href,
77
+ content,
78
+ contentType: "text/markdown",
79
+ size: Buffer.byteLength(content, "utf-8"),
80
+ notes: [],
81
+ };
82
+ }
83
+ }
@@ -10,6 +10,7 @@
10
10
 
11
11
  export * from "./agent-protocol";
12
12
  export * from "./artifact-protocol";
13
+ export * from "./embedded-protocol";
13
14
  export * from "./gjc-protocol";
14
15
  export * from "./issue-pr-protocol";
15
16
  export * from "./json-query";
@@ -13,6 +13,25 @@ import type { InternalUrl } from "./types";
13
13
 
14
14
  const SCHEME_HOST_RE = /^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i;
15
15
  const PATHNAME_RE = /^[a-z][a-z0-9+.-]*:\/\/[^/?#]*(\/[^?#]*)?/i;
16
+ // Schemes whose canonical spelling omits the authority slashes. `embedded:` is
17
+ // the identifier tools print for bundled (non-filesystem) resources, so both
18
+ // `embedded:gjc/...` and `embedded://gjc/...` must route to the same handler.
19
+ const SLASHLESS_SCHEMES = new Set(["embedded"]);
20
+ const SLASHLESS_SCHEME_RE = /^([a-z][a-z0-9+.-]*):(?!\/\/)(.*)$/is;
21
+
22
+ /**
23
+ * Canonicalize an internal URL so slashless schemes carry an authority.
24
+ *
25
+ * Every entry point that inspects or routes an internal URL (router,
26
+ * read/write tools, selector splitting) MUST normalize first, so handlers only
27
+ * ever see the `scheme://authority/path` form.
28
+ */
29
+ export function normalizeInternalUrlInput(input: string): string {
30
+ const match = input.match(SLASHLESS_SCHEME_RE);
31
+ if (!match) return input;
32
+ if (!SLASHLESS_SCHEMES.has(match[1].toLowerCase())) return input;
33
+ return `${match[1].toLowerCase()}://${match[2]}`;
34
+ }
16
35
 
17
36
  /**
18
37
  * Parse an internal URL into an InternalUrl.
@@ -20,7 +39,8 @@ const PATHNAME_RE = /^[a-z][a-z0-9+.-]*:\/\/[^/?#]*(\/[^?#]*)?/i;
20
39
  * Handles URLs where `new URL()` would fail (e.g., `skill://plugin:name`
21
40
  * where the colon is not a port separator).
22
41
  */
23
- export function parseInternalUrl(input: string): InternalUrl {
42
+ export function parseInternalUrl(rawInput: string): InternalUrl {
43
+ const input = normalizeInternalUrlInput(rawInput);
24
44
  const hostMatch = input.match(SCHEME_HOST_RE);
25
45
  const pathMatch = input.match(PATHNAME_RE);
26
46
 
@@ -7,11 +7,12 @@
7
7
  */
8
8
  import { AgentProtocolHandler } from "./agent-protocol";
9
9
  import { ArtifactProtocolHandler } from "./artifact-protocol";
10
+ import { EmbeddedProtocolHandler } from "./embedded-protocol";
10
11
  import { GjcProtocolHandler } from "./gjc-protocol";
11
12
  import { IssueProtocolHandler, PrProtocolHandler } from "./issue-pr-protocol";
12
13
  import { LocalProtocolHandler } from "./local-protocol";
13
14
  import { MemoryProtocolHandler } from "./memory-protocol";
14
- import { parseInternalUrl } from "./parse";
15
+ import { normalizeInternalUrlInput, parseInternalUrl } from "./parse";
15
16
  import { RuleProtocolHandler } from "./rule-protocol";
16
17
  import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext } from "./types";
17
18
 
@@ -29,6 +30,7 @@ export class InternalUrlRouter {
29
30
  this.register(new RuleProtocolHandler());
30
31
  this.register(new IssueProtocolHandler());
31
32
  this.register(new PrProtocolHandler());
33
+ this.register(new EmbeddedProtocolHandler());
32
34
  }
33
35
 
34
36
  /** Process-global router instance. */
@@ -55,7 +57,7 @@ export class InternalUrlRouter {
55
57
  }
56
58
 
57
59
  canHandle(input: string): boolean {
58
- const match = input.match(/^([a-z][a-z0-9+.-]*):\/\//i);
60
+ const match = normalizeInternalUrlInput(input).match(/^([a-z][a-z0-9+.-]*):\/\//i);
59
61
  if (!match) return false;
60
62
  return this.#handlers.has(match[1].toLowerCase());
61
63
  }
package/src/main.ts CHANGED
@@ -29,7 +29,12 @@ import { resolveLaunchDisposition } from "./cli/launch-disposition";
29
29
  import { runListModelsCommand } from "./cli/list-models";
30
30
  import { selectSession } from "./cli/session-picker";
31
31
  import { findConfigFile } from "./config";
32
- import { activateModelProfile, ModelProfileCredentialError } from "./config/model-profile-activation";
32
+ import {
33
+ activateModelProfile,
34
+ applyModelProfileRuntimeBindings,
35
+ ModelProfileCredentialError,
36
+ } from "./config/model-profile-activation";
37
+ import { UnknownModelProfileError } from "./config/model-profile-contract";
33
38
  import { ModelRegistry, ModelsConfigFile } from "./config/model-registry";
34
39
  import {
35
40
  parseModelString,
@@ -59,6 +64,9 @@ import type { SubmittedUserInput } from "./modes/types";
59
64
  import { applyCliRuntimeApiKeyOverride } from "./runtime-api-key";
60
65
  import { type CliCredentialSelector, parseCliCredentialSelector } from "./runtime-credential-selector";
61
66
  import type { MCPManager } from "./runtime-mcp";
67
+ // Leaf path, not the barrel: the capability registry must stay out of the
68
+ // runtime-mcp import graph that every root command would otherwise load.
69
+ import { attachExactMcpControls } from "./runtime-mcp/redaction";
62
70
  import {
63
71
  type CreateAgentSessionOptions,
64
72
  type CreateAgentSessionResult,
@@ -460,30 +468,50 @@ type StartupModelProfileArgs = {
460
468
  session: AgentSession;
461
469
  settings: Settings;
462
470
  modelRegistry: ModelRegistry;
463
- parsedArgs: Pick<Args, "default" | "model" | "mpreset" | "thinking">;
471
+ parsedArgs: Pick<Args, "continue" | "default" | "fork" | "model" | "mpreset" | "resume" | "thinking">;
464
472
  startupModel?: CreateAgentSessionOptions["model"];
465
473
  startupThinkingLevel?: CreateAgentSessionOptions["thinkingLevel"];
466
474
  preferCachedModels?: boolean;
467
475
  preferCachedDefaultProfile?: boolean;
468
476
  };
469
477
 
478
+ function staleDefaultProfileMessage(error: UnknownModelProfileError, profileCatalogRefreshUnavailable = false): string {
479
+ const refreshNotice = profileCatalogRefreshUnavailable
480
+ ? " The online profile catalog could not be refreshed; continuing with the last accepted catalog."
481
+ : "";
482
+ return `Configured modelProfile.default is stale: unknown model profile ${JSON.stringify(error.details.requestedProfile)}. Select a replacement in the UI. To clear it, remove modelProfile.default from the project's .gjc/config.yml or .gjc/settings.json if set there, or run gjc config reset modelProfile.default for the global setting.${refreshNotice}`;
483
+ }
484
+
470
485
  async function applyStartupModelProfilesWithPolicy(
471
486
  args: StartupModelProfileArgs,
472
487
  onCredentialError?: (error: ModelProfileCredentialError) => void,
488
+ onUnknownDefault?: (error: UnknownModelProfileError, profileCatalogRefreshUnavailable: boolean) => void,
473
489
  ): Promise<void> {
490
+ let profileCatalogRefreshUnavailable = false;
474
491
  const applyProfile = async (
475
492
  profileName: string,
476
493
  persistDefault: boolean,
477
494
  options: {
478
495
  thinkingLevelOverride?: CreateAgentSessionOptions["thinkingLevel"];
479
496
  tolerateCredentialError?: boolean;
497
+ tolerateUnknownDefault?: boolean;
498
+ runtimeBindingsOnly?: boolean;
480
499
  } = {},
481
500
  ): Promise<boolean> => {
482
501
  try {
483
- await activateModelProfile(
484
- { session: args.session, modelRegistry: args.modelRegistry, settings: args.settings, profileName },
485
- { persistDefault, thinkingLevelOverride: options.thinkingLevelOverride },
486
- );
502
+ if (options.runtimeBindingsOnly) {
503
+ await applyModelProfileRuntimeBindings({
504
+ session: args.session,
505
+ modelRegistry: args.modelRegistry,
506
+ settings: args.settings,
507
+ profileName,
508
+ });
509
+ } else {
510
+ await activateModelProfile(
511
+ { session: args.session, modelRegistry: args.modelRegistry, settings: args.settings, profileName },
512
+ { persistDefault, thinkingLevelOverride: options.thinkingLevelOverride },
513
+ );
514
+ }
487
515
  return true;
488
516
  } catch (error) {
489
517
  if (error instanceof ModelProfileCredentialError && (onCredentialError || options.tolerateCredentialError)) {
@@ -491,6 +519,14 @@ async function applyStartupModelProfilesWithPolicy(
491
519
  else process.stderr.write(`${chalk.yellow(`Warning: ${error.message}`)}\n`);
492
520
  return false;
493
521
  }
522
+ if (error instanceof UnknownModelProfileError && options.tolerateUnknownDefault) {
523
+ if (onUnknownDefault) onUnknownDefault(error, profileCatalogRefreshUnavailable);
524
+ else
525
+ process.stderr.write(
526
+ `${chalk.yellow(`Warning: ${staleDefaultProfileMessage(error, profileCatalogRefreshUnavailable)}`)}\n`,
527
+ );
528
+ return false;
529
+ }
494
530
  throw error;
495
531
  }
496
532
  };
@@ -498,8 +534,8 @@ async function applyStartupModelProfilesWithPolicy(
498
534
  // An explicit startup selector (--mpreset or --model) fully replaces the
499
535
  // persisted default profile for this session, so a failing default must not
500
536
  // abort a non-interactive run: it is reported as a warning and the explicit
501
- // selection proceeds. Without an explicit selector the historic fatal
502
- // contract is unchanged.
537
+ // selection proceeds. Without an explicit selector, failures remain fatal
538
+ // except for a stale default on input-free interactive startup.
503
539
  const tolerateDefaultProfileFailure = args.parsedArgs.mpreset !== undefined || args.parsedArgs.model !== undefined;
504
540
 
505
541
  // Capture the explicitly-selected startup model BEFORE profile activation can
@@ -510,7 +546,7 @@ async function applyStartupModelProfilesWithPolicy(
510
546
  const preferCachedProfiles =
511
547
  (args.preferCachedModels === true && args.parsedArgs.mpreset !== undefined) ||
512
548
  (args.preferCachedDefaultProfile === true && defaultProfile !== undefined);
513
- const applyConfiguredProfiles = async (): Promise<boolean> => {
549
+ const applyConfiguredProfiles = async (allowMissingDefault: boolean): Promise<boolean> => {
514
550
  let applied = true;
515
551
  if (defaultProfile) {
516
552
  applied =
@@ -519,6 +555,9 @@ async function applyStartupModelProfilesWithPolicy(
519
555
  ? args.settings.get("defaultThinkingLevel")
520
556
  : undefined,
521
557
  tolerateCredentialError: tolerateDefaultProfileFailure,
558
+ tolerateUnknownDefault:
559
+ allowMissingDefault && (onUnknownDefault !== undefined || tolerateDefaultProfileFailure),
560
+ runtimeBindingsOnly: args.session.hasRecoveredDefaultFallbackChain(),
522
561
  })) && applied;
523
562
  }
524
563
  if (args.parsedArgs.mpreset) {
@@ -531,12 +570,23 @@ async function applyStartupModelProfilesWithPolicy(
531
570
  let applied: boolean;
532
571
  let refreshedOnline = false;
533
572
  try {
534
- applied = await applyConfiguredProfiles();
573
+ applied = await applyConfiguredProfiles(false);
535
574
  } catch (error) {
536
575
  if (error instanceof ModelProfileCredentialError) throw error;
576
+ if (error instanceof UnknownModelProfileError) {
577
+ try {
578
+ await args.modelRegistry.refreshModelPresetProfilesFromRegistry();
579
+ } catch (refreshError) {
580
+ if (args.modelRegistry.getError()) throw refreshError;
581
+ profileCatalogRefreshUnavailable = true;
582
+ logger.warn("Failed to refresh model profile catalog before startup recovery", {
583
+ error: refreshError instanceof Error ? refreshError.message : String(refreshError),
584
+ });
585
+ }
586
+ }
537
587
  await args.modelRegistry.refresh("online-if-uncached", args.session.credentialSessionId);
538
588
  refreshedOnline = true;
539
- applied = await applyConfiguredProfiles();
589
+ applied = await applyConfiguredProfiles(true);
540
590
  }
541
591
  if (applied && !refreshedOnline)
542
592
  args.modelRegistry.refreshInBackground("online-if-uncached", args.session.credentialSessionId);
@@ -544,7 +594,7 @@ async function applyStartupModelProfilesWithPolicy(
544
594
  if (defaultProfile || args.parsedArgs.mpreset) {
545
595
  await args.modelRegistry.refresh("online-if-uncached", args.session.credentialSessionId);
546
596
  }
547
- await applyConfiguredProfiles();
597
+ await applyConfiguredProfiles(true);
548
598
  }
549
599
 
550
600
  // Explicit CLI --model/--thinking must win over any activated or skipped profile.
@@ -600,6 +650,20 @@ export function isStartupModelProfileCredentialRecoveryEligible(options: {
600
650
  );
601
651
  }
602
652
 
653
+ function isStartupModelProfileStaleDefaultRecoveryEligible(
654
+ options: Parameters<typeof isStartupModelProfileCredentialRecoveryEligible>[0] & {
655
+ parsedArgs: Pick<Args, "continue" | "fork" | "resume">;
656
+ },
657
+ ): boolean {
658
+ return (
659
+ isStartupModelProfileCredentialRecoveryEligible(options) &&
660
+ options.parsedArgs.continue !== true &&
661
+ options.parsedArgs.fork === undefined &&
662
+ ((options.parsedArgs.resume === undefined && options.resumeAction === undefined) ||
663
+ (options.parsedArgs.resume === true && options.resumeAction === "open-idle"))
664
+ );
665
+ }
666
+
603
667
  export async function applyStartupModelProfilesForRoot(
604
668
  args: StartupModelProfileArgs & {
605
669
  isInteractive: boolean;
@@ -609,19 +673,21 @@ export async function applyStartupModelProfilesForRoot(
609
673
  resumeAction: "continue-tail" | "open-idle" | undefined;
610
674
  },
611
675
  ): Promise<{ recoverableErrors: string[] }> {
612
- const policyArgs = { ...args, preferCachedModels: args.isInteractive };
613
- if (!isStartupModelProfileCredentialRecoveryEligible(args)) {
614
- try {
615
- await applyStartupModelProfilesWithPolicy(policyArgs);
616
- } catch (error) {
617
- await exitForStartupModelProfileError(args, error);
618
- }
619
- return { recoverableErrors: [] };
620
- }
621
-
676
+ const policyArgs = {
677
+ ...args,
678
+ preferCachedModels: args.isInteractive,
679
+ preferCachedDefaultProfile: args.isInteractive,
680
+ };
622
681
  const recoverableErrors: string[] = [];
682
+ const onCredentialError = isStartupModelProfileCredentialRecoveryEligible(args)
683
+ ? (error: ModelProfileCredentialError) => recoverableErrors.push(error.message)
684
+ : undefined;
685
+ const onUnknownDefault = isStartupModelProfileStaleDefaultRecoveryEligible(args)
686
+ ? (error: UnknownModelProfileError, profileCatalogRefreshUnavailable: boolean) =>
687
+ recoverableErrors.push(staleDefaultProfileMessage(error, profileCatalogRefreshUnavailable))
688
+ : undefined;
623
689
  try {
624
- await applyStartupModelProfilesWithPolicy(policyArgs, error => recoverableErrors.push(error.message));
690
+ await applyStartupModelProfilesWithPolicy(policyArgs, onCredentialError, onUnknownDefault);
625
691
  } catch (error) {
626
692
  await exitForStartupModelProfileError(args, error);
627
693
  }
@@ -651,7 +717,9 @@ async function applyDeferredStartupModelProfilesForRoot(
651
717
  const onCredentialError = isStartupModelProfileCredentialRecoveryEligible(args)
652
718
  ? (error: ModelProfileCredentialError) => recoverableErrors.push(error.message)
653
719
  : undefined;
654
- await applyStartupModelProfilesWithPolicy({ ...args, preferCachedModels: true }, onCredentialError);
720
+ await applyStartupModelProfilesWithPolicy({ ...args, preferCachedModels: true }, onCredentialError, error =>
721
+ recoverableErrors.push(staleDefaultProfileMessage(error)),
722
+ );
655
723
  return { recoverableErrors };
656
724
  }
657
725
 
@@ -780,6 +848,10 @@ function hasResumePickerTerminal(): boolean {
780
848
  return process.stdin.isTTY === true && process.stdout.isTTY === true;
781
849
  }
782
850
 
851
+ export function shouldNotifyModelFallback(authBootstrap: boolean | undefined, isInteractive: boolean): boolean {
852
+ return !(authBootstrap === true && isInteractive);
853
+ }
854
+
783
855
  export async function runInteractiveMode(
784
856
  session: AgentSession,
785
857
  version: string,
@@ -1405,6 +1477,80 @@ export interface RunRootCommandDependencies {
1405
1477
  loadSettingsForScope?: typeof Settings.loadForScope;
1406
1478
  }
1407
1479
 
1480
+ type DirectSessionManager = Pick<SessionManager, "getCwd" | "getSessionFile" | "getSessionId">;
1481
+
1482
+ /**
1483
+ * Direct CLI liveness is meaningful only for sessions with a durable transcript.
1484
+ * An in-memory manager has no artifacts for GC to fence and must not touch the
1485
+ * shared SDK session-index lock.
1486
+ */
1487
+ export function directSessionRegistrationId(
1488
+ sessionManager: DirectSessionManager | undefined,
1489
+ lifecycleRequestId: string | undefined,
1490
+ ): string | undefined {
1491
+ if (lifecycleRequestId || sessionManager?.getSessionFile() === undefined) return undefined;
1492
+ return sessionManager.getSessionId();
1493
+ }
1494
+
1495
+ interface DirectSessionRegistrationDependencies {
1496
+ createIndex?: (agentDir: string) => SessionIndex;
1497
+ processIncarnation?: typeof processIncarnation;
1498
+ registerPostmortem?: typeof postmortem.register;
1499
+ masterRole?: { ownerSessionId: string; attestationEpoch: string };
1500
+ }
1501
+
1502
+ /** Register a durable direct CLI session while leaving ephemeral sessions lock-free. */
1503
+ export async function registerDirectSession(
1504
+ sessionManager: DirectSessionManager | undefined,
1505
+ agentDir: string,
1506
+ lifecycleRequestId: string | undefined,
1507
+ dependencies: DirectSessionRegistrationDependencies = {},
1508
+ ): Promise<void> {
1509
+ const directSessionId = directSessionRegistrationId(sessionManager, lifecycleRequestId);
1510
+ if (!directSessionId || !sessionManager) return;
1511
+ const sessionIndex = dependencies.createIndex?.(agentDir) ?? new SessionIndex(agentDir);
1512
+ const locator = await resolveSessionLocator(sessionManager.getCwd(), agentDir);
1513
+ const directSessionIncarnation = (dependencies.processIncarnation ?? processIncarnation)(process.pid);
1514
+ await sessionIndex.append({
1515
+ type: "host_registered",
1516
+ sessionId: directSessionId,
1517
+ locator,
1518
+ endpointGeneration: 0,
1519
+ pid: process.pid,
1520
+ ...(directSessionIncarnation ? { processIncarnation: directSessionIncarnation } : {}),
1521
+ ...(dependencies.masterRole && directSessionIncarnation
1522
+ ? {
1523
+ masterRole: {
1524
+ version: 2 as const,
1525
+ ownerSessionId: dependencies.masterRole.ownerSessionId,
1526
+ launchPid: process.pid,
1527
+ launchProcessIncarnation: directSessionIncarnation,
1528
+ role: "master" as const,
1529
+ attestationEpoch: dependencies.masterRole.attestationEpoch,
1530
+ },
1531
+ }
1532
+ : {}),
1533
+ });
1534
+ if (locator.worktreeRoot !== null) {
1535
+ try {
1536
+ await releaseLaunchWorktreeReservationAfterRegistration(agentDir, locator.worktreeRoot);
1537
+ } catch (error) {
1538
+ logger.warn("Failed to release launch worktree reservation after host registration", {
1539
+ error: error instanceof Error ? error.message : String(error),
1540
+ });
1541
+ }
1542
+ }
1543
+ (dependencies.registerPostmortem ?? postmortem.register)("direct-session-index", async _reason => {
1544
+ await sessionIndex.append({
1545
+ type: "host_unregistered",
1546
+ sessionId: directSessionId,
1547
+ locator,
1548
+ endpointGeneration: 0,
1549
+ pid: process.pid,
1550
+ });
1551
+ });
1552
+ }
1553
+
1408
1554
  export interface ModelRoleOverrides {
1409
1555
  smol?: string;
1410
1556
  slow?: string;
@@ -1987,55 +2133,15 @@ export async function runRootCommand(
1987
2133
  }
1988
2134
  // Register a resumed direct session before constructing the agent: GC holds the
1989
2135
  // same index lock while deleting artifacts, so startup and deletion are fenced.
1990
- const directSessionId = process.env.GJC_LIFECYCLE_REQUEST_ID ? undefined : sessionManager?.getSessionId();
1991
- if (directSessionId) {
1992
- const sessionIndex = new SessionIndex(settingsInstance.getAgentDir());
1993
- const locator = await resolveSessionLocator(sessionManager?.getCwd() ?? cwd, settingsInstance.getAgentDir());
1994
- // A pid is reusable, so the broker's teardown fence needs this session's OS
1995
- // start incarnation recorded alongside the pid it publishes.
1996
- const directSessionIncarnation = processIncarnation(process.pid);
1997
- await sessionIndex.append({
1998
- type: "host_registered",
1999
- sessionId: directSessionId,
2000
- locator,
2001
- endpointGeneration: 0,
2002
- pid: process.pid,
2003
- ...(directSessionIncarnation ? { processIncarnation: directSessionIncarnation } : {}),
2004
- ...(masterModeContext && directSessionIncarnation
2005
- ? {
2006
- masterRole: {
2007
- version: 2,
2008
- ownerSessionId: masterModeContext.ownerSessionId,
2009
- launchPid: process.pid,
2010
- launchProcessIncarnation: directSessionIncarnation,
2011
- role: "master" as const,
2012
- attestationEpoch: masterModeContext.attestationEpoch,
2013
- },
2014
- }
2015
- : {}),
2016
- });
2017
- if (locator.worktreeRoot !== null) {
2018
- try {
2019
- await releaseLaunchWorktreeReservationAfterRegistration(
2020
- settingsInstance.getAgentDir(),
2021
- locator.worktreeRoot,
2022
- );
2023
- } catch (error) {
2024
- logger.warn("Failed to release launch worktree reservation after host registration", {
2025
- error: error instanceof Error ? error.message : String(error),
2026
- });
2027
- }
2028
- }
2029
- postmortem.register("direct-session-index", async () => {
2030
- await sessionIndex.append({
2031
- type: "host_unregistered",
2032
- sessionId: directSessionId,
2033
- locator,
2034
- endpointGeneration: 0,
2035
- pid: process.pid,
2036
- });
2037
- });
2038
- }
2136
+ // Ephemeral sessions have no durable artifacts or liveness authority to fence.
2137
+ await registerDirectSession(sessionManager, settingsInstance.getAgentDir(), process.env.GJC_LIFECYCLE_REQUEST_ID, {
2138
+ masterRole: masterModeContext
2139
+ ? {
2140
+ ownerSessionId: masterModeContext.ownerSessionId,
2141
+ attestationEpoch: masterModeContext.attestationEpoch,
2142
+ }
2143
+ : undefined,
2144
+ });
2039
2145
 
2040
2146
  const createAgentSessionImpl = deps.createAgentSession ?? createAgentSession;
2041
2147
  const createSession: CreateSessionForMain = async (options, context): Promise<CreateAgentSessionResult> => {
@@ -2076,6 +2182,18 @@ export async function runRootCommand(
2076
2182
  // Herdr integration: report gjc lifecycle state when running in a Herdr pane.
2077
2183
  installHerdrReporter(listener => session.subscribe(listener));
2078
2184
 
2185
+ // Exact MCP capability attaches at the root interactive entry point.
2186
+ // Granted by creation path, not by call order:
2187
+ // only a session this root command built for an interactive run with an
2188
+ // explicit --mcp-config gets one. Sessions built through createAgentSession
2189
+ // directly, sub-sessions, ACP, and print/text/json runs never reach here.
2190
+ if (isInteractive && sessionOptions.mcpConfigPath) {
2191
+ attachExactMcpControls(session, {
2192
+ grantSource: "root-interactive-exact-config",
2193
+ configPath: sessionOptions.mcpConfigPath,
2194
+ });
2195
+ }
2196
+
2079
2197
  let startDeferredModelProfiles: DeferredModelProfileStartup | undefined;
2080
2198
  if (!(parsedArgs.authBootstrap === true && isInteractive)) {
2081
2199
  const profileArgs = {
@@ -2114,7 +2232,7 @@ export async function runRootCommand(
2114
2232
  }
2115
2233
  }
2116
2234
 
2117
- if (modelFallbackMessage) {
2235
+ if (modelFallbackMessage && shouldNotifyModelFallback(parsedArgs.authBootstrap, isInteractive)) {
2118
2236
  notifs.push({ kind: "warn", message: modelFallbackMessage });
2119
2237
  }
2120
2238