@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,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
- }