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