@gajae-code/coding-agent 0.17.1 → 0.17.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/CHANGELOG.md +266 -0
  2. package/dist/types/async/job-manager.d.ts +7 -6
  3. package/dist/types/cli/daemon-cli.d.ts +3 -1
  4. package/dist/types/cli/github-release.d.ts +17 -0
  5. package/dist/types/cli/public-command-entry.d.ts +56 -0
  6. package/dist/types/cli/public-command-errors.d.ts +126 -0
  7. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  8. package/dist/types/cli/public-command-help.d.ts +65 -0
  9. package/dist/types/cli/public-command-registry.d.ts +69 -0
  10. package/dist/types/cli/session-picker.d.ts +1 -1
  11. package/dist/types/cli/setup-cli.d.ts +1 -0
  12. package/dist/types/cli/skills-cli.d.ts +5 -0
  13. package/dist/types/cli.d.ts +3 -0
  14. package/dist/types/commands/daemon.d.ts +4 -50
  15. package/dist/types/commands/sdk.d.ts +20 -37
  16. package/dist/types/commands/setup.d.ts +3 -0
  17. package/dist/types/commands/skills.d.ts +9 -0
  18. package/dist/types/config/autorouting-tier-map.d.ts +24 -0
  19. package/dist/types/config/file-lock.d.ts +10 -1
  20. package/dist/types/config/model-profile-activation.d.ts +63 -4
  21. package/dist/types/config/model-registry.d.ts +20 -2
  22. package/dist/types/config/settings-schema.d.ts +11 -0
  23. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  24. package/dist/types/coordinator-mcp/server.d.ts +3 -0
  25. package/dist/types/daemon/operator-contract.d.ts +5 -1
  26. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  28. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  29. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  30. package/dist/types/extensibility/shared-events.d.ts +3 -1
  31. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  32. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  33. package/dist/types/internal-urls/index.d.ts +1 -0
  34. package/dist/types/internal-urls/parse.d.ts +9 -1
  35. package/dist/types/main.d.ts +22 -0
  36. package/dist/types/modes/acp/acp-agent.d.ts +94 -1
  37. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  38. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  39. package/dist/types/modes/components/session-selector.d.ts +5 -2
  40. package/dist/types/modes/components/thinking-selector.d.ts +2 -1
  41. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  42. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  43. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  44. package/dist/types/modes/interactive-mode.d.ts +1 -1
  45. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  46. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  47. package/dist/types/modes/types.d.ts +2 -2
  48. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  49. package/dist/types/runtime-mcp/manager.d.ts +56 -0
  50. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  51. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  52. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  53. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  54. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  55. package/dist/types/sdk/acp/adapter.d.ts +27 -0
  56. package/dist/types/sdk/acp/final-text.d.ts +8 -0
  57. package/dist/types/sdk/broker/broker.d.ts +13 -2
  58. package/dist/types/sdk/broker/ensure.d.ts +46 -1
  59. package/dist/types/sdk/broker/identity.d.ts +3 -1
  60. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  61. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  62. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  63. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  64. package/dist/types/sdk/broker/spawn-authority.d.ts +4 -0
  65. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  66. package/dist/types/sdk/bus/index.d.ts +19 -0
  67. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
  68. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  69. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  70. package/dist/types/sdk/cli/rows.d.ts +19 -1
  71. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/guides/cli.d.ts +3 -4
  74. package/dist/types/sdk/guides/verify.d.ts +2 -0
  75. package/dist/types/sdk/host/host.d.ts +9 -0
  76. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  77. package/dist/types/sdk/host/types.d.ts +10 -0
  78. package/dist/types/sdk/index.d.ts +1 -0
  79. package/dist/types/sdk/prompt-deadline-flush.d.ts +83 -0
  80. package/dist/types/sdk/prompt-deadline-manager.d.ts +38 -1
  81. package/dist/types/sdk/prompt-failure.d.ts +30 -1
  82. package/dist/types/sdk/prompt-status.d.ts +8 -0
  83. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  84. package/dist/types/sdk/router/replay-retention-gap-cache.d.ts +13 -0
  85. package/dist/types/sdk/router/session-router.d.ts +2 -0
  86. package/dist/types/sdk/startup-capability.d.ts +2 -0
  87. package/dist/types/sdk/transport/relay.d.ts +1 -0
  88. package/dist/types/sdk/transport/serve-cli.d.ts +73 -2
  89. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  90. package/dist/types/session/agent-session.d.ts +168 -21
  91. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  92. package/dist/types/session/fold-coordinator.d.ts +17 -3
  93. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  94. package/dist/types/session/session-manager.d.ts +64 -1
  95. package/dist/types/session/session-work-lease.d.ts +14 -0
  96. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  97. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  98. package/dist/types/thinking.d.ts +3 -1
  99. package/dist/types/tools/bash.d.ts +37 -11
  100. package/dist/types/tools/job.d.ts +1 -1
  101. package/dist/types/tools/steer-fold.d.ts +31 -0
  102. package/dist/types/utils/git.d.ts +28 -2
  103. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  104. package/dist/types/utils/mupdf-wasm-embedded.d.ts +2 -0
  105. package/dist/types/utils/mupdf.d.ts +4 -0
  106. package/dist/types/utils/session-title-generation.d.ts +6 -0
  107. package/dist/types/utils/title-generator.d.ts +11 -2
  108. package/dist/types/web/scrapers/types.d.ts +3 -0
  109. package/package.json +18 -10
  110. package/scripts/build-binary.ts +9 -3
  111. package/scripts/compile-args.ts +0 -9
  112. package/scripts/embed-mupdf.ts +52 -0
  113. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  114. package/scripts/vendor-markit.ts +196 -0
  115. package/src/async/job-manager.ts +60 -9
  116. package/src/cli/daemon-cli.ts +53 -18
  117. package/src/cli/github-release.ts +87 -5
  118. package/src/cli/mcp-cli.ts +38 -4
  119. package/src/cli/public-command-entry.ts +450 -0
  120. package/src/cli/public-command-errors.ts +581 -0
  121. package/src/cli/public-command-evidence.ts +717 -0
  122. package/src/cli/public-command-help.ts +360 -0
  123. package/src/cli/public-command-registry.ts +535 -0
  124. package/src/cli/session-picker.ts +2 -1
  125. package/src/cli/setup-cli.ts +9 -1
  126. package/src/cli/skills-cli.ts +46 -2
  127. package/src/cli.ts +61 -1
  128. package/src/commands/daemon.ts +65 -69
  129. package/src/commands/sdk.ts +232 -100
  130. package/src/commands/setup.ts +2 -0
  131. package/src/commands/skills.ts +11 -0
  132. package/src/config/autorouting-tier-map.ts +16 -0
  133. package/src/config/file-lock.ts +199 -68
  134. package/src/config/model-profile-activation.ts +406 -53
  135. package/src/config/model-registry.ts +204 -25
  136. package/src/config/settings-schema.ts +26 -2
  137. package/src/coordinator-mcp/policy.ts +10 -5
  138. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  139. package/src/coordinator-mcp/question-state.ts +175 -8
  140. package/src/coordinator-mcp/server.ts +528 -87
  141. package/src/coordinator-mcp/session-reaper.ts +6 -4
  142. package/src/crash/record-loader.ts +6 -2
  143. package/src/daemon/operator-contract.ts +26 -12
  144. package/src/debug/report-bundle.ts +114 -24
  145. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  146. package/src/eval/js/context-manager.ts +8 -8
  147. package/src/eval/js/worker-core.ts +9 -4
  148. package/src/eval/js/worker-protocol.ts +2 -0
  149. package/src/extensibility/extensions/runner.ts +52 -4
  150. package/src/extensibility/extensions/types.ts +10 -0
  151. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  152. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  153. package/src/extensibility/shared-events.ts +3 -1
  154. package/src/gjc-runtime/managed-owner-admission.ts +67 -50
  155. package/src/gjc-runtime/session-state-lock.ts +165 -24
  156. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  157. package/src/internal-urls/docs-index.generated.ts +21 -19
  158. package/src/internal-urls/embedded-protocol.ts +83 -0
  159. package/src/internal-urls/index.ts +1 -0
  160. package/src/internal-urls/parse.ts +21 -1
  161. package/src/internal-urls/router.ts +4 -2
  162. package/src/main.ts +123 -55
  163. package/src/modes/acp/acp-agent.ts +593 -47
  164. package/src/modes/acp/acp-event-mapper.ts +9 -0
  165. package/src/modes/acp/startup-provenance.ts +59 -0
  166. package/src/modes/components/custom-provider-wizard.ts +308 -7
  167. package/src/modes/components/model-selector.ts +31 -15
  168. package/src/modes/components/oauth-selector.ts +9 -0
  169. package/src/modes/components/session-selector.ts +47 -4
  170. package/src/modes/components/status-line/segments.ts +6 -1
  171. package/src/modes/components/thinking-selector.ts +7 -3
  172. package/src/modes/components/user-message-selector.ts +57 -15
  173. package/src/modes/controllers/command-controller.ts +58 -32
  174. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  175. package/src/modes/controllers/input-controller.ts +4 -0
  176. package/src/modes/controllers/selector-controller.ts +177 -18
  177. package/src/modes/interactive-mode.ts +21 -7
  178. package/src/modes/runtime-init.ts +1 -0
  179. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  180. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  181. package/src/modes/types.ts +2 -2
  182. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  183. package/src/prompts/system/title-system.md +1 -1
  184. package/src/prompts/tools/bash.md +1 -1
  185. package/src/prompts/tools/job.md +1 -1
  186. package/src/prompts/tools/read.md +2 -0
  187. package/src/runtime/network-prewarm-service.test.ts +36 -1
  188. package/src/runtime/network-prewarm-service.ts +28 -3
  189. package/src/runtime/process-lifecycle.ts +22 -11
  190. package/src/runtime-mcp/config.ts +16 -1
  191. package/src/runtime-mcp/manager.ts +689 -55
  192. package/src/runtime-mcp/pool.test.ts +31 -0
  193. package/src/runtime-mcp/pool.ts +304 -28
  194. package/src/runtime-mcp/redaction.ts +42 -0
  195. package/src/runtime-mcp/startup-policy.ts +7 -0
  196. package/src/runtime-mcp/tool-bridge.ts +71 -0
  197. package/src/runtime-mcp/transports/http.ts +108 -25
  198. package/src/sdk/acp/adapter.ts +90 -9
  199. package/src/sdk/acp/final-text.ts +19 -2
  200. package/src/sdk/broker/broker.ts +378 -52
  201. package/src/sdk/broker/ensure.ts +97 -19
  202. package/src/sdk/broker/identity.ts +9 -1
  203. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  204. package/src/sdk/broker/lifecycle.ts +690 -141
  205. package/src/sdk/broker/runtime.ts +1 -1
  206. package/src/sdk/broker/session-index.ts +97 -4
  207. package/src/sdk/broker/spawn-authority.ts +35 -7
  208. package/src/sdk/broker/stderr-drainer.ts +59 -0
  209. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  210. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  211. package/src/sdk/bus/index.ts +721 -84
  212. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  213. package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
  214. package/src/sdk/bus/telegram-daemon.ts +10 -3
  215. package/src/sdk/cli/master-cli.ts +47 -36
  216. package/src/sdk/cli/rows.ts +30 -7
  217. package/src/sdk/cli/session-cli.ts +687 -184
  218. package/src/sdk/client/client.ts +18 -0
  219. package/src/sdk/guides/catalog.ts +2 -2
  220. package/src/sdk/guides/cli.ts +20 -62
  221. package/src/sdk/guides/verify.ts +14 -0
  222. package/src/sdk/host/host.ts +49 -5
  223. package/src/sdk/host/session-runtime.test.ts +636 -9
  224. package/src/sdk/host/session-runtime.ts +499 -118
  225. package/src/sdk/host/types.ts +12 -1
  226. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  227. package/src/sdk/host/websocket-transport.ts +40 -6
  228. package/src/sdk/index.ts +11 -0
  229. package/src/sdk/prompt-deadline-flush.ts +334 -0
  230. package/src/sdk/prompt-deadline-manager.ts +136 -4
  231. package/src/sdk/prompt-failure.ts +43 -1
  232. package/src/sdk/prompt-status.ts +8 -0
  233. package/src/sdk/prompt-tool-boundary.ts +121 -0
  234. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  235. package/src/sdk/router/replay-retention-gap-cache.ts +27 -0
  236. package/src/sdk/router/session-router.ts +31 -4
  237. package/src/sdk/session.ts +194 -16
  238. package/src/sdk/startup-capability.ts +1 -1
  239. package/src/sdk/transport/relay.ts +71 -6
  240. package/src/sdk/transport/serve-cli.ts +494 -49
  241. package/src/sdk/transport/socket.ts +12 -11
  242. package/src/sdk/transport/stdio.ts +7 -3
  243. package/src/session/agent-session.ts +2437 -400
  244. package/src/session/fallback-chain-controller.ts +6 -7
  245. package/src/session/fold-coordinator.ts +24 -5
  246. package/src/session/internal/managed-session-scope.ts +58 -18
  247. package/src/session/internal/managed-session-storage.ts +304 -11
  248. package/src/session/session-manager.ts +382 -44
  249. package/src/session/session-work-lease.ts +34 -0
  250. package/src/session-import/codex.ts +12 -3
  251. package/src/setup/model-onboarding-guidance.ts +1 -1
  252. package/src/setup/provider-onboarding.ts +397 -24
  253. package/src/slash-commands/builtin-registry.ts +258 -14
  254. package/src/task/index.ts +14 -2
  255. package/src/thinking.ts +21 -2
  256. package/src/tools/bash.ts +98 -78
  257. package/src/tools/fetch.ts +119 -20
  258. package/src/tools/job.ts +151 -25
  259. package/src/tools/output-meta.ts +15 -2
  260. package/src/tools/path-utils.ts +27 -3
  261. package/src/tools/read.ts +3 -3
  262. package/src/tools/steer-fold.ts +107 -0
  263. package/src/tools/tool-catalog.generated.ts +29 -2
  264. package/src/tools/tool-errors.ts +4 -0
  265. package/src/utils/git.ts +53 -3
  266. package/src/utils/markit.ts +55 -41
  267. package/src/utils/mupdf-assets.d.ts +4 -0
  268. package/src/utils/mupdf-embedded.ts +4 -0
  269. package/src/utils/mupdf-wasm-embedded.ts +3 -0
  270. package/src/utils/mupdf-wasm.ts +24 -2
  271. package/src/utils/mupdf.ts +129 -0
  272. package/src/utils/session-title-generation.ts +29 -0
  273. package/src/utils/title-generator.ts +46 -2
  274. package/src/web/scrapers/types.ts +24 -3
  275. package/vendor/markit-ai/LICENSE +21 -0
  276. package/vendor/markit-ai/MANIFEST.json +412 -0
  277. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  278. package/vendor/markit-ai/dist/commands/config.js +139 -0
  279. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  280. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  281. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  282. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  283. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  284. package/vendor/markit-ai/dist/commands/init.js +29 -0
  285. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  286. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  287. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  288. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  289. package/vendor/markit-ai/dist/config.d.ts +26 -0
  290. package/vendor/markit-ai/dist/config.js +42 -0
  291. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  292. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  293. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  294. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  295. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  296. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  297. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  298. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  299. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  300. package/vendor/markit-ai/dist/converters/github.js +148 -0
  301. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  302. package/vendor/markit-ai/dist/converters/html.js +30 -0
  303. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  304. package/vendor/markit-ai/dist/converters/image.js +124 -0
  305. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  306. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  307. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  308. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  309. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  310. package/vendor/markit-ai/dist/converters/json.js +21 -0
  311. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  312. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  313. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  314. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  315. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  316. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  317. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  318. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  319. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  320. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  321. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  322. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  323. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  324. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  325. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  326. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  327. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  328. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  329. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  330. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  331. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  332. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  333. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  334. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  335. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  336. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  337. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  338. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  339. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  340. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  341. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  342. package/vendor/markit-ai/dist/index.d.ts +30 -0
  343. package/vendor/markit-ai/dist/index.js +26 -0
  344. package/vendor/markit-ai/dist/main.d.ts +2 -0
  345. package/vendor/markit-ai/dist/main.js +191 -0
  346. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  347. package/vendor/markit-ai/dist/markit.js +267 -0
  348. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  349. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  350. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  351. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  352. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  353. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  354. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  355. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  356. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  357. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  358. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  359. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  360. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  361. package/vendor/markit-ai/dist/providers/index.js +56 -0
  362. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  363. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  364. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  365. package/vendor/markit-ai/dist/providers/types.js +1 -0
  366. package/vendor/markit-ai/dist/types.d.ts +36 -0
  367. package/vendor/markit-ai/dist/types.js +1 -0
  368. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  369. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  370. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  371. package/vendor/markit-ai/dist/utils/output.js +31 -0
  372. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  373. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  374. package/vendor/markit-ai/package.json +74 -0
  375. package/vendor/markit-ai.patch +49 -0
@@ -1,3 +1,4 @@
1
+ import { logger } from "@gajae-code/utils";
1
2
  import type { KindAwareReconciliation } from "./bus/kind-aware-reconciliation";
2
3
  import type { InvocationCorrelation, InvocationReconciliation } from "./host/session-runtime";
3
4
  import {
@@ -16,6 +17,56 @@ const MAX_UNCERTAINTY_RETRIES = 3;
16
17
  const EXPIRY_RETRY_DELAY_MS = 1_000;
17
18
  const UNCERTAINTY_RETRY_DELAY_MS = 1_000;
18
19
 
20
+ /**
21
+ * Hard real-time bound on the best-effort durability hook, shared with
22
+ * `prompt-deadline-flush` so the manager's race and the flush's own abort
23
+ * signal cannot drift apart.
24
+ */
25
+ export const DEADLINE_FLUSH_TIMEOUT_MS = 10_000;
26
+
27
+ /**
28
+ * Run a best-effort durability flush under a hard real-time bound that ALWAYS
29
+ * settles, and never let its result reach the caller.
30
+ *
31
+ * Shared by both expiry paths — this manager and the notification bus's own
32
+ * terminalization (#5583) — so there is one bound, one abort, and one warning,
33
+ * with no drift between them. A rejection is swallowed; a `run` that never
34
+ * settles is abandoned after `timeoutMs` with its signal aborted so any git
35
+ * subprocess dies. The signal alone is not sufficient: `git.withRepoLock`
36
+ * awaits its predecessor before honouring it, so a hung predecessor in the
37
+ * per-repo write chain is cut only by this outer race.
38
+ */
39
+ export async function runBoundedDeadlineFlush(
40
+ run: (signal: AbortSignal) => unknown,
41
+ timeoutMs: number = DEADLINE_FLUSH_TIMEOUT_MS,
42
+ ): Promise<void> {
43
+ const controller = new AbortController();
44
+ let timer: ReturnType<typeof setTimeout> | undefined;
45
+ // An async wrapper so a `run` that throws synchronously becomes a rejection.
46
+ const flushed = (async () => {
47
+ await run(controller.signal);
48
+ })();
49
+ // The abandoned promise may still reject long after we stop awaiting it.
50
+ flushed.catch(() => {});
51
+ try {
52
+ const bound = new Promise<"timeout">(resolve => {
53
+ timer = setTimeout(() => resolve("timeout"), timeoutMs);
54
+ // Never let a pending bound keep the process alive.
55
+ (timer as unknown as { unref?: () => void }).unref?.();
56
+ });
57
+ if ((await Promise.race([flushed.then(() => "flushed" as const), bound])) === "timeout") {
58
+ controller.abort(new Error(`prompt deadline flush exceeded ${timeoutMs}ms`));
59
+ logger.warn(
60
+ `sdk: prompt deadline flush exceeded its ${timeoutMs}ms bound; abandoning it and continuing teardown`,
61
+ );
62
+ }
63
+ } catch {
64
+ // A failing flush never changes the deadline outcome.
65
+ } finally {
66
+ if (timer !== undefined) clearTimeout(timer);
67
+ }
68
+ }
69
+
19
70
  type DeadlineReconciliation = InvocationReconciliation | KindAwareReconciliation;
20
71
 
21
72
  export type PromptDeadlineOutcome = Extract<SdkPromptTerminalOutcome, { kind: "failed" }> & {
@@ -48,20 +99,69 @@ export class PromptDeadlineManager {
48
99
  readonly #getLeaseMs: () => number;
49
100
  readonly #getMaxMs: () => number;
50
101
  readonly #now: () => number;
51
- readonly #onExpired?: (correlation: InvocationCorrelation) => void;
102
+ readonly #onExpired?: (correlation: InvocationCorrelation, outcome?: PromptDeadlineOutcome) => void;
103
+ readonly #onDeadlineExceeded?: (
104
+ correlation: InvocationCorrelation,
105
+ signal: AbortSignal,
106
+ isCurrent?: () => boolean,
107
+ ) => void | Promise<void>;
108
+ readonly #deadlineFlushTimeoutMs: number;
52
109
 
53
110
  constructor(options: {
54
111
  reconciliation: DeadlineReconciliation;
55
112
  getLeaseMs: () => number;
56
113
  getMaxMs: () => number;
57
114
  now?: () => number;
58
- onExpired?: (correlation: InvocationCorrelation) => void;
115
+ onExpired?: (correlation: InvocationCorrelation, outcome?: PromptDeadlineOutcome) => void;
116
+ /**
117
+ * Best-effort durability hook for the single path that genuinely retires a
118
+ * prompt as `prompt_deadline_exceeded` (#5583). Awaited after the durable
119
+ * pending claim but BEFORE the durable terminal, so a crash in that window
120
+ * leaves the record pending and recovery retries the prompt; a
121
+ * rejection is swallowed and never changes the deadline outcome. Not called
122
+ * when a real terminal transition or a real failure won the race, nor when
123
+ * renewed progress supersedes this expiry instance. The hook receives an
124
+ * abort signal that fires when it outruns `deadlineFlushTimeoutMs`, plus a
125
+ * generation fence for irreversible worktree adoption.
126
+ */
127
+ onDeadlineExceeded?: (
128
+ correlation: InvocationCorrelation,
129
+ signal: AbortSignal,
130
+ isCurrent?: () => boolean,
131
+ ) => void | Promise<void>;
132
+ /**
133
+ * Hard bound on `onDeadlineExceeded`. Measured with a real timer, not
134
+ * `now`, because it guards real subprocesses — which is also why it is a
135
+ * constructor option: a fake clock cannot shorten it for tests.
136
+ */
137
+ deadlineFlushTimeoutMs?: number;
59
138
  }) {
60
139
  this.#reconciliation = options.reconciliation;
61
140
  this.#getLeaseMs = options.getLeaseMs;
62
141
  this.#getMaxMs = options.getMaxMs;
63
142
  this.#now = options.now ?? Date.now;
64
143
  this.#onExpired = options.onExpired;
144
+ this.#onDeadlineExceeded = options.onDeadlineExceeded;
145
+ this.#deadlineFlushTimeoutMs = options.deadlineFlushTimeoutMs ?? DEADLINE_FLUSH_TIMEOUT_MS;
146
+ }
147
+
148
+ /** Run the durability hook under the shared bound; see `runBoundedDeadlineFlush`. */
149
+ async #runDeadlineFlush(
150
+ correlation: InvocationCorrelation,
151
+ lease: PromptDeadlineLease,
152
+ generation: number,
153
+ ): Promise<void> {
154
+ const hook = this.#onDeadlineExceeded;
155
+ if (hook === undefined) return;
156
+ const key = leaseKey(correlation);
157
+ await runBoundedDeadlineFlush(
158
+ signal =>
159
+ hook(correlation, signal, () => {
160
+ const current = this.#leases.get(key);
161
+ return current === lease && current.generation === generation;
162
+ }),
163
+ this.#deadlineFlushTimeoutMs,
164
+ );
65
165
  }
66
166
 
67
167
  #clearTimer(key: string): void {
@@ -165,16 +265,48 @@ export class PromptDeadlineManager {
165
265
  provenance: "deadline",
166
266
  evidence: {},
167
267
  }) as PromptDeadlineOutcome;
268
+ let winner: SdkPromptTerminalOutcome = outcome;
168
269
  try {
169
- await this.#reconciliation.claimPendingOutcome("prompt", correlation, outcome);
270
+ const claimed = await this.#reconciliation.claimPendingOutcome("prompt", correlation, outcome);
271
+ if (claimed !== undefined) winner = claimed;
170
272
  } catch {
171
273
  // claim may fail if already claimed (e.g., cancellation won); ignore.
172
274
  }
275
+ // A real terminal may win between lookup and this claim. Its existing
276
+ // pending outcome is authoritative: release this expiry fence without
277
+ // running the deadline-only durability hook or publishing a deadline result.
278
+ if (winner.kind !== "failed" || winner.code !== "prompt_deadline_exceeded" || winner.provenance !== "deadline") {
279
+ this.#expiring.delete(key);
280
+ this.#expiryRetries.delete(key);
281
+ return;
282
+ }
173
283
  // Re-verify the captured lease is still authoritative after the claim
174
284
  // await (exact-head review P2): fresh attributable progress during the
175
285
  // claim must cancel this expiry instance instead of surfacing an exceeded
176
286
  // outcome for a prompt that is demonstrably alive.
177
287
  if (this.#backOffIfSuperseded(key, lease, generation)) return;
288
+ // Durability BEFORE the durable terminal (#5583, #5623 review round 4). The
289
+ // claim above is already the durable pending marker, so a process death
290
+ // anywhere in this window leaves the record PENDING and restart recovery
291
+ // retries the prompt — work that was never autosaved is never reported as
292
+ // finished. Running the flush after `finalizeOutcome` instead made the
293
+ // autosave the one step a crash could silently skip, which is the whole
294
+ // durability guarantee of this change. The cost is that the durable terminal
295
+ // is delayed by at most the flush's bound.
296
+ //
297
+ // The wait is BOUNDED, not just guarded (#5623 review round 2): a hook that
298
+ // never settles — a blocking git lock, a credential prompt — would leave the
299
+ // finalize, `#onExpired` and `clear` below unreachable, stranding the prompt
300
+ // with neither a terminal nor an owner. A try/catch cannot rescue a promise
301
+ // that never settles, so the flush is raced against a real timer and
302
+ // abandoned if it outruns it.
303
+ await this.#runDeadlineFlush(correlation, lease, generation);
304
+ // Fence again AFTER the flush (#5623 review round 2): the flush is an await
305
+ // like any other here, and up to ten seconds long, so progress can land and
306
+ // renew the lease while it runs. A renewed prompt must not be terminalized as
307
+ // deadline-exceeded by this stale pass; `#backOffIfSuperseded` reschedules on
308
+ // the way out, so it keeps a live deadline.
309
+ if (this.#backOffIfSuperseded(key, lease, generation)) return;
178
310
  try {
179
311
  await this.#reconciliation.finalizeOutcome("prompt", correlation, outcome, () => {
180
312
  const current = this.#leases.get(key);
@@ -197,7 +329,7 @@ export class PromptDeadlineManager {
197
329
  // accepted/in-flight invocation without an owner, retry, or deadline
198
330
  // recovery path.
199
331
  try {
200
- this.#onExpired?.(correlation);
332
+ this.#onExpired?.(correlation, outcome);
201
333
  } catch {}
202
334
  this.#expiryRetries.delete(key);
203
335
  this.clear(correlation);
@@ -3,7 +3,12 @@
3
3
  * Provider error text is retained only in the local diagnostic log; wire and
4
4
  * persisted reconciliation details expose a fixed redacted message.
5
5
  */
6
- import type { SdkPromptFailureCategory, SdkPromptFailurePhase, SdkPromptTerminalOutcome } from "./prompt-status";
6
+ import type {
7
+ SdkPromptFailureCategory,
8
+ SdkPromptFailurePhase,
9
+ SdkPromptFailureRetryability,
10
+ SdkPromptTerminalOutcome,
11
+ } from "./prompt-status";
7
12
 
8
13
  export const PROMPT_FAILURE_CODE_MAX = 64;
9
14
  const LOCAL_FAILURE_LOG_MAX = 16_384;
@@ -79,6 +84,43 @@ export function promptFailureCategory(
79
84
  return "unknown";
80
85
  }
81
86
 
87
+ /**
88
+ * Whether the bounded category says an identical re-submission could still
89
+ * succeed. Read off the category alone, so it cannot drift from the sets above.
90
+ *
91
+ * `provider_transport` is the only transient class: every classifier in
92
+ * `PROVIDER_TRANSPORT_CODES` (and the 5xx range) describes the link to the
93
+ * provider failing, never a judgement about the request, so the same bytes may
94
+ * well succeed on a second attempt. That is exactly the class the shipped
95
+ * first-turn gate (`isStartupReadinessFailure`, issue #5574) already treats as
96
+ * re-submittable, so the wire signal and the internal gate stay in agreement.
97
+ *
98
+ * Everything else is terminal for this turn: `provider_rejected` is the provider
99
+ * judging this request (quota, refusal, 4xx) and re-sending it reproduces the
100
+ * rejection; `deadline` means the turn's budget is spent, which a re-submit does
101
+ * not restore; `agent_runtime` is a local fault that re-running the same prompt
102
+ * re-enters. `unknown` stays `unknown` — the module's standing contract is to
103
+ * preserve uncertain attribution rather than guess a recovery for it.
104
+ *
105
+ * This is advisory classification for the caller, not a retry gate: nothing in
106
+ * this repo's retry paths consults it.
107
+ */
108
+ export function promptFailureRetryability(category: SdkPromptFailureCategory): SdkPromptFailureRetryability {
109
+ if (category === "provider_transport") return "transient";
110
+ if (category === "unknown") return "unknown";
111
+ return "terminal";
112
+ }
113
+
114
+ /**
115
+ * Whether a value is a safe bounded classifier token — the same rule
116
+ * `sanitizePromptFailure` and `assistantFailureCode` apply before retaining one.
117
+ * Anything else is provider text rather than a classifier and must not be
118
+ * forwarded to a caller.
119
+ */
120
+ export function isSafePromptFailureCode(value: unknown): value is string {
121
+ return typeof value === "string" && value.length <= PROMPT_FAILURE_CODE_MAX && /^[A-Za-z0-9._-]+$/.test(value);
122
+ }
123
+
82
124
  /**
83
125
  * Phase- and category-aware safe wording. A post-start failure is never
84
126
  * described as a submission rejection; the wording says only what the bounded
@@ -75,6 +75,14 @@ export type SdkPromptFailureCategory =
75
75
  | "agent_runtime"
76
76
  | "deadline"
77
77
  | "unknown";
78
+ /**
79
+ * Whether the failure class says an identical re-submission could still succeed.
80
+ * Derived from `SdkPromptFailureCategory` alone (see `promptFailureRetryability`)
81
+ * so a consumer never has to re-implement the category matrix or parse a message.
82
+ * `unknown` is preserved rather than collapsed into `terminal`: an uncertain
83
+ * attribution is not evidence that the turn is unrecoverable.
84
+ */
85
+ export type SdkPromptFailureRetryability = "transient" | "terminal" | "unknown";
78
86
  export type SdkPromptTerminalOutcome =
79
87
  | { kind: "stopped"; reason: SdkPromptStopReason; provenance: "agent" | "client_cancel" }
80
88
  | {
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Bounded wait for an in-flight dispatched tool call to reach its boundary
3
+ * before an expired prompt deadline force-terminates the run (#5637).
4
+ *
5
+ * Terminal fencing aborts the run's cancellation domain FIRST and only proves
6
+ * settlement afterwards (`RunResourceLedger.waitForSettlement` resolves once the
7
+ * run is sealed and its tracked `kind: "tool"` resources have settled), so a
8
+ * tool that was mid-write when the deadline expired observes the aborted signal
9
+ * DURING its write and leaves a torn artifact behind. Waiting for that call's
10
+ * own `tool_execution_end` — under a short, finite grace — turns the kill into a
11
+ * boundary abort. When the grace is exhausted the run is force-terminated
12
+ * exactly as before, and the fact that a tool was still executing is returned as
13
+ * structured evidence rather than dropped.
14
+ *
15
+ * Deliberately dependency-light and clock-injectable: the contended bus module
16
+ * takes only a call, and the behaviour is testable without a live transport.
17
+ */
18
+
19
+ /**
20
+ * Hard bound on how long deadline expiry will wait for an in-flight tool call to
21
+ * reach its boundary before force-terminating. This guards a real subprocess, so
22
+ * it is a real timer rather than the lease clock — and a parameter rather than a
23
+ * bare module constant, so a test may shorten it explicitly instead of a fake
24
+ * clock silently shortening it for production code too.
25
+ */
26
+ export const TOOL_CALL_BOUNDARY_GRACE_MS = 5_000;
27
+
28
+ /**
29
+ * Re-check interval for the pending set while the grace runs.
30
+ *
31
+ * The authoritative source of "is a tool running?" is the run resource ledger,
32
+ * a SYNCHRONOUS snapshot with no completion signal of its own, so the wait has
33
+ * to look again rather than being told. `whenIdle` only wakes the check early
34
+ * when the event-derived view happens to drain first. Bounded by the grace, so
35
+ * this costs at most `graceMs / pollMs` array reads on the rare expiry-with-a-
36
+ * tool-running path and nothing at all on the idle path.
37
+ */
38
+ export const TOOL_CALL_BOUNDARY_POLL_MS = 25;
39
+
40
+ export type ToolBoundaryOutcome = "idle" | "settled" | "forced";
41
+
42
+ export interface ToolBoundaryWaitResult {
43
+ outcome: ToolBoundaryOutcome;
44
+ waitedMs: number;
45
+ /**
46
+ * Non-empty ONLY for "forced": the dispatched tool calls still running when
47
+ * the grace expired. Ids only — never tool arguments, output or paths.
48
+ */
49
+ pendingToolCallIds: string[];
50
+ }
51
+
52
+ /**
53
+ * Shared result for the common case of no dispatched tool running at expiry.
54
+ * Frozen because it is handed to every idle caller: the deadline path must stay
55
+ * byte-identical to its pre-#5637 behaviour, which includes allocating nothing
56
+ * and arming no timer.
57
+ */
58
+ export const IDLE_TOOL_BOUNDARY_RESULT: ToolBoundaryWaitResult = Object.freeze({
59
+ outcome: "idle" as const,
60
+ waitedMs: 0,
61
+ pendingToolCallIds: Object.freeze([]) as unknown as string[],
62
+ });
63
+
64
+ /**
65
+ * Wait for the pending dispatched tool calls to drain, bounded by `graceMs`.
66
+ *
67
+ * Never composed with an abort signal: at the only call site nothing has been
68
+ * aborted yet, and a signal that was already aborted would make this wait
69
+ * unreachable — which is precisely the mid-tool kill being fixed.
70
+ */
71
+ export async function waitForToolCallBoundary(input: {
72
+ pending: () => readonly string[];
73
+ /**
74
+ * Resolves when the event-derived view of the pending set drains. A wake-up
75
+ * HINT only: `pending()` is re-read before the wait is allowed to settle,
76
+ * because the authoritative source may still hold a call this signal knows
77
+ * nothing about. Expected never to reject.
78
+ */
79
+ whenIdle: () => Promise<void>;
80
+ graceMs?: number;
81
+ pollMs?: number;
82
+ now?: () => number;
83
+ }): Promise<ToolBoundaryWaitResult> {
84
+ const now = input.now ?? Date.now;
85
+ // Idle prompts pay nothing: no timer, no allocation, no extra microtask turn
86
+ // beyond the caller's own await.
87
+ if (input.pending().length === 0) return IDLE_TOOL_BOUNDARY_RESULT;
88
+ const graceMs = Math.max(0, input.graceMs ?? TOOL_CALL_BOUNDARY_GRACE_MS);
89
+ const pollMs = Math.max(1, input.pollMs ?? TOOL_CALL_BOUNDARY_POLL_MS);
90
+ const startedAt = now();
91
+ let graceTimer: ReturnType<typeof setTimeout> | undefined;
92
+ let pollTimer: ReturnType<typeof setInterval> | undefined;
93
+ try {
94
+ const settled = new Promise<"settled">(resolve => {
95
+ // `pending()` is the single arbiter of settlement; the idle signal and
96
+ // the poll only decide WHEN it is consulted.
97
+ const check = () => {
98
+ if (input.pending().length === 0) resolve("settled");
99
+ };
100
+ // The loser of the race is abandoned rather than cancelled, so a rejection
101
+ // from it must be swallowed here or it surfaces as an unhandled rejection
102
+ // and takes the host down. A rejected idle simply leaves the poll and the
103
+ // grace timer as the arbiters.
104
+ void input.whenIdle().then(check, () => {});
105
+ pollTimer = setInterval(check, pollMs);
106
+ pollTimer?.unref?.();
107
+ });
108
+ const forced = new Promise<"forced">(resolve => {
109
+ graceTimer = setTimeout(() => resolve("forced"), graceMs);
110
+ // Never hold the process open for a tool that will not come back.
111
+ graceTimer?.unref?.();
112
+ });
113
+ const outcome = await Promise.race([settled, forced]);
114
+ return outcome === "settled"
115
+ ? { outcome: "settled", waitedMs: now() - startedAt, pendingToolCallIds: [] }
116
+ : { outcome: "forced", waitedMs: now() - startedAt, pendingToolCallIds: [...input.pending()] };
117
+ } finally {
118
+ clearTimeout(graceTimer);
119
+ clearInterval(pollTimer);
120
+ }
121
+ }
@@ -2144,6 +2144,17 @@
2144
2144
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
2145
2145
  ]
2146
2146
  },
2147
+ {
2148
+ "sourceId": "slash_command:mcp",
2149
+ "sourceFile": "packages/coding-agent/src/slash-commands/builtin-registry.ts",
2150
+ "sourceKind": "slash_command",
2151
+ "decision": "exclude",
2152
+ "rationale": "interactive exact-config MCP status and session control command; terminal-only handleTui surface is not dispatched through ACP or the public SDK",
2153
+ "exclusionMetadata": {
2154
+ "adapterMappings": "not_applicable",
2155
+ "testIds": "not_applicable"
2156
+ }
2157
+ },
2147
2158
  {
2148
2159
  "sourceId": "slash_command:agents",
2149
2160
  "sourceFile": "packages/coding-agent/src/slash-commands/builtin-registry.ts",
@@ -2188,6 +2199,24 @@
2188
2199
  "testIds": "not_applicable"
2189
2200
  }
2190
2201
  },
2202
+ {
2203
+ "sourceId": "slash_command:fork",
2204
+ "sourceFile": "packages/coding-agent/src/slash-commands/builtin-registry.ts",
2205
+ "sourceKind": "slash_command",
2206
+ "decision": "include",
2207
+ "sdkId": "session.branch",
2208
+ "adapterMappings": {
2209
+ "telegram": "prohibited",
2210
+ "discord": "prohibited",
2211
+ "slack": "prohibited",
2212
+ "mcp": "prohibited",
2213
+ "acp": "prohibited",
2214
+ "daemonCli": "prohibited"
2215
+ },
2216
+ "testIds": [
2217
+ "packages/coding-agent/test/sdk-operation-inventory.test.ts"
2218
+ ]
2219
+ },
2191
2220
  {
2192
2221
  "sourceId": "slash_command:provider",
2193
2222
  "sourceFile": "packages/coding-agent/src/slash-commands/builtin-registry.ts",
@@ -3202,6 +3231,28 @@
3202
3231
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
3203
3232
  ]
3204
3233
  },
3234
+ {
3235
+ "sourceId": "agent_session:getExactMcpStatusSnapshot",
3236
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
3237
+ "sourceKind": "agent_session",
3238
+ "decision": "exclude",
3239
+ "rationale": "internal exact-config MCP status accessor used only by the terminal-only /mcp command; its capability is granted only to root interactive --mcp-config sessions, not a public SDK query",
3240
+ "exclusionMetadata": {
3241
+ "adapterMappings": "not_applicable",
3242
+ "testIds": "not_applicable"
3243
+ }
3244
+ },
3245
+ {
3246
+ "sourceId": "agent_session:controlExactMcpServer",
3247
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
3248
+ "sourceKind": "agent_session",
3249
+ "decision": "exclude",
3250
+ "rationale": "internal session-local exact-config MCP suspend/resume/reconnect mutation used only by the terminal-only /mcp command; runtime suppression is not persistent user authority or a public SDK control",
3251
+ "exclusionMetadata": {
3252
+ "adapterMappings": "not_applicable",
3253
+ "testIds": "not_applicable"
3254
+ }
3255
+ },
3205
3256
  {
3206
3257
  "sourceId": "agent_session:getSelectedMCPToolNames",
3207
3258
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -3891,6 +3942,17 @@
3891
3942
  "packages/coding-agent/test/sdk-operation-inventory.test.ts"
3892
3943
  ]
3893
3944
  },
3945
+ {
3946
+ "sourceId": "agent_session:submitUserMessage",
3947
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
3948
+ "sourceKind": "agent_session",
3949
+ "decision": "exclude",
3950
+ "rationale": "public in-process embedder lifecycle API; direct handle surface, not an SDK transport operation",
3951
+ "exclusionMetadata": {
3952
+ "adapterMappings": "not_applicable",
3953
+ "testIds": "not_applicable"
3954
+ }
3955
+ },
3894
3956
  {
3895
3957
  "sourceId": "agent_session:clearQueue",
3896
3958
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -4182,6 +4244,17 @@
4182
4244
  "testIds": "not_applicable"
4183
4245
  }
4184
4246
  },
4247
+ {
4248
+ "sourceId": "agent_session:pendingToolExecutions",
4249
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4250
+ "sourceKind": "agent_session",
4251
+ "decision": "exclude",
4252
+ "rationale": "internal read-only run-resource-ledger view, threaded via terminalAbortSeams so the prompt deadline can find a tool-call boundary; not a user-facing SDK control seam",
4253
+ "exclusionMetadata": {
4254
+ "adapterMappings": "not_applicable",
4255
+ "testIds": "not_applicable"
4256
+ }
4257
+ },
4185
4258
  {
4186
4259
  "sourceId": "agent_session:abortPromptAndWait",
4187
4260
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -4466,6 +4539,39 @@
4466
4539
  "testIds": "not_applicable"
4467
4540
  }
4468
4541
  },
4542
+ {
4543
+ "sourceId": "agent_session:installRecoveredDefaultFallbackChain",
4544
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4545
+ "sourceKind": "agent_session",
4546
+ "decision": "exclude",
4547
+ "rationale": "internal recovered fallback-chain installation during session startup, not a user-facing SDK control seam",
4548
+ "exclusionMetadata": {
4549
+ "adapterMappings": "not_applicable",
4550
+ "testIds": "not_applicable"
4551
+ }
4552
+ },
4553
+ {
4554
+ "sourceId": "agent_session:markStartupRecoveryBindingsRequired",
4555
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4556
+ "sourceKind": "agent_session",
4557
+ "decision": "exclude",
4558
+ "rationale": "internal startup recovery binding marker, not a user-facing SDK control seam",
4559
+ "exclusionMetadata": {
4560
+ "adapterMappings": "not_applicable",
4561
+ "testIds": "not_applicable"
4562
+ }
4563
+ },
4564
+ {
4565
+ "sourceId": "agent_session:hasRecoveredDefaultFallbackChain",
4566
+ "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
4567
+ "sourceKind": "agent_session",
4568
+ "decision": "exclude",
4569
+ "rationale": "internal recovered fallback-chain state query, not a user-facing SDK control seam",
4570
+ "exclusionMetadata": {
4571
+ "adapterMappings": "not_applicable",
4572
+ "testIds": "not_applicable"
4573
+ }
4574
+ },
4469
4575
  {
4470
4576
  "sourceId": "agent_session:seedDefaultFallbackResolution",
4471
4577
  "sourceFile": "packages/coding-agent/src/session/agent-session.ts",
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Retention-gap concessions are durable stream facts, but a Router can observe
3
+ * many streams over its lifetime. Keep the warning memo bounded while retaining
4
+ * enough recent coordinates to suppress reconnect/poll duplicates.
5
+ */
6
+ export const REPLAY_CONCESSION_CACHE_LIMIT = 1_024;
7
+
8
+ /**
9
+ * Records one stream/gap coordinate in an LRU memo.
10
+ *
11
+ * `undefined` means this is the first observation; a number is the duplicate
12
+ * count after the coordinate was already observed.
13
+ */
14
+ export function rememberReplayRetentionGap(cache: Map<string, number>, key: string): number | undefined {
15
+ const previous = cache.get(key);
16
+ if (previous !== undefined) {
17
+ cache.delete(key);
18
+ cache.set(key, previous + 1);
19
+ return previous + 1;
20
+ }
21
+ cache.set(key, 0);
22
+ if (cache.size > REPLAY_CONCESSION_CACHE_LIMIT) {
23
+ const oldest = cache.keys().next().value;
24
+ if (oldest !== undefined) cache.delete(oldest);
25
+ }
26
+ return undefined;
27
+ }
@@ -25,6 +25,7 @@ import {
25
25
  readSdkSessionEndpoint,
26
26
  type SdkSessionEndpoint,
27
27
  } from "../client/discovery";
28
+ import { SESSION_HOST_OBSERVER_CAPABILITY, TURN_STREAM_CAPABILITY } from "../host/host";
28
29
  import {
29
30
  type ActivatedPreparedSession,
30
31
  type PreparedSessionActivationClient,
@@ -33,6 +34,7 @@ import {
33
34
  } from "../session-activation";
34
35
  import type { SessionBindingAuthority } from "../session-authority";
35
36
  import { ACP_SESSION_RECONNECT, SESSION_REQUEST_TIMEOUT_MS } from "../session-reconnect";
37
+ import { rememberReplayRetentionGap } from "./replay-retention-gap-cache";
36
38
 
37
39
  export type { SessionBindingAuthority, SessionEndpointAuthority } from "../session-authority";
38
40
 
@@ -285,6 +287,8 @@ export interface SessionRouterOptions {
285
287
  agentDir: string;
286
288
  /** Limits attachment to exact ids selected by a Broker-scoped operation. */
287
289
  sessionIds?: readonly string[];
290
+ /** Marks default SDK clients as notification-only observers; demanding by default. */
291
+ observer?: boolean;
288
292
  deps?: SessionRouterDeps;
289
293
  /** Runtime-specific identity validation; Router supplies a conservative fallback. */
290
294
  correlateFrame?: SessionRouterFrameCorrelator;
@@ -611,6 +615,7 @@ type AdoptedSession = {
611
615
  export class SessionRouter {
612
616
  readonly #agentDir: string;
613
617
  readonly #sessionIds: ReadonlySet<string> | undefined;
618
+ readonly #observer: boolean;
614
619
  readonly #deps: SessionRouterDeps;
615
620
  readonly #correlateFrame: SessionRouterFrameCorrelator;
616
621
  readonly #index: SessionIndex;
@@ -627,6 +632,8 @@ export class SessionRouter {
627
632
  >();
628
633
  readonly #reviving = new Set<string>();
629
634
  readonly #notificationReceipts = new Map<string, NotificationCleanupReceipt>();
635
+ /** Recent retention-gap coordinates already reported at warning level. */
636
+ readonly #concededReplayGaps = new Map<string, number>();
630
637
  #stopTimer: (() => void) | undefined;
631
638
  #reconcileTail: Promise<void> = Promise.resolve();
632
639
  #reconcilePending: { readonly runEpoch: number; force: boolean } | undefined;
@@ -650,6 +657,7 @@ export class SessionRouter {
650
657
  constructor(options: SessionRouterOptions) {
651
658
  this.#agentDir = options.agentDir;
652
659
  this.#sessionIds = options.sessionIds === undefined ? undefined : new Set(options.sessionIds);
660
+ this.#observer = options.observer === true;
653
661
  this.#deps = options.deps ?? {};
654
662
  this.#correlateFrame = options.correlateFrame ?? fallbackCorrelation;
655
663
  this.#index = this.#deps.createIndex?.(options.agentDir) ?? new DefaultSessionIndex(options.agentDir);
@@ -1516,7 +1524,10 @@ export class SessionRouter {
1516
1524
  endpointMtimeMs,
1517
1525
  });
1518
1526
  } else {
1519
- const defaultClient = new SdkClient(endpoint.url, endpoint.token, { ...ACP_SESSION_RECONNECT });
1527
+ const defaultClient = new SdkClient(endpoint.url, endpoint.token, {
1528
+ ...ACP_SESSION_RECONNECT,
1529
+ ...(this.#observer ? { capabilities: [SESSION_HOST_OBSERVER_CAPABILITY, TURN_STREAM_CAPABILITY] } : {}),
1530
+ });
1520
1531
  transport = defaultClient;
1521
1532
  connection = defaultClient.connect().then(() => defaultClient);
1522
1533
  }
@@ -2203,6 +2214,24 @@ export class SessionRouter {
2203
2214
  `chat daemon replay barrier failed (${reason}); rebuilding session ${attached.sessionId} at generation ${attached.generation} from seq ${attached.cursor.seq}.`,
2204
2215
  );
2205
2216
  }
2217
+
2218
+ #logReplayRetentionGap(
2219
+ attached: AttachedSession,
2220
+ gap: Readonly<{ fromSeq: number; toSeq: number }>,
2221
+ recoveredNote: string,
2222
+ ): void {
2223
+ const key = JSON.stringify([attached.sessionId, attached.generation, gap.fromSeq, gap.toSeq]);
2224
+ const repeat = rememberReplayRetentionGap(this.#concededReplayGaps, key);
2225
+ if (repeat !== undefined) {
2226
+ logger.debug(
2227
+ `chat daemon replay retention gap repeated (sequences ${gap.fromSeq}-${gap.toSeq}); suppressed warning ${repeat} for session ${attached.sessionId} generation ${attached.generation}.`,
2228
+ );
2229
+ return;
2230
+ }
2231
+ logger.warn(
2232
+ `chat daemon replay conceded a retention gap (sequences ${gap.fromSeq}-${gap.toSeq} are gone from the host${recoveredNote}); session ${attached.sessionId} generation ${attached.generation} resumes at seq ${gap.toSeq + 1}.`,
2233
+ );
2234
+ }
2206
2235
  #failDelivery(attached: AttachedSession, seq: number, error: unknown): void {
2207
2236
  const previous = this.#undelivered.get(attached.sessionId);
2208
2237
  const attempts = previous?.generation === attached.generation && previous.seq === seq ? previous.attempts + 1 : 1;
@@ -2503,9 +2532,7 @@ export class SessionRouter {
2503
2532
  held.splice(0, held.length, ...carried);
2504
2533
  const recoveredNote =
2505
2534
  recovered.length > 0 ? `, ${recovered.length} of them recovered from live delivery` : "";
2506
- logger.warn(
2507
- `chat daemon replay conceded a retention gap (sequences ${gap.fromSeq}-${gap.toSeq} are gone from the host${recoveredNote}); session ${attached.sessionId} generation ${attached.generation} resumes at seq ${gap.toSeq + 1}.`,
2508
- );
2535
+ this.#logReplayRetentionGap(attached, gap, recoveredNote);
2509
2536
  for (const entry of recovered) this.#rememberRecoveredFrame(attached, entry.seq, entry.frame);
2510
2537
  if (!(await this.#deliverRecoveredFrames(attached))) return;
2511
2538
  if (gap.toSeq > attached.cursor.seq) attached.cursor.seq = gap.toSeq;