@gajae-code/coding-agent 0.10.2 → 0.11.0

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 (465) hide show
  1. package/CHANGELOG.md +50 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/cli/args.d.ts +4 -5
  4. package/dist/types/cli/daemon-cli.d.ts +12 -1
  5. package/dist/types/cli/notify-cli.d.ts +21 -1
  6. package/dist/types/cli.d.ts +3 -0
  7. package/dist/types/commands/daemon.d.ts +39 -0
  8. package/dist/types/commands/launch.d.ts +3 -0
  9. package/dist/types/commands/notify.d.ts +28 -1
  10. package/dist/types/commands/sdk.d.ts +33 -0
  11. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  12. package/dist/types/config/model-profile-activation.d.ts +35 -15
  13. package/dist/types/config/model-profiles.d.ts +11 -5
  14. package/dist/types/config/model-registry.d.ts +3 -3
  15. package/dist/types/config/model-resolver.d.ts +39 -6
  16. package/dist/types/config/model-selector-value.d.ts +17 -0
  17. package/dist/types/config/models-config-schema.d.ts +10 -6
  18. package/dist/types/config/settings-schema.d.ts +133 -6
  19. package/dist/types/config/settings.d.ts +63 -35
  20. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  21. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  22. package/dist/types/daemon/builtin.d.ts +6 -5
  23. package/dist/types/daemon/control-types.d.ts +1 -1
  24. package/dist/types/discovery/mcp-json.d.ts +12 -1
  25. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  27. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  28. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  29. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  30. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  31. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  32. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  33. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  34. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  35. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  36. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  37. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  38. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  39. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  40. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  41. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  42. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  43. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  44. package/dist/types/harness-control-plane/types.d.ts +3 -4
  45. package/dist/types/lsp/index.d.ts +1 -1
  46. package/dist/types/main.d.ts +32 -38
  47. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  48. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  49. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  50. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  51. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  52. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  53. package/dist/types/modes/components/model-selector.d.ts +1 -0
  54. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  55. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  56. package/dist/types/modes/components/welcome.d.ts +1 -1
  57. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  58. package/dist/types/modes/index.d.ts +0 -4
  59. package/dist/types/modes/interactive-mode.d.ts +3 -0
  60. package/dist/types/modes/runtime-init.d.ts +2 -2
  61. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  62. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  63. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  64. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  65. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  66. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
  67. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  68. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  69. package/dist/types/modes/types.d.ts +5 -0
  70. package/dist/types/runtime-mcp/client.d.ts +2 -0
  71. package/dist/types/runtime-mcp/config.d.ts +5 -1
  72. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  73. package/dist/types/runtime-mcp/types.d.ts +4 -0
  74. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  75. package/dist/types/sdk/acp/index.d.ts +2 -0
  76. package/dist/types/sdk/broker/broker.d.ts +53 -0
  77. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  78. package/dist/types/sdk/broker/ensure.d.ts +33 -0
  79. package/dist/types/sdk/broker/identity.d.ts +3 -0
  80. package/dist/types/sdk/broker/index.d.ts +8 -0
  81. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  82. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  83. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  84. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  85. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  86. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  87. package/dist/types/sdk/broker/transport.d.ts +9 -0
  88. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  89. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  90. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  91. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  92. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  93. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  94. package/dist/types/sdk/bus/config.d.ts +274 -0
  95. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  96. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  97. package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
  98. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  99. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  100. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  101. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  102. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  103. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  104. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  105. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  106. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  107. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  108. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  109. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  110. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  111. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  112. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  113. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  114. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  115. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  116. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  117. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
  118. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  119. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  120. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  121. package/dist/types/sdk/cli/index.d.ts +1 -0
  122. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  123. package/dist/types/sdk/client/client.d.ts +1 -0
  124. package/dist/types/sdk/client/discovery.d.ts +27 -0
  125. package/dist/types/sdk/client/index.d.ts +2 -0
  126. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  127. package/dist/types/sdk/host/control/index.d.ts +2 -0
  128. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  129. package/dist/types/sdk/host/events.d.ts +35 -0
  130. package/dist/types/sdk/host/host.d.ts +35 -0
  131. package/dist/types/sdk/host/index.d.ts +4 -0
  132. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  133. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  134. package/dist/types/sdk/host/query/index.d.ts +3 -0
  135. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  136. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  137. package/dist/types/sdk/host/types.d.ts +32 -0
  138. package/dist/types/sdk/index.d.ts +6 -0
  139. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  140. package/dist/types/sdk/mcp/index.d.ts +1 -0
  141. package/dist/types/sdk/mcp/server.d.ts +37 -0
  142. package/dist/types/sdk/models.d.ts +44 -0
  143. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  144. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  145. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  146. package/dist/types/sdk/startup-capability.d.ts +50 -0
  147. package/dist/types/session/agent-session.d.ts +114 -21
  148. package/dist/types/session/default-model-selection.d.ts +25 -0
  149. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  150. package/dist/types/session/session-manager.d.ts +58 -1
  151. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  152. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  153. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  154. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  155. package/dist/types/tools/browser/launch.d.ts +22 -0
  156. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  157. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  158. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  159. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  160. package/dist/types/tools/browser/registry.d.ts +19 -0
  161. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  162. package/dist/types/tools/index.d.ts +8 -8
  163. package/package.json +34 -13
  164. package/scripts/build-sdk-package-smoke.ts +94 -0
  165. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  166. package/scripts/compile-args.ts +4 -2
  167. package/scripts/g005-daemon-smoke.ts +4 -5
  168. package/scripts/g011-daemon-path-smoke.ts +5 -5
  169. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  170. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  171. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  172. package/scripts/manifest-schema.ts +124 -0
  173. package/scripts/run-test-manifest.ts +153 -0
  174. package/scripts/run-threat-model-check.ts +157 -0
  175. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  176. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  177. package/src/append-only-mode.ts +1 -1
  178. package/src/cli/args.ts +43 -12
  179. package/src/cli/auth-gateway-cli.ts +2 -2
  180. package/src/cli/config-cli.ts +2 -1
  181. package/src/cli/daemon-cli.ts +63 -14
  182. package/src/cli/list-models.ts +1 -1
  183. package/src/cli/notify-cli.ts +288 -286
  184. package/src/cli.ts +21 -2
  185. package/src/commands/daemon.ts +50 -6
  186. package/src/commands/harness.ts +93 -36
  187. package/src/commands/launch.ts +5 -2
  188. package/src/commands/mcp-serve.ts +19 -12
  189. package/src/commands/notify.ts +36 -3
  190. package/src/commands/sdk.ts +426 -0
  191. package/src/commit/agentic/agent.ts +1 -0
  192. package/src/config/atomic-yaml-patch.ts +423 -0
  193. package/src/config/model-profile-activation.ts +240 -89
  194. package/src/config/model-profiles.ts +18 -15
  195. package/src/config/model-registry.ts +51 -26
  196. package/src/config/model-resolver.ts +138 -51
  197. package/src/config/model-selector-value.ts +50 -0
  198. package/src/config/models-config-schema.ts +14 -21
  199. package/src/config/settings-schema.ts +128 -10
  200. package/src/config/settings.ts +1120 -158
  201. package/src/coordinator-mcp/model-preset.ts +74 -20
  202. package/src/coordinator-mcp/server.ts +1597 -3052
  203. package/src/daemon/builtin.ts +8 -5
  204. package/src/daemon/control-types.ts +1 -1
  205. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  206. package/src/discovery/mcp-json.ts +327 -20
  207. package/src/extensibility/custom-tools/types.ts +1 -1
  208. package/src/extensibility/extensions/compact-handler.ts +3 -3
  209. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  210. package/src/extensibility/extensions/loader.ts +69 -5
  211. package/src/extensibility/extensions/runner.ts +112 -4
  212. package/src/extensibility/extensions/types.ts +176 -17
  213. package/src/extensibility/hooks/types.ts +1 -1
  214. package/src/gjc-runtime/launch-tmux.ts +170 -86
  215. package/src/gjc-runtime/psmux-detect.ts +82 -4
  216. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  217. package/src/gjc-runtime/team-runtime.ts +54 -35
  218. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  219. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  220. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  221. package/src/gjc-runtime/ultragoal-guard.ts +53 -6
  222. package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
  223. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  224. package/src/harness-control-plane/operate.ts +9 -9
  225. package/src/harness-control-plane/owner.ts +283 -39
  226. package/src/harness-control-plane/receipts.ts +0 -1
  227. package/src/harness-control-plane/sdk-transport.ts +395 -0
  228. package/src/harness-control-plane/session-transport.ts +94 -0
  229. package/src/harness-control-plane/types.ts +1 -1
  230. package/src/internal-urls/docs-index.generated.ts +34 -35
  231. package/src/lsp/client.ts +42 -6
  232. package/src/lsp/index.ts +2 -2
  233. package/src/main.ts +299 -204
  234. package/src/modes/DESIGN.md +258 -0
  235. package/src/modes/acp/acp-agent.ts +1228 -2612
  236. package/src/modes/acp/acp-client-bridge.ts +2 -20
  237. package/src/modes/acp/acp-event-mapper.ts +18 -2
  238. package/src/modes/acp/acp-mode.ts +8 -36
  239. package/src/modes/acp/permission-mode.ts +25 -0
  240. package/src/modes/acp/startup-options.ts +6 -0
  241. package/src/modes/components/agent-dashboard.ts +37 -17
  242. package/src/modes/components/model-selector.ts +93 -35
  243. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  244. package/src/modes/components/settings-selector.ts +60 -11
  245. package/src/modes/components/welcome.ts +4 -4
  246. package/src/modes/controllers/command-controller.ts +1 -2
  247. package/src/modes/controllers/event-controller.ts +11 -16
  248. package/src/modes/controllers/extension-ui-controller.ts +348 -4
  249. package/src/modes/controllers/selector-controller.ts +674 -36
  250. package/src/modes/index.ts +0 -22
  251. package/src/modes/interactive-mode.ts +59 -20
  252. package/src/modes/runtime-init.ts +298 -6
  253. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  254. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  255. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  256. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  257. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  258. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
  259. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  260. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  261. package/src/modes/types.ts +5 -0
  262. package/src/runtime-mcp/client.ts +94 -19
  263. package/src/runtime-mcp/config.ts +27 -15
  264. package/src/runtime-mcp/manager.ts +343 -105
  265. package/src/runtime-mcp/oauth-flow.ts +42 -12
  266. package/src/runtime-mcp/transports/http.ts +49 -19
  267. package/src/runtime-mcp/transports/stdio.ts +47 -28
  268. package/src/runtime-mcp/types.ts +10 -0
  269. package/src/sdk/acp/adapter.ts +418 -0
  270. package/src/sdk/acp/index.ts +2 -0
  271. package/src/sdk/broker/broker.ts +642 -0
  272. package/src/sdk/broker/discovery.ts +94 -0
  273. package/src/sdk/broker/ensure.ts +249 -0
  274. package/src/sdk/broker/identity.ts +42 -0
  275. package/src/sdk/broker/index.ts +8 -0
  276. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  277. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  278. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  279. package/src/sdk/broker/lifecycle.ts +2157 -0
  280. package/src/sdk/broker/process-incarnation.ts +159 -0
  281. package/src/sdk/broker/runtime.ts +164 -0
  282. package/src/sdk/broker/session-index.ts +318 -0
  283. package/src/sdk/broker/state-version.ts +23 -0
  284. package/src/sdk/broker/transport.ts +125 -0
  285. package/src/sdk/bus/chat-command-policy.ts +107 -0
  286. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  287. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  288. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  289. package/src/sdk/bus/chat-effect-journal.ts +353 -0
  290. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  291. package/src/sdk/bus/config.ts +433 -0
  292. package/src/sdk/bus/conversation-store.ts +391 -0
  293. package/src/sdk/bus/discord-conversation.ts +85 -0
  294. package/src/sdk/bus/discord-daemon.ts +2275 -0
  295. package/src/sdk/bus/discord-live-provider.ts +521 -0
  296. package/src/sdk/bus/discord-provider.ts +56 -0
  297. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  298. package/src/sdk/bus/index.ts +3943 -0
  299. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  300. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  301. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  302. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  303. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  304. package/src/sdk/bus/natives-augment.d.ts +38 -0
  305. package/src/sdk/bus/notification-orchestration.ts +535 -0
  306. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  307. package/src/sdk/bus/session-control.ts +333 -0
  308. package/src/sdk/bus/slack-conversation.ts +74 -0
  309. package/src/sdk/bus/slack-daemon.ts +2144 -0
  310. package/src/sdk/bus/slack-live-provider.ts +380 -0
  311. package/src/sdk/bus/slack-provider.ts +76 -0
  312. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  313. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  314. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  315. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  316. package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
  317. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  318. package/src/sdk/bus/telegram-setup.ts +663 -0
  319. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  320. package/src/sdk/cli/index.ts +1 -0
  321. package/src/sdk/cli/session-cli.ts +275 -0
  322. package/src/sdk/client/client.ts +1 -0
  323. package/src/sdk/client/discovery.ts +108 -0
  324. package/src/sdk/client/index.ts +2 -0
  325. package/src/sdk/host/control/dispatch.ts +367 -0
  326. package/src/sdk/host/control/index.ts +10 -0
  327. package/src/sdk/host/control/operations.ts +63 -0
  328. package/src/sdk/host/events.ts +91 -0
  329. package/src/sdk/host/host.ts +296 -0
  330. package/src/sdk/host/index.ts +4 -0
  331. package/src/sdk/host/query/cursor.ts +189 -0
  332. package/src/sdk/host/query/handlers.ts +533 -0
  333. package/src/sdk/host/query/index.ts +3 -0
  334. package/src/sdk/host/query/revision-store.ts +1126 -0
  335. package/src/sdk/host/reverse-leases.ts +325 -0
  336. package/src/sdk/host/types.ts +29 -0
  337. package/src/sdk/index.ts +13 -0
  338. package/src/sdk/lifecycle-session.ts +39 -0
  339. package/src/sdk/mcp/index.ts +1 -0
  340. package/src/sdk/mcp/server.ts +332 -0
  341. package/src/sdk/models.ts +168 -0
  342. package/src/sdk/protocol/adapter-validation.ts +48 -0
  343. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  344. package/src/sdk/protocol/operation-registry.ts +312 -0
  345. package/src/{sdk.ts → sdk/session.ts} +339 -212
  346. package/src/sdk/startup-capability.ts +189 -0
  347. package/src/session/agent-session.ts +2453 -894
  348. package/src/session/default-model-selection.ts +93 -0
  349. package/src/session/fallback-chain-controller.ts +136 -0
  350. package/src/session/session-manager.ts +438 -11
  351. package/src/session/session-storage.ts +8 -1
  352. package/src/setup/credential-auto-import.ts +290 -35
  353. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  354. package/src/slash-commands/builtin-registry.ts +2 -1
  355. package/src/task/executor.ts +62 -13
  356. package/src/tools/ask-answer-registry.ts +1 -1
  357. package/src/tools/ask.ts +13 -8
  358. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  359. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  360. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  361. package/src/tools/browser/launch.ts +124 -19
  362. package/src/tools/browser/profile-discovery.ts +63 -0
  363. package/src/tools/browser/profile-posture.ts +59 -0
  364. package/src/tools/browser/profile-reuse.ts +102 -0
  365. package/src/tools/browser/profile-warmup.ts +109 -0
  366. package/src/tools/browser/registry.ts +87 -11
  367. package/src/tools/browser/tab-protocol.ts +1 -0
  368. package/src/tools/browser/tab-supervisor.ts +1 -0
  369. package/src/tools/browser/tab-worker.ts +1 -1
  370. package/src/tools/browser.ts +6 -0
  371. package/src/tools/index.ts +8 -8
  372. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  373. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  374. package/src/tools/telegram-send.ts +2 -2
  375. package/vendor/insane-search/MANIFEST.json +2 -1
  376. package/vendor/insane-search/engine/bias_check.py +4 -1
  377. package/vendor/insane-search/engine/phase0.py +26 -1
  378. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  379. package/dist/types/modes/bridge/auth.d.ts +0 -12
  380. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  381. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  382. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  383. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  384. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  385. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  386. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  387. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  388. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  389. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  390. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  391. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  392. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  393. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  394. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  395. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  396. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  397. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  398. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  399. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  400. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  401. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  402. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  403. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  404. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  405. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  406. package/dist/types/notifications/config.d.ts +0 -132
  407. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  408. package/src/modes/bridge/auth.ts +0 -41
  409. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  410. package/src/modes/bridge/bridge-mode.ts +0 -675
  411. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  412. package/src/modes/bridge/event-stream.ts +0 -70
  413. package/src/modes/rpc/host-tools.ts +0 -1
  414. package/src/modes/rpc/host-uris.ts +0 -1
  415. package/src/modes/rpc/rpc-client.ts +0 -1166
  416. package/src/modes/rpc/rpc-mode.ts +0 -1029
  417. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  418. package/src/modes/rpc/rpc-types.ts +0 -637
  419. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  420. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  421. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  422. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  423. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  424. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  425. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  426. package/src/modes/shared/agent-wire/responses.ts +0 -17
  427. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  428. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  429. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  430. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  431. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  432. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  433. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  434. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  435. package/src/notifications/config.ts +0 -219
  436. package/src/notifications/index.ts +0 -1835
  437. package/src/notifications/telegram-daemon-cli.ts +0 -243
  438. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  439. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  440. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  441. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  442. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  443. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  444. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  445. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  446. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  447. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  448. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  449. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  450. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  453. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  454. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  455. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  456. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  457. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  458. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  459. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  460. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  461. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  462. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  463. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -1,426 +0,0 @@
1
- /**
2
- * Unattended run controller (#318).
3
- *
4
- * The single required owner of negotiated unattended state. Entering unattended
5
- * mode is fail-closed: a controller can only be created via {@link
6
- * UnattendedRunController.negotiate}, which rejects a missing/partial budget, an
7
- * invalid declaration, or a provider that cannot account for tokens/cost.
8
- *
9
- * The controller owns budget accounting across metrics and phases. Scope/action
10
- * authorization (#319) and the durable audit trail (#320) layer onto the same
11
- * controller; this slice wires the budget floor and abort coordination.
12
- *
13
- * Attended mode never constructs a controller, so by construction the attended
14
- * path is unaffected by everything here.
15
- */
16
- import type {
17
- RpcActionDenied,
18
- RpcBudgetExceeded,
19
- RpcBudgetMetric,
20
- RpcScopeDenied,
21
- RpcUnattendedActionClass,
22
- RpcUnattendedBudget,
23
- RpcUnattendedDeclaration,
24
- RpcUnattendedRefusalCode,
25
- } from "../../rpc/rpc-types";
26
- import type { BridgeCommandScope } from "./scopes";
27
- import { BRIDGE_COMMAND_SCOPES, MANDATORY_FLOOR_COMMAND_SCOPES } from "./scopes";
28
- import { actionClassForScope, classifyBashAction, RPC_UNATTENDED_ACTION_CLASSES } from "./unattended-action-policy";
29
-
30
- /** Coordinated abort surfaces invoked exactly once on a budget breach / abort. */
31
- export interface UnattendedAbortHooks {
32
- abortModelStream?(): void | Promise<void>;
33
- abortBash?(): void | Promise<void>;
34
- cancelHostTools?(reason: string): void | Promise<void>;
35
- cancelHostUris?(reason: string): void | Promise<void>;
36
- stopWorkflow?(reason: string): void | Promise<void>;
37
- }
38
-
39
- export type UnattendedAuditEvent =
40
- | { event: "unattended_negotiated"; run_id: string; actor: string }
41
- | { event: "budget_exceeded"; payload: RpcBudgetExceeded }
42
- | { event: "unattended_aborted"; run_id: string; reason: string }
43
- | { event: "unattended_abort_settled"; run_id: string; status: "aborted" | "abort_failed"; failures: number }
44
- | { event: "scope_denied"; payload: RpcScopeDenied }
45
- | { event: "action_denied"; payload: RpcActionDenied };
46
-
47
- export interface NegotiateContext {
48
- runId: string;
49
- sessionId?: string;
50
- audit?(event: UnattendedAuditEvent): void;
51
- abortHooks?: UnattendedAbortHooks;
52
- /**
53
- * Whether the active provider can report token usage and cost. Unattended
54
- * mode rejects providers without this accounting up front (fail-closed).
55
- */
56
- providerSupportsTokenCostMetrics?: boolean;
57
- /** Injectable clock for deterministic tests. Defaults to Date.now. */
58
- now?(): number;
59
- }
60
-
61
- export class UnattendedNegotiationError extends Error {
62
- constructor(
63
- readonly code: RpcUnattendedRefusalCode,
64
- message: string,
65
- ) {
66
- super(message);
67
- this.name = "UnattendedNegotiationError";
68
- }
69
- }
70
-
71
- export class UnattendedBudgetExceededError extends Error {
72
- constructor(readonly payload: RpcBudgetExceeded) {
73
- super(`budget_exceeded: ${payload.metric} ${payload.observed}/${payload.limit} at ${payload.phase}`);
74
- this.name = "UnattendedBudgetExceededError";
75
- }
76
- }
77
-
78
- /** Thrown when a provider/tool reports a non-finite usage value (fail-closed). */
79
- export class UnattendedAccountingError extends Error {
80
- constructor(
81
- readonly metric: RpcBudgetMetric,
82
- readonly phase: string,
83
- value: unknown,
84
- ) {
85
- super(`non-finite ${metric} usage (${String(value)}) at ${phase}`);
86
- this.name = "UnattendedAccountingError";
87
- }
88
- }
89
-
90
- /** Thrown when a command's coarse scope is outside the declared allowlist (#319). */
91
- export class ScopeDeniedError extends Error {
92
- constructor(readonly payload: RpcScopeDenied) {
93
- super(`scope_denied: ${payload.scope}${payload.command ? ` (${payload.command})` : ""}`);
94
- this.name = "ScopeDeniedError";
95
- }
96
- }
97
-
98
- /** Thrown when an action class is outside the declared allowlist (default-deny, #319). */
99
- export class ActionDeniedError extends Error {
100
- constructor(readonly payload: RpcActionDenied) {
101
- super(`action_denied: ${payload.action}${payload.command ? ` (${payload.command})` : ""}`);
102
- this.name = "ActionDeniedError";
103
- }
104
- }
105
-
106
- interface Usage {
107
- tokens: number;
108
- toolCalls: number;
109
- costUsd: number;
110
- }
111
-
112
- function isPositiveFiniteNumber(v: unknown): v is number {
113
- return typeof v === "number" && Number.isFinite(v) && v > 0;
114
- }
115
-
116
- function validateBudget(budget: unknown): RpcUnattendedBudget {
117
- if (typeof budget !== "object" || budget === null) {
118
- throw new UnattendedNegotiationError("incomplete_budget", "budget declaration is required for unattended mode");
119
- }
120
- const b = budget as Record<string, unknown>;
121
- const fields: Array<keyof RpcUnattendedBudget> = [
122
- "max_tokens",
123
- "max_tool_calls",
124
- "max_wall_time_ms",
125
- "max_cost_usd",
126
- ];
127
- for (const f of fields) {
128
- if (!isPositiveFiniteNumber(b[f])) {
129
- throw new UnattendedNegotiationError("incomplete_budget", `budget.${f} must be a positive finite number`);
130
- }
131
- }
132
- return {
133
- max_tokens: b.max_tokens as number,
134
- max_tool_calls: b.max_tool_calls as number,
135
- max_wall_time_ms: b.max_wall_time_ms as number,
136
- max_cost_usd: b.max_cost_usd as number,
137
- };
138
- }
139
-
140
- export class UnattendedRunController {
141
- readonly runId: string;
142
- readonly sessionId?: string;
143
- readonly actor: string;
144
- readonly budget: RpcUnattendedBudget;
145
- readonly scopes: ReadonlySet<string>;
146
- readonly actionAllowlist: ReadonlySet<string>;
147
-
148
- private readonly usage: Usage = { tokens: 0, toolCalls: 0, costUsd: 0 };
149
- private readonly startedAt: number;
150
- private readonly now: () => number;
151
- private readonly audit?: (event: UnattendedAuditEvent) => void;
152
- private readonly abortHooks: UnattendedAbortHooks;
153
- private aborted = false;
154
- private abortPromise?: Promise<void>;
155
-
156
- private constructor(declaration: RpcUnattendedDeclaration, ctx: NegotiateContext, budget: RpcUnattendedBudget) {
157
- this.runId = ctx.runId;
158
- this.sessionId = ctx.sessionId;
159
- this.actor = declaration.actor;
160
- this.budget = budget;
161
- this.scopes = new Set([...declaration.scopes, ...MANDATORY_FLOOR_COMMAND_SCOPES]);
162
- this.actionAllowlist = new Set([
163
- ...declaration.action_allowlist,
164
- ...MANDATORY_FLOOR_COMMAND_SCOPES.map(actionClassForScope),
165
- ]);
166
- this.now = ctx.now ?? Date.now;
167
- this.audit = ctx.audit;
168
- this.abortHooks = ctx.abortHooks ?? {};
169
- this.startedAt = this.now();
170
- }
171
-
172
- /** Fail-closed entry: validate the declaration + budget, or throw. */
173
- static negotiate(declaration: unknown, ctx: NegotiateContext): UnattendedRunController {
174
- if (typeof declaration !== "object" || declaration === null) {
175
- throw new UnattendedNegotiationError("invalid_unattended_declaration", "declaration is required");
176
- }
177
- const d = declaration as Record<string, unknown>;
178
- if (typeof d.actor !== "string" || d.actor.trim() === "") {
179
- throw new UnattendedNegotiationError("invalid_unattended_declaration", "declaration.actor is required");
180
- }
181
- if (!Array.isArray(d.scopes) || !d.scopes.every(s => typeof s === "string")) {
182
- throw new UnattendedNegotiationError("invalid_unattended_declaration", "declaration.scopes must be string[]");
183
- }
184
- if (!Array.isArray(d.action_allowlist) || !d.action_allowlist.every(s => typeof s === "string")) {
185
- throw new UnattendedNegotiationError(
186
- "invalid_unattended_declaration",
187
- "declaration.action_allowlist must be string[]",
188
- );
189
- }
190
- const unknownScopes = d.scopes.filter(scope => !BRIDGE_COMMAND_SCOPES.includes(scope as BridgeCommandScope));
191
- if (unknownScopes.length > 0) {
192
- throw new UnattendedNegotiationError(
193
- "invalid_unattended_declaration",
194
- `declaration.scopes contains unknown scope(s): ${unknownScopes.join(", ")}`,
195
- );
196
- }
197
- const unknownActions = d.action_allowlist.filter(
198
- action => !RPC_UNATTENDED_ACTION_CLASSES.includes(action as RpcUnattendedActionClass),
199
- );
200
- if (unknownActions.length > 0) {
201
- throw new UnattendedNegotiationError(
202
- "invalid_unattended_declaration",
203
- `declaration.action_allowlist contains unknown action class(es): ${unknownActions.join(", ")}`,
204
- );
205
- }
206
- const budget = validateBudget(d.budget);
207
- // Reject providers that cannot account for tokens/cost (fail-closed): require
208
- // an explicit positive capability signal — omitted/unknown is refused too.
209
- if (ctx.providerSupportsTokenCostMetrics !== true) {
210
- throw new UnattendedNegotiationError(
211
- "unsupported_budget_metric",
212
- "unattended mode requires an explicit provider token/cost accounting capability",
213
- );
214
- }
215
- const controller = new UnattendedRunController(d as unknown as RpcUnattendedDeclaration, ctx, budget);
216
- ctx.audit?.({ event: "unattended_negotiated", run_id: ctx.runId, actor: controller.actor });
217
- return controller;
218
- }
219
-
220
- get isAborted(): boolean {
221
- return this.aborted;
222
- }
223
-
224
- usageSnapshot(): Readonly<Usage> & { wallTimeMs: number } {
225
- return { ...this.usage, wallTimeMs: this.now() - this.startedAt };
226
- }
227
-
228
- remainingWallTimeMs(): number {
229
- return Math.max(0, this.budget.max_wall_time_ms - (this.now() - this.startedAt));
230
- }
231
-
232
- /**
233
- * Authorize a command's coarse scope against the declared allowlist. Throws
234
- * ScopeDeniedError (pre-side-effect) when the scope was not declared.
235
- */
236
- authorizeScope(scope: BridgeCommandScope, command?: string): void {
237
- if (this.scopes.has(scope)) return;
238
- const payload: RpcScopeDenied = {
239
- code: "scope_denied",
240
- scope,
241
- command,
242
- run_id: this.runId,
243
- session_id: this.sessionId,
244
- pre_side_effect: true,
245
- };
246
- this.audit?.({ event: "scope_denied", payload });
247
- throw new ScopeDeniedError(payload);
248
- }
249
-
250
- /**
251
- * Authorize an action class against the declared allowlist. Default-deny: any
252
- * class not explicitly declared is rejected with ActionDeniedError before the
253
- * side effect runs.
254
- */
255
- authorizeAction(action: RpcUnattendedActionClass, command?: string): void {
256
- if (this.actionAllowlist.has(action)) return;
257
- const payload: RpcActionDenied = {
258
- code: "action_denied",
259
- action,
260
- command,
261
- run_id: this.runId,
262
- session_id: this.sessionId,
263
- pre_side_effect: true,
264
- };
265
- this.audit?.({ event: "action_denied", payload });
266
- throw new ActionDeniedError(payload);
267
- }
268
-
269
- /**
270
- * Classify a bash command and authorize the resulting action class BEFORE the
271
- * command is executed. Returns the classified action class on success.
272
- */
273
- authorizeBash(command: string): RpcUnattendedActionClass {
274
- this.authorizeScope("bash", command);
275
- const action = classifyBashAction(command);
276
- this.authorizeAction(action, command);
277
- return action;
278
- }
279
-
280
- /** Convenience: map a coarse scope to its `command.<scope>` action class. */
281
- static actionClassForScope = actionClassForScope;
282
-
283
- /** Pre-turn estimate: refuse to start a turn that would obviously breach. */
284
- preTurnEstimate(estimate: { tokens?: number; costUsd?: number }): void {
285
- this.checkWallTime("pre-turn estimate");
286
- if (estimate.tokens !== undefined) {
287
- if (!Number.isFinite(estimate.tokens)) {
288
- void this.fireAbort("accounting:tokens");
289
- throw new UnattendedAccountingError("tokens", "pre-turn estimate", estimate.tokens);
290
- }
291
- if (this.usage.tokens + estimate.tokens > this.budget.max_tokens) {
292
- this.breach("tokens", this.budget.max_tokens, this.usage.tokens + estimate.tokens, "pre-turn estimate");
293
- }
294
- }
295
- if (estimate.costUsd !== undefined) {
296
- if (!Number.isFinite(estimate.costUsd)) {
297
- void this.fireAbort("accounting:cost");
298
- throw new UnattendedAccountingError("cost", "pre-turn estimate", estimate.costUsd);
299
- }
300
- if (this.usage.costUsd + estimate.costUsd > this.budget.max_cost_usd) {
301
- this.breach("cost", this.budget.max_cost_usd, this.usage.costUsd + estimate.costUsd, "pre-turn estimate");
302
- }
303
- }
304
- }
305
-
306
- /** Reserve one tool-call unit BEFORE any side effect; breach if it would exceed. */
307
- preflightToolCall(phase = "tool-call preflight"): void {
308
- this.checkWallTime(phase);
309
- if (this.usage.toolCalls + 1 > this.budget.max_tool_calls) {
310
- this.breach("tool_calls", this.budget.max_tool_calls, this.usage.toolCalls + 1, phase);
311
- }
312
- this.usage.toolCalls += 1;
313
- }
314
-
315
- /** Post-turn reconciliation of actual token usage. Fails closed on non-finite. */
316
- recordTokens(tokens: number, phase = "post-turn reconciliation"): void {
317
- if (!Number.isFinite(tokens)) {
318
- void this.fireAbort(`accounting:tokens`);
319
- throw new UnattendedAccountingError("tokens", phase, tokens);
320
- }
321
- this.usage.tokens += Math.max(0, tokens);
322
- if (this.usage.tokens > this.budget.max_tokens) {
323
- this.breach("tokens", this.budget.max_tokens, this.usage.tokens, phase);
324
- }
325
- }
326
-
327
- recordCost(costUsd: number, phase = "post-turn reconciliation"): void {
328
- if (!Number.isFinite(costUsd)) {
329
- void this.fireAbort(`accounting:cost`);
330
- throw new UnattendedAccountingError("cost", phase, costUsd);
331
- }
332
- this.usage.costUsd += Math.max(0, costUsd);
333
- if (this.usage.costUsd > this.budget.max_cost_usd) {
334
- this.breach("cost", this.budget.max_cost_usd, this.usage.costUsd, phase);
335
- }
336
- }
337
-
338
- /** Combined post-turn reconciliation. */
339
- reconcile(actual: { tokens?: number; costUsd?: number }, phase = "post-turn reconciliation"): void {
340
- if (actual.tokens !== undefined) this.recordTokens(actual.tokens, phase);
341
- if (actual.costUsd !== undefined) this.recordCost(actual.costUsd, phase);
342
- }
343
-
344
- /** Wall-time check; call before/inside long operations. */
345
- checkWallTime(phase = "wall-time"): void {
346
- const elapsed = this.now() - this.startedAt;
347
- if (elapsed > this.budget.max_wall_time_ms) {
348
- this.breach("wall_time", this.budget.max_wall_time_ms, elapsed, phase);
349
- }
350
- }
351
-
352
- private breach(metric: RpcBudgetMetric, limit: number, observed: number, phase: string): never {
353
- // Initiate the (idempotent, awaitable) abort. breach() throws synchronously,
354
- // so the payload reports `aborting`; the settled status (aborted/abort_failed)
355
- // is emitted as an unattended_abort_settled audit event once hooks complete.
356
- void this.fireAbort(`budget_exceeded:${metric}`);
357
- const abortStatus: RpcBudgetExceeded["abort_status"] = "aborting";
358
- const payload: RpcBudgetExceeded = {
359
- code: "budget_exceeded",
360
- metric,
361
- limit,
362
- observed,
363
- phase,
364
- run_id: this.runId,
365
- session_id: this.sessionId,
366
- abort_status: abortStatus,
367
- };
368
- this.audit?.({ event: "budget_exceeded", payload });
369
- throw new UnattendedBudgetExceededError(payload);
370
- }
371
-
372
- /**
373
- * Idempotent abort: runs every abort hook at most once. Safe to call from the
374
- * synchronous breach path (which does not await) and from callers that do; both
375
- * share a single abort promise so hook completion can be awaited deterministically.
376
- */
377
- async abort(reason: string): Promise<void> {
378
- await this.fireAbort(reason);
379
- }
380
-
381
- /** Returns the in-flight/settled abort completion once aborting has begun. */
382
- get abortCompletion(): Promise<void> | undefined {
383
- return this.abortPromise;
384
- }
385
-
386
- private fireAbort(reason: string): Promise<void> {
387
- if (this.abortPromise) return this.abortPromise;
388
- this.aborted = true;
389
- this.abortPromise = this.runAbortHooks().then(failures => {
390
- this.audit?.({ event: "unattended_aborted", run_id: this.runId, reason });
391
- this.audit?.({
392
- event: "unattended_abort_settled",
393
- run_id: this.runId,
394
- status: failures === 0 ? "aborted" : "abort_failed",
395
- failures,
396
- });
397
- });
398
- return this.abortPromise;
399
- }
400
-
401
- /**
402
- * Invoke every configured abort hook exactly once with per-hook isolation, so a
403
- * failing hook never prevents the other cancellation surfaces from running.
404
- * Returns the number of hooks that rejected.
405
- */
406
- private async runAbortHooks(): Promise<number> {
407
- const calls: Array<Promise<unknown>> = [];
408
- const run = (fn: (() => void | Promise<void>) | undefined) => {
409
- if (!fn) return;
410
- // Invoke synchronously so the hook's synchronous prefix runs immediately,
411
- // but capture sync throws and async rejections so allSettled isolates them.
412
- try {
413
- calls.push(Promise.resolve(fn()));
414
- } catch (err) {
415
- calls.push(Promise.reject(err));
416
- }
417
- };
418
- run(this.abortHooks.abortModelStream);
419
- run(this.abortHooks.abortBash);
420
- run(() => this.abortHooks.cancelHostTools?.("unattended abort"));
421
- run(() => this.abortHooks.cancelHostUris?.("unattended abort"));
422
- run(() => this.abortHooks.stopWorkflow?.("unattended abort"));
423
- const results = await Promise.allSettled(calls);
424
- return results.filter(r => r.status === "rejected").length;
425
- }
426
- }