@gajae-code/coding-agent 0.10.2 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (476) hide show
  1. package/CHANGELOG.md +58 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/async/job-manager.d.ts +46 -7
  4. package/dist/types/cli/args.d.ts +4 -5
  5. package/dist/types/cli/daemon-cli.d.ts +12 -1
  6. package/dist/types/cli/notify-cli.d.ts +21 -1
  7. package/dist/types/cli.d.ts +3 -0
  8. package/dist/types/commands/daemon.d.ts +39 -0
  9. package/dist/types/commands/launch.d.ts +3 -0
  10. package/dist/types/commands/notify.d.ts +28 -1
  11. package/dist/types/commands/sdk.d.ts +33 -0
  12. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  13. package/dist/types/config/model-profile-activation.d.ts +35 -15
  14. package/dist/types/config/model-profiles.d.ts +11 -5
  15. package/dist/types/config/model-registry.d.ts +3 -3
  16. package/dist/types/config/model-resolver.d.ts +39 -6
  17. package/dist/types/config/model-selector-value.d.ts +17 -0
  18. package/dist/types/config/models-config-schema.d.ts +10 -6
  19. package/dist/types/config/settings-schema.d.ts +133 -6
  20. package/dist/types/config/settings.d.ts +63 -35
  21. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  22. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  23. package/dist/types/daemon/builtin.d.ts +6 -5
  24. package/dist/types/daemon/control-types.d.ts +1 -1
  25. package/dist/types/discovery/mcp-json.d.ts +12 -1
  26. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  27. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  28. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  29. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  31. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  32. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  33. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  34. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  35. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  36. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  37. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  38. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  39. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
  40. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  41. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  42. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  43. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  44. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  45. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  46. package/dist/types/harness-control-plane/types.d.ts +3 -4
  47. package/dist/types/lsp/index.d.ts +1 -1
  48. package/dist/types/main.d.ts +32 -38
  49. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  50. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  51. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  52. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  53. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  54. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  55. package/dist/types/modes/components/model-selector.d.ts +1 -0
  56. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  57. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  58. package/dist/types/modes/components/welcome.d.ts +1 -1
  59. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  60. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  61. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  62. package/dist/types/modes/index.d.ts +0 -4
  63. package/dist/types/modes/interactive-mode.d.ts +5 -2
  64. package/dist/types/modes/runtime-init.d.ts +2 -2
  65. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  66. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  67. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  68. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  69. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  72. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  73. package/dist/types/modes/types.d.ts +7 -2
  74. package/dist/types/runtime-mcp/client.d.ts +2 -0
  75. package/dist/types/runtime-mcp/config.d.ts +5 -1
  76. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  77. package/dist/types/runtime-mcp/types.d.ts +4 -0
  78. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  79. package/dist/types/sdk/acp/index.d.ts +2 -0
  80. package/dist/types/sdk/broker/broker.d.ts +53 -0
  81. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  82. package/dist/types/sdk/broker/ensure.d.ts +42 -0
  83. package/dist/types/sdk/broker/identity.d.ts +3 -0
  84. package/dist/types/sdk/broker/index.d.ts +8 -0
  85. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  86. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  87. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  88. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  89. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  90. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  91. package/dist/types/sdk/broker/transport.d.ts +9 -0
  92. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  93. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  94. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  95. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  96. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  97. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  98. package/dist/types/sdk/bus/config.d.ts +274 -0
  99. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  100. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  101. package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
  102. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  103. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  104. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  105. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  107. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  108. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  109. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  110. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  111. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  112. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  113. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  114. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  115. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  116. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  117. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  118. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  119. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  121. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
  122. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  123. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  124. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  125. package/dist/types/sdk/cli/index.d.ts +1 -0
  126. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  127. package/dist/types/sdk/client/client.d.ts +1 -0
  128. package/dist/types/sdk/client/discovery.d.ts +27 -0
  129. package/dist/types/sdk/client/index.d.ts +2 -0
  130. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  131. package/dist/types/sdk/host/control/index.d.ts +2 -0
  132. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  133. package/dist/types/sdk/host/events.d.ts +35 -0
  134. package/dist/types/sdk/host/host.d.ts +35 -0
  135. package/dist/types/sdk/host/index.d.ts +4 -0
  136. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  137. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  138. package/dist/types/sdk/host/query/index.d.ts +3 -0
  139. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  140. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  141. package/dist/types/sdk/host/types.d.ts +32 -0
  142. package/dist/types/sdk/index.d.ts +6 -0
  143. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  144. package/dist/types/sdk/mcp/index.d.ts +1 -0
  145. package/dist/types/sdk/mcp/server.d.ts +37 -0
  146. package/dist/types/sdk/models.d.ts +44 -0
  147. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  148. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  149. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  150. package/dist/types/sdk/startup-capability.d.ts +50 -0
  151. package/dist/types/session/agent-session.d.ts +114 -21
  152. package/dist/types/session/default-model-selection.d.ts +25 -0
  153. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  154. package/dist/types/session/session-manager.d.ts +58 -1
  155. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  156. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  157. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  158. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  159. package/dist/types/tools/browser/launch.d.ts +22 -0
  160. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  161. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  162. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  163. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  164. package/dist/types/tools/browser/registry.d.ts +19 -0
  165. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  166. package/dist/types/tools/index.d.ts +8 -8
  167. package/dist/types/tools/subagent-render.d.ts +1 -0
  168. package/dist/types/tools/subagent.d.ts +6 -1
  169. package/package.json +34 -13
  170. package/scripts/build-sdk-package-smoke.ts +99 -0
  171. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  172. package/scripts/compile-args.ts +4 -2
  173. package/scripts/g005-daemon-smoke.ts +4 -5
  174. package/scripts/g011-daemon-path-smoke.ts +5 -5
  175. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  176. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  177. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  178. package/scripts/manifest-schema.ts +124 -0
  179. package/scripts/run-test-manifest.ts +153 -0
  180. package/scripts/run-threat-model-check.ts +157 -0
  181. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  182. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  183. package/src/append-only-mode.ts +1 -1
  184. package/src/async/job-manager.ts +406 -63
  185. package/src/cli/args.ts +43 -12
  186. package/src/cli/auth-gateway-cli.ts +2 -2
  187. package/src/cli/config-cli.ts +2 -1
  188. package/src/cli/daemon-cli.ts +63 -14
  189. package/src/cli/list-models.ts +1 -1
  190. package/src/cli/notify-cli.ts +288 -286
  191. package/src/cli.ts +21 -2
  192. package/src/commands/daemon.ts +50 -6
  193. package/src/commands/harness.ts +93 -36
  194. package/src/commands/launch.ts +5 -2
  195. package/src/commands/mcp-serve.ts +19 -12
  196. package/src/commands/notify.ts +36 -3
  197. package/src/commands/sdk.ts +426 -0
  198. package/src/commit/agentic/agent.ts +1 -0
  199. package/src/config/atomic-yaml-patch.ts +423 -0
  200. package/src/config/model-profile-activation.ts +240 -89
  201. package/src/config/model-profiles.ts +18 -15
  202. package/src/config/model-registry.ts +51 -26
  203. package/src/config/model-resolver.ts +138 -51
  204. package/src/config/model-selector-value.ts +50 -0
  205. package/src/config/models-config-schema.ts +14 -21
  206. package/src/config/settings-schema.ts +128 -10
  207. package/src/config/settings.ts +1120 -158
  208. package/src/coordinator-mcp/model-preset.ts +74 -20
  209. package/src/coordinator-mcp/server.ts +1597 -3052
  210. package/src/daemon/builtin.ts +8 -5
  211. package/src/daemon/control-types.ts +1 -1
  212. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  213. package/src/discovery/mcp-json.ts +327 -20
  214. package/src/extensibility/custom-tools/types.ts +1 -1
  215. package/src/extensibility/extensions/compact-handler.ts +3 -3
  216. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  217. package/src/extensibility/extensions/loader.ts +69 -5
  218. package/src/extensibility/extensions/runner.ts +112 -4
  219. package/src/extensibility/extensions/types.ts +176 -17
  220. package/src/extensibility/hooks/types.ts +1 -1
  221. package/src/gjc-runtime/launch-tmux.ts +170 -86
  222. package/src/gjc-runtime/psmux-detect.ts +82 -4
  223. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  224. package/src/gjc-runtime/team-runtime.ts +54 -35
  225. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  226. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  227. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  228. package/src/gjc-runtime/ultragoal-guard.ts +108 -14
  229. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  230. package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
  231. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  232. package/src/harness-control-plane/operate.ts +9 -9
  233. package/src/harness-control-plane/owner.ts +283 -39
  234. package/src/harness-control-plane/receipts.ts +0 -1
  235. package/src/harness-control-plane/sdk-transport.ts +395 -0
  236. package/src/harness-control-plane/session-transport.ts +94 -0
  237. package/src/harness-control-plane/types.ts +1 -1
  238. package/src/internal-urls/docs-index.generated.ts +34 -35
  239. package/src/lsp/client.ts +42 -6
  240. package/src/lsp/index.ts +2 -2
  241. package/src/main.ts +299 -204
  242. package/src/modes/DESIGN.md +258 -0
  243. package/src/modes/acp/acp-agent.ts +1228 -2612
  244. package/src/modes/acp/acp-client-bridge.ts +2 -20
  245. package/src/modes/acp/acp-event-mapper.ts +18 -2
  246. package/src/modes/acp/acp-mode.ts +8 -36
  247. package/src/modes/acp/permission-mode.ts +25 -0
  248. package/src/modes/acp/startup-options.ts +6 -0
  249. package/src/modes/components/agent-dashboard.ts +37 -17
  250. package/src/modes/components/model-selector.ts +93 -35
  251. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  252. package/src/modes/components/settings-selector.ts +60 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +10 -17
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +396 -28
  257. package/src/modes/controllers/selector-controller.ts +674 -36
  258. package/src/modes/index.ts +0 -22
  259. package/src/modes/interactive-mode.ts +87 -36
  260. package/src/modes/runtime-init.ts +298 -6
  261. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  262. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  263. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  264. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  265. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  266. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
  267. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  268. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  269. package/src/modes/types.ts +7 -2
  270. package/src/runtime-mcp/client.ts +94 -19
  271. package/src/runtime-mcp/config.ts +27 -15
  272. package/src/runtime-mcp/manager.ts +343 -105
  273. package/src/runtime-mcp/oauth-flow.ts +42 -12
  274. package/src/runtime-mcp/transports/http.ts +49 -19
  275. package/src/runtime-mcp/transports/stdio.ts +47 -28
  276. package/src/runtime-mcp/types.ts +10 -0
  277. package/src/sdk/acp/adapter.ts +418 -0
  278. package/src/sdk/acp/index.ts +2 -0
  279. package/src/sdk/broker/broker.ts +642 -0
  280. package/src/sdk/broker/discovery.ts +113 -0
  281. package/src/sdk/broker/ensure.ts +307 -0
  282. package/src/sdk/broker/identity.ts +42 -0
  283. package/src/sdk/broker/index.ts +8 -0
  284. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  285. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  286. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  287. package/src/sdk/broker/lifecycle.ts +2157 -0
  288. package/src/sdk/broker/process-incarnation.ts +159 -0
  289. package/src/sdk/broker/runtime.ts +164 -0
  290. package/src/sdk/broker/session-index.ts +318 -0
  291. package/src/sdk/broker/state-version.ts +23 -0
  292. package/src/sdk/broker/transport.ts +125 -0
  293. package/src/sdk/bus/chat-command-policy.ts +107 -0
  294. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  295. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  296. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  297. package/src/sdk/bus/chat-effect-journal.ts +355 -0
  298. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  299. package/src/sdk/bus/config.ts +433 -0
  300. package/src/sdk/bus/conversation-store.ts +391 -0
  301. package/src/sdk/bus/discord-conversation.ts +85 -0
  302. package/src/sdk/bus/discord-daemon.ts +2292 -0
  303. package/src/sdk/bus/discord-live-provider.ts +521 -0
  304. package/src/sdk/bus/discord-provider.ts +56 -0
  305. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  306. package/src/sdk/bus/index.ts +3979 -0
  307. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  309. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  310. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  311. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  312. package/src/sdk/bus/natives-augment.d.ts +38 -0
  313. package/src/sdk/bus/notification-orchestration.ts +535 -0
  314. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  315. package/src/sdk/bus/session-control.ts +333 -0
  316. package/src/sdk/bus/slack-conversation.ts +74 -0
  317. package/src/sdk/bus/slack-daemon.ts +2144 -0
  318. package/src/sdk/bus/slack-live-provider.ts +380 -0
  319. package/src/sdk/bus/slack-provider.ts +76 -0
  320. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  321. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  322. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  323. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  324. package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
  325. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  326. package/src/sdk/bus/telegram-setup.ts +663 -0
  327. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  328. package/src/sdk/cli/index.ts +1 -0
  329. package/src/sdk/cli/session-cli.ts +275 -0
  330. package/src/sdk/client/client.ts +1 -0
  331. package/src/sdk/client/discovery.ts +108 -0
  332. package/src/sdk/client/index.ts +2 -0
  333. package/src/sdk/host/control/dispatch.ts +367 -0
  334. package/src/sdk/host/control/index.ts +10 -0
  335. package/src/sdk/host/control/operations.ts +63 -0
  336. package/src/sdk/host/events.ts +91 -0
  337. package/src/sdk/host/host.ts +296 -0
  338. package/src/sdk/host/index.ts +4 -0
  339. package/src/sdk/host/query/cursor.ts +189 -0
  340. package/src/sdk/host/query/handlers.ts +533 -0
  341. package/src/sdk/host/query/index.ts +3 -0
  342. package/src/sdk/host/query/revision-store.ts +1126 -0
  343. package/src/sdk/host/reverse-leases.ts +325 -0
  344. package/src/sdk/host/types.ts +29 -0
  345. package/src/sdk/index.ts +13 -0
  346. package/src/sdk/lifecycle-session.ts +39 -0
  347. package/src/sdk/mcp/index.ts +1 -0
  348. package/src/sdk/mcp/server.ts +332 -0
  349. package/src/sdk/models.ts +168 -0
  350. package/src/sdk/protocol/adapter-validation.ts +48 -0
  351. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  352. package/src/sdk/protocol/operation-registry.ts +312 -0
  353. package/src/{sdk.ts → sdk/session.ts} +339 -212
  354. package/src/sdk/startup-capability.ts +189 -0
  355. package/src/session/agent-session.ts +2650 -944
  356. package/src/session/default-model-selection.ts +93 -0
  357. package/src/session/fallback-chain-controller.ts +136 -0
  358. package/src/session/session-manager.ts +438 -11
  359. package/src/session/session-storage.ts +8 -1
  360. package/src/setup/credential-auto-import.ts +290 -35
  361. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  362. package/src/slash-commands/builtin-registry.ts +2 -1
  363. package/src/task/executor.ts +62 -13
  364. package/src/task/index.ts +26 -16
  365. package/src/tools/ask-answer-registry.ts +1 -1
  366. package/src/tools/ask.ts +13 -8
  367. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  368. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  369. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  370. package/src/tools/browser/launch.ts +124 -19
  371. package/src/tools/browser/profile-discovery.ts +63 -0
  372. package/src/tools/browser/profile-posture.ts +59 -0
  373. package/src/tools/browser/profile-reuse.ts +102 -0
  374. package/src/tools/browser/profile-warmup.ts +109 -0
  375. package/src/tools/browser/registry.ts +87 -11
  376. package/src/tools/browser/tab-protocol.ts +1 -0
  377. package/src/tools/browser/tab-supervisor.ts +1 -0
  378. package/src/tools/browser/tab-worker.ts +1 -1
  379. package/src/tools/browser.ts +6 -0
  380. package/src/tools/index.ts +8 -8
  381. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  382. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  383. package/src/tools/subagent-render.ts +19 -8
  384. package/src/tools/subagent.ts +84 -32
  385. package/src/tools/telegram-send.ts +2 -2
  386. package/vendor/insane-search/MANIFEST.json +2 -1
  387. package/vendor/insane-search/engine/bias_check.py +4 -1
  388. package/vendor/insane-search/engine/phase0.py +26 -1
  389. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  390. package/dist/types/modes/bridge/auth.d.ts +0 -12
  391. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  392. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  393. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  394. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  395. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  396. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  397. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  398. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  399. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  400. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  401. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  402. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  403. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  404. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  405. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  406. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  407. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  408. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  409. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  410. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  411. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  412. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  413. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  414. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  415. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  416. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  417. package/dist/types/notifications/config.d.ts +0 -132
  418. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  419. package/src/modes/bridge/auth.ts +0 -41
  420. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  421. package/src/modes/bridge/bridge-mode.ts +0 -675
  422. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  423. package/src/modes/bridge/event-stream.ts +0 -70
  424. package/src/modes/rpc/host-tools.ts +0 -1
  425. package/src/modes/rpc/host-uris.ts +0 -1
  426. package/src/modes/rpc/rpc-client.ts +0 -1166
  427. package/src/modes/rpc/rpc-mode.ts +0 -1029
  428. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  429. package/src/modes/rpc/rpc-types.ts +0 -637
  430. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  431. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  432. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  433. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  434. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  435. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  436. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  437. package/src/modes/shared/agent-wire/responses.ts +0 -17
  438. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  439. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  440. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  441. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  442. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  443. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  444. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  445. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  446. package/src/notifications/config.ts +0 -219
  447. package/src/notifications/index.ts +0 -1835
  448. package/src/notifications/telegram-daemon-cli.ts +0 -243
  449. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  450. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  462. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  463. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  475. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  476. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -0,0 +1,391 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { randomUUID } from "node:crypto";
3
+ import { readFileSync } from "node:fs";
4
+ import * as fs from "node:fs/promises";
5
+ import * as path from "node:path";
6
+
7
+ export const CONVERSATION_STORE_VERSION = 1;
8
+ export const MAX_DEDUPE_IDS = 128;
9
+
10
+ export interface ConversationRecord {
11
+ generation: number;
12
+ }
13
+
14
+ export interface ConversationStoreDocument<T extends ConversationRecord> {
15
+ version: typeof CONVERSATION_STORE_VERSION;
16
+ conversations: Record<string, T>;
17
+ }
18
+
19
+ export interface ConversationStoreFileHandle {
20
+ sync(): Promise<void>;
21
+ close(): Promise<void>;
22
+ writeFile(data: string, encoding: "utf8"): Promise<void>;
23
+ }
24
+
25
+ /** Minimal persistence seam; callers can inject it to make durability failures deterministic. */
26
+ export interface ConversationStoreFs {
27
+ mkdir(directory: string, options: { recursive: true; mode: number }): Promise<unknown>;
28
+ chmod(target: string, mode: number): Promise<void>;
29
+ readFile(file: string, encoding: "utf8"): Promise<string>;
30
+ writeFile(file: string, data: string, options: { mode: number }): Promise<void>;
31
+ rename(from: string, to: string): Promise<void>;
32
+ unlink(file: string): Promise<void>;
33
+ open(file: string, flags: string): Promise<ConversationStoreFileHandle>;
34
+ stat?(file: string): Promise<{ mtimeMs: number }>;
35
+ }
36
+
37
+ export class ConversationLockTimeoutError extends Error {
38
+ constructor(
39
+ readonly lockFile: string,
40
+ readonly timeoutMs: number,
41
+ ) {
42
+ super(`Timed out waiting ${timeoutMs}ms for conversation store lock: ${lockFile}`);
43
+ this.name = "ConversationLockTimeoutError";
44
+ }
45
+ }
46
+
47
+ interface ConversationStoreLock {
48
+ pid: number;
49
+ incarnation: string;
50
+ timestamp: number;
51
+ }
52
+
53
+ const nodeFs: ConversationStoreFs = fs;
54
+ const UNPUBLISHED_LOCK_STALE_MS = 30_000;
55
+
56
+ export function conversationStorePath(agentDir: string, kind: string, fileName = "conversations.json"): string {
57
+ return path.join(agentDir, "sdk", "daemons", kind, fileName);
58
+ }
59
+
60
+ export function boundedDedupe(ids: readonly string[], limit = MAX_DEDUPE_IDS): string[] {
61
+ const unique: string[] = [];
62
+ const seen = new Set<string>();
63
+ for (const id of ids) {
64
+ if (!id || seen.has(id)) continue;
65
+ seen.add(id);
66
+ unique.push(id);
67
+ }
68
+ return unique.length <= limit ? unique : unique.slice(unique.length - limit);
69
+ }
70
+
71
+ function emptyDocument<T extends ConversationRecord>(): ConversationStoreDocument<T> {
72
+ return { version: CONVERSATION_STORE_VERSION, conversations: {} };
73
+ }
74
+
75
+ function isRecord(value: unknown): value is Record<string, unknown> {
76
+ return typeof value === "object" && value !== null && !Array.isArray(value);
77
+ }
78
+
79
+ /**
80
+ * Durable, per-transport mapping store. Every mutation takes an exclusive
81
+ * lock file shared across processes and reloads the on-disk document before
82
+ * applying its monotonic-generation compare-and-swap, preventing either stale
83
+ * writers or unrelated-key updates from replacing newer mappings.
84
+ */
85
+ export class ConversationStore<T extends ConversationRecord> {
86
+ readonly #directory: string;
87
+ readonly #file: string;
88
+ readonly #fs: ConversationStoreFs;
89
+ readonly #clock: () => number;
90
+ readonly #locks = new Map<string, Promise<void>>();
91
+ readonly #pid: number;
92
+ readonly #pidIncarnation: (pid: number) => string | undefined;
93
+ readonly #pidAlive: (pid: number) => boolean;
94
+ readonly #sleep: (ms: number) => Promise<void>;
95
+ readonly #lockTimeoutMs: number;
96
+
97
+ constructor(input: {
98
+ agentDir: string;
99
+ kind: string;
100
+ fileName?: string;
101
+ fs?: ConversationStoreFs;
102
+ now?: () => number;
103
+ pid?: number;
104
+ pidIncarnation?: (pid: number) => string | undefined;
105
+ pidAlive?: (pid: number) => boolean;
106
+ sleep?: (ms: number) => Promise<void>;
107
+ lockTimeoutMs?: number;
108
+ }) {
109
+ this.#file = conversationStorePath(input.agentDir, input.kind, input.fileName);
110
+ this.#directory = path.dirname(this.#file);
111
+ this.#fs = input.fs ?? nodeFs;
112
+ this.#clock = input.now ?? Date.now;
113
+ this.#pid = input.pid ?? process.pid;
114
+ this.#pidIncarnation = input.pidIncarnation ?? defaultPidIncarnation;
115
+ this.#pidAlive = input.pidAlive ?? defaultPidAlive;
116
+ this.#sleep = input.sleep ?? (async ms => await Bun.sleep(ms));
117
+ this.#lockTimeoutMs = input.lockTimeoutMs ?? 1_000;
118
+ }
119
+
120
+ get filePath(): string {
121
+ return this.#file;
122
+ }
123
+
124
+ async load(): Promise<ConversationStoreDocument<T>> {
125
+ return this.#readDocument();
126
+ }
127
+
128
+ async read(key: string): Promise<T | undefined> {
129
+ return (await this.#readDocument()).conversations[key];
130
+ }
131
+
132
+ /**
133
+ * Atomically write one mapping when its observed generation still matches.
134
+ * `undefined` only creates an absent mapping; successful writes must advance
135
+ * the generation by exactly one.
136
+ */
137
+ async write(key: string, expectedGeneration: number | undefined, record: T): Promise<boolean> {
138
+ return this.#withLock(async () => {
139
+ const document = await this.#readDocument();
140
+ const current = document.conversations[key];
141
+ if (current?.generation !== expectedGeneration) return false;
142
+ if (!current && expectedGeneration !== undefined) return false;
143
+ const nextGeneration = (expectedGeneration ?? 0) + 1;
144
+ if (record.generation !== nextGeneration) {
145
+ throw new Error(`Conversation generation must advance to ${nextGeneration}`);
146
+ }
147
+ document.conversations[key] = record;
148
+ await this.#persist(document);
149
+ return true;
150
+ });
151
+ }
152
+ async delete(key: string, expectedGeneration: number): Promise<boolean> {
153
+ return this.#withLock(async () => {
154
+ const document = await this.#readDocument();
155
+ const current = document.conversations[key];
156
+ if (!current || current.generation !== expectedGeneration) return false;
157
+ delete document.conversations[key];
158
+ await this.#persist(document);
159
+ return true;
160
+ });
161
+ }
162
+
163
+ /** Apply a synchronous update under the mapping lock, retrying no stale state. */
164
+ async transact(key: string, update: (current: T | undefined) => T | undefined): Promise<T | undefined> {
165
+ return this.#withLock(async () => {
166
+ const document = await this.#readDocument();
167
+ const current = document.conversations[key];
168
+ const next = update(current);
169
+ if (!next || next === current) return current;
170
+ const expectedGeneration = current?.generation;
171
+ const expectedNext = (expectedGeneration ?? 0) + 1;
172
+ if (next.generation !== expectedNext) {
173
+ throw new Error(`Conversation generation must advance to ${expectedNext}`);
174
+ }
175
+ document.conversations[key] = next;
176
+ await this.#persist(document);
177
+ return next;
178
+ });
179
+ }
180
+
181
+ async #withLock<R>(operation: () => Promise<R>): Promise<R> {
182
+ const previous = this.#locks.get(this.#file) ?? Promise.resolve();
183
+ const gate = Promise.withResolvers<void>();
184
+ const tail = previous.then(() => gate.promise);
185
+ this.#locks.set(this.#file, tail);
186
+ await previous;
187
+ let fileLock: ConversationStoreFileHandle | undefined;
188
+ try {
189
+ fileLock = await this.#acquireFileLock();
190
+ return await operation();
191
+ } finally {
192
+ try {
193
+ await fileLock?.close();
194
+ if (fileLock)
195
+ await this.#fs.unlink(`${this.#file}.lock`).catch(error => {
196
+ if (!isMissing(error)) throw error;
197
+ });
198
+ } finally {
199
+ gate.resolve();
200
+ if (this.#locks.get(this.#file) === tail) this.#locks.delete(this.#file);
201
+ }
202
+ }
203
+ }
204
+
205
+ async #acquireFileLock(): Promise<ConversationStoreFileHandle> {
206
+ const lockFile = `${this.#file}.lock`;
207
+ const deadline = Date.now() + this.#lockTimeoutMs;
208
+ await this.#fs.mkdir(this.#directory, { recursive: true, mode: 0o700 });
209
+ for (;;) {
210
+ try {
211
+ const handle = await this.#fs.open(lockFile, "wx");
212
+ try {
213
+ const lock: ConversationStoreLock = {
214
+ pid: this.#pid,
215
+ incarnation: this.#pidIncarnation(this.#pid) ?? "unavailable",
216
+ timestamp: this.#clock(),
217
+ };
218
+ await handle.writeFile(`${JSON.stringify(lock)}\n`, "utf8");
219
+ await handle.sync();
220
+ return handle;
221
+ } catch (error) {
222
+ await handle.close().catch(() => undefined);
223
+ await this.#fs.unlink(lockFile).catch(() => undefined);
224
+ throw error;
225
+ }
226
+ } catch (error) {
227
+ if (!isAlreadyExists(error)) throw error;
228
+ if (await this.#reclaimStaleLock(lockFile)) continue;
229
+ if (Date.now() >= deadline) throw new ConversationLockTimeoutError(lockFile, this.#lockTimeoutMs);
230
+ await this.#sleep(Math.min(10, Math.max(1, deadline - Date.now())));
231
+ }
232
+ }
233
+ }
234
+
235
+ async #reclaimStaleLock(lockFile: string): Promise<boolean> {
236
+ if (!(await this.#isStaleLock(lockFile))) return false;
237
+ const reclaimFile = `${lockFile}.reclaim`;
238
+ const reclaimLock = await this.#acquireReclaimLock(reclaimFile);
239
+ if (!reclaimLock) return false;
240
+ try {
241
+ if (!(await this.#isStaleLock(lockFile))) return false;
242
+ await this.#fs.unlink(lockFile).catch(() => undefined);
243
+ return true;
244
+ } finally {
245
+ await reclaimLock.close().catch(() => undefined);
246
+ await this.#fs.unlink(reclaimFile).catch(() => undefined);
247
+ }
248
+ }
249
+ async #acquireReclaimLock(reclaimFile: string): Promise<ConversationStoreFileHandle | undefined> {
250
+ try {
251
+ return await this.#createLockFile(reclaimFile);
252
+ } catch (error) {
253
+ if (!isAlreadyExists(error) || !(await this.#isStaleLock(reclaimFile))) return undefined;
254
+ await this.#fs.unlink(reclaimFile).catch(() => undefined);
255
+ try {
256
+ return await this.#createLockFile(reclaimFile);
257
+ } catch (retryError) {
258
+ if (isAlreadyExists(retryError)) return undefined;
259
+ throw retryError;
260
+ }
261
+ }
262
+ }
263
+ async #createLockFile(lockFile: string): Promise<ConversationStoreFileHandle> {
264
+ const handle = await this.#fs.open(lockFile, "wx");
265
+ try {
266
+ const lock: ConversationStoreLock = {
267
+ pid: this.#pid,
268
+ incarnation: this.#pidIncarnation(this.#pid) ?? "unavailable",
269
+ timestamp: this.#clock(),
270
+ };
271
+ await handle.writeFile(`${JSON.stringify(lock)}\n`, "utf8");
272
+ await handle.sync();
273
+ return handle;
274
+ } catch (error) {
275
+ await handle.close().catch(() => undefined);
276
+ await this.#fs.unlink(lockFile).catch(() => undefined);
277
+ throw error;
278
+ }
279
+ }
280
+ async #isStaleLock(lockFile: string): Promise<boolean> {
281
+ let parsed: unknown;
282
+ try {
283
+ parsed = JSON.parse(await this.#fs.readFile(lockFile, "utf8"));
284
+ } catch (error) {
285
+ if (isMissing(error)) return true;
286
+ return await this.#isExpiredUnpublishedLock(lockFile);
287
+ }
288
+ if (!isConversationStoreLock(parsed)) return await this.#isExpiredUnpublishedLock(lockFile);
289
+ const currentIncarnation = this.#pidIncarnation(parsed.pid);
290
+ return (
291
+ !this.#pidAlive(parsed.pid) ||
292
+ (currentIncarnation !== undefined &&
293
+ parsed.incarnation !== "unavailable" &&
294
+ currentIncarnation !== parsed.incarnation)
295
+ );
296
+ }
297
+ async #isExpiredUnpublishedLock(lockFile: string): Promise<boolean> {
298
+ const stat = this.#fs.stat ? await this.#fs.stat(lockFile).catch(() => undefined) : undefined;
299
+ return Boolean(stat && this.#clock() - stat.mtimeMs >= UNPUBLISHED_LOCK_STALE_MS);
300
+ }
301
+
302
+ async #readDocument(): Promise<ConversationStoreDocument<T>> {
303
+ try {
304
+ const parsed: unknown = JSON.parse(await this.#fs.readFile(this.#file, "utf8"));
305
+ if (!isRecord(parsed) || parsed.version !== CONVERSATION_STORE_VERSION || !isRecord(parsed.conversations)) {
306
+ throw new Error("Invalid conversation store document");
307
+ }
308
+ return { version: CONVERSATION_STORE_VERSION, conversations: parsed.conversations as Record<string, T> };
309
+ } catch (error) {
310
+ if (isMissing(error)) return emptyDocument<T>();
311
+ throw error;
312
+ }
313
+ }
314
+
315
+ async #persist(document: ConversationStoreDocument<T>): Promise<void> {
316
+ await this.#fs.mkdir(this.#directory, { recursive: true, mode: 0o700 });
317
+ await this.#fs.chmod(this.#directory, 0o700);
318
+ const temporary = `${this.#file}.${process.pid}.${randomUUID()}.tmp`;
319
+ try {
320
+ await this.#fs.writeFile(temporary, `${JSON.stringify(document)}\n`, { mode: 0o600 });
321
+ await this.#fs.chmod(temporary, 0o600);
322
+ const handle = await this.#fs.open(temporary, "r");
323
+ try {
324
+ await handle.sync();
325
+ } finally {
326
+ await handle.close();
327
+ }
328
+ await this.#fs.rename(temporary, this.#file);
329
+ const directory = await this.#fs.open(this.#directory, "r");
330
+ try {
331
+ await directory.sync();
332
+ } finally {
333
+ await directory.close();
334
+ }
335
+ } catch (error) {
336
+ await this.#fs.unlink(temporary).catch(() => undefined);
337
+ throw error;
338
+ }
339
+ }
340
+ }
341
+
342
+ function isMissing(error: unknown): error is NodeJS.ErrnoException {
343
+ return isRecord(error) && error.code === "ENOENT";
344
+ }
345
+
346
+ function isAlreadyExists(error: unknown): error is NodeJS.ErrnoException {
347
+ return isRecord(error) && error.code === "EEXIST";
348
+ }
349
+
350
+ function defaultPidAlive(pid: number): boolean {
351
+ try {
352
+ process.kill(pid, 0);
353
+ return true;
354
+ } catch {
355
+ return false;
356
+ }
357
+ }
358
+
359
+ function defaultPidIncarnation(pid: number): string | undefined {
360
+ if (!Number.isSafeInteger(pid) || pid <= 0) return undefined;
361
+ if (process.platform === "linux") {
362
+ try {
363
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
364
+ return `linux:${
365
+ stat
366
+ .slice(stat.lastIndexOf(")") + 2)
367
+ .trim()
368
+ .split(/\s+/)[19]
369
+ }`;
370
+ } catch {
371
+ return undefined;
372
+ }
373
+ }
374
+ if (process.platform === "darwin") {
375
+ const result = spawnSync("ps", ["-o", "lstart=", "-p", String(pid)], { encoding: "utf8" });
376
+ const startedAt = result.status === 0 ? result.stdout.trim() : "";
377
+ return startedAt ? `darwin:${startedAt}` : undefined;
378
+ }
379
+ return undefined;
380
+ }
381
+
382
+ function isConversationStoreLock(value: unknown): value is ConversationStoreLock {
383
+ return (
384
+ isRecord(value) &&
385
+ typeof value.pid === "number" &&
386
+ Number.isSafeInteger(value.pid) &&
387
+ value.pid > 0 &&
388
+ typeof value.incarnation === "string" &&
389
+ typeof value.timestamp === "number"
390
+ );
391
+ }
@@ -0,0 +1,85 @@
1
+ import { boundedDedupe, type ConversationRecord } from "./conversation-store";
2
+
3
+ /** Identifier-only reference to an inbound effect whose payload and lifecycle live in ChatEffectJournal. */
4
+ export interface DiscordInboundDispatchReceipt {
5
+ key: string;
6
+ eventId: string;
7
+ interactionId?: string;
8
+ kind: "action" | "command";
9
+ actionId?: string;
10
+ actionNonce?: string;
11
+ endpointGeneration: number;
12
+ effectId: string;
13
+ idempotencyKey: string;
14
+ }
15
+
16
+ export type DiscordConversationState = "absent" | "creating" | "active" | "archived" | "resuming" | "closed" | "error";
17
+
18
+ /** Durable Discord mapping. It deliberately contains identifiers only: never endpoint tokens or message bodies. */
19
+ export interface DiscordConversation extends ConversationRecord {
20
+ state: DiscordConversationState;
21
+ appId: string;
22
+ guildId: string;
23
+ parentChannelId: string;
24
+ threadId?: string;
25
+ sessionId?: string;
26
+ createNonce?: string;
27
+ /** A lease makes thread creation exclusive across daemon processes. */
28
+ createOwner?: string;
29
+ createLeaseExpiresAt?: number;
30
+ endpointGeneration?: number;
31
+ /** Immutable lineage for archive and resume provider effects. */
32
+ effectIncarnationId?: string;
33
+ /** Current archive operation authority. */
34
+ archiveOccurrenceId?: string;
35
+ archiveEffectId?: string;
36
+ /** Current resume operation authority. */
37
+ resumeOccurrenceId?: string;
38
+ resumeEffectId?: string;
39
+ /** Action authority only; action bodies and endpoint credentials are never persisted. */
40
+ pendingActionId?: string;
41
+ /** Immutable per-publication action authority, bound to component routes and inbound effects. */
42
+ pendingActionNonce?: string;
43
+ /** Durable journal identity for the immutable outbound action publication intent. */
44
+ pendingActionEffectId?: string;
45
+ /** Replayable durable receipts for acknowledged inbound effects. */
46
+ inboundDispatches?: DiscordInboundDispatchReceipt[];
47
+ updatedAt: number;
48
+ archivedAt?: number;
49
+ closedAt?: number;
50
+ supersededByThreadId?: string;
51
+ seenEventIds: string[];
52
+ seenInteractionIds: string[];
53
+ }
54
+
55
+ export function discordConversationKey(input: {
56
+ appId: string;
57
+ guildId: string;
58
+ parentChannelId: string;
59
+ threadId: string;
60
+ }): string {
61
+ return `${input.appId}:${input.guildId}:${input.parentChannelId}:${input.threadId}`;
62
+ }
63
+
64
+ export function normalizeDiscordConversation(record: DiscordConversation): DiscordConversation {
65
+ const dispatches = record.inboundDispatches ?? [];
66
+ return {
67
+ ...record,
68
+ seenEventIds: boundedDedupe(record.seenEventIds),
69
+ seenInteractionIds: boundedDedupe(record.seenInteractionIds),
70
+ ...(dispatches.length === 0 ? {} : { inboundDispatches: dispatches }),
71
+ };
72
+ }
73
+
74
+ export function acceptsDiscordInbound(
75
+ record: DiscordConversation,
76
+ threadId: string,
77
+ endpointGeneration: number,
78
+ ): boolean {
79
+ return (
80
+ record.state === "active" &&
81
+ record.threadId === threadId &&
82
+ record.supersededByThreadId === undefined &&
83
+ record.endpointGeneration === endpointGeneration
84
+ );
85
+ }