@gajae-code/coding-agent 0.10.1 → 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 (474) hide show
  1. package/CHANGELOG.md +70 -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/gajae-pet-widget.d.ts +1 -0
  54. package/dist/types/modes/components/model-selector.d.ts +1 -0
  55. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  56. package/dist/types/modes/components/pet-capability.d.ts +37 -0
  57. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  58. package/dist/types/modes/components/settings-selector.d.ts +15 -4
  59. package/dist/types/modes/components/welcome.d.ts +1 -1
  60. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  61. package/dist/types/modes/index.d.ts +0 -4
  62. package/dist/types/modes/interactive-mode.d.ts +5 -1
  63. package/dist/types/modes/runtime-init.d.ts +2 -2
  64. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  65. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  66. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  67. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  68. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  69. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  72. package/dist/types/modes/types.d.ts +16 -1
  73. package/dist/types/runtime-mcp/client.d.ts +2 -0
  74. package/dist/types/runtime-mcp/config.d.ts +5 -1
  75. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  76. package/dist/types/runtime-mcp/types.d.ts +4 -0
  77. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  78. package/dist/types/sdk/acp/index.d.ts +2 -0
  79. package/dist/types/sdk/broker/broker.d.ts +53 -0
  80. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  81. package/dist/types/sdk/broker/ensure.d.ts +33 -0
  82. package/dist/types/sdk/broker/identity.d.ts +3 -0
  83. package/dist/types/sdk/broker/index.d.ts +8 -0
  84. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  85. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  86. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  87. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  88. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  89. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  90. package/dist/types/sdk/broker/transport.d.ts +9 -0
  91. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  92. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  93. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  94. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  95. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  96. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  97. package/dist/types/sdk/bus/config.d.ts +274 -0
  98. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  99. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  100. package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
  101. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  102. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  103. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  104. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  105. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  107. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  108. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  109. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  110. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  111. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  112. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  113. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  114. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  115. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  116. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  117. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  118. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  119. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
  121. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  122. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  123. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  124. package/dist/types/sdk/cli/index.d.ts +1 -0
  125. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  126. package/dist/types/sdk/client/client.d.ts +1 -0
  127. package/dist/types/sdk/client/discovery.d.ts +27 -0
  128. package/dist/types/sdk/client/index.d.ts +2 -0
  129. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  130. package/dist/types/sdk/host/control/index.d.ts +2 -0
  131. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  132. package/dist/types/sdk/host/events.d.ts +35 -0
  133. package/dist/types/sdk/host/host.d.ts +35 -0
  134. package/dist/types/sdk/host/index.d.ts +4 -0
  135. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  136. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  137. package/dist/types/sdk/host/query/index.d.ts +3 -0
  138. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  139. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  140. package/dist/types/sdk/host/types.d.ts +32 -0
  141. package/dist/types/sdk/index.d.ts +6 -0
  142. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  143. package/dist/types/sdk/mcp/index.d.ts +1 -0
  144. package/dist/types/sdk/mcp/server.d.ts +37 -0
  145. package/dist/types/sdk/models.d.ts +44 -0
  146. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  147. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  148. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  149. package/dist/types/sdk/startup-capability.d.ts +50 -0
  150. package/dist/types/session/agent-session.d.ts +114 -21
  151. package/dist/types/session/default-model-selection.d.ts +25 -0
  152. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  153. package/dist/types/session/session-manager.d.ts +58 -1
  154. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  155. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  156. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  157. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  158. package/dist/types/tools/browser/launch.d.ts +22 -0
  159. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  160. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  161. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  162. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  163. package/dist/types/tools/browser/registry.d.ts +19 -0
  164. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  165. package/dist/types/tools/index.d.ts +8 -8
  166. package/package.json +34 -13
  167. package/scripts/build-sdk-package-smoke.ts +94 -0
  168. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  169. package/scripts/compile-args.ts +4 -2
  170. package/scripts/g005-daemon-smoke.ts +4 -5
  171. package/scripts/g011-daemon-path-smoke.ts +5 -5
  172. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  173. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  174. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  175. package/scripts/manifest-schema.ts +124 -0
  176. package/scripts/run-test-manifest.ts +153 -0
  177. package/scripts/run-threat-model-check.ts +157 -0
  178. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  179. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  180. package/src/append-only-mode.ts +1 -1
  181. package/src/cli/args.ts +43 -12
  182. package/src/cli/auth-gateway-cli.ts +2 -2
  183. package/src/cli/config-cli.ts +2 -1
  184. package/src/cli/daemon-cli.ts +63 -14
  185. package/src/cli/list-models.ts +1 -1
  186. package/src/cli/notify-cli.ts +288 -286
  187. package/src/cli.ts +21 -2
  188. package/src/commands/daemon.ts +50 -6
  189. package/src/commands/harness.ts +93 -36
  190. package/src/commands/launch.ts +5 -2
  191. package/src/commands/mcp-serve.ts +19 -12
  192. package/src/commands/notify.ts +36 -3
  193. package/src/commands/sdk.ts +426 -0
  194. package/src/commit/agentic/agent.ts +1 -0
  195. package/src/config/atomic-yaml-patch.ts +423 -0
  196. package/src/config/model-profile-activation.ts +240 -89
  197. package/src/config/model-profiles.ts +37 -34
  198. package/src/config/model-registry.ts +51 -26
  199. package/src/config/model-resolver.ts +138 -51
  200. package/src/config/model-selector-value.ts +50 -0
  201. package/src/config/models-config-schema.ts +14 -21
  202. package/src/config/settings-schema.ts +128 -10
  203. package/src/config/settings.ts +1120 -158
  204. package/src/coordinator-mcp/model-preset.ts +74 -20
  205. package/src/coordinator-mcp/server.ts +1597 -3052
  206. package/src/daemon/builtin.ts +8 -5
  207. package/src/daemon/control-types.ts +1 -1
  208. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  209. package/src/discovery/mcp-json.ts +327 -20
  210. package/src/extensibility/custom-tools/types.ts +1 -1
  211. package/src/extensibility/extensions/compact-handler.ts +3 -3
  212. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  213. package/src/extensibility/extensions/loader.ts +69 -5
  214. package/src/extensibility/extensions/runner.ts +112 -4
  215. package/src/extensibility/extensions/types.ts +176 -17
  216. package/src/extensibility/hooks/types.ts +1 -1
  217. package/src/extensibility/slash-commands.ts +3 -3
  218. package/src/gjc-runtime/launch-tmux.ts +170 -86
  219. package/src/gjc-runtime/psmux-detect.ts +82 -4
  220. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  221. package/src/gjc-runtime/team-runtime.ts +54 -35
  222. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  223. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -2
  224. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  225. package/src/gjc-runtime/ultragoal-guard.ts +53 -6
  226. package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
  227. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  228. package/src/harness-control-plane/operate.ts +9 -9
  229. package/src/harness-control-plane/owner.ts +283 -39
  230. package/src/harness-control-plane/receipts.ts +0 -1
  231. package/src/harness-control-plane/sdk-transport.ts +395 -0
  232. package/src/harness-control-plane/session-transport.ts +94 -0
  233. package/src/harness-control-plane/types.ts +1 -1
  234. package/src/internal-urls/docs-index.generated.ts +36 -37
  235. package/src/lsp/client.ts +42 -6
  236. package/src/lsp/index.ts +2 -2
  237. package/src/main.ts +299 -204
  238. package/src/modes/DESIGN.md +258 -0
  239. package/src/modes/acp/acp-agent.ts +1228 -2612
  240. package/src/modes/acp/acp-client-bridge.ts +2 -20
  241. package/src/modes/acp/acp-event-mapper.ts +18 -2
  242. package/src/modes/acp/acp-mode.ts +8 -36
  243. package/src/modes/acp/permission-mode.ts +25 -0
  244. package/src/modes/acp/startup-options.ts +6 -0
  245. package/src/modes/components/agent-dashboard.ts +37 -17
  246. package/src/modes/components/custom-editor.ts +1 -0
  247. package/src/modes/components/gajae-pet-widget.ts +169 -20
  248. package/src/modes/components/model-selector.ts +93 -35
  249. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  250. package/src/modes/components/pet-capability.ts +115 -0
  251. package/src/modes/components/pet-selector.ts +4 -6
  252. package/src/modes/components/settings-selector.ts +86 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +1 -2
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +357 -12
  257. package/src/modes/controllers/input-controller.ts +43 -13
  258. package/src/modes/controllers/selector-controller.ts +671 -44
  259. package/src/modes/index.ts +0 -22
  260. package/src/modes/interactive-mode.ts +108 -24
  261. package/src/modes/runtime-init.ts +298 -6
  262. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  263. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  264. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  265. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  266. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  267. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
  268. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  269. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  270. package/src/modes/types.ts +16 -1
  271. package/src/runtime-mcp/client.ts +94 -19
  272. package/src/runtime-mcp/config.ts +27 -15
  273. package/src/runtime-mcp/manager.ts +343 -105
  274. package/src/runtime-mcp/oauth-flow.ts +42 -12
  275. package/src/runtime-mcp/transports/http.ts +49 -19
  276. package/src/runtime-mcp/transports/stdio.ts +47 -28
  277. package/src/runtime-mcp/types.ts +10 -0
  278. package/src/sdk/acp/adapter.ts +418 -0
  279. package/src/sdk/acp/index.ts +2 -0
  280. package/src/sdk/broker/broker.ts +642 -0
  281. package/src/sdk/broker/discovery.ts +94 -0
  282. package/src/sdk/broker/ensure.ts +249 -0
  283. package/src/sdk/broker/identity.ts +42 -0
  284. package/src/sdk/broker/index.ts +8 -0
  285. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  286. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  287. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  288. package/src/sdk/broker/lifecycle.ts +2157 -0
  289. package/src/sdk/broker/process-incarnation.ts +159 -0
  290. package/src/sdk/broker/runtime.ts +164 -0
  291. package/src/sdk/broker/session-index.ts +318 -0
  292. package/src/sdk/broker/state-version.ts +23 -0
  293. package/src/sdk/broker/transport.ts +125 -0
  294. package/src/sdk/bus/chat-command-policy.ts +107 -0
  295. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  296. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  297. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  298. package/src/sdk/bus/chat-effect-journal.ts +353 -0
  299. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  300. package/src/sdk/bus/config.ts +433 -0
  301. package/src/sdk/bus/conversation-store.ts +391 -0
  302. package/src/sdk/bus/discord-conversation.ts +85 -0
  303. package/src/sdk/bus/discord-daemon.ts +2275 -0
  304. package/src/sdk/bus/discord-live-provider.ts +521 -0
  305. package/src/sdk/bus/discord-provider.ts +56 -0
  306. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  307. package/src/sdk/bus/index.ts +3943 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  309. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  310. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  311. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  312. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  313. package/src/sdk/bus/natives-augment.d.ts +38 -0
  314. package/src/sdk/bus/notification-orchestration.ts +535 -0
  315. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  316. package/src/sdk/bus/session-control.ts +333 -0
  317. package/src/sdk/bus/slack-conversation.ts +74 -0
  318. package/src/sdk/bus/slack-daemon.ts +2144 -0
  319. package/src/sdk/bus/slack-live-provider.ts +380 -0
  320. package/src/sdk/bus/slack-provider.ts +76 -0
  321. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  322. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  323. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  324. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  325. package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
  326. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  327. package/src/sdk/bus/telegram-setup.ts +663 -0
  328. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  329. package/src/sdk/cli/index.ts +1 -0
  330. package/src/sdk/cli/session-cli.ts +275 -0
  331. package/src/sdk/client/client.ts +1 -0
  332. package/src/sdk/client/discovery.ts +108 -0
  333. package/src/sdk/client/index.ts +2 -0
  334. package/src/sdk/host/control/dispatch.ts +367 -0
  335. package/src/sdk/host/control/index.ts +10 -0
  336. package/src/sdk/host/control/operations.ts +63 -0
  337. package/src/sdk/host/events.ts +91 -0
  338. package/src/sdk/host/host.ts +296 -0
  339. package/src/sdk/host/index.ts +4 -0
  340. package/src/sdk/host/query/cursor.ts +189 -0
  341. package/src/sdk/host/query/handlers.ts +533 -0
  342. package/src/sdk/host/query/index.ts +3 -0
  343. package/src/sdk/host/query/revision-store.ts +1126 -0
  344. package/src/sdk/host/reverse-leases.ts +325 -0
  345. package/src/sdk/host/types.ts +29 -0
  346. package/src/sdk/index.ts +13 -0
  347. package/src/sdk/lifecycle-session.ts +39 -0
  348. package/src/sdk/mcp/index.ts +1 -0
  349. package/src/sdk/mcp/server.ts +332 -0
  350. package/src/sdk/models.ts +168 -0
  351. package/src/sdk/protocol/adapter-validation.ts +48 -0
  352. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  353. package/src/sdk/protocol/operation-registry.ts +312 -0
  354. package/src/{sdk.ts → sdk/session.ts} +339 -212
  355. package/src/sdk/startup-capability.ts +189 -0
  356. package/src/session/agent-session.ts +2470 -866
  357. package/src/session/default-model-selection.ts +93 -0
  358. package/src/session/fallback-chain-controller.ts +136 -0
  359. package/src/session/session-manager.ts +447 -13
  360. package/src/session/session-storage.ts +8 -1
  361. package/src/setup/credential-auto-import.ts +290 -35
  362. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  363. package/src/slash-commands/builtin-registry.ts +33 -30
  364. package/src/task/executor.ts +62 -13
  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/telegram-send.ts +2 -2
  384. package/vendor/insane-search/MANIFEST.json +2 -1
  385. package/vendor/insane-search/engine/bias_check.py +4 -1
  386. package/vendor/insane-search/engine/phase0.py +26 -1
  387. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  388. package/dist/types/modes/bridge/auth.d.ts +0 -12
  389. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  390. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  391. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  392. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  393. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  394. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  395. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  396. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  397. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  398. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  399. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  400. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  401. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  402. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  403. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  404. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  405. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  406. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  407. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  408. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  409. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  410. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  411. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  412. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  413. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  414. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  415. package/dist/types/notifications/config.d.ts +0 -132
  416. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  417. package/src/modes/bridge/auth.ts +0 -41
  418. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  419. package/src/modes/bridge/bridge-mode.ts +0 -675
  420. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  421. package/src/modes/bridge/event-stream.ts +0 -70
  422. package/src/modes/rpc/host-tools.ts +0 -1
  423. package/src/modes/rpc/host-uris.ts +0 -1
  424. package/src/modes/rpc/rpc-client.ts +0 -1166
  425. package/src/modes/rpc/rpc-mode.ts +0 -1029
  426. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  427. package/src/modes/rpc/rpc-types.ts +0 -637
  428. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  429. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  430. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  431. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  432. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  433. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  434. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  435. package/src/modes/shared/agent-wire/responses.ts +0 -17
  436. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  437. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  438. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  439. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  440. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  441. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  442. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  443. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  444. package/src/notifications/config.ts +0 -219
  445. package/src/notifications/index.ts +0 -1835
  446. package/src/notifications/telegram-daemon-cli.ts +0 -243
  447. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  448. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  449. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  450. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  462. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  463. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -0,0 +1,395 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import * as path from "node:path";
3
+ import { readSdkSessionEndpoint, SdkClient } from "../sdk/client";
4
+ import type { HarnessSessionTransport, SessionStateSnapshot } from "./session-transport";
5
+
6
+ const DISCOVERY_TIMEOUT_MS = 10_000;
7
+ const DISCOVERY_POLL_MS = 50;
8
+ const TERM_GRACE_MS = 2_000;
9
+ const KILL_VERIFY_MS = 1_000;
10
+
11
+ export class HarnessSdkTransportError extends Error {
12
+ constructor(
13
+ readonly code: "endpoint_unavailable" | "invalid_response",
14
+ message: string,
15
+ readonly cause?: unknown,
16
+ ) {
17
+ super(message);
18
+ this.name = "HarnessSdkTransportError";
19
+ }
20
+ }
21
+
22
+ export interface SpawnedHarnessSession {
23
+ stop(): Promise<void>;
24
+ }
25
+
26
+ export interface CreateSdkSessionTransportOptions {
27
+ repo: string;
28
+ sessionId: string;
29
+ /** Starts the normal GJC session before discovery. Test callers may provide a deterministic SDK host. */
30
+ spawn?: () => SpawnedHarnessSession | Promise<SpawnedHarnessSession>;
31
+ discoveryTimeoutMs?: number;
32
+ /** Test seam: inject SDK client/endpoint resolution to avoid a process-global module mock. */
33
+ connect?: typeof SdkClient.connect;
34
+ readEndpoint?: (repo: string, sessionId: string) => Promise<{ url: string; token: string } | null>;
35
+ }
36
+
37
+ function invalidResponse(detail: string): never {
38
+ throw new HarnessSdkTransportError("invalid_response", detail);
39
+ }
40
+
41
+ function record(value: unknown, detail = "SDK returned a non-object response."): Record<string, unknown> {
42
+ if (!value || typeof value !== "object" || Array.isArray(value)) invalidResponse(detail);
43
+ return value as Record<string, unknown>;
44
+ }
45
+
46
+ function stringAt(value: Record<string, unknown>, key: string, detail: string): string {
47
+ const candidate = value[key];
48
+ if (typeof candidate !== "string" || candidate.length === 0) invalidResponse(detail);
49
+ return candidate;
50
+ }
51
+
52
+ function nonNegativeIntegerAt(value: Record<string, unknown>, key: string, detail: string): number {
53
+ const candidate = value[key];
54
+ if (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0) invalidResponse(detail);
55
+ return candidate;
56
+ }
57
+
58
+ function queryItem(value: unknown, query: string): Record<string, unknown> {
59
+ const response = record(value, `SDK ${query} response was not an object.`);
60
+ if (response.type !== "query_response" || response.ok !== true || typeof response.id !== "string")
61
+ invalidResponse(`SDK ${query} response had an invalid envelope.`);
62
+ const page = record(response.page, `SDK ${query} response was missing a page.`);
63
+ if (page.complete !== true || typeof page.revision !== "string")
64
+ invalidResponse(`SDK ${query} response had an invalid page.`);
65
+ const items = page.items;
66
+ if (!Array.isArray(items) || items.length !== 1)
67
+ invalidResponse(`SDK ${query} response did not contain exactly one item.`);
68
+ return record(items[0], `SDK ${query} response item was not an object.`);
69
+ }
70
+
71
+ function metadataItem(value: unknown): void {
72
+ const metadata = queryItem(value, "session.metadata");
73
+ for (const key of ["sessionId", "name", "cwd", "kind"])
74
+ stringAt(metadata, key, "SDK session.metadata response was missing required fields.");
75
+ }
76
+
77
+ function contextItem(value: unknown): SessionStateSnapshot {
78
+ const context = queryItem(value, "context.get");
79
+ if (typeof context.isStreaming !== "boolean") invalidResponse("SDK context.get response was missing isStreaming.");
80
+ return {
81
+ isStreaming: context.isStreaming,
82
+ steeringQueueDepth: nonNegativeIntegerAt(
83
+ context,
84
+ "steeringQueueDepth",
85
+ "SDK context.get response had an invalid steeringQueueDepth.",
86
+ ),
87
+ followupQueueDepth: nonNegativeIntegerAt(
88
+ context,
89
+ "followupQueueDepth",
90
+ "SDK context.get response had an invalid followupQueueDepth.",
91
+ ),
92
+ };
93
+ }
94
+
95
+ function replayEvents(value: unknown): Record<string, unknown>[] {
96
+ const response = record(value, "SDK event replay response was not an object.");
97
+ if (response.type !== "event_replay_result" || response.ok !== true || typeof response.id !== "string")
98
+ invalidResponse("SDK event replay response had an invalid envelope.");
99
+ nonNegativeIntegerAt(response, "generation", "SDK event replay response had an invalid generation.");
100
+ nonNegativeIntegerAt(response, "lastSeq", "SDK event replay response had an invalid lastSeq.");
101
+ if (!Array.isArray(response.events)) invalidResponse("SDK event replay response was missing events.");
102
+ return response.events.map(event => record(event, "SDK event replay response contained a malformed event."));
103
+ }
104
+
105
+ function acceptedPrompt(value: unknown): string {
106
+ const response = record(value, "SDK control response was not an object.");
107
+ if (response.type !== "control_response" || response.ok !== true || typeof response.id !== "string")
108
+ invalidResponse("SDK control response had an invalid envelope.");
109
+ const result = record(response.result, "SDK control response was missing a result.");
110
+ // Only a literal accepted:true acknowledges the prompt; false, missing, or
111
+ // any non-boolean value is a contract violation, never a silent acceptance.
112
+ if (result.accepted !== true) invalidResponse("SDK control response did not accept the prompt.");
113
+ return stringAt(result, "commandId", "SDK control response was missing commandId.");
114
+ }
115
+
116
+ function sdkEventToAgentWire(frame: Record<string, unknown>): Record<string, unknown> {
117
+ if (frame.type !== "event") return frame;
118
+ const payload = frame.payload;
119
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) return frame;
120
+ const event = payload as Record<string, unknown>;
121
+ const eventType =
122
+ typeof event.type === "string" ? event.type : typeof event.kind === "string" ? event.kind : undefined;
123
+ return eventType ? { type: "event", payload: { event_type: eventType, event } } : frame;
124
+ }
125
+
126
+ /**
127
+ * Connects an owner to the child session's public SDK endpoint. The SDK client owns
128
+ * hello-gated reconnects; this adapter only owns the bounded discovery wait and child
129
+ * lifecycle.
130
+ */
131
+ export async function createSdkSessionTransport(
132
+ options: CreateSdkSessionTransportOptions,
133
+ ): Promise<HarnessSessionTransport> {
134
+ let child: SpawnedHarnessSession | undefined;
135
+ const readEndpoint = options.readEndpoint ?? readSdkSessionEndpoint;
136
+ let endpoint = await readEndpoint(options.repo, options.sessionId);
137
+ if (!endpoint && options.spawn) child = await options.spawn();
138
+ const timeoutMs = options.discoveryTimeoutMs ?? DISCOVERY_TIMEOUT_MS;
139
+ const deadline = Date.now() + timeoutMs;
140
+ while (!endpoint && Date.now() < deadline) {
141
+ await new Promise(resolve => setTimeout(resolve, DISCOVERY_POLL_MS));
142
+ try {
143
+ endpoint = await readEndpoint(options.repo, options.sessionId);
144
+ } catch (error) {
145
+ // A discovery read that fails after spawn must not orphan the spawned child;
146
+ // await stop before propagating, preserving both causes on dual failure (no double stop).
147
+ try {
148
+ await child?.stop();
149
+ } catch (cleanupError) {
150
+ throw new AggregateError(
151
+ [error, cleanupError],
152
+ "SDK endpoint discovery and spawned harness child cleanup both failed.",
153
+ );
154
+ }
155
+ throw error;
156
+ }
157
+ }
158
+ if (!endpoint) {
159
+ const timeoutError = new HarnessSdkTransportError(
160
+ "endpoint_unavailable",
161
+ `SDK endpoint for harness session ${options.sessionId} did not appear within ${timeoutMs}ms.`,
162
+ );
163
+ try {
164
+ // Await child stop so a discovery timeout never orphans the spawned session.
165
+ await child?.stop();
166
+ } catch (cleanupError) {
167
+ throw new AggregateError(
168
+ [timeoutError, cleanupError],
169
+ "SDK endpoint discovery timed out and spawned harness child cleanup failed.",
170
+ );
171
+ }
172
+ throw timeoutError;
173
+ }
174
+
175
+ let client: SdkClient;
176
+ try {
177
+ client = await (options.connect ?? SdkClient.connect)(endpoint.url, endpoint.token);
178
+ } catch (error) {
179
+ try {
180
+ await child?.stop();
181
+ } catch (cleanupError) {
182
+ throw new AggregateError(
183
+ [error, cleanupError],
184
+ "SDK connection and spawned harness child cleanup both failed.",
185
+ );
186
+ }
187
+ throw error;
188
+ }
189
+ let cursor = 0;
190
+ let lastFrameAt: string | null = null;
191
+ let live = true;
192
+ const frames = new Set<(frame: Record<string, unknown>) => void>();
193
+ client.onFrame(frame => {
194
+ if (frame.type === "hello" || frame.type === "server_hello") return;
195
+ cursor += 1;
196
+ lastFrameAt = new Date().toISOString();
197
+ const normalized = sdkEventToAgentWire(frame);
198
+ for (const listener of frames) listener(normalized);
199
+ });
200
+ client.onReconnectFailed(() => {
201
+ live = false;
202
+ });
203
+
204
+ const replay = async (): Promise<void> => {
205
+ const response = await client.request({
206
+ type: "event_replay",
207
+ id: randomUUID(),
208
+ sinceGeneration: 0,
209
+ sinceSeq: 0,
210
+ });
211
+ for (const event of replayEvents(response)) {
212
+ cursor += 1;
213
+ lastFrameAt = new Date().toISOString();
214
+ const normalized = sdkEventToAgentWire(event);
215
+ for (const listener of frames) listener(normalized);
216
+ }
217
+ };
218
+ try {
219
+ await replay();
220
+ } catch (error) {
221
+ const failures: unknown[] = [error];
222
+ try {
223
+ await client.close();
224
+ } catch (cleanupError) {
225
+ failures.push(cleanupError);
226
+ }
227
+ try {
228
+ await child?.stop();
229
+ } catch (cleanupError) {
230
+ failures.push(cleanupError);
231
+ }
232
+ if (failures.length > 1) throw new AggregateError(failures, "SDK replay and harness child cleanup failed.");
233
+ throw error;
234
+ }
235
+
236
+ return {
237
+ async getState(): Promise<SessionStateSnapshot> {
238
+ const [metadata, context] = await Promise.all([client.query("session.metadata"), client.query("context.get")]);
239
+ metadataItem(metadata);
240
+ return contextItem(context);
241
+ },
242
+ async sendPrompt(prompt: string): Promise<{ commandId: string; ack: boolean }> {
243
+ return {
244
+ commandId: acceptedPrompt(
245
+ await client.control("turn.prompt", { text: prompt }, { idempotencyKey: randomUUID() }),
246
+ ),
247
+ ack: true,
248
+ };
249
+ },
250
+ eventCursor: () => cursor,
251
+ async waitForAgentStart(afterCursor: number, timeout: number): Promise<{ cursor: number } | null> {
252
+ return await new Promise(resolve => {
253
+ const listener = (frame: Record<string, unknown>): void => {
254
+ const payload = frame.payload;
255
+ const event =
256
+ payload && typeof payload === "object" && !Array.isArray(payload)
257
+ ? (payload as Record<string, unknown>)
258
+ : {};
259
+ if (cursor > afterCursor && event.event_type === "agent_start") {
260
+ clearTimeout(timer);
261
+ frames.delete(listener);
262
+ resolve({ cursor });
263
+ }
264
+ };
265
+ frames.add(listener);
266
+ const timer = setTimeout(() => {
267
+ frames.delete(listener);
268
+ resolve(null);
269
+ }, timeout);
270
+ });
271
+ },
272
+ onEventFrame(listener) {
273
+ frames.add(listener);
274
+ return () => frames.delete(listener);
275
+ },
276
+ isLive: () => live,
277
+ lastFrameAt: () => lastFrameAt,
278
+ async getLastAssistantText(): Promise<string | null> {
279
+ const value = queryItem(await client.query("session.last_assistant"), "session.last_assistant");
280
+ return typeof value.text === "string" ? value.text : typeof value.content === "string" ? value.content : null;
281
+ },
282
+ async close(): Promise<void> {
283
+ live = false;
284
+ const failures: unknown[] = [];
285
+ try {
286
+ await client.close();
287
+ } catch (error) {
288
+ failures.push(error);
289
+ }
290
+ try {
291
+ // Await child stop so close never orphans the spawned session.
292
+ await child?.stop();
293
+ } catch (error) {
294
+ failures.push(error);
295
+ }
296
+ if (failures.length > 1)
297
+ throw new AggregateError(failures, "SDK client and harness child cleanup both failed.");
298
+ if (failures.length === 1) throw failures[0];
299
+ },
300
+ };
301
+ }
302
+
303
+ export interface ReapableHarnessChild {
304
+ kill(signal?: number | NodeJS.Signals): void;
305
+ readonly exited: Promise<number>;
306
+ readonly exitCode: number | null;
307
+ }
308
+
309
+ /**
310
+ * Stop an exact spawned child: SIGTERM with bounded grace, SIGKILL escalation, then
311
+ * authoritative `child.exited` verification. A rejected exit promise is NOT proof of exit
312
+ * and therefore fails closed after SIGKILL rather than being mistaken for termination.
313
+ * Failure to verify exit after SIGKILL throws — the caller must not assume the child died.
314
+ */
315
+ async function reapChild(child: ReapableHarnessChild, termGraceMs: number, killVerifyMs: number): Promise<void> {
316
+ const exited = child.exited.then(
317
+ () => true,
318
+ () => false,
319
+ );
320
+ const send = (signal: NodeJS.Signals): void => {
321
+ if (child.exitCode !== null) return;
322
+ try {
323
+ child.kill(signal);
324
+ } catch {
325
+ // Kill may fail if the child already exited; the exited race below is authoritative.
326
+ }
327
+ };
328
+ if (child.exitCode !== null) return;
329
+ send("SIGTERM");
330
+ let verified = await Promise.race([exited, Bun.sleep(termGraceMs).then(() => false)]);
331
+ if (!verified) {
332
+ send("SIGKILL");
333
+ verified = await Promise.race([exited, Bun.sleep(killVerifyMs).then(() => false)]);
334
+ }
335
+ if (!verified) {
336
+ throw new HarnessSdkTransportError("endpoint_unavailable", "Harness child session did not exit after SIGKILL.");
337
+ }
338
+ }
339
+
340
+ function ownedHarnessSession(
341
+ child: ReapableHarnessChild,
342
+ termGraceMs: number,
343
+ killVerifyMs: number,
344
+ ): SpawnedHarnessSession {
345
+ let stopPromise: Promise<void> | null = null;
346
+ return {
347
+ stop(): Promise<void> {
348
+ if (stopPromise) return stopPromise;
349
+ const pending = reapChild(child, termGraceMs, killVerifyMs);
350
+ stopPromise = pending;
351
+ void pending.catch(() => {
352
+ if (stopPromise === pending) stopPromise = null;
353
+ });
354
+ return pending;
355
+ },
356
+ };
357
+ }
358
+
359
+ export function spawnNormalHarnessSession(
360
+ repo: string,
361
+ sessionId: string,
362
+ options: { termGraceMs?: number; killVerifyMs?: number } = {},
363
+ ): SpawnedHarnessSession {
364
+ const entry = process.argv[1];
365
+ if (process.env.GJC_SDK_DISABLE === "1") {
366
+ throw new HarnessSdkTransportError(
367
+ "endpoint_unavailable",
368
+ "SDK hosting is disabled for the harness child session.",
369
+ );
370
+ }
371
+ if (!entry)
372
+ throw new HarnessSdkTransportError(
373
+ "endpoint_unavailable",
374
+ "Cannot determine the GJC CLI entrypoint for harness session startup.",
375
+ );
376
+ const child = Bun.spawn([process.execPath, path.resolve(entry)], {
377
+ cwd: repo,
378
+ env: { ...process.env, GJC_LIFECYCLE_REQUEST_ID: `harness-${sessionId}`, GJC_SESSION_ID: sessionId },
379
+ terminal: { cols: 80, rows: 24 },
380
+ stdout: "ignore",
381
+ stderr: "ignore",
382
+ });
383
+ child.unref();
384
+ const termGraceMs = options.termGraceMs ?? TERM_GRACE_MS;
385
+ const killVerifyMs = options.killVerifyMs ?? KILL_VERIFY_MS;
386
+ return ownedHarnessSession(child, termGraceMs, killVerifyMs);
387
+ }
388
+
389
+ /** Test hook for exact-child stop serialization and retry semantics. */
390
+ export function ownedHarnessSessionForTest(
391
+ child: ReapableHarnessChild,
392
+ options: { termGraceMs?: number; killVerifyMs?: number } = {},
393
+ ): SpawnedHarnessSession {
394
+ return ownedHarnessSession(child, options.termGraceMs ?? TERM_GRACE_MS, options.killVerifyMs ?? KILL_VERIFY_MS);
395
+ }
@@ -0,0 +1,94 @@
1
+ export interface SessionStateSnapshot {
2
+ isStreaming: boolean;
3
+ steeringQueueDepth: number;
4
+ followupQueueDepth: number;
5
+ }
6
+
7
+ export interface HarnessSessionTransportCloseContext {
8
+ /**
9
+ * Immediate cycle-break acknowledgment for the exact direct close path.
10
+ *
11
+ * Invoke this method synchronously before an async close() reaches its first await
12
+ * (or before a non-async close() returns its promise); the returned promise may be
13
+ * awaited later. It does NOT signal that RuntimeOwner teardown has completed.
14
+ */
15
+ acknowledgeDirectOwnerStopReentry(): Promise<void>;
16
+ }
17
+
18
+ /** SDK-backed transport contract for a live harness session. */
19
+ export interface HarnessSessionTransport {
20
+ getState(): Promise<SessionStateSnapshot>;
21
+ sendPrompt(prompt: string): Promise<{ commandId: string; ack: boolean }>;
22
+ eventCursor(): number;
23
+ waitForAgentStart(afterCursor: number, timeoutMs: number): Promise<{ cursor: number } | null>;
24
+ /**
25
+ * Await every transport-owned cleanup step. close() MUST NOT call public
26
+ * RuntimeOwner.stop(), which would circularly await this close and hang. A transport
27
+ * that needs that direct cycle break must synchronously invoke
28
+ * `context.acknowledgeDirectOwnerStopReentry()` before its first await.
29
+ */
30
+ close(context?: HarnessSessionTransportCloseContext): Promise<void>;
31
+ /** Return a synchronous disposer that fully severs this event subscription. */
32
+ onEventFrame?(listener: (frame: Record<string, unknown>) => void): () => void;
33
+ isLive?(): boolean;
34
+ lastFrameAt?(): string | null;
35
+ getLastAssistantText?(): Promise<string | null>;
36
+ }
37
+
38
+ export interface AcceptanceResult {
39
+ accepted: boolean;
40
+ reason: string;
41
+ commandId: string | null;
42
+ preSubmitCursor: number;
43
+ agentStartCursor: number | null;
44
+ preSubmitState: SessionStateSnapshot;
45
+ }
46
+
47
+ export async function singleFlightAccept(
48
+ transport: HarnessSessionTransport,
49
+ prompt: string,
50
+ timeoutMs: number,
51
+ ): Promise<AcceptanceResult> {
52
+ const pre = await transport.getState();
53
+ const preSubmitCursor = transport.eventCursor();
54
+ if (pre.isStreaming || pre.steeringQueueDepth > 0 || pre.followupQueueDepth > 0) {
55
+ return {
56
+ accepted: false,
57
+ reason: "pre-state-not-idle",
58
+ commandId: null,
59
+ preSubmitCursor,
60
+ agentStartCursor: null,
61
+ preSubmitState: pre,
62
+ };
63
+ }
64
+ const { commandId, ack } = await transport.sendPrompt(prompt);
65
+ if (!ack) {
66
+ return {
67
+ accepted: false,
68
+ reason: "no-ack",
69
+ commandId,
70
+ preSubmitCursor,
71
+ agentStartCursor: null,
72
+ preSubmitState: pre,
73
+ };
74
+ }
75
+ const started = await transport.waitForAgentStart(preSubmitCursor, timeoutMs);
76
+ if (!started) {
77
+ return {
78
+ accepted: false,
79
+ reason: "no-agent-start-within-timeout",
80
+ commandId,
81
+ preSubmitCursor,
82
+ agentStartCursor: null,
83
+ preSubmitState: pre,
84
+ };
85
+ }
86
+ return {
87
+ accepted: true,
88
+ reason: "protocol-ack-single-flight",
89
+ commandId,
90
+ preSubmitCursor,
91
+ agentStartCursor: started.cursor,
92
+ preSubmitState: pre,
93
+ };
94
+ }
@@ -155,7 +155,7 @@ export interface SessionHandle {
155
155
  base: string | null;
156
156
  issueOrPr: string | null;
157
157
  processHandle: { kind: "runtime-owner"; ownerId: string | null; pid: number | null };
158
- rpcHandle: { kind: "rpc-subprocess"; pid: number | null; sessionDir: string };
158
+ sdkHandle: { kind: "sdk-session-endpoint"; sessionId: string };
159
159
  ownerHandle: { leasePath: string; endpoint: string | null; heartbeatAt: string | null };
160
160
  routerHandle: { kind: "default-in-owner"; policy: string; eventsPath: string };
161
161
  viewportHandle: { kind: "event-monitor"; tmuxSessionName: string | null; viewOnly: true };