@gajae-code/coding-agent 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/CHANGELOG.md +70 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/cli/args.d.ts +4 -5
  4. package/dist/types/cli/daemon-cli.d.ts +12 -1
  5. package/dist/types/cli/notify-cli.d.ts +21 -1
  6. package/dist/types/cli.d.ts +3 -0
  7. package/dist/types/commands/daemon.d.ts +39 -0
  8. package/dist/types/commands/launch.d.ts +3 -0
  9. package/dist/types/commands/notify.d.ts +28 -1
  10. package/dist/types/commands/sdk.d.ts +33 -0
  11. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  12. package/dist/types/config/model-profile-activation.d.ts +35 -15
  13. package/dist/types/config/model-profiles.d.ts +11 -5
  14. package/dist/types/config/model-registry.d.ts +3 -3
  15. package/dist/types/config/model-resolver.d.ts +39 -6
  16. package/dist/types/config/model-selector-value.d.ts +17 -0
  17. package/dist/types/config/models-config-schema.d.ts +10 -6
  18. package/dist/types/config/settings-schema.d.ts +133 -6
  19. package/dist/types/config/settings.d.ts +63 -35
  20. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  21. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  22. package/dist/types/daemon/builtin.d.ts +6 -5
  23. package/dist/types/daemon/control-types.d.ts +1 -1
  24. package/dist/types/discovery/mcp-json.d.ts +12 -1
  25. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  27. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  28. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  29. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  30. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  31. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  32. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  33. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  34. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  35. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  36. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  37. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  38. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  39. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  40. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  41. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  42. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  43. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  44. package/dist/types/harness-control-plane/types.d.ts +3 -4
  45. package/dist/types/lsp/index.d.ts +1 -1
  46. package/dist/types/main.d.ts +32 -38
  47. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  48. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  49. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  50. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  51. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  52. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  53. package/dist/types/modes/components/gajae-pet-widget.d.ts +1 -0
  54. package/dist/types/modes/components/model-selector.d.ts +1 -0
  55. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  56. package/dist/types/modes/components/pet-capability.d.ts +37 -0
  57. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  58. package/dist/types/modes/components/settings-selector.d.ts +15 -4
  59. package/dist/types/modes/components/welcome.d.ts +1 -1
  60. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  61. package/dist/types/modes/index.d.ts +0 -4
  62. package/dist/types/modes/interactive-mode.d.ts +5 -1
  63. package/dist/types/modes/runtime-init.d.ts +2 -2
  64. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  65. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  66. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  67. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  68. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  69. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  72. package/dist/types/modes/types.d.ts +16 -1
  73. package/dist/types/runtime-mcp/client.d.ts +2 -0
  74. package/dist/types/runtime-mcp/config.d.ts +5 -1
  75. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  76. package/dist/types/runtime-mcp/types.d.ts +4 -0
  77. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  78. package/dist/types/sdk/acp/index.d.ts +2 -0
  79. package/dist/types/sdk/broker/broker.d.ts +53 -0
  80. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  81. package/dist/types/sdk/broker/ensure.d.ts +33 -0
  82. package/dist/types/sdk/broker/identity.d.ts +3 -0
  83. package/dist/types/sdk/broker/index.d.ts +8 -0
  84. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  85. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  86. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  87. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  88. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  89. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  90. package/dist/types/sdk/broker/transport.d.ts +9 -0
  91. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  92. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  93. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  94. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  95. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  96. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  97. package/dist/types/sdk/bus/config.d.ts +274 -0
  98. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  99. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  100. package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
  101. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  102. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  103. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  104. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  105. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  107. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  108. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  109. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  110. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  111. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  112. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  113. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  114. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  115. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  116. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  117. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  118. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  119. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
  121. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  122. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  123. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  124. package/dist/types/sdk/cli/index.d.ts +1 -0
  125. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  126. package/dist/types/sdk/client/client.d.ts +1 -0
  127. package/dist/types/sdk/client/discovery.d.ts +27 -0
  128. package/dist/types/sdk/client/index.d.ts +2 -0
  129. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  130. package/dist/types/sdk/host/control/index.d.ts +2 -0
  131. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  132. package/dist/types/sdk/host/events.d.ts +35 -0
  133. package/dist/types/sdk/host/host.d.ts +35 -0
  134. package/dist/types/sdk/host/index.d.ts +4 -0
  135. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  136. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  137. package/dist/types/sdk/host/query/index.d.ts +3 -0
  138. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  139. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  140. package/dist/types/sdk/host/types.d.ts +32 -0
  141. package/dist/types/sdk/index.d.ts +6 -0
  142. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  143. package/dist/types/sdk/mcp/index.d.ts +1 -0
  144. package/dist/types/sdk/mcp/server.d.ts +37 -0
  145. package/dist/types/sdk/models.d.ts +44 -0
  146. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  147. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  148. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  149. package/dist/types/sdk/startup-capability.d.ts +50 -0
  150. package/dist/types/session/agent-session.d.ts +114 -21
  151. package/dist/types/session/default-model-selection.d.ts +25 -0
  152. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  153. package/dist/types/session/session-manager.d.ts +58 -1
  154. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  155. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  156. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  157. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  158. package/dist/types/tools/browser/launch.d.ts +22 -0
  159. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  160. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  161. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  162. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  163. package/dist/types/tools/browser/registry.d.ts +19 -0
  164. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  165. package/dist/types/tools/index.d.ts +8 -8
  166. package/package.json +34 -13
  167. package/scripts/build-sdk-package-smoke.ts +94 -0
  168. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  169. package/scripts/compile-args.ts +4 -2
  170. package/scripts/g005-daemon-smoke.ts +4 -5
  171. package/scripts/g011-daemon-path-smoke.ts +5 -5
  172. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  173. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  174. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  175. package/scripts/manifest-schema.ts +124 -0
  176. package/scripts/run-test-manifest.ts +153 -0
  177. package/scripts/run-threat-model-check.ts +157 -0
  178. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  179. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  180. package/src/append-only-mode.ts +1 -1
  181. package/src/cli/args.ts +43 -12
  182. package/src/cli/auth-gateway-cli.ts +2 -2
  183. package/src/cli/config-cli.ts +2 -1
  184. package/src/cli/daemon-cli.ts +63 -14
  185. package/src/cli/list-models.ts +1 -1
  186. package/src/cli/notify-cli.ts +288 -286
  187. package/src/cli.ts +21 -2
  188. package/src/commands/daemon.ts +50 -6
  189. package/src/commands/harness.ts +93 -36
  190. package/src/commands/launch.ts +5 -2
  191. package/src/commands/mcp-serve.ts +19 -12
  192. package/src/commands/notify.ts +36 -3
  193. package/src/commands/sdk.ts +426 -0
  194. package/src/commit/agentic/agent.ts +1 -0
  195. package/src/config/atomic-yaml-patch.ts +423 -0
  196. package/src/config/model-profile-activation.ts +240 -89
  197. package/src/config/model-profiles.ts +37 -34
  198. package/src/config/model-registry.ts +51 -26
  199. package/src/config/model-resolver.ts +138 -51
  200. package/src/config/model-selector-value.ts +50 -0
  201. package/src/config/models-config-schema.ts +14 -21
  202. package/src/config/settings-schema.ts +128 -10
  203. package/src/config/settings.ts +1120 -158
  204. package/src/coordinator-mcp/model-preset.ts +74 -20
  205. package/src/coordinator-mcp/server.ts +1597 -3052
  206. package/src/daemon/builtin.ts +8 -5
  207. package/src/daemon/control-types.ts +1 -1
  208. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  209. package/src/discovery/mcp-json.ts +327 -20
  210. package/src/extensibility/custom-tools/types.ts +1 -1
  211. package/src/extensibility/extensions/compact-handler.ts +3 -3
  212. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  213. package/src/extensibility/extensions/loader.ts +69 -5
  214. package/src/extensibility/extensions/runner.ts +112 -4
  215. package/src/extensibility/extensions/types.ts +176 -17
  216. package/src/extensibility/hooks/types.ts +1 -1
  217. package/src/extensibility/slash-commands.ts +3 -3
  218. package/src/gjc-runtime/launch-tmux.ts +170 -86
  219. package/src/gjc-runtime/psmux-detect.ts +82 -4
  220. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  221. package/src/gjc-runtime/team-runtime.ts +54 -35
  222. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  223. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -2
  224. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  225. package/src/gjc-runtime/ultragoal-guard.ts +53 -6
  226. package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
  227. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  228. package/src/harness-control-plane/operate.ts +9 -9
  229. package/src/harness-control-plane/owner.ts +283 -39
  230. package/src/harness-control-plane/receipts.ts +0 -1
  231. package/src/harness-control-plane/sdk-transport.ts +395 -0
  232. package/src/harness-control-plane/session-transport.ts +94 -0
  233. package/src/harness-control-plane/types.ts +1 -1
  234. package/src/internal-urls/docs-index.generated.ts +36 -37
  235. package/src/lsp/client.ts +42 -6
  236. package/src/lsp/index.ts +2 -2
  237. package/src/main.ts +299 -204
  238. package/src/modes/DESIGN.md +258 -0
  239. package/src/modes/acp/acp-agent.ts +1228 -2612
  240. package/src/modes/acp/acp-client-bridge.ts +2 -20
  241. package/src/modes/acp/acp-event-mapper.ts +18 -2
  242. package/src/modes/acp/acp-mode.ts +8 -36
  243. package/src/modes/acp/permission-mode.ts +25 -0
  244. package/src/modes/acp/startup-options.ts +6 -0
  245. package/src/modes/components/agent-dashboard.ts +37 -17
  246. package/src/modes/components/custom-editor.ts +1 -0
  247. package/src/modes/components/gajae-pet-widget.ts +169 -20
  248. package/src/modes/components/model-selector.ts +93 -35
  249. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  250. package/src/modes/components/pet-capability.ts +115 -0
  251. package/src/modes/components/pet-selector.ts +4 -6
  252. package/src/modes/components/settings-selector.ts +86 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +1 -2
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +357 -12
  257. package/src/modes/controllers/input-controller.ts +43 -13
  258. package/src/modes/controllers/selector-controller.ts +671 -44
  259. package/src/modes/index.ts +0 -22
  260. package/src/modes/interactive-mode.ts +108 -24
  261. package/src/modes/runtime-init.ts +298 -6
  262. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  263. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  264. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  265. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  266. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  267. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
  268. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  269. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  270. package/src/modes/types.ts +16 -1
  271. package/src/runtime-mcp/client.ts +94 -19
  272. package/src/runtime-mcp/config.ts +27 -15
  273. package/src/runtime-mcp/manager.ts +343 -105
  274. package/src/runtime-mcp/oauth-flow.ts +42 -12
  275. package/src/runtime-mcp/transports/http.ts +49 -19
  276. package/src/runtime-mcp/transports/stdio.ts +47 -28
  277. package/src/runtime-mcp/types.ts +10 -0
  278. package/src/sdk/acp/adapter.ts +418 -0
  279. package/src/sdk/acp/index.ts +2 -0
  280. package/src/sdk/broker/broker.ts +642 -0
  281. package/src/sdk/broker/discovery.ts +94 -0
  282. package/src/sdk/broker/ensure.ts +249 -0
  283. package/src/sdk/broker/identity.ts +42 -0
  284. package/src/sdk/broker/index.ts +8 -0
  285. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  286. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  287. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  288. package/src/sdk/broker/lifecycle.ts +2157 -0
  289. package/src/sdk/broker/process-incarnation.ts +159 -0
  290. package/src/sdk/broker/runtime.ts +164 -0
  291. package/src/sdk/broker/session-index.ts +318 -0
  292. package/src/sdk/broker/state-version.ts +23 -0
  293. package/src/sdk/broker/transport.ts +125 -0
  294. package/src/sdk/bus/chat-command-policy.ts +107 -0
  295. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  296. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  297. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  298. package/src/sdk/bus/chat-effect-journal.ts +353 -0
  299. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  300. package/src/sdk/bus/config.ts +433 -0
  301. package/src/sdk/bus/conversation-store.ts +391 -0
  302. package/src/sdk/bus/discord-conversation.ts +85 -0
  303. package/src/sdk/bus/discord-daemon.ts +2275 -0
  304. package/src/sdk/bus/discord-live-provider.ts +521 -0
  305. package/src/sdk/bus/discord-provider.ts +56 -0
  306. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  307. package/src/sdk/bus/index.ts +3943 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  309. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  310. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  311. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  312. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  313. package/src/sdk/bus/natives-augment.d.ts +38 -0
  314. package/src/sdk/bus/notification-orchestration.ts +535 -0
  315. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  316. package/src/sdk/bus/session-control.ts +333 -0
  317. package/src/sdk/bus/slack-conversation.ts +74 -0
  318. package/src/sdk/bus/slack-daemon.ts +2144 -0
  319. package/src/sdk/bus/slack-live-provider.ts +380 -0
  320. package/src/sdk/bus/slack-provider.ts +76 -0
  321. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  322. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  323. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  324. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  325. package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
  326. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  327. package/src/sdk/bus/telegram-setup.ts +663 -0
  328. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  329. package/src/sdk/cli/index.ts +1 -0
  330. package/src/sdk/cli/session-cli.ts +275 -0
  331. package/src/sdk/client/client.ts +1 -0
  332. package/src/sdk/client/discovery.ts +108 -0
  333. package/src/sdk/client/index.ts +2 -0
  334. package/src/sdk/host/control/dispatch.ts +367 -0
  335. package/src/sdk/host/control/index.ts +10 -0
  336. package/src/sdk/host/control/operations.ts +63 -0
  337. package/src/sdk/host/events.ts +91 -0
  338. package/src/sdk/host/host.ts +296 -0
  339. package/src/sdk/host/index.ts +4 -0
  340. package/src/sdk/host/query/cursor.ts +189 -0
  341. package/src/sdk/host/query/handlers.ts +533 -0
  342. package/src/sdk/host/query/index.ts +3 -0
  343. package/src/sdk/host/query/revision-store.ts +1126 -0
  344. package/src/sdk/host/reverse-leases.ts +325 -0
  345. package/src/sdk/host/types.ts +29 -0
  346. package/src/sdk/index.ts +13 -0
  347. package/src/sdk/lifecycle-session.ts +39 -0
  348. package/src/sdk/mcp/index.ts +1 -0
  349. package/src/sdk/mcp/server.ts +332 -0
  350. package/src/sdk/models.ts +168 -0
  351. package/src/sdk/protocol/adapter-validation.ts +48 -0
  352. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  353. package/src/sdk/protocol/operation-registry.ts +312 -0
  354. package/src/{sdk.ts → sdk/session.ts} +339 -212
  355. package/src/sdk/startup-capability.ts +189 -0
  356. package/src/session/agent-session.ts +2470 -866
  357. package/src/session/default-model-selection.ts +93 -0
  358. package/src/session/fallback-chain-controller.ts +136 -0
  359. package/src/session/session-manager.ts +447 -13
  360. package/src/session/session-storage.ts +8 -1
  361. package/src/setup/credential-auto-import.ts +290 -35
  362. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  363. package/src/slash-commands/builtin-registry.ts +33 -30
  364. package/src/task/executor.ts +62 -13
  365. package/src/tools/ask-answer-registry.ts +1 -1
  366. package/src/tools/ask.ts +13 -8
  367. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  368. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  369. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  370. package/src/tools/browser/launch.ts +124 -19
  371. package/src/tools/browser/profile-discovery.ts +63 -0
  372. package/src/tools/browser/profile-posture.ts +59 -0
  373. package/src/tools/browser/profile-reuse.ts +102 -0
  374. package/src/tools/browser/profile-warmup.ts +109 -0
  375. package/src/tools/browser/registry.ts +87 -11
  376. package/src/tools/browser/tab-protocol.ts +1 -0
  377. package/src/tools/browser/tab-supervisor.ts +1 -0
  378. package/src/tools/browser/tab-worker.ts +1 -1
  379. package/src/tools/browser.ts +6 -0
  380. package/src/tools/index.ts +8 -8
  381. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  382. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  383. package/src/tools/telegram-send.ts +2 -2
  384. package/vendor/insane-search/MANIFEST.json +2 -1
  385. package/vendor/insane-search/engine/bias_check.py +4 -1
  386. package/vendor/insane-search/engine/phase0.py +26 -1
  387. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  388. package/dist/types/modes/bridge/auth.d.ts +0 -12
  389. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  390. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  391. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  392. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  393. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  394. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  395. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  396. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  397. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  398. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  399. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  400. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  401. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  402. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  403. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  404. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  405. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  406. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  407. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  408. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  409. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  410. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  411. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  412. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  413. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  414. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  415. package/dist/types/notifications/config.d.ts +0 -132
  416. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  417. package/src/modes/bridge/auth.ts +0 -41
  418. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  419. package/src/modes/bridge/bridge-mode.ts +0 -675
  420. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  421. package/src/modes/bridge/event-stream.ts +0 -70
  422. package/src/modes/rpc/host-tools.ts +0 -1
  423. package/src/modes/rpc/host-uris.ts +0 -1
  424. package/src/modes/rpc/rpc-client.ts +0 -1166
  425. package/src/modes/rpc/rpc-mode.ts +0 -1029
  426. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  427. package/src/modes/rpc/rpc-types.ts +0 -637
  428. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  429. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  430. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  431. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  432. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  433. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  434. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  435. package/src/modes/shared/agent-wire/responses.ts +0 -17
  436. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  437. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  438. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  439. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  440. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  441. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  442. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  443. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  444. package/src/notifications/config.ts +0 -219
  445. package/src/notifications/index.ts +0 -1835
  446. package/src/notifications/telegram-daemon-cli.ts +0 -243
  447. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  448. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  449. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  450. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  462. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  463. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -0,0 +1,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
+ }