@gajae-code/coding-agent 0.10.2 → 0.11.1

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 (476) hide show
  1. package/CHANGELOG.md +58 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/async/job-manager.d.ts +46 -7
  4. package/dist/types/cli/args.d.ts +4 -5
  5. package/dist/types/cli/daemon-cli.d.ts +12 -1
  6. package/dist/types/cli/notify-cli.d.ts +21 -1
  7. package/dist/types/cli.d.ts +3 -0
  8. package/dist/types/commands/daemon.d.ts +39 -0
  9. package/dist/types/commands/launch.d.ts +3 -0
  10. package/dist/types/commands/notify.d.ts +28 -1
  11. package/dist/types/commands/sdk.d.ts +33 -0
  12. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  13. package/dist/types/config/model-profile-activation.d.ts +35 -15
  14. package/dist/types/config/model-profiles.d.ts +11 -5
  15. package/dist/types/config/model-registry.d.ts +3 -3
  16. package/dist/types/config/model-resolver.d.ts +39 -6
  17. package/dist/types/config/model-selector-value.d.ts +17 -0
  18. package/dist/types/config/models-config-schema.d.ts +10 -6
  19. package/dist/types/config/settings-schema.d.ts +133 -6
  20. package/dist/types/config/settings.d.ts +63 -35
  21. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  22. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  23. package/dist/types/daemon/builtin.d.ts +6 -5
  24. package/dist/types/daemon/control-types.d.ts +1 -1
  25. package/dist/types/discovery/mcp-json.d.ts +12 -1
  26. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  27. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  28. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  29. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  31. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  32. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  33. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  34. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  35. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  36. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  37. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  38. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  39. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
  40. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  41. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  42. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  43. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  44. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  45. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  46. package/dist/types/harness-control-plane/types.d.ts +3 -4
  47. package/dist/types/lsp/index.d.ts +1 -1
  48. package/dist/types/main.d.ts +32 -38
  49. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  50. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  51. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  52. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  53. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  54. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  55. package/dist/types/modes/components/model-selector.d.ts +1 -0
  56. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  57. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  58. package/dist/types/modes/components/welcome.d.ts +1 -1
  59. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  60. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  61. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  62. package/dist/types/modes/index.d.ts +0 -4
  63. package/dist/types/modes/interactive-mode.d.ts +5 -2
  64. package/dist/types/modes/runtime-init.d.ts +2 -2
  65. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  66. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  67. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  68. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  69. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  72. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  73. package/dist/types/modes/types.d.ts +7 -2
  74. package/dist/types/runtime-mcp/client.d.ts +2 -0
  75. package/dist/types/runtime-mcp/config.d.ts +5 -1
  76. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  77. package/dist/types/runtime-mcp/types.d.ts +4 -0
  78. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  79. package/dist/types/sdk/acp/index.d.ts +2 -0
  80. package/dist/types/sdk/broker/broker.d.ts +53 -0
  81. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  82. package/dist/types/sdk/broker/ensure.d.ts +42 -0
  83. package/dist/types/sdk/broker/identity.d.ts +3 -0
  84. package/dist/types/sdk/broker/index.d.ts +8 -0
  85. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  86. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  87. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  88. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  89. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  90. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  91. package/dist/types/sdk/broker/transport.d.ts +9 -0
  92. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  93. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  94. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  95. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  96. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  97. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  98. package/dist/types/sdk/bus/config.d.ts +274 -0
  99. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  100. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  101. package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
  102. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  103. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  104. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  105. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  107. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  108. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  109. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  110. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  111. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  112. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  113. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  114. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  115. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  116. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  117. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  118. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  119. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  121. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
  122. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  123. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  124. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  125. package/dist/types/sdk/cli/index.d.ts +1 -0
  126. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  127. package/dist/types/sdk/client/client.d.ts +1 -0
  128. package/dist/types/sdk/client/discovery.d.ts +27 -0
  129. package/dist/types/sdk/client/index.d.ts +2 -0
  130. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  131. package/dist/types/sdk/host/control/index.d.ts +2 -0
  132. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  133. package/dist/types/sdk/host/events.d.ts +35 -0
  134. package/dist/types/sdk/host/host.d.ts +35 -0
  135. package/dist/types/sdk/host/index.d.ts +4 -0
  136. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  137. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  138. package/dist/types/sdk/host/query/index.d.ts +3 -0
  139. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  140. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  141. package/dist/types/sdk/host/types.d.ts +32 -0
  142. package/dist/types/sdk/index.d.ts +6 -0
  143. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  144. package/dist/types/sdk/mcp/index.d.ts +1 -0
  145. package/dist/types/sdk/mcp/server.d.ts +37 -0
  146. package/dist/types/sdk/models.d.ts +44 -0
  147. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  148. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  149. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  150. package/dist/types/sdk/startup-capability.d.ts +50 -0
  151. package/dist/types/session/agent-session.d.ts +114 -21
  152. package/dist/types/session/default-model-selection.d.ts +25 -0
  153. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  154. package/dist/types/session/session-manager.d.ts +58 -1
  155. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  156. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  157. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  158. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  159. package/dist/types/tools/browser/launch.d.ts +22 -0
  160. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  161. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  162. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  163. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  164. package/dist/types/tools/browser/registry.d.ts +19 -0
  165. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  166. package/dist/types/tools/index.d.ts +8 -8
  167. package/dist/types/tools/subagent-render.d.ts +1 -0
  168. package/dist/types/tools/subagent.d.ts +6 -1
  169. package/package.json +34 -13
  170. package/scripts/build-sdk-package-smoke.ts +99 -0
  171. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  172. package/scripts/compile-args.ts +4 -2
  173. package/scripts/g005-daemon-smoke.ts +4 -5
  174. package/scripts/g011-daemon-path-smoke.ts +5 -5
  175. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  176. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  177. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  178. package/scripts/manifest-schema.ts +124 -0
  179. package/scripts/run-test-manifest.ts +153 -0
  180. package/scripts/run-threat-model-check.ts +157 -0
  181. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  182. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  183. package/src/append-only-mode.ts +1 -1
  184. package/src/async/job-manager.ts +406 -63
  185. package/src/cli/args.ts +43 -12
  186. package/src/cli/auth-gateway-cli.ts +2 -2
  187. package/src/cli/config-cli.ts +2 -1
  188. package/src/cli/daemon-cli.ts +63 -14
  189. package/src/cli/list-models.ts +1 -1
  190. package/src/cli/notify-cli.ts +288 -286
  191. package/src/cli.ts +21 -2
  192. package/src/commands/daemon.ts +50 -6
  193. package/src/commands/harness.ts +93 -36
  194. package/src/commands/launch.ts +5 -2
  195. package/src/commands/mcp-serve.ts +19 -12
  196. package/src/commands/notify.ts +36 -3
  197. package/src/commands/sdk.ts +426 -0
  198. package/src/commit/agentic/agent.ts +1 -0
  199. package/src/config/atomic-yaml-patch.ts +423 -0
  200. package/src/config/model-profile-activation.ts +240 -89
  201. package/src/config/model-profiles.ts +18 -15
  202. package/src/config/model-registry.ts +51 -26
  203. package/src/config/model-resolver.ts +138 -51
  204. package/src/config/model-selector-value.ts +50 -0
  205. package/src/config/models-config-schema.ts +14 -21
  206. package/src/config/settings-schema.ts +128 -10
  207. package/src/config/settings.ts +1120 -158
  208. package/src/coordinator-mcp/model-preset.ts +74 -20
  209. package/src/coordinator-mcp/server.ts +1597 -3052
  210. package/src/daemon/builtin.ts +8 -5
  211. package/src/daemon/control-types.ts +1 -1
  212. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  213. package/src/discovery/mcp-json.ts +327 -20
  214. package/src/extensibility/custom-tools/types.ts +1 -1
  215. package/src/extensibility/extensions/compact-handler.ts +3 -3
  216. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  217. package/src/extensibility/extensions/loader.ts +69 -5
  218. package/src/extensibility/extensions/runner.ts +112 -4
  219. package/src/extensibility/extensions/types.ts +176 -17
  220. package/src/extensibility/hooks/types.ts +1 -1
  221. package/src/gjc-runtime/launch-tmux.ts +170 -86
  222. package/src/gjc-runtime/psmux-detect.ts +82 -4
  223. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  224. package/src/gjc-runtime/team-runtime.ts +54 -35
  225. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  226. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  227. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  228. package/src/gjc-runtime/ultragoal-guard.ts +108 -14
  229. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  230. package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
  231. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  232. package/src/harness-control-plane/operate.ts +9 -9
  233. package/src/harness-control-plane/owner.ts +283 -39
  234. package/src/harness-control-plane/receipts.ts +0 -1
  235. package/src/harness-control-plane/sdk-transport.ts +395 -0
  236. package/src/harness-control-plane/session-transport.ts +94 -0
  237. package/src/harness-control-plane/types.ts +1 -1
  238. package/src/internal-urls/docs-index.generated.ts +34 -35
  239. package/src/lsp/client.ts +42 -6
  240. package/src/lsp/index.ts +2 -2
  241. package/src/main.ts +299 -204
  242. package/src/modes/DESIGN.md +258 -0
  243. package/src/modes/acp/acp-agent.ts +1228 -2612
  244. package/src/modes/acp/acp-client-bridge.ts +2 -20
  245. package/src/modes/acp/acp-event-mapper.ts +18 -2
  246. package/src/modes/acp/acp-mode.ts +8 -36
  247. package/src/modes/acp/permission-mode.ts +25 -0
  248. package/src/modes/acp/startup-options.ts +6 -0
  249. package/src/modes/components/agent-dashboard.ts +37 -17
  250. package/src/modes/components/model-selector.ts +93 -35
  251. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  252. package/src/modes/components/settings-selector.ts +60 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +10 -17
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +396 -28
  257. package/src/modes/controllers/selector-controller.ts +674 -36
  258. package/src/modes/index.ts +0 -22
  259. package/src/modes/interactive-mode.ts +87 -36
  260. package/src/modes/runtime-init.ts +298 -6
  261. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  262. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  263. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  264. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  265. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  266. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
  267. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  268. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  269. package/src/modes/types.ts +7 -2
  270. package/src/runtime-mcp/client.ts +94 -19
  271. package/src/runtime-mcp/config.ts +27 -15
  272. package/src/runtime-mcp/manager.ts +343 -105
  273. package/src/runtime-mcp/oauth-flow.ts +42 -12
  274. package/src/runtime-mcp/transports/http.ts +49 -19
  275. package/src/runtime-mcp/transports/stdio.ts +47 -28
  276. package/src/runtime-mcp/types.ts +10 -0
  277. package/src/sdk/acp/adapter.ts +418 -0
  278. package/src/sdk/acp/index.ts +2 -0
  279. package/src/sdk/broker/broker.ts +642 -0
  280. package/src/sdk/broker/discovery.ts +113 -0
  281. package/src/sdk/broker/ensure.ts +307 -0
  282. package/src/sdk/broker/identity.ts +42 -0
  283. package/src/sdk/broker/index.ts +8 -0
  284. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  285. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  286. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  287. package/src/sdk/broker/lifecycle.ts +2157 -0
  288. package/src/sdk/broker/process-incarnation.ts +159 -0
  289. package/src/sdk/broker/runtime.ts +164 -0
  290. package/src/sdk/broker/session-index.ts +318 -0
  291. package/src/sdk/broker/state-version.ts +23 -0
  292. package/src/sdk/broker/transport.ts +125 -0
  293. package/src/sdk/bus/chat-command-policy.ts +107 -0
  294. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  295. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  296. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  297. package/src/sdk/bus/chat-effect-journal.ts +355 -0
  298. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  299. package/src/sdk/bus/config.ts +433 -0
  300. package/src/sdk/bus/conversation-store.ts +391 -0
  301. package/src/sdk/bus/discord-conversation.ts +85 -0
  302. package/src/sdk/bus/discord-daemon.ts +2292 -0
  303. package/src/sdk/bus/discord-live-provider.ts +521 -0
  304. package/src/sdk/bus/discord-provider.ts +56 -0
  305. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  306. package/src/sdk/bus/index.ts +3979 -0
  307. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  309. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  310. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  311. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  312. package/src/sdk/bus/natives-augment.d.ts +38 -0
  313. package/src/sdk/bus/notification-orchestration.ts +535 -0
  314. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  315. package/src/sdk/bus/session-control.ts +333 -0
  316. package/src/sdk/bus/slack-conversation.ts +74 -0
  317. package/src/sdk/bus/slack-daemon.ts +2144 -0
  318. package/src/sdk/bus/slack-live-provider.ts +380 -0
  319. package/src/sdk/bus/slack-provider.ts +76 -0
  320. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  321. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  322. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  323. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  324. package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
  325. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  326. package/src/sdk/bus/telegram-setup.ts +663 -0
  327. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  328. package/src/sdk/cli/index.ts +1 -0
  329. package/src/sdk/cli/session-cli.ts +275 -0
  330. package/src/sdk/client/client.ts +1 -0
  331. package/src/sdk/client/discovery.ts +108 -0
  332. package/src/sdk/client/index.ts +2 -0
  333. package/src/sdk/host/control/dispatch.ts +367 -0
  334. package/src/sdk/host/control/index.ts +10 -0
  335. package/src/sdk/host/control/operations.ts +63 -0
  336. package/src/sdk/host/events.ts +91 -0
  337. package/src/sdk/host/host.ts +296 -0
  338. package/src/sdk/host/index.ts +4 -0
  339. package/src/sdk/host/query/cursor.ts +189 -0
  340. package/src/sdk/host/query/handlers.ts +533 -0
  341. package/src/sdk/host/query/index.ts +3 -0
  342. package/src/sdk/host/query/revision-store.ts +1126 -0
  343. package/src/sdk/host/reverse-leases.ts +325 -0
  344. package/src/sdk/host/types.ts +29 -0
  345. package/src/sdk/index.ts +13 -0
  346. package/src/sdk/lifecycle-session.ts +39 -0
  347. package/src/sdk/mcp/index.ts +1 -0
  348. package/src/sdk/mcp/server.ts +332 -0
  349. package/src/sdk/models.ts +168 -0
  350. package/src/sdk/protocol/adapter-validation.ts +48 -0
  351. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  352. package/src/sdk/protocol/operation-registry.ts +312 -0
  353. package/src/{sdk.ts → sdk/session.ts} +339 -212
  354. package/src/sdk/startup-capability.ts +189 -0
  355. package/src/session/agent-session.ts +2650 -944
  356. package/src/session/default-model-selection.ts +93 -0
  357. package/src/session/fallback-chain-controller.ts +136 -0
  358. package/src/session/session-manager.ts +438 -11
  359. package/src/session/session-storage.ts +8 -1
  360. package/src/setup/credential-auto-import.ts +290 -35
  361. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  362. package/src/slash-commands/builtin-registry.ts +2 -1
  363. package/src/task/executor.ts +62 -13
  364. package/src/task/index.ts +26 -16
  365. package/src/tools/ask-answer-registry.ts +1 -1
  366. package/src/tools/ask.ts +13 -8
  367. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  368. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  369. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  370. package/src/tools/browser/launch.ts +124 -19
  371. package/src/tools/browser/profile-discovery.ts +63 -0
  372. package/src/tools/browser/profile-posture.ts +59 -0
  373. package/src/tools/browser/profile-reuse.ts +102 -0
  374. package/src/tools/browser/profile-warmup.ts +109 -0
  375. package/src/tools/browser/registry.ts +87 -11
  376. package/src/tools/browser/tab-protocol.ts +1 -0
  377. package/src/tools/browser/tab-supervisor.ts +1 -0
  378. package/src/tools/browser/tab-worker.ts +1 -1
  379. package/src/tools/browser.ts +6 -0
  380. package/src/tools/index.ts +8 -8
  381. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  382. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  383. package/src/tools/subagent-render.ts +19 -8
  384. package/src/tools/subagent.ts +84 -32
  385. package/src/tools/telegram-send.ts +2 -2
  386. package/vendor/insane-search/MANIFEST.json +2 -1
  387. package/vendor/insane-search/engine/bias_check.py +4 -1
  388. package/vendor/insane-search/engine/phase0.py +26 -1
  389. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  390. package/dist/types/modes/bridge/auth.d.ts +0 -12
  391. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  392. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  393. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  394. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  395. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  396. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  397. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  398. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  399. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  400. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  401. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  402. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  403. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  404. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  405. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  406. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  407. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  408. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  409. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  410. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  411. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  412. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  413. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  414. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  415. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  416. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  417. package/dist/types/notifications/config.d.ts +0 -132
  418. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  419. package/src/modes/bridge/auth.ts +0 -41
  420. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  421. package/src/modes/bridge/bridge-mode.ts +0 -675
  422. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  423. package/src/modes/bridge/event-stream.ts +0 -70
  424. package/src/modes/rpc/host-tools.ts +0 -1
  425. package/src/modes/rpc/host-uris.ts +0 -1
  426. package/src/modes/rpc/rpc-client.ts +0 -1166
  427. package/src/modes/rpc/rpc-mode.ts +0 -1029
  428. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  429. package/src/modes/rpc/rpc-types.ts +0 -637
  430. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  431. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  432. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  433. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  434. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  435. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  436. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  437. package/src/modes/shared/agent-wire/responses.ts +0 -17
  438. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  439. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  440. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  441. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  442. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  443. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  444. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  445. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  446. package/src/notifications/config.ts +0 -219
  447. package/src/notifications/index.ts +0 -1835
  448. package/src/notifications/telegram-daemon-cli.ts +0 -243
  449. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  450. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  462. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  463. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  475. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  476. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -1,675 +0,0 @@
1
- import type { ExtensionUIContext } from "../../extensibility/extensions";
2
- import { workflowGatePath } from "../../gjc-runtime/session-layout";
3
- import type { AgentSession } from "../../session/agent-session";
4
- import type { ClientBridgePermissionOutcome } from "../../session/client-bridge";
5
- import type { RpcCommand, RpcResponse, RpcWorkflowGateResponse } from "../rpc/rpc-types";
6
- import { dispatchRpcCommand } from "../shared/agent-wire/command-dispatch";
7
- import { isRpcCommand } from "../shared/agent-wire/command-validation";
8
- import {
9
- BridgeFrameSequencer,
10
- toBridgeEventFrame,
11
- toBridgeWorkflowGateFrame,
12
- } from "../shared/agent-wire/event-envelope";
13
- import type { BridgeCapability } from "../shared/agent-wire/handshake";
14
- import {
15
- type BridgeHandshakeRequest,
16
- isBridgeHandshakeRequest,
17
- negotiateBridgeHandshake,
18
- } from "../shared/agent-wire/handshake";
19
- import { isRpcHostToolResult, isRpcHostToolUpdate, RpcHostToolBridge } from "../shared/agent-wire/host-tool-bridge";
20
- import { isRpcHostUriResult, RpcHostUriBridge } from "../shared/agent-wire/host-uri-bridge";
21
- import type { BridgeFrameType } from "../shared/agent-wire/protocol";
22
- import {
23
- BRIDGE_COMMAND_SCOPES,
24
- type BridgeCommandScope,
25
- isRpcCommandAllowed,
26
- isRpcCommandType,
27
- scopeForRpcCommand,
28
- } from "../shared/agent-wire/scopes";
29
- import { UiRequestBroker } from "../shared/agent-wire/ui-request-broker";
30
- import type { BridgeUiResult } from "../shared/agent-wire/ui-result";
31
- import { defaultAuditPath, UnattendedAuditLog } from "../shared/agent-wire/unattended-audit";
32
- import { modelSupportsTokenCostMetrics, UnattendedSessionControlPlane } from "../shared/agent-wire/unattended-session";
33
- import { FileGateStore } from "../shared/agent-wire/workflow-gate-broker";
34
- import { assertSafeBridgeBind, isBridgeTokenAuthorized } from "./auth";
35
- import { type BridgePermissionRequestPayload, createBridgeClientBridge } from "./bridge-client-bridge";
36
- import { BridgeExtensionUIContext, type BridgeUiRequestPayload } from "./bridge-ui-context";
37
- import { BridgeEventStream } from "./event-stream";
38
-
39
- const DEFAULT_BRIDGE_HOST = "127.0.0.1";
40
- const DEFAULT_BRIDGE_PORT = 4077;
41
-
42
- const SERVER_CAPABILITIES: readonly BridgeCapability[] = [
43
- "events",
44
- "prompt",
45
- "permission",
46
- "elicitation",
47
- "ui.declarative",
48
- "host_tools",
49
- "host_uri",
50
- "workflow_gate",
51
- ];
52
-
53
- const DEFAULT_BRIDGE_SCOPES: readonly BridgeCommandScope[] = ["prompt"];
54
- interface BridgeEndpointMatrix {
55
- events: boolean;
56
- commands: boolean;
57
- control: boolean;
58
- uiResponses: boolean;
59
- hostToolResults: boolean;
60
- hostUriResults: boolean;
61
- }
62
-
63
- const FAIL_CLOSED_BRIDGE_ENDPOINTS: BridgeEndpointMatrix = {
64
- events: false,
65
- commands: false,
66
- control: false,
67
- uiResponses: false,
68
- hostToolResults: false,
69
- hostUriResults: false,
70
- };
71
-
72
- const MAX_IDEMPOTENCY_RECORDS = 1_000;
73
-
74
- const SERVER_FRAME_TYPES: readonly BridgeFrameType[] = [
75
- "ready",
76
- "event",
77
- "response",
78
- "ui_request",
79
- "permission_request",
80
- "host_tool_call",
81
- "host_uri_request",
82
- "reset",
83
- "workflow_gate",
84
- "error",
85
- ];
86
-
87
- interface BridgeFetchHandlerOptions {
88
- sessionId: string;
89
- token: string;
90
- eventStream?: BridgeEventStream;
91
- commandDispatcher?: (command: RpcCommand) => Promise<RpcResponse>;
92
- commandScopes?: readonly BridgeCommandScope[];
93
- idempotencyCache?: BridgeIdempotencyCache;
94
- permissionBroker?: UiRequestBroker<BridgePermissionRequestPayload, ClientBridgePermissionOutcome>;
95
- uiBroker?: UiRequestBroker<BridgeUiRequestPayload, BridgeUiResult<unknown>>;
96
- hostToolBridge?: RpcHostToolBridge;
97
- hostUriBridge?: RpcHostUriBridge;
98
- endpointMatrix?: Partial<BridgeEndpointMatrix>;
99
- unattendedControlPlane?: UnattendedSessionControlPlane;
100
- }
101
-
102
- interface BridgeIdempotencyRecord {
103
- route: string;
104
- ownerToken?: string;
105
- body: string | Promise<string>;
106
- response: unknown | Promise<unknown>;
107
- pending?: boolean;
108
- }
109
-
110
- type BridgeIdempotencyCache = Map<string, BridgeIdempotencyRecord>;
111
-
112
- function idempotencyConflict(): Response {
113
- return jsonResponse(409, { error: "idempotency_conflict" });
114
- }
115
-
116
- function cachedIdempotencyResponse(
117
- cache: BridgeIdempotencyCache | undefined,
118
- key: string | undefined,
119
- record: Omit<BridgeIdempotencyRecord, "response">,
120
- ): Response | Promise<Response> | undefined {
121
- if (!key) return undefined;
122
- const cached = cache?.get(key);
123
- if (!cached) return undefined;
124
- return Promise.resolve(cached.body).then(body => {
125
- if (body !== record.body || cached.route !== record.route) return idempotencyConflict();
126
- if (cached.ownerToken !== record.ownerToken)
127
- return jsonResponse(403, { status: "rejected", code: "not_controller" });
128
- return Promise.resolve(cached.response).then(response => jsonResponse(200, response));
129
- });
130
- }
131
-
132
- function rememberIdempotencyResponse(
133
- cache: BridgeIdempotencyCache | undefined,
134
- key: string | undefined,
135
- record: BridgeIdempotencyRecord,
136
- ): void {
137
- if (!key) return;
138
- cache?.set(key, record);
139
- if (cache && cache.size > MAX_IDEMPOTENCY_RECORDS) {
140
- for (const [candidateKey, candidate] of cache) {
141
- if (!candidate.pending) {
142
- cache.delete(candidateKey);
143
- break;
144
- }
145
- }
146
- }
147
- }
148
-
149
- function jsonResponse(status: number, body: unknown): Response {
150
- return new Response(JSON.stringify(body), {
151
- status,
152
- headers: { "Content-Type": "application/json" },
153
- });
154
- }
155
-
156
- function isBridgeControllerOwner(options: BridgeFetchHandlerOptions, ownerToken: string): boolean {
157
- if (!ownerToken) return false;
158
- const ownerTokens = [options.permissionBroker?.ownerToken, options.uiBroker?.ownerToken].filter(
159
- (token): token is string => typeof token === "string" && token.length > 0,
160
- );
161
- return ownerTokens.length > 0 && ownerTokens.every(token => token === ownerToken);
162
- }
163
-
164
- function parseBridgeScopes(value: string | undefined): readonly BridgeCommandScope[] {
165
- if (!value?.trim()) return DEFAULT_BRIDGE_SCOPES;
166
- const allowed = new Set(BRIDGE_COMMAND_SCOPES);
167
- const scopes = new Set<BridgeCommandScope>(DEFAULT_BRIDGE_SCOPES);
168
- for (const raw of value.split(",")) {
169
- const scope = raw.trim();
170
- if (!scope) continue;
171
- if (!allowed.has(scope as BridgeCommandScope)) throw new Error(`Invalid GJC_BRIDGE_SCOPES entry: ${scope}`);
172
- scopes.add(scope as BridgeCommandScope);
173
- }
174
- return [...scopes];
175
- }
176
-
177
- // Opt-in endpoint enablement via GJC_BRIDGE_ENDPOINTS (default undefined -> fail closed, backward compatible).
178
- // Accepts "all" or a comma list of matrix keys.
179
- export function parseBridgeEndpoints(value: string | undefined): Partial<BridgeEndpointMatrix> | undefined {
180
- if (!value?.trim()) return undefined;
181
- const allowed = new Set<string>(Object.keys(FAIL_CLOSED_BRIDGE_ENDPOINTS));
182
- const matrix: Partial<BridgeEndpointMatrix> = {};
183
- if (value.trim().toLowerCase() === "all") {
184
- for (const key of allowed) matrix[key as keyof BridgeEndpointMatrix] = true;
185
- return matrix;
186
- }
187
- for (const raw of value.split(",")) {
188
- const key = raw.trim();
189
- if (!key) continue;
190
- if (!allowed.has(key)) throw new Error(`Invalid GJC_BRIDGE_ENDPOINTS entry: ${key}`);
191
- matrix[key as keyof BridgeEndpointMatrix] = true;
192
- }
193
- return matrix;
194
- }
195
-
196
- function hasScope(scopes: readonly BridgeCommandScope[] | undefined, scope: BridgeCommandScope): boolean {
197
- return new Set(scopes ?? DEFAULT_BRIDGE_SCOPES).has(scope);
198
- }
199
- function bridgeEndpointMatrix(options: BridgeFetchHandlerOptions): BridgeEndpointMatrix {
200
- return { ...FAIL_CLOSED_BRIDGE_ENDPOINTS, ...options.endpointMatrix };
201
- }
202
-
203
- function disabledEndpointResponse(endpoint: keyof BridgeEndpointMatrix): Response {
204
- return jsonResponse(403, { error: "endpoint_disabled", endpoint });
205
- }
206
-
207
- function bridgeHelpResponse(matrix: BridgeEndpointMatrix): Response {
208
- return jsonResponse(200, {
209
- status: "experimental_gated",
210
- message: "Bridge mode is experimental; session-control endpoints fail closed by default.",
211
- endpoints: matrix,
212
- });
213
- }
214
-
215
- function auditOutcomeFor(event: string): "accepted" | "rejected" | "denied" | "exceeded" | "aborted" | "info" {
216
- if (event.includes("denied")) return "denied";
217
- if (event.includes("exceeded")) return "exceeded";
218
- if (event.includes("abort")) return "aborted";
219
- if (event.includes("rejected") || event.includes("conflict")) return "rejected";
220
- if (event.includes("accepted") || event.includes("negotiated") || event.includes("emitted")) return "accepted";
221
- return "info";
222
- }
223
-
224
- function frameTypeForDispatchOutput(obj: RpcResponse | object): BridgeFrameType {
225
- const type = typeof obj === "object" && obj !== null && "type" in obj ? (obj as { type?: unknown }).type : undefined;
226
- if (type === "host_tool_call" || type === "host_tool_cancel") return "host_tool_call";
227
- if (type === "host_uri_request" || type === "host_uri_cancel") return "host_uri_request";
228
- if (type === "extension_ui_request") return "ui_request";
229
- if (type === "response") return "response";
230
- return "response";
231
- }
232
-
233
- export function createBridgeFetchHandler(options: BridgeFetchHandlerOptions): (request: Request) => Promise<Response> {
234
- return async request => {
235
- const endpointMatrix = bridgeEndpointMatrix(options);
236
- const url = new URL(request.url);
237
- if (request.method === "GET" && url.pathname === "/healthz") {
238
- return jsonResponse(200, { status: "ok" });
239
- }
240
- if (request.method === "GET" && url.pathname === "/v1/help") {
241
- return bridgeHelpResponse(endpointMatrix);
242
- }
243
-
244
- if (request.method === "GET" && url.pathname === `/v1/sessions/${options.sessionId}/events`) {
245
- if (!isBridgeTokenAuthorized(request.headers.get("Authorization"), { token: options.token })) {
246
- return jsonResponse(401, { error: "unauthorized" });
247
- }
248
- if (!endpointMatrix.events) return disabledEndpointResponse("events");
249
- const lastSeqRaw = url.searchParams.get("last_seq");
250
- if (lastSeqRaw !== null && !/^\d+$/.test(lastSeqRaw)) return jsonResponse(400, { error: "invalid_last_seq" });
251
- const lastSeq = lastSeqRaw === null ? 0 : Number.parseInt(lastSeqRaw, 10);
252
- return options.eventStream?.response(lastSeq) ?? jsonResponse(503, { error: "events_unavailable" });
253
- }
254
-
255
- if (!isBridgeTokenAuthorized(request.headers.get("Authorization"), { token: options.token })) {
256
- return jsonResponse(401, { error: "unauthorized" });
257
- }
258
-
259
- if (request.method === "POST" && url.pathname === "/v1/handshake") {
260
- let payload: BridgeHandshakeRequest;
261
- try {
262
- payload = (await request.json()) as BridgeHandshakeRequest;
263
- } catch {
264
- return jsonResponse(400, { error: "invalid_json" });
265
- }
266
- if (!isBridgeHandshakeRequest(payload)) {
267
- return jsonResponse(400, { error: "invalid_request" });
268
- }
269
- let acceptedUnattended = options.unattendedControlPlane?.isUnattended() ? payload.unattended : undefined;
270
- if (
271
- acceptedUnattended === undefined &&
272
- payload.unattended !== undefined &&
273
- endpointMatrix.events &&
274
- options.unattendedControlPlane
275
- ) {
276
- try {
277
- options.unattendedControlPlane.negotiate(payload.unattended);
278
- acceptedUnattended = payload.unattended;
279
- } catch (err) {
280
- const error =
281
- err instanceof Error && "code" in err
282
- ? { code: (err as { code: unknown }).code, message: err.message }
283
- : { error: err instanceof Error ? err.message : String(err) };
284
- return jsonResponse(403, error);
285
- }
286
- }
287
- return jsonResponse(
288
- 200,
289
- negotiateBridgeHandshake(payload, {
290
- sessionId: options.sessionId,
291
- capabilities: endpointMatrix.events ? SERVER_CAPABILITIES : [],
292
- scopes: endpointMatrix.commands ? (options.commandScopes ?? DEFAULT_BRIDGE_SCOPES) : [],
293
- endpoints: {
294
- events: endpointMatrix.events ? `/v1/sessions/${options.sessionId}/events` : "",
295
- commands: endpointMatrix.commands ? `/v1/sessions/${options.sessionId}/commands` : "",
296
- uiResponses: endpointMatrix.uiResponses
297
- ? `/v1/sessions/${options.sessionId}/ui-responses/{correlation_id}`
298
- : "",
299
- claimControl: endpointMatrix.control ? `/v1/sessions/${options.sessionId}/control:claim` : "",
300
- disconnectControl: endpointMatrix.control
301
- ? `/v1/sessions/${options.sessionId}/control:disconnect`
302
- : "",
303
- hostToolResults: endpointMatrix.hostToolResults
304
- ? `/v1/sessions/${options.sessionId}/host-tool-results/{correlation_id}`
305
- : "",
306
- hostUriResults: endpointMatrix.hostUriResults
307
- ? `/v1/sessions/${options.sessionId}/host-uri-results/{correlation_id}`
308
- : "",
309
- },
310
- frameTypes: endpointMatrix.events ? SERVER_FRAME_TYPES : [],
311
- acceptedUnattended,
312
- }),
313
- );
314
- }
315
-
316
- if (request.method === "POST" && url.pathname === `/v1/sessions/${options.sessionId}/commands`) {
317
- if (!endpointMatrix.commands) return disabledEndpointResponse("commands");
318
- if (!options.commandDispatcher) return jsonResponse(503, { error: "commands_unavailable" });
319
- const idempotencyKey = request.headers.get("Idempotency-Key") ?? undefined;
320
- const existingRecord = idempotencyKey ? options.idempotencyCache?.get(idempotencyKey) : undefined;
321
- let body = "";
322
- let payload: unknown;
323
- let pendingResponse: PromiseWithResolvers<unknown> | undefined;
324
- try {
325
- if (existingRecord) {
326
- body = await request.text();
327
- const cached = cachedIdempotencyResponse(options.idempotencyCache, idempotencyKey, {
328
- route: url.pathname,
329
- body,
330
- });
331
- if (cached) return await cached;
332
- } else {
333
- const bodyPromise = request.text();
334
- pendingResponse = Promise.withResolvers<unknown>();
335
- void pendingResponse.promise.catch(() => undefined);
336
- rememberIdempotencyResponse(options.idempotencyCache, idempotencyKey, {
337
- route: url.pathname,
338
- body: bodyPromise,
339
- response: pendingResponse.promise,
340
- pending: true,
341
- });
342
- body = await bodyPromise;
343
- }
344
- payload = JSON.parse(body) as unknown;
345
- } catch {
346
- options.idempotencyCache?.delete(idempotencyKey ?? "");
347
- pendingResponse?.reject(new Error("invalid_json"));
348
- return jsonResponse(400, { error: "invalid_json" });
349
- }
350
- const type =
351
- typeof payload === "object" && payload !== null && "type" in payload
352
- ? (payload as { type?: unknown }).type
353
- : undefined;
354
- if (!isRpcCommandType(type)) {
355
- options.idempotencyCache?.delete(idempotencyKey ?? "");
356
- pendingResponse?.reject(new Error("invalid_command"));
357
- return jsonResponse(400, { error: "invalid_command" });
358
- }
359
- if (!isRpcCommand(payload)) {
360
- options.idempotencyCache?.delete(idempotencyKey ?? "");
361
- pendingResponse?.reject(new Error("invalid_command"));
362
- return jsonResponse(400, { error: "invalid_command" });
363
- }
364
- const scopes = new Set(options.commandScopes ?? DEFAULT_BRIDGE_SCOPES);
365
- if (!isRpcCommandAllowed(type, scopes)) {
366
- options.idempotencyCache?.delete(idempotencyKey ?? "");
367
- pendingResponse?.reject(new Error("scope_denied"));
368
- return jsonResponse(403, { error: "scope_denied", scope: scopeForRpcCommand(type) });
369
- }
370
- try {
371
- const response = await options.commandDispatcher(payload);
372
- pendingResponse?.resolve(response);
373
- const cachedRecord = idempotencyKey ? options.idempotencyCache?.get(idempotencyKey) : undefined;
374
- if (cachedRecord) cachedRecord.pending = false;
375
- return jsonResponse(200, response);
376
- } catch (err) {
377
- options.idempotencyCache?.delete(idempotencyKey ?? "");
378
- pendingResponse?.reject(err);
379
- throw err;
380
- }
381
- }
382
- if (request.method === "POST" && url.pathname === `/v1/sessions/${options.sessionId}/control:claim`) {
383
- if (!endpointMatrix.control) return disabledEndpointResponse("control");
384
- if (!hasScope(options.commandScopes, "control"))
385
- return jsonResponse(403, { error: "scope_denied", scope: "control" });
386
- if (options.permissionBroker?.ownerToken || options.uiBroker?.ownerToken)
387
- return jsonResponse(409, { error: "controller_busy" });
388
- const ownerToken = request.headers.get("X-GJC-Bridge-Owner-Token") ?? crypto.randomUUID();
389
- const permissionClaim = options.permissionBroker?.claimController(ownerToken);
390
- const uiClaim = options.uiBroker?.claimController(ownerToken);
391
- if (permissionClaim?.status === "busy" || uiClaim?.status === "busy")
392
- return jsonResponse(409, { error: "controller_busy" });
393
- return jsonResponse(200, { status: "claimed", ownerToken });
394
- }
395
- if (request.method === "POST" && url.pathname === `/v1/sessions/${options.sessionId}/control:disconnect`) {
396
- if (!endpointMatrix.control) return disabledEndpointResponse("control");
397
- if (!hasScope(options.commandScopes, "control"))
398
- return jsonResponse(403, { error: "scope_denied", scope: "control" });
399
- const ownerToken = request.headers.get("X-GJC-Bridge-Owner-Token") ?? "";
400
- const permissionReleased = options.permissionBroker?.disconnectController(ownerToken) ?? true;
401
- const uiReleased = options.uiBroker?.disconnectController(ownerToken) ?? true;
402
- return permissionReleased && uiReleased
403
- ? jsonResponse(200, { status: "released" })
404
- : jsonResponse(403, { status: "rejected", code: "not_controller" });
405
- }
406
-
407
- const uiResponsePrefix = `/v1/sessions/${options.sessionId}/ui-responses/`;
408
- if (request.method === "POST" && url.pathname.startsWith(uiResponsePrefix)) {
409
- if (!endpointMatrix.uiResponses) return disabledEndpointResponse("uiResponses");
410
- if (!hasScope(options.commandScopes, "control"))
411
- return jsonResponse(403, { error: "scope_denied", scope: "control" });
412
- const correlationId = decodeURIComponent(url.pathname.slice(uiResponsePrefix.length));
413
- const ownerToken = request.headers.get("X-GJC-Bridge-Owner-Token") ?? "";
414
- const idempotencyKey = request.headers.get("Idempotency-Key") ?? undefined;
415
- let body = "";
416
- let payload: unknown;
417
- try {
418
- body = await request.text();
419
- const cached = cachedIdempotencyResponse(options.idempotencyCache, idempotencyKey, {
420
- route: url.pathname,
421
- ownerToken,
422
- body,
423
- });
424
- if (cached) return await cached;
425
- payload = JSON.parse(body) as unknown;
426
- } catch {
427
- return jsonResponse(400, { error: "invalid_json" });
428
- }
429
- if (
430
- payload !== null &&
431
- typeof payload === "object" &&
432
- "gate_id" in payload &&
433
- "answer" in payload &&
434
- (correlationId === (payload as RpcWorkflowGateResponse).gate_id || correlationId.startsWith("wg_"))
435
- ) {
436
- if (!isBridgeControllerOwner(options, ownerToken)) {
437
- return jsonResponse(403, { status: "rejected", code: "not_controller" });
438
- }
439
- try {
440
- const resolution = await options.unattendedControlPlane?.resolveGate({
441
- gate_id: (payload as RpcWorkflowGateResponse).gate_id,
442
- answer: (payload as RpcWorkflowGateResponse).answer,
443
- idempotency_key: (payload as RpcWorkflowGateResponse).idempotency_key ?? idempotencyKey,
444
- });
445
- if (resolution) {
446
- rememberIdempotencyResponse(options.idempotencyCache, idempotencyKey, {
447
- route: url.pathname,
448
- ownerToken,
449
- body,
450
- response: resolution,
451
- });
452
- return jsonResponse(200, resolution);
453
- }
454
- } catch (err) {
455
- const error =
456
- err instanceof Error && "code" in err
457
- ? { code: (err as { code: unknown }).code, message: err.message }
458
- : { error: err instanceof Error ? err.message : String(err) };
459
- return jsonResponse(409, error);
460
- }
461
- }
462
- const permissionResult = options.permissionBroker?.respond(
463
- correlationId,
464
- ownerToken,
465
- payload as ClientBridgePermissionOutcome,
466
- );
467
- if (permissionResult?.status === "accepted") {
468
- rememberIdempotencyResponse(options.idempotencyCache, idempotencyKey, {
469
- route: url.pathname,
470
- ownerToken,
471
- body,
472
- response: permissionResult,
473
- });
474
- return jsonResponse(200, permissionResult);
475
- }
476
- const uiResult = options.uiBroker?.respond(correlationId, ownerToken, payload as BridgeUiResult<unknown>);
477
- if (uiResult?.status === "accepted") {
478
- rememberIdempotencyResponse(options.idempotencyCache, idempotencyKey, {
479
- route: url.pathname,
480
- ownerToken,
481
- body,
482
- response: uiResult,
483
- });
484
- return jsonResponse(200, uiResult);
485
- }
486
- const rejection = uiResult ?? permissionResult ?? { status: "rejected", code: "unknown_request" };
487
- return jsonResponse(
488
- rejection.status === "rejected" && rejection.code === "not_controller" ? 403 : 409,
489
- rejection,
490
- );
491
- }
492
- const hostToolResultPrefix = `/v1/sessions/${options.sessionId}/host-tool-results/`;
493
- if (request.method === "POST" && url.pathname.startsWith(hostToolResultPrefix)) {
494
- if (!endpointMatrix.hostToolResults) return disabledEndpointResponse("hostToolResults");
495
- if (!hasScope(options.commandScopes, "host_tools"))
496
- return jsonResponse(403, { error: "scope_denied", scope: "host_tools" });
497
- if (!options.hostToolBridge) return jsonResponse(503, { error: "host_tools_unavailable" });
498
- const id = decodeURIComponent(url.pathname.slice(hostToolResultPrefix.length));
499
- let payload: unknown;
500
- try {
501
- payload = await request.json();
502
- } catch {
503
- return jsonResponse(400, { error: "invalid_json" });
504
- }
505
- const frame = typeof payload === "object" && payload !== null ? { ...payload, id } : { id };
506
- let handled = false;
507
- if (isRpcHostToolUpdate(frame)) {
508
- handled = options.hostToolBridge.handleUpdate(frame);
509
- } else if (isRpcHostToolResult(frame)) {
510
- handled = options.hostToolBridge.handleResult(frame);
511
- } else {
512
- return jsonResponse(400, { error: "invalid_host_tool_result" });
513
- }
514
- return handled ? jsonResponse(200, { status: "accepted" }) : jsonResponse(404, { error: "unknown_request" });
515
- }
516
-
517
- const hostUriResultPrefix = `/v1/sessions/${options.sessionId}/host-uri-results/`;
518
- if (request.method === "POST" && url.pathname.startsWith(hostUriResultPrefix)) {
519
- if (!endpointMatrix.hostUriResults) return disabledEndpointResponse("hostUriResults");
520
- if (!hasScope(options.commandScopes, "host_uri"))
521
- return jsonResponse(403, { error: "scope_denied", scope: "host_uri" });
522
- if (!options.hostUriBridge) return jsonResponse(503, { error: "host_uri_unavailable" });
523
- const id = decodeURIComponent(url.pathname.slice(hostUriResultPrefix.length));
524
- let payload: unknown;
525
- try {
526
- payload = await request.json();
527
- } catch {
528
- return jsonResponse(400, { error: "invalid_json" });
529
- }
530
- const frame = typeof payload === "object" && payload !== null ? { ...payload, id } : { id };
531
- if (!isRpcHostUriResult(frame)) return jsonResponse(400, { error: "invalid_host_uri_result" });
532
- return options.hostUriBridge.handleResult(frame)
533
- ? jsonResponse(200, { status: "accepted" })
534
- : jsonResponse(404, { error: "unknown_request" });
535
- }
536
- return jsonResponse(404, { error: "not_found" });
537
- };
538
- }
539
-
540
- export async function runBridgeMode(
541
- session: AgentSession,
542
- setToolUIContext?: (uiContext: ExtensionUIContext, hasUI: boolean) => void,
543
- ): Promise<never> {
544
- const token = Bun.env.GJC_BRIDGE_TOKEN;
545
- if (!token) {
546
- throw new Error("GJC_BRIDGE_TOKEN is required for --mode bridge");
547
- }
548
- const hostname = Bun.env.GJC_BRIDGE_HOST ?? DEFAULT_BRIDGE_HOST;
549
- const port = Bun.env.GJC_BRIDGE_PORT ? Number.parseInt(Bun.env.GJC_BRIDGE_PORT, 10) : DEFAULT_BRIDGE_PORT;
550
- if (!Number.isInteger(port) || port <= 0 || port > 65_535) {
551
- throw new Error(`Invalid GJC_BRIDGE_PORT: ${Bun.env.GJC_BRIDGE_PORT}`);
552
- }
553
- const commandScopes = parseBridgeScopes(Bun.env.GJC_BRIDGE_SCOPES);
554
- const endpointMatrix = parseBridgeEndpoints(Bun.env.GJC_BRIDGE_ENDPOINTS);
555
-
556
- const certPath = Bun.env.GJC_BRIDGE_TLS_CERT;
557
- const keyPath = Bun.env.GJC_BRIDGE_TLS_KEY;
558
- const tlsConfigured = Boolean(certPath && keyPath);
559
- assertSafeBridgeBind({ hostname, port, tlsConfigured });
560
-
561
- const tls = tlsConfigured
562
- ? {
563
- cert: await Bun.file(certPath!).text(),
564
- key: await Bun.file(keyPath!).text(),
565
- }
566
- : undefined;
567
-
568
- const eventStream = new BridgeEventStream();
569
- const sequencer = new BridgeFrameSequencer(session.sessionId);
570
- const permissionBroker = new UiRequestBroker<BridgePermissionRequestPayload, ClientBridgePermissionOutcome>({
571
- emitRequest: (correlationId, request) => {
572
- eventStream.publish(sequencer.next("permission_request", request, correlationId));
573
- },
574
- });
575
- const uiBroker = new UiRequestBroker<BridgeUiRequestPayload, BridgeUiResult<unknown>>({
576
- emitRequest: (correlationId, request) => {
577
- eventStream.publish(sequencer.next("ui_request", request, correlationId));
578
- },
579
- });
580
- const uiContext = new BridgeExtensionUIContext({
581
- broker: uiBroker,
582
- emit: payload => eventStream.publish(sequencer.next("ui_request", payload)),
583
- });
584
- setToolUIContext?.(uiContext, true);
585
- session.setClientBridge(createBridgeClientBridge(permissionBroker));
586
- session.subscribe(event => eventStream.publish(toBridgeEventFrame(event, sequencer)));
587
- const output = (obj: RpcResponse | object) => {
588
- eventStream.publish(sequencer.next(frameTypeForDispatchOutput(obj), obj));
589
- };
590
- const hostToolBridge = new RpcHostToolBridge(output);
591
- const hostUriBridge = new RpcHostUriBridge(output);
592
- const idempotencyCache: BridgeIdempotencyCache = new Map();
593
- const auditLog = new UnattendedAuditLog(defaultAuditPath(session.sessionId, session.sessionManager.getCwd()), {
594
- redactAnswers: true,
595
- });
596
- const recordAudit = (event: { event: string; [key: string]: unknown }) => {
597
- const payload =
598
- typeof event.payload === "object" && event.payload !== null
599
- ? (event.payload as Record<string, unknown>)
600
- : undefined;
601
- const gateId =
602
- typeof event.gate_id === "string"
603
- ? event.gate_id
604
- : typeof payload?.gate_id === "string"
605
- ? payload.gate_id
606
- : undefined;
607
- auditLog.record({
608
- run_id: session.sessionId,
609
- session_id: session.sessionId,
610
- actor: typeof event.actor === "string" ? event.actor : undefined,
611
- event: event.event,
612
- outcome: auditOutcomeFor(event.event),
613
- dedupe_key: `${event.event}:${gateId ?? "run"}:${JSON.stringify(payload ?? event)}`,
614
- gate_id: gateId,
615
- stage: typeof event.stage === "string" ? (event.stage as never) : undefined,
616
- kind: typeof event.kind === "string" ? (event.kind as never) : undefined,
617
- scope: typeof payload?.scope === "string" ? payload.scope : undefined,
618
- action: typeof payload?.action === "string" ? payload.action : undefined,
619
- budget: event.event === "budget_exceeded" ? (payload as never) : undefined,
620
- answer_hash: typeof event.answer_hash === "string" ? event.answer_hash : undefined,
621
- error: payload && event.event.endsWith("denied") ? payload : undefined,
622
- });
623
- };
624
- const gateStore = new FileGateStore(
625
- workflowGatePath(session.sessionManager.getCwd(), session.sessionId, session.sessionId),
626
- );
627
- const unattendedControlPlane = new UnattendedSessionControlPlane({
628
- runId: session.sessionId,
629
- sessionId: session.sessionId,
630
- emitFrame: gate => eventStream.publish(toBridgeWorkflowGateFrame(gate, sequencer)),
631
- store: gateStore,
632
- audit: recordAudit,
633
- providerSupportsTokenCostMetrics: modelSupportsTokenCostMetrics(session.model),
634
- getUsageSnapshot: () => {
635
- const stats = session.getSessionStats();
636
- return { tokens: stats.tokens.total, costUsd: stats.cost };
637
- },
638
- });
639
- session.setWorkflowGateEmitter(unattendedControlPlane);
640
- unattendedControlPlane
641
- .recover()
642
- .catch(err =>
643
- eventStream.publish(sequencer.next("error", { error: err instanceof Error ? err.message : String(err) })),
644
- );
645
-
646
- Bun.serve({
647
- hostname,
648
- port,
649
- ...(tls ? { tls } : {}),
650
- fetch: createBridgeFetchHandler({
651
- sessionId: session.sessionId,
652
- token,
653
- eventStream,
654
- idempotencyCache,
655
- permissionBroker,
656
- uiBroker,
657
- hostToolBridge,
658
- hostUriBridge,
659
- commandScopes,
660
- endpointMatrix,
661
- unattendedControlPlane,
662
- commandDispatcher: command =>
663
- dispatchRpcCommand(command, {
664
- session,
665
- output,
666
- hostToolRegistry: hostToolBridge,
667
- hostUriRegistry: hostUriBridge,
668
- createUiContext: () => uiContext,
669
- unattendedControlPlane,
670
- }),
671
- }),
672
- });
673
-
674
- return new Promise<never>(() => {});
675
- }