@wrongstack/core 0.313.0 → 0.316.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 (343) hide show
  1. package/dist/chronicle/index.js +84 -6391
  2. package/dist/chronicle/legacy-journal-import.d.ts +0 -6
  3. package/dist/chronicle/metrics-ingest.d.ts +14 -0
  4. package/dist/chronicle/metrics-schema.d.ts +10 -1
  5. package/dist/chronicle/metrics-store.d.ts +20 -2
  6. package/dist/chronicle/project-server.js +98 -4874
  7. package/dist/chronicle/sink.d.ts +13 -0
  8. package/dist/chronicle/sqlite-journal.d.ts +20 -2
  9. package/dist/chunk-25LSLC3G.js +334 -0
  10. package/dist/chunk-27QIURLN.js +1073 -0
  11. package/dist/chunk-2FK4WTFF.js +207 -0
  12. package/dist/chunk-2YU4WVBW.js +134 -0
  13. package/dist/chunk-3AGWVSS7.js +4608 -0
  14. package/dist/chunk-3BDV7RL3.js +211 -0
  15. package/dist/chunk-3ECENVHL.js +325 -0
  16. package/dist/chunk-3XPVB7BA.js +135 -0
  17. package/dist/chunk-45WI72ZB.js +16884 -0
  18. package/dist/chunk-4BMVPOHO.js +3748 -0
  19. package/dist/chunk-4I7HGVVA.js +363 -0
  20. package/dist/chunk-4LCZVJVF.js +317 -0
  21. package/dist/chunk-4SJNS7OB.js +217 -0
  22. package/dist/chunk-4VWO3ZXL.js +342 -0
  23. package/dist/chunk-57GEWK5X.js +26 -0
  24. package/dist/chunk-5BMIE7QG.js +46 -0
  25. package/dist/chunk-5S437PRC.js +50 -0
  26. package/dist/chunk-5XDUGTKN.js +511 -0
  27. package/dist/chunk-5YPSXQXM.js +1443 -0
  28. package/dist/chunk-6FHWXLPT.js +10 -0
  29. package/dist/chunk-6H5GEOET.js +2406 -0
  30. package/dist/chunk-6NWEVFEL.js +151 -0
  31. package/dist/chunk-AYW5YINX.js +58 -0
  32. package/dist/chunk-B4AMLZPB.js +9 -0
  33. package/dist/chunk-B7F4WVP4.js +65 -0
  34. package/dist/chunk-BJHVULHO.js +55 -0
  35. package/dist/chunk-BPBKKBUK.js +2085 -0
  36. package/dist/chunk-BYD345OX.js +589 -0
  37. package/dist/chunk-C27KDLOX.js +279 -0
  38. package/dist/chunk-CU546ESW.js +597 -0
  39. package/dist/chunk-DLHHXUAM.js +172 -0
  40. package/dist/chunk-DOTHQSJ2.js +429 -0
  41. package/dist/chunk-DYLPMV4Q.js +711 -0
  42. package/dist/chunk-EODDVJBM.js +82 -0
  43. package/dist/chunk-F3JWNST7.js +361 -0
  44. package/dist/chunk-FC2ZGRF3.js +140 -0
  45. package/dist/chunk-FCBTO76Z.js +5786 -0
  46. package/dist/chunk-FHZVFYSL.js +396 -0
  47. package/dist/chunk-FNXVT7HF.js +52 -0
  48. package/dist/chunk-FWNLEZYG.js +259 -0
  49. package/dist/chunk-FXQLIX3K.js +211 -0
  50. package/dist/chunk-G5S3S5ZN.js +38 -0
  51. package/dist/chunk-GDQ7CZRQ.js +116 -0
  52. package/dist/chunk-GJJGJB2R.js +1374 -0
  53. package/dist/chunk-GTCU6DZ3.js +1 -0
  54. package/dist/chunk-HA4ZYA6T.js +178 -0
  55. package/dist/chunk-HI3JGZR2.js +188 -0
  56. package/dist/chunk-HMLIGAU7.js +395 -0
  57. package/dist/chunk-HXKZ7OBQ.js +303 -0
  58. package/dist/chunk-I7DALG7J.js +292 -0
  59. package/dist/chunk-IRUTEHCE.js +960 -0
  60. package/dist/chunk-IYFBFX34.js +86 -0
  61. package/dist/chunk-J2WRWR37.js +1104 -0
  62. package/dist/chunk-JFPJ6LLQ.js +129 -0
  63. package/dist/chunk-JMULFFLN.js +9 -0
  64. package/dist/chunk-JO4MGB6Z.js +1264 -0
  65. package/dist/chunk-JVKB2TBL.js +48 -0
  66. package/dist/chunk-JX7VBZDK.js +31 -0
  67. package/dist/chunk-K6BXGITA.js +931 -0
  68. package/dist/chunk-KDQJCT2J.js +45 -0
  69. package/dist/chunk-KJ2ZTQSL.js +47 -0
  70. package/dist/chunk-KZMSZV32.js +187 -0
  71. package/dist/chunk-LA7CLDRW.js +129 -0
  72. package/dist/chunk-LHOA5DWA.js +28 -0
  73. package/dist/chunk-LSMMOS2Z.js +119 -0
  74. package/dist/chunk-LX5QWLBL.js +27 -0
  75. package/dist/chunk-LXWCMQNJ.js +789 -0
  76. package/dist/chunk-M27LIEKV.js +2829 -0
  77. package/dist/chunk-MJPHJRAL.js +663 -0
  78. package/dist/chunk-MTL4O5YR.js +228 -0
  79. package/dist/chunk-NDBIPFNY.js +102 -0
  80. package/dist/chunk-NEMIWEXC.js +1199 -0
  81. package/dist/chunk-NHJ75HXY.js +1 -0
  82. package/dist/chunk-NIOAGFPB.js +1510 -0
  83. package/dist/chunk-NS52ISWS.js +355 -0
  84. package/dist/chunk-NSOFPKGT.js +5352 -0
  85. package/dist/chunk-NVIZG63R.js +757 -0
  86. package/dist/chunk-O37BQ65S.js +21 -0
  87. package/dist/chunk-OOYZPOXM.js +308 -0
  88. package/dist/chunk-OSGLYW5J.js +28 -0
  89. package/dist/chunk-PFCMSSUF.js +1640 -0
  90. package/dist/chunk-PFZO3C6H.js +14 -0
  91. package/dist/chunk-PGRVXIMY.js +158 -0
  92. package/dist/chunk-PHH7LD45.js +113 -0
  93. package/dist/chunk-PISBFBJN.js +109 -0
  94. package/dist/chunk-POOOIWE5.js +9 -0
  95. package/dist/chunk-PQNS3U7Z.js +1240 -0
  96. package/dist/chunk-QSTSJOCK.js +402 -0
  97. package/dist/chunk-RFQMOKWK.js +282 -0
  98. package/dist/chunk-RJIZEJ42.js +30 -0
  99. package/dist/chunk-RTOTNK3P.js +484 -0
  100. package/dist/chunk-RXKSDUAU.js +1172 -0
  101. package/dist/chunk-S45JPKQN.js +3317 -0
  102. package/dist/chunk-SAFHACFA.js +152 -0
  103. package/dist/chunk-SQJVFEBV.js +41 -0
  104. package/dist/chunk-SVT4RNTR.js +49 -0
  105. package/dist/chunk-SWUFN7XM.js +43 -0
  106. package/dist/chunk-SXMVYC5H.js +174 -0
  107. package/dist/chunk-SZ6AYUIZ.js +23 -0
  108. package/dist/chunk-TBRL2RCC.js +9 -0
  109. package/dist/chunk-TCCHINEF.js +655 -0
  110. package/dist/chunk-THEGTRAG.js +316 -0
  111. package/dist/chunk-TR4LQE7L.js +2256 -0
  112. package/dist/chunk-TRT2HRWZ.js +18 -0
  113. package/dist/chunk-TWJMGXCI.js +900 -0
  114. package/dist/chunk-U45AXT5D.js +1023 -0
  115. package/dist/chunk-U4FWBSO3.js +509 -0
  116. package/dist/chunk-UBGDX6FI.js +147 -0
  117. package/dist/chunk-UJILKYES.js +75 -0
  118. package/dist/chunk-ULMAQV3T.js +234 -0
  119. package/dist/chunk-VVBP6KGT.js +9 -0
  120. package/dist/chunk-W5VITDM2.js +168 -0
  121. package/dist/chunk-WAHQVNWT.js +194 -0
  122. package/dist/chunk-WBPVKEEE.js +227 -0
  123. package/dist/chunk-WGGYRBXH.js +5434 -0
  124. package/dist/chunk-WLYKU45P.js +5770 -0
  125. package/dist/chunk-WP7BVANJ.js +53 -0
  126. package/dist/chunk-WQQON3SV.js +473 -0
  127. package/dist/chunk-WQTOVMGV.js +119 -0
  128. package/dist/chunk-XBDP4QPW.js +7 -0
  129. package/dist/chunk-XEBHSJLT.js +103 -0
  130. package/dist/chunk-XF4VUMKW.js +231 -0
  131. package/dist/chunk-XQ2ECNK3.js +1 -0
  132. package/dist/chunk-Y5YXDM7D.js +74 -0
  133. package/dist/chunk-YOPAUVU4.js +2588 -0
  134. package/dist/chunk-YPT4A46F.js +362 -0
  135. package/dist/chunk-YWXT3JNM.js +425 -0
  136. package/dist/chunk-YY6APYUM.js +49 -0
  137. package/dist/chunk-Z2IJUO45.js +691 -0
  138. package/dist/chunk-ZHZ2Y2DH.js +1643 -0
  139. package/dist/chunk-ZT7JNIGX.js +152 -0
  140. package/dist/coordination/agent-monitor.d.ts +9 -1
  141. package/dist/coordination/agent-subagent-runner.d.ts +1 -1
  142. package/dist/coordination/agents/agent-prompts.d.ts +8 -0
  143. package/dist/coordination/agents/index.d.ts +33 -1
  144. package/dist/coordination/agents/index.js +184 -6269
  145. package/dist/coordination/agents/phase3-wave1-platform.d.ts +1 -3
  146. package/dist/coordination/agents/phase3-wave2-meta.d.ts +1 -3
  147. package/dist/coordination/agents/phase8-wave3-products.d.ts +1 -3
  148. package/dist/coordination/agents/phase9-wave4-platform-meta.d.ts +1 -3
  149. package/dist/coordination/agents/project-agent-identity.d.ts +11 -11
  150. package/dist/coordination/agents/types.d.ts +13 -2
  151. package/dist/coordination/brain-monitor.d.ts +30 -7
  152. package/dist/coordination/collab-debug.d.ts +1 -1
  153. package/dist/coordination/collab-pause.d.ts +1 -1
  154. package/dist/coordination/delegate-tool.d.ts +7 -5
  155. package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -0
  156. package/dist/coordination/director-options.d.ts +7 -0
  157. package/dist/coordination/director-spawn-model.d.ts +17 -0
  158. package/dist/coordination/director-tools.d.ts +2 -2
  159. package/dist/coordination/director.d.ts +12 -0
  160. package/dist/coordination/dispatcher.d.ts +8 -0
  161. package/dist/coordination/fleet-bus.d.ts +35 -4
  162. package/dist/coordination/fleet-supervisor.d.ts +10 -2
  163. package/dist/coordination/fleet.d.ts +16 -7
  164. package/dist/coordination/index.d.ts +4 -0
  165. package/dist/coordination/index.js +402 -34324
  166. package/dist/coordination/kanban-dispatch-port.d.ts +2 -2
  167. package/dist/coordination/mailbox-http-router.d.ts +4 -3
  168. package/dist/coordination/mailbox-http-validation.d.ts +1 -1
  169. package/dist/coordination/mailbox-project-server.js +48 -3276
  170. package/dist/coordination/mailbox-types.d.ts +24 -6
  171. package/dist/coordination/model-tier-leader.d.ts +122 -0
  172. package/dist/coordination/model-tier.d.ts +122 -0
  173. package/dist/coordination/multi-agent-coordinator.d.ts +24 -0
  174. package/dist/coordination/origin-session.d.ts +16 -0
  175. package/dist/coordination/provider-status-tracker.d.ts +41 -5
  176. package/dist/coordination/session-note-hub.d.ts +44 -0
  177. package/dist/coordination/session-note-tool.d.ts +10 -0
  178. package/dist/core/agent.d.ts +15 -2
  179. package/dist/core/context.d.ts +22 -3
  180. package/dist/core/index.d.ts +2 -0
  181. package/dist/core/index.js +239 -12360
  182. package/dist/core/model-ref.js +5 -23
  183. package/dist/core/provider-runner.d.ts +36 -1
  184. package/dist/core/request-conversation-binding.d.ts +37 -0
  185. package/dist/core/session-notes.d.ts +25 -0
  186. package/dist/core/system-prompt-builder.d.ts +11 -2
  187. package/dist/core/system-prompt-variants.d.ts +78 -0
  188. package/dist/design/index.js +50 -1087
  189. package/dist/execution/auto-compaction-middleware.d.ts +11 -0
  190. package/dist/execution/autonomy-brain.d.ts +2 -1
  191. package/dist/execution/autonomy-prompt-contributor.d.ts +7 -2
  192. package/dist/execution/compaction-core.d.ts +4 -4
  193. package/dist/execution/eternal-autonomy.d.ts +1 -1
  194. package/dist/execution/index.d.ts +1 -1
  195. package/dist/execution/index.js +1615 -21895
  196. package/dist/execution/model-runtime.d.ts +0 -7
  197. package/dist/execution/parallel-eternal-engine.d.ts +7 -7
  198. package/dist/execution/prompt-enhancer.js +16 -535
  199. package/dist/execution/retry-policy.d.ts +31 -1
  200. package/dist/extension/index.js +7 -311
  201. package/dist/goal/index.js +33 -3435
  202. package/dist/hooks/index.js +14 -1138
  203. package/dist/hq/index.js +114 -5139
  204. package/dist/hq/persistence/event-log.d.ts +0 -1
  205. package/dist/hq/persistence.d.ts +4 -4
  206. package/dist/hq/protocol.js +21 -668
  207. package/dist/hq/publisher.d.ts +2 -0
  208. package/dist/index.d.ts +14 -11
  209. package/dist/index.js +1502 -92655
  210. package/dist/infrastructure/index.d.ts +4 -4
  211. package/dist/infrastructure/index.js +504 -5230
  212. package/dist/infrastructure/token-counter.d.ts +9 -0
  213. package/dist/kernel/events/agent-events.d.ts +77 -3
  214. package/dist/kernel/events/brain-events.d.ts +12 -0
  215. package/dist/kernel/events/provider-events.d.ts +22 -1
  216. package/dist/kernel/events/session-events.d.ts +14 -0
  217. package/dist/kernel/events/tool-events.d.ts +13 -0
  218. package/dist/kernel/index.js +14 -992
  219. package/dist/mailbox-attach.d.ts +1 -1
  220. package/dist/models/index.js +41 -1117
  221. package/dist/notifications/index.js +3 -108
  222. package/dist/observability/event-bridge.d.ts +25 -5
  223. package/dist/observability/index.d.ts +9 -8
  224. package/dist/observability/index.js +477 -631
  225. package/dist/observability/tool-usage-source.d.ts +65 -0
  226. package/dist/plugin/index.d.ts +5 -0
  227. package/dist/plugin/index.js +600 -14835
  228. package/dist/plugins/auto-review-plugin.d.ts +3 -2
  229. package/dist/plugins/review-finding-commands.d.ts +0 -8
  230. package/dist/plugins/review-finding-store.js +22 -0
  231. package/dist/plugins/review-finding-types.js +19 -0
  232. package/dist/plugins/review-report-integration.js +21 -0
  233. package/dist/plugins/review-report-store.js +20 -0
  234. package/dist/plugins/review-report-types.js +13 -0
  235. package/dist/prompts/index.js +14 -948
  236. package/dist/registry/index.js +9 -822
  237. package/dist/registry/tool-registry.d.ts +59 -9
  238. package/dist/registry-7N4O3E7W.js +14 -0
  239. package/dist/replay/index.js +6 -84
  240. package/dist/security/capabilities.d.ts +6 -0
  241. package/dist/security/file-permissions.d.ts +1 -1
  242. package/dist/security/index.js +161 -2235
  243. package/dist/security/permission-policy.d.ts +12 -1
  244. package/dist/security/secret-scrubber.d.ts +15 -0
  245. package/dist/session-catalog/index.d.ts +1 -0
  246. package/dist/session-catalog/index.js +41 -2103
  247. package/dist/session-catalog/project-server.js +59 -1435
  248. package/dist/session-catalog/protocol.d.ts +32 -1
  249. package/dist/session-catalog/registry.d.ts +17 -1
  250. package/dist/session-catalog/session-agents.d.ts +56 -0
  251. package/dist/session-catalog/store-rebuild.d.ts +14 -0
  252. package/dist/session-catalog/store-schema.d.ts +26 -0
  253. package/dist/session-catalog/store.d.ts +27 -1
  254. package/dist/session-note-attach.d.ts +9 -0
  255. package/dist/skills/index.js +35 -1578
  256. package/dist/statusline/index.d.ts +43 -0
  257. package/dist/statusline/index.js +102 -0
  258. package/dist/storage/board-store-port.d.ts +2 -2
  259. package/dist/storage/config-loader/in-project-policy.d.ts +29 -0
  260. package/dist/storage/config-loader.d.ts +3 -2
  261. package/dist/storage/file-session-writer.d.ts +4 -2
  262. package/dist/storage/goal-coordination.d.ts +6 -1
  263. package/dist/storage/goal-kanban.d.ts +4 -1
  264. package/dist/storage/index.d.ts +12 -4
  265. package/dist/storage/index.js +198 -15601
  266. package/dist/storage/input-history-store.d.ts +2 -4
  267. package/dist/storage/memory-curator.d.ts +133 -0
  268. package/dist/storage/session-agent-attribution.d.ts +39 -0
  269. package/dist/storage/session-doctor.d.ts +109 -0
  270. package/dist/storage/session-event-bridge.d.ts +5 -7
  271. package/dist/storage/session-outcome.d.ts +42 -0
  272. package/dist/storage/session-recovery.d.ts +55 -0
  273. package/dist/storage/session-store/load-session-data.d.ts +11 -0
  274. package/dist/storage/session-store/prune-helpers.d.ts +1 -1
  275. package/dist/storage/session-store/resume-session.d.ts +0 -2
  276. package/dist/storage/session-store/types.d.ts +8 -0
  277. package/dist/storage/session-store.d.ts +3 -3
  278. package/dist/storage/session-summary-tracker.d.ts +8 -1
  279. package/dist/storage/session-write-buffer.d.ts +18 -0
  280. package/dist/storage/session-writer-truncate.d.ts +2 -0
  281. package/dist/tasking/index.js +10 -676
  282. package/dist/tools/fallback-manage-tools.d.ts +6 -4
  283. package/dist/tools/index.js +52 -9590
  284. package/dist/tools/model-tier-set-tool.d.ts +66 -0
  285. package/dist/types/agent-bridge.d.ts +2 -1
  286. package/dist/types/config/autonomy.d.ts +5 -0
  287. package/dist/types/config/mcp-features.d.ts +7 -0
  288. package/dist/types/config/model-tiers.d.ts +148 -0
  289. package/dist/types/config/root.d.ts +9 -0
  290. package/dist/types/config/tools.d.ts +73 -0
  291. package/dist/types/config/ui.d.ts +1 -1
  292. package/dist/types/config.d.ts +1 -0
  293. package/dist/types/context.d.ts +2 -0
  294. package/dist/types/default-config.d.ts +6 -0
  295. package/dist/types/errors.d.ts +20 -1
  296. package/dist/types/index.d.ts +11 -9
  297. package/dist/types/index.js +131 -1342
  298. package/dist/types/multi-agent.d.ts +43 -0
  299. package/dist/types/plugin.d.ts +1 -1
  300. package/dist/types/provider-runner.d.ts +8 -0
  301. package/dist/types/provider.d.ts +15 -0
  302. package/dist/types/runtime-capability-manifest.d.ts +1 -1
  303. package/dist/types/secret-scrubber.d.ts +15 -0
  304. package/dist/types/session-markers.d.ts +37 -10
  305. package/dist/types/session-markers.js +8 -144
  306. package/dist/types/session-timeline.d.ts +197 -0
  307. package/dist/types/session-timeline.js +12 -0
  308. package/dist/types/session.d.ts +172 -11
  309. package/dist/types/system-prompt.d.ts +27 -0
  310. package/dist/utils/config-backup.d.ts +9 -1
  311. package/dist/utils/error.js +3 -4
  312. package/dist/utils/expect-defined.js +3 -9
  313. package/dist/utils/heap-watchdog.js +6 -706
  314. package/dist/utils/index.js +271 -5685
  315. package/dist/utils/message-invariants.d.ts +4 -1
  316. package/dist/utils/regex-guard.d.ts +1 -1
  317. package/dist/utils/sage-output-block.js +5 -42
  318. package/dist/utils/socket-path.d.ts +1 -1
  319. package/dist/utils/token-estimate.d.ts +6 -2
  320. package/dist/utils/wstack-paths.d.ts +2 -0
  321. package/dist/wiring/proxy-rewrite.d.ts +46 -0
  322. package/dist/wiring/proxy-rewrite.js +24 -121
  323. package/dist/worktree/index.js +6 -887
  324. package/instructions/agents/explore-companion.md +45 -18
  325. package/instructions/agents/memory-curator.md +34 -22
  326. package/instructions/coordination/director-preamble.md +12 -7
  327. package/instructions/coordination/subagent-baseline.md +26 -5
  328. package/instructions/leader-after-task.md +4 -1
  329. package/instructions/llm/chimera-review.md +30 -9
  330. package/instructions/llm/memory-curator.md +31 -0
  331. package/instructions/sections/tool/delegation-compact.md +2 -0
  332. package/instructions/sections/tool/delegation-full.md +5 -1
  333. package/instructions/sections/tool/mailbox-compact.md +5 -1
  334. package/instructions/sections/tool/mailbox-full.md +3 -0
  335. package/instructions/sections/tool/session-note-compact.md +3 -0
  336. package/instructions/sections/tool/session-note-full.md +15 -0
  337. package/instructions/system-lite.md +9 -4
  338. package/instructions/system-pro.md +66 -143
  339. package/instructions/system.md +73 -175
  340. package/package.json +32 -4
  341. package/dist/coordination/agents.d.ts +0 -8
  342. package/dist/coordination/transport.d.ts +0 -2
  343. package/dist/storage/session-writer/session-writer-summary-tracker.d.ts +0 -28
@@ -0,0 +1,960 @@
1
+ import {
2
+ isMailboxReceiptRecordV2,
3
+ normalizeRecipient,
4
+ validateSendType
5
+ } from "./chunk-FWNLEZYG.js";
6
+ import {
7
+ withSqliteExperimentalWarningSuppressed
8
+ } from "./chunk-LX5QWLBL.js";
9
+ import {
10
+ projectSlug
11
+ } from "./chunk-SAFHACFA.js";
12
+
13
+ // src/coordination/mailbox-constants.ts
14
+ var AGENT_STALE_MS = 6e4;
15
+ var CLIENT_STALE_MS = 6e4;
16
+ var HEARTBEAT_THROTTLE_MS = 5e3;
17
+ var LINE_SEPARATOR = "\n";
18
+ var MAILBOX_AWARENESS_INTERVAL_MS = 3e4;
19
+ var MAILBOX_HEARTBEAT_INTERVAL_MS = 3e4;
20
+ var HQ_MAILBOX_SNAPSHOT_MIN_INTERVAL_MS = 1e4;
21
+ var PULSE_MIN_READ_INTERVAL_MS = 3e4;
22
+ var UNREAD_CHECK_MIN_INTERVAL_MS = 1e3;
23
+ var AUTO_COMPACT_INTERVAL_MS = 3e5;
24
+ var AUTO_COMPACT_READ_MAX_AGE_MS = 6e5;
25
+ var AUTO_COMPACT_DEFAULT_TTL_MS = 864e5;
26
+ var AUTO_COMPACT_TYPE_TTL_MS = {
27
+ status: 18e5
28
+ // 30 min
29
+ };
30
+ var MAILBOX_MAX_QUERY_LIMIT = 500;
31
+ var MAILBOX_MAX_ACK_BATCH = 500;
32
+
33
+ // src/coordination/mailbox-credential-store.ts
34
+ import * as crypto from "node:crypto";
35
+ var CREDENTIAL_STORE_FILE = "_mailbox_credentials.json";
36
+ var MAX_CREDENTIAL_TTL = {
37
+ agent: 7 * 24 * 60 * 60 * 1e3,
38
+ // 7 days
39
+ operator: 24 * 60 * 60 * 1e3,
40
+ // 24 hours
41
+ service: 30 * 24 * 60 * 60 * 1e3
42
+ // 30 days
43
+ };
44
+ var ROTATION_OVERLAP_MS = 60 * 60 * 1e3;
45
+ function createMailboxCredential(opts, now = Date.now()) {
46
+ const ttlMs = Math.min(opts.ttlMs, MAX_CREDENTIAL_TTL[opts.kind]);
47
+ const credentialId = crypto.randomUUID();
48
+ const secret = crypto.randomBytes(32).toString("hex");
49
+ const verifierKey = crypto.createHash("sha256").update(secret).digest();
50
+ const verifier = crypto.createHmac("sha256", verifierKey).update(credentialId).digest("hex");
51
+ return {
52
+ credential: {
53
+ credentialId,
54
+ verifier,
55
+ verifierAlgorithm: "hmac-sha256",
56
+ principalId: opts.principalId,
57
+ projectId: opts.projectId,
58
+ capabilities: opts.capabilities,
59
+ kind: opts.kind,
60
+ issuedAt: new Date(now).toISOString(),
61
+ expiresAt: new Date(now + ttlMs).toISOString(),
62
+ notBefore: opts.notBefore?.toISOString(),
63
+ status: "active",
64
+ statusChangedAt: new Date(now).toISOString(),
65
+ supersedes: opts.supersedes,
66
+ lastModifiedBy: opts.issuedBy
67
+ },
68
+ secret
69
+ };
70
+ }
71
+ function redactMailboxCredential(credential) {
72
+ const { verifier: _verifier, verifierAlgorithm: _algorithm, ...rest } = credential;
73
+ return rest;
74
+ }
75
+ function verifyMailboxCredential(credential, secret, now = Date.now()) {
76
+ if (credential === void 0) {
77
+ return { valid: false, reason: "credential not found" };
78
+ }
79
+ const rotationStillValid = credential.status === "rotated_out" && credential.rotationValidUntil !== void 0 && new Date(credential.rotationValidUntil).getTime() >= now;
80
+ if (credential.status !== "active" && !rotationStillValid) {
81
+ return { valid: false, reason: `credential is ${credential.status}`, credential };
82
+ }
83
+ if (new Date(credential.expiresAt).getTime() <= now) {
84
+ return { valid: false, reason: "credential expired", credential };
85
+ }
86
+ if (credential.notBefore !== void 0 && new Date(credential.notBefore).getTime() > now) {
87
+ return { valid: false, reason: "credential not yet valid", credential };
88
+ }
89
+ const verifierKey = crypto.createHash("sha256").update(secret).digest();
90
+ const expected = crypto.createHmac("sha256", verifierKey).update(credential.credentialId).digest("hex");
91
+ const actualBytes = Buffer.from(credential.verifier, "hex");
92
+ const expectedBytes = Buffer.from(expected, "hex");
93
+ if (actualBytes.length !== expectedBytes.length || !crypto.timingSafeEqual(actualBytes, expectedBytes)) {
94
+ return { valid: false, reason: "invalid secret" };
95
+ }
96
+ return { valid: true, credential };
97
+ }
98
+
99
+ // src/coordination/global-mailbox-paths.ts
100
+ import * as path from "node:path";
101
+ var GLOBAL_MAILBOX_FILE = "_mailbox.jsonl";
102
+ var GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE = "_mailbox.clients.json";
103
+ function resolveProjectDir(projectRoot, globalRoot) {
104
+ return path.join(globalRoot, "projects", projectSlug(projectRoot));
105
+ }
106
+
107
+ // src/coordination/mailbox-message-codec.ts
108
+ var MESSAGE_TYPES = /* @__PURE__ */ new Set([
109
+ "note",
110
+ "ask",
111
+ "assign",
112
+ "steer",
113
+ "btw",
114
+ "broadcast",
115
+ "status",
116
+ "result",
117
+ "review",
118
+ "control"
119
+ ]);
120
+ var PRIORITIES = /* @__PURE__ */ new Set(["low", "normal", "high"]);
121
+ var AUDIENCES = /* @__PURE__ */ new Set(["all", "leaders"]);
122
+ var TASK_STATUSES = /* @__PURE__ */ new Set([
123
+ "pending",
124
+ "in_progress",
125
+ "completed",
126
+ "failed",
127
+ "idle",
128
+ "running",
129
+ "streaming",
130
+ "waiting_user",
131
+ "error",
132
+ "offline",
133
+ "busy"
134
+ ]);
135
+ function isRecord(value) {
136
+ return typeof value === "object" && value !== null && !Array.isArray(value);
137
+ }
138
+ function requiredString(record, key) {
139
+ const value = record[key];
140
+ if (typeof value !== "string") {
141
+ throw new TypeError(`mailbox message field "${key}" must be a string`);
142
+ }
143
+ return value;
144
+ }
145
+ function optionalString(record, key) {
146
+ const value = record[key];
147
+ if (value === void 0) return {};
148
+ if (typeof value !== "string") {
149
+ throw new TypeError(`mailbox message field "${key}" must be a string when present`);
150
+ }
151
+ return { [key]: value };
152
+ }
153
+ function parseMessageType(value) {
154
+ if (value === "info") return "note";
155
+ if (value === "task") return "assign";
156
+ if (typeof value === "string" && MESSAGE_TYPES.has(value)) {
157
+ return value;
158
+ }
159
+ throw new TypeError('mailbox message field "type" is invalid');
160
+ }
161
+ function normalizeMailboxMessageType(value) {
162
+ return parseMessageType(value);
163
+ }
164
+ function resolveSendType(type, to) {
165
+ const normalizedTo = normalizeRecipient(to);
166
+ const resolved = type ?? (normalizedTo === "*" || normalizedTo.startsWith("@session:") ? "broadcast" : "note");
167
+ validateSendType(resolved, normalizedTo);
168
+ return resolved;
169
+ }
170
+ function resolveSendTypeSafe(type, to) {
171
+ try {
172
+ return { ok: true, type: resolveSendType(type, to) };
173
+ } catch (err) {
174
+ return { ok: false, error: err.message };
175
+ }
176
+ }
177
+ function parsePriority(value) {
178
+ if (typeof value === "string" && PRIORITIES.has(value)) {
179
+ return value;
180
+ }
181
+ if (typeof value === "string") return "normal";
182
+ throw new TypeError('mailbox message field "priority" must be a string');
183
+ }
184
+ function parseAudience(value) {
185
+ if (value === void 0 || value === "all") return void 0;
186
+ if (typeof value === "string" && AUDIENCES.has(value)) {
187
+ return value;
188
+ }
189
+ throw new TypeError('mailbox message field "audience" is invalid');
190
+ }
191
+ function parseReadReceipts(record, to) {
192
+ const value = record["readBy"];
193
+ if (value === void 0) {
194
+ const legacyReadAt = record["readAt"];
195
+ return record["read"] === true && typeof legacyReadAt === "string" ? { [to || "unknown"]: legacyReadAt } : {};
196
+ }
197
+ if (!isRecord(value)) {
198
+ throw new TypeError('mailbox message field "readBy" must be an object');
199
+ }
200
+ const receipts = {};
201
+ for (const [agentId, timestamp] of Object.entries(value)) {
202
+ if (typeof timestamp !== "string") {
203
+ throw new TypeError("mailbox message read receipt timestamps must be strings");
204
+ }
205
+ receipts[agentId] = timestamp;
206
+ }
207
+ return receipts;
208
+ }
209
+ function parseTaskContext(value) {
210
+ if (value === void 0) return void 0;
211
+ if (!isRecord(value)) {
212
+ throw new TypeError('mailbox message field "taskContext" must be an object');
213
+ }
214
+ const status = value["status"];
215
+ if (status !== void 0 && (typeof status !== "string" || !TASK_STATUSES.has(status))) {
216
+ throw new TypeError("mailbox message taskContext status is invalid");
217
+ }
218
+ return {
219
+ ...optionalString(value, "agentRole"),
220
+ ...optionalString(value, "agentName"),
221
+ ...optionalString(value, "taskId"),
222
+ ...status === void 0 ? {} : { status }
223
+ };
224
+ }
225
+ function parseSessionAffinity(value) {
226
+ if (value === void 0) return void 0;
227
+ if (!isRecord(value)) {
228
+ throw new TypeError('mailbox message field "sessionAffinity" must be an object');
229
+ }
230
+ const sessionId = value["sessionId"];
231
+ const reportId = value["reportId"];
232
+ const kind = optionalString(value, "kind");
233
+ if (sessionId !== void 0) {
234
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
235
+ throw new TypeError("mailbox message sessionAffinity.sessionId must be a non-empty string");
236
+ }
237
+ return {
238
+ sessionId,
239
+ ...optionalString(value, "reportId"),
240
+ ...kind
241
+ };
242
+ }
243
+ if (typeof reportId !== "string" || reportId.length === 0) {
244
+ throw new TypeError(
245
+ "mailbox message sessionAffinity.reportId must be a non-empty string when sessionId is absent"
246
+ );
247
+ }
248
+ return {
249
+ reportId,
250
+ ...kind
251
+ };
252
+ }
253
+ function parseMailboxMessage(value) {
254
+ if (!isRecord(value)) throw new TypeError("mailbox message must be an object");
255
+ const to = value["to"] === void 0 ? "" : requiredString(value, "to");
256
+ const completed = value["completed"];
257
+ if (typeof completed !== "boolean") {
258
+ throw new TypeError('mailbox message field "completed" must be a boolean');
259
+ }
260
+ const taskContext = parseTaskContext(value["taskContext"]);
261
+ const audience = parseAudience(value["audience"]);
262
+ const sessionAffinity = parseSessionAffinity(value["sessionAffinity"]);
263
+ return {
264
+ id: requiredString(value, "id"),
265
+ from: requiredString(value, "from"),
266
+ to,
267
+ type: parseMessageType(value["type"]),
268
+ ...audience === void 0 ? {} : { audience },
269
+ subject: requiredString(value, "subject"),
270
+ body: requiredString(value, "body"),
271
+ priority: parsePriority(value["priority"]),
272
+ readBy: parseReadReceipts(value, to),
273
+ completed,
274
+ timestamp: requiredString(value, "timestamp"),
275
+ ...optionalString(value, "completedBy"),
276
+ ...optionalString(value, "outcome"),
277
+ ...optionalString(value, "completedAt"),
278
+ ...optionalString(value, "deletedAt"),
279
+ ...optionalString(value, "deletedBy"),
280
+ ...optionalString(value, "replyTo"),
281
+ ...optionalString(value, "senderSessionId"),
282
+ ...optionalString(value, "expiresAt"),
283
+ ...taskContext === void 0 ? {} : { taskContext },
284
+ ...sessionAffinity === void 0 ? {} : { sessionAffinity }
285
+ };
286
+ }
287
+ function isAckRecord(value) {
288
+ return typeof value === "object" && value !== null && !Array.isArray(value) && value["__ack"] === true;
289
+ }
290
+ function applyAckToMessage(msg, ack) {
291
+ if (ack.read && !(ack.readerId in msg.readBy)) {
292
+ msg.readBy[ack.readerId] = ack.timestamp;
293
+ }
294
+ if (ack.completed && !msg.completed) {
295
+ msg.completed = true;
296
+ msg.completedBy = ack.completedBy ?? ack.readerId;
297
+ msg.completedAt = ack.timestamp;
298
+ }
299
+ if (ack.outcome !== void 0 && msg.outcome !== ack.outcome) {
300
+ msg.outcome = ack.outcome;
301
+ }
302
+ if (ack.deleted === true) {
303
+ msg.deletedAt = ack.timestamp;
304
+ msg.deletedBy = ack.deletedBy ?? ack.readerId;
305
+ }
306
+ if (ack.deleted === false) {
307
+ delete msg.deletedAt;
308
+ delete msg.deletedBy;
309
+ }
310
+ }
311
+
312
+ // src/coordination/mailbox-receipt-folding.ts
313
+ function isFanOutRecipient(to) {
314
+ if (to === "*") return true;
315
+ if (to.startsWith("@session:")) return true;
316
+ return !to.includes("@") && !to.includes("#");
317
+ }
318
+ function materializeMessage(msg, msgReceipts) {
319
+ const recipientState = foldRecipientState(msg, msgReceipts);
320
+ const legacyGlobalCompletion = classifyLegacyCompletion(msg, msgReceipts);
321
+ return {
322
+ ...msg,
323
+ recipientState,
324
+ ...legacyGlobalCompletion ? { legacyGlobalCompletion: true } : {}
325
+ };
326
+ }
327
+ function foldRecipientState(msg, v2Receipts) {
328
+ const state = {};
329
+ for (const [actorId, readAt] of Object.entries(msg.readBy)) {
330
+ state[actorId] = { actorId, readAt };
331
+ }
332
+ if (msg.completed && msg.completedBy && !isFanOutRecipient(msg.to)) {
333
+ const existing = state[msg.completedBy] ?? { actorId: msg.completedBy };
334
+ state[msg.completedBy] = {
335
+ ...existing,
336
+ completedAt: msg.completedAt ?? msg.timestamp,
337
+ completedBy: msg.completedBy,
338
+ ...msg.outcome !== void 0 ? { outcome: msg.outcome } : {}
339
+ };
340
+ }
341
+ const sorted = [...v2Receipts].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
342
+ for (const receipt of sorted) {
343
+ const actorId = receipt.actorId;
344
+ const existing = state[actorId] ?? { actorId };
345
+ const readAt = existing.readAt ?? (receipt.read === true ? receipt.timestamp : void 0);
346
+ let completedAt = existing.completedAt;
347
+ let completedBy = existing.completedBy;
348
+ if (receipt.completed === true) {
349
+ completedAt = receipt.timestamp;
350
+ completedBy = actorId;
351
+ } else if (receipt.completed === false) {
352
+ completedAt = void 0;
353
+ completedBy = void 0;
354
+ }
355
+ const outcome = receipt.outcome !== void 0 ? receipt.outcome : existing.outcome;
356
+ state[actorId] = { actorId, readAt, completedAt, completedBy, outcome };
357
+ }
358
+ return state;
359
+ }
360
+ function classifyLegacyCompletion(msg, v2Receipts) {
361
+ if (!msg.completed) return false;
362
+ if (v2Receipts.some((r) => r.completed === true)) return false;
363
+ return isFanOutRecipient(msg.to);
364
+ }
365
+
366
+ // src/coordination/sqlite-mailbox-rows.ts
367
+ var MALFORMED_TIMESTAMP = "last_seen_at NOT GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T*'";
368
+ function withoutAggregateCompletion(message) {
369
+ const stored = {
370
+ ...message,
371
+ completed: message.legacyGlobalCompletion === true
372
+ };
373
+ if (!stored.completed) {
374
+ delete stored.completedBy;
375
+ delete stored.completedAt;
376
+ }
377
+ delete stored.outcome;
378
+ return stored;
379
+ }
380
+ function persistMessage(db, message, legacyGlobalCompletion = false) {
381
+ const stored = { ...message, readBy: { ...message.readBy } };
382
+ delete stored.recipientState;
383
+ delete stored.legacyGlobalCompletion;
384
+ db.prepare(`
385
+ INSERT INTO messages(
386
+ id, from_id, to_id, type, priority, timestamp, completed, completed_at,
387
+ deleted_at, sender_session_id, reply_to, expires_at,
388
+ legacy_global_completion, data
389
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
390
+ ON CONFLICT(id) DO UPDATE SET
391
+ from_id = excluded.from_id,
392
+ to_id = excluded.to_id,
393
+ type = excluded.type,
394
+ priority = excluded.priority,
395
+ timestamp = excluded.timestamp,
396
+ completed = excluded.completed,
397
+ completed_at = excluded.completed_at,
398
+ deleted_at = excluded.deleted_at,
399
+ sender_session_id = excluded.sender_session_id,
400
+ reply_to = excluded.reply_to,
401
+ expires_at = excluded.expires_at,
402
+ legacy_global_completion = excluded.legacy_global_completion,
403
+ data = excluded.data
404
+ `).run(
405
+ message.id,
406
+ message.from,
407
+ message.to,
408
+ message.type,
409
+ message.priority,
410
+ message.timestamp,
411
+ message.completed ? 1 : 0,
412
+ message.completedAt ?? null,
413
+ message.deletedAt ?? null,
414
+ message.senderSessionId ?? null,
415
+ message.replyTo ?? null,
416
+ message.expiresAt ?? null,
417
+ legacyGlobalCompletion ? 1 : 0,
418
+ JSON.stringify(stored)
419
+ );
420
+ }
421
+ function persistReceipt(db, messageId, state) {
422
+ db.prepare(`
423
+ INSERT INTO message_receipts(
424
+ message_id, actor_id, read_at, completed_at, completed_by, outcome
425
+ ) VALUES (?, ?, ?, ?, ?, ?)
426
+ ON CONFLICT(message_id, actor_id) DO UPDATE SET
427
+ read_at = excluded.read_at,
428
+ completed_at = excluded.completed_at,
429
+ completed_by = excluded.completed_by,
430
+ outcome = excluded.outcome
431
+ `).run(
432
+ messageId,
433
+ state.actorId,
434
+ state.readAt ?? null,
435
+ state.completedAt ?? null,
436
+ state.completedBy ?? null,
437
+ state.outcome ?? null
438
+ );
439
+ }
440
+ function materializeMessageRows(db, rows) {
441
+ if (rows.length === 0) return [];
442
+ const receiptRows = [];
443
+ for (const ids of chunk(
444
+ rows.map((row) => row.id),
445
+ 400
446
+ )) {
447
+ const receiptSql = `
448
+ SELECT message_id, actor_id, read_at, completed_at, completed_by, outcome
449
+ FROM message_receipts
450
+ WHERE message_id IN (${ids.map(() => "?").join(", ")})
451
+ `;
452
+ receiptRows.push(...db.prepare(receiptSql).all(...ids));
453
+ }
454
+ const receiptState = /* @__PURE__ */ new Map();
455
+ for (const row of receiptRows) {
456
+ const states = receiptState.get(row.message_id) ?? {};
457
+ states[row.actor_id] = {
458
+ actorId: row.actor_id,
459
+ ...row.read_at !== null ? { readAt: row.read_at } : {},
460
+ ...row.completed_at !== null ? { completedAt: row.completed_at } : {},
461
+ ...row.completed_by !== null ? { completedBy: row.completed_by } : {},
462
+ ...row.outcome !== null ? { outcome: row.outcome } : {}
463
+ };
464
+ receiptState.set(row.message_id, states);
465
+ }
466
+ return rows.map((row) => {
467
+ const base = JSON.parse(row.data);
468
+ const recipientState = receiptState.get(row.id) ?? {};
469
+ const readBy = { ...base.readBy };
470
+ for (const state of Object.values(recipientState)) {
471
+ if (state.readAt !== void 0) readBy[state.actorId] = state.readAt;
472
+ }
473
+ return {
474
+ ...base,
475
+ readBy,
476
+ recipientState,
477
+ ...row.legacy_global_completion === 1 ? { legacyGlobalCompletion: true } : {}
478
+ };
479
+ });
480
+ }
481
+ function deleteMessages(db, ids) {
482
+ for (const chunkIds of chunk(ids, 400)) {
483
+ db.prepare(`DELETE FROM messages WHERE id IN (${chunkIds.map(() => "?").join(", ")})`).run(
484
+ ...chunkIds
485
+ );
486
+ }
487
+ }
488
+ function* chunk(values, size) {
489
+ for (let start = 0; start < values.length; start += size) {
490
+ yield values.slice(start, start + size);
491
+ }
492
+ }
493
+ function persistAgent(db, agent) {
494
+ db.prepare(`
495
+ INSERT INTO agents(
496
+ agent_id, session_id, name, role, status, current_tool, current_task,
497
+ iterations, tool_calls, registered_at, last_seen_at, pid, source
498
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
499
+ ON CONFLICT(agent_id) DO UPDATE SET
500
+ session_id = excluded.session_id,
501
+ name = excluded.name,
502
+ role = excluded.role,
503
+ status = excluded.status,
504
+ current_tool = excluded.current_tool,
505
+ current_task = excluded.current_task,
506
+ iterations = excluded.iterations,
507
+ tool_calls = excluded.tool_calls,
508
+ registered_at = excluded.registered_at,
509
+ last_seen_at = excluded.last_seen_at,
510
+ pid = excluded.pid,
511
+ source = excluded.source
512
+ `).run(
513
+ agent.agentId,
514
+ agent.sessionId,
515
+ agent.name,
516
+ agent.role ?? null,
517
+ agent.status,
518
+ agent.currentTool ?? null,
519
+ agent.currentTask ?? null,
520
+ agent.iterations,
521
+ agent.toolCalls,
522
+ agent.registeredAt,
523
+ agent.lastSeenAt,
524
+ agent.pid,
525
+ agent.source ?? null
526
+ );
527
+ }
528
+ function readAgents(db) {
529
+ const rows = db.prepare("SELECT * FROM agents").all();
530
+ const agents = /* @__PURE__ */ new Map();
531
+ for (const row of rows) {
532
+ const agent = {
533
+ agentId: String(row["agent_id"]),
534
+ sessionId: String(row["session_id"]),
535
+ name: String(row["name"]),
536
+ ...row["role"] !== null ? { role: String(row["role"]) } : {},
537
+ status: row["status"],
538
+ ...row["current_tool"] !== null ? { currentTool: String(row["current_tool"]) } : {},
539
+ ...row["current_task"] !== null ? { currentTask: String(row["current_task"]) } : {},
540
+ iterations: Number(row["iterations"]),
541
+ toolCalls: Number(row["tool_calls"]),
542
+ registeredAt: String(row["registered_at"]),
543
+ lastSeenAt: String(row["last_seen_at"]),
544
+ pid: Number(row["pid"]),
545
+ ...row["source"] !== null ? { source: row["source"] } : {}
546
+ };
547
+ agents.set(agent.agentId, agent);
548
+ }
549
+ return agents;
550
+ }
551
+ function pruneAgents(db, maxAgeMs = AGENT_STALE_MS) {
552
+ const cutoff = new Date(Date.now() - Math.max(0, maxAgeMs)).toISOString();
553
+ const result = db.prepare(`DELETE FROM agents WHERE last_seen_at < ? OR ${MALFORMED_TIMESTAMP}`).run(cutoff);
554
+ return Number(result.changes);
555
+ }
556
+ function persistClient(db, client) {
557
+ db.prepare(`
558
+ INSERT INTO clients(
559
+ client_id, session_id, name, source, registered_at, last_seen_at, pid
560
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
561
+ ON CONFLICT(client_id) DO UPDATE SET
562
+ session_id = excluded.session_id,
563
+ name = excluded.name,
564
+ source = excluded.source,
565
+ registered_at = excluded.registered_at,
566
+ last_seen_at = excluded.last_seen_at,
567
+ pid = excluded.pid
568
+ `).run(
569
+ client.clientId,
570
+ client.sessionId,
571
+ client.name,
572
+ client.source,
573
+ client.registeredAt,
574
+ client.lastSeenAt,
575
+ client.pid
576
+ );
577
+ }
578
+ function readClients(db) {
579
+ const rows = db.prepare("SELECT * FROM clients").all();
580
+ const clients = /* @__PURE__ */ new Map();
581
+ for (const row of rows) {
582
+ const client = {
583
+ clientId: String(row["client_id"]),
584
+ sessionId: String(row["session_id"]),
585
+ name: String(row["name"]),
586
+ source: row["source"],
587
+ registeredAt: String(row["registered_at"]),
588
+ lastSeenAt: String(row["last_seen_at"]),
589
+ pid: Number(row["pid"])
590
+ };
591
+ clients.set(client.clientId, client);
592
+ }
593
+ return clients;
594
+ }
595
+ function pruneClients(db) {
596
+ const cutoff = new Date(Date.now() - CLIENT_STALE_MS).toISOString();
597
+ const result = db.prepare(`DELETE FROM clients WHERE last_seen_at < ? OR ${MALFORMED_TIMESTAMP}`).run(cutoff);
598
+ return Number(result.changes);
599
+ }
600
+ function persistCredential(db, credential) {
601
+ db.prepare(`
602
+ INSERT INTO credentials(credential_id, status, principal_id, expires_at, data)
603
+ VALUES (?, ?, ?, ?, ?)
604
+ ON CONFLICT(credential_id) DO UPDATE SET
605
+ status = excluded.status,
606
+ principal_id = excluded.principal_id,
607
+ expires_at = excluded.expires_at,
608
+ data = excluded.data
609
+ `).run(
610
+ credential.credentialId,
611
+ credential.status,
612
+ credential.principalId,
613
+ credential.expiresAt,
614
+ JSON.stringify(credential)
615
+ );
616
+ }
617
+
618
+ // src/coordination/sqlite-mailbox-schema.ts
619
+ import * as fs from "node:fs";
620
+ import * as path2 from "node:path";
621
+ import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
622
+
623
+ // src/coordination/mailbox-parse-state.ts
624
+ function parseMailboxFile(raw) {
625
+ return createMailboxParseState(raw).projections;
626
+ }
627
+ function createMailboxParseState(raw) {
628
+ const state = {
629
+ messages: [],
630
+ projections: [],
631
+ indexById: /* @__PURE__ */ new Map(),
632
+ receiptsByMessage: /* @__PURE__ */ new Map()
633
+ };
634
+ ingestMailboxChunk(state, raw);
635
+ return state;
636
+ }
637
+ function ingestMailboxChunk(state, chunk2) {
638
+ const firstNewIndex = state.messages.length;
639
+ const ackRecords = [];
640
+ const staleExisting = /* @__PURE__ */ new Set();
641
+ for (const line of chunk2.split(LINE_SEPARATOR)) {
642
+ if (line.trim().length === 0) continue;
643
+ let parsed;
644
+ try {
645
+ parsed = JSON.parse(line);
646
+ } catch {
647
+ continue;
648
+ }
649
+ if (isMailboxReceiptRecordV2(parsed)) {
650
+ const list = state.receiptsByMessage.get(parsed.messageId);
651
+ if (list) list.push(parsed);
652
+ else state.receiptsByMessage.set(parsed.messageId, [parsed]);
653
+ for (const index2 of state.indexById.get(parsed.messageId) ?? []) {
654
+ if (index2 < firstNewIndex) staleExisting.add(index2);
655
+ }
656
+ continue;
657
+ }
658
+ if (isAckRecord(parsed)) {
659
+ ackRecords.push(parsed);
660
+ continue;
661
+ }
662
+ let message;
663
+ try {
664
+ message = parseMailboxMessage(parsed);
665
+ } catch {
666
+ continue;
667
+ }
668
+ const index = state.messages.length;
669
+ state.messages.push(message);
670
+ const indices = state.indexById.get(message.id);
671
+ if (indices) indices.push(index);
672
+ else state.indexById.set(message.id, [index]);
673
+ }
674
+ for (const ack of ackRecords) {
675
+ const indices = state.indexById.get(ack.messageId);
676
+ if (indices === void 0 || indices.length === 0) continue;
677
+ const index = indices[indices.length - 1];
678
+ applyAckToMessage(state.messages[index], ack);
679
+ if (index < firstNewIndex) staleExisting.add(index);
680
+ }
681
+ for (const index of staleExisting) {
682
+ const message = state.messages[index];
683
+ state.projections[index] = materializeMessage(
684
+ message,
685
+ state.receiptsByMessage.get(message.id) ?? []
686
+ );
687
+ }
688
+ for (let index = firstNewIndex; index < state.messages.length; index++) {
689
+ const message = state.messages[index];
690
+ state.projections.push(
691
+ materializeMessage(message, state.receiptsByMessage.get(message.id) ?? [])
692
+ );
693
+ }
694
+ }
695
+
696
+ // src/coordination/mailbox-registry-codec.ts
697
+ function parseAgentRegistryEntry(value) {
698
+ if (typeof value !== "object" || value === null) return null;
699
+ const v = value;
700
+ if (typeof v.agentId !== "string") return null;
701
+ if (typeof v.sessionId !== "string") return null;
702
+ const statuses = ["idle", "busy", "running", "streaming", "waiting_user", "error"];
703
+ const status = typeof v.status === "string" && statuses.includes(v.status) ? v.status : "idle";
704
+ return {
705
+ ...v,
706
+ agentId: v.agentId,
707
+ sessionId: v.sessionId,
708
+ name: typeof v.name === "string" ? v.name : v.agentId,
709
+ registeredAt: typeof v.registeredAt === "string" ? v.registeredAt : (/* @__PURE__ */ new Date(0)).toISOString(),
710
+ lastSeenAt: typeof v.lastSeenAt === "string" ? v.lastSeenAt : (/* @__PURE__ */ new Date(0)).toISOString(),
711
+ iterations: typeof v.iterations === "number" && Number.isFinite(v.iterations) ? v.iterations : 0,
712
+ toolCalls: typeof v.toolCalls === "number" && Number.isFinite(v.toolCalls) ? v.toolCalls : 0,
713
+ pid: typeof v.pid === "number" && Number.isFinite(v.pid) ? v.pid : 0,
714
+ status
715
+ };
716
+ }
717
+ function parseClientRegistryEntry(value) {
718
+ if (typeof value !== "object" || value === null) return null;
719
+ const v = value;
720
+ if (typeof v.clientId !== "string") return null;
721
+ if (typeof v.sessionId !== "string") return null;
722
+ const sources = ["repl", "tui", "webui", "http"];
723
+ const source = typeof v.source === "string" && sources.includes(v.source) ? v.source : "http";
724
+ return {
725
+ ...v,
726
+ clientId: v.clientId,
727
+ sessionId: v.sessionId,
728
+ name: typeof v.name === "string" ? v.name : v.clientId,
729
+ registeredAt: typeof v.registeredAt === "string" ? v.registeredAt : (/* @__PURE__ */ new Date(0)).toISOString(),
730
+ lastSeenAt: typeof v.lastSeenAt === "string" ? v.lastSeenAt : (/* @__PURE__ */ new Date(0)).toISOString(),
731
+ pid: typeof v.pid === "number" && Number.isFinite(v.pid) ? v.pid : 0,
732
+ source
733
+ };
734
+ }
735
+
736
+ // src/coordination/sqlite-mailbox-schema.ts
737
+ var SQLITE_MAILBOX_SCHEMA_VERSION = 2;
738
+ var DatabaseSyncCtor;
739
+ function loadDatabaseSync() {
740
+ if (DatabaseSyncCtor) return DatabaseSyncCtor;
741
+ return withSqliteExperimentalWarningSuppressed(() => {
742
+ DatabaseSyncCtor = loadRuntimeDatabaseSync();
743
+ return DatabaseSyncCtor;
744
+ });
745
+ }
746
+ function initializeSchema(ctx) {
747
+ const { db } = ctx;
748
+ db.exec(`
749
+ CREATE TABLE IF NOT EXISTS mailbox_meta (
750
+ key TEXT PRIMARY KEY,
751
+ value TEXT NOT NULL
752
+ );
753
+ CREATE TABLE IF NOT EXISTS messages (
754
+ id TEXT PRIMARY KEY,
755
+ from_id TEXT NOT NULL,
756
+ to_id TEXT NOT NULL,
757
+ type TEXT NOT NULL,
758
+ priority TEXT NOT NULL,
759
+ timestamp TEXT NOT NULL,
760
+ completed INTEGER NOT NULL DEFAULT 0,
761
+ completed_at TEXT,
762
+ deleted_at TEXT,
763
+ sender_session_id TEXT,
764
+ reply_to TEXT,
765
+ expires_at TEXT,
766
+ legacy_global_completion INTEGER NOT NULL DEFAULT 0,
767
+ data TEXT NOT NULL
768
+ );
769
+ CREATE TABLE IF NOT EXISTS message_receipts (
770
+ message_id TEXT NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
771
+ actor_id TEXT NOT NULL,
772
+ read_at TEXT,
773
+ completed_at TEXT,
774
+ completed_by TEXT,
775
+ outcome TEXT,
776
+ PRIMARY KEY (message_id, actor_id)
777
+ );
778
+ CREATE TABLE IF NOT EXISTS agents (
779
+ agent_id TEXT PRIMARY KEY,
780
+ session_id TEXT NOT NULL,
781
+ name TEXT NOT NULL,
782
+ role TEXT,
783
+ status TEXT NOT NULL,
784
+ current_tool TEXT,
785
+ current_task TEXT,
786
+ iterations INTEGER NOT NULL,
787
+ tool_calls INTEGER NOT NULL,
788
+ registered_at TEXT NOT NULL,
789
+ last_seen_at TEXT NOT NULL,
790
+ pid INTEGER NOT NULL,
791
+ source TEXT
792
+ );
793
+ CREATE TABLE IF NOT EXISTS clients (
794
+ client_id TEXT PRIMARY KEY,
795
+ session_id TEXT NOT NULL,
796
+ name TEXT NOT NULL,
797
+ source TEXT NOT NULL,
798
+ registered_at TEXT NOT NULL,
799
+ last_seen_at TEXT NOT NULL,
800
+ pid INTEGER NOT NULL
801
+ );
802
+ CREATE TABLE IF NOT EXISTS credentials (
803
+ credential_id TEXT PRIMARY KEY,
804
+ status TEXT NOT NULL,
805
+ principal_id TEXT NOT NULL,
806
+ expires_at TEXT NOT NULL,
807
+ data TEXT NOT NULL
808
+ );
809
+ CREATE INDEX IF NOT EXISTS idx_messages_to_timestamp ON messages(to_id, timestamp DESC);
810
+ CREATE INDEX IF NOT EXISTS idx_messages_from_timestamp ON messages(from_id, timestamp DESC);
811
+ CREATE INDEX IF NOT EXISTS idx_messages_type_timestamp ON messages(type, timestamp DESC);
812
+ CREATE INDEX IF NOT EXISTS idx_messages_deleted_at ON messages(deleted_at);
813
+ CREATE INDEX IF NOT EXISTS idx_messages_session_timestamp ON messages(sender_session_id, timestamp DESC);
814
+ CREATE INDEX IF NOT EXISTS idx_messages_reply_timestamp ON messages(reply_to, timestamp DESC);
815
+ CREATE INDEX IF NOT EXISTS idx_receipts_actor ON message_receipts(actor_id, message_id);
816
+ CREATE INDEX IF NOT EXISTS idx_agents_last_seen ON agents(last_seen_at);
817
+ CREATE INDEX IF NOT EXISTS idx_clients_last_seen ON clients(last_seen_at);
818
+ CREATE INDEX IF NOT EXISTS idx_credentials_status ON credentials(status, expires_at);
819
+ `);
820
+ db.prepare("INSERT INTO mailbox_meta(key, value) VALUES (?, ?) ON CONFLICT(key) DO NOTHING").run(
821
+ "schema_version",
822
+ String(SQLITE_MAILBOX_SCHEMA_VERSION)
823
+ );
824
+ const schema = db.prepare("SELECT value FROM mailbox_meta WHERE key = ?").get("schema_version");
825
+ const foundVersion = Number(schema?.value);
826
+ if (!Number.isInteger(foundVersion) || foundVersion < 1 || foundVersion > SQLITE_MAILBOX_SCHEMA_VERSION) {
827
+ throw new Error(
828
+ `Unsupported mailbox SQLite schema ${schema?.value ?? "missing"}; this build supports ${SQLITE_MAILBOX_SCHEMA_VERSION}`
829
+ );
830
+ }
831
+ if (foundVersion < SQLITE_MAILBOX_SCHEMA_VERSION) {
832
+ db.prepare("UPDATE mailbox_meta SET value = ? WHERE key = ?").run(
833
+ String(SQLITE_MAILBOX_SCHEMA_VERSION),
834
+ "schema_version"
835
+ );
836
+ }
837
+ migrateLegacyCredentials(ctx);
838
+ }
839
+ function migrateLegacyCredentials(ctx) {
840
+ const { db } = ctx;
841
+ const marker = db.prepare("SELECT value FROM mailbox_meta WHERE key = ?").get("legacy_credentials_imported");
842
+ if (marker !== void 0) return;
843
+ const legacyPath = path2.join(ctx.projectDir, CREDENTIAL_STORE_FILE);
844
+ const credentials = [];
845
+ try {
846
+ for (const line of fs.readFileSync(legacyPath, "utf8").split(/\r?\n/u)) {
847
+ if (!line.trim()) continue;
848
+ try {
849
+ const credential = JSON.parse(line);
850
+ if (typeof credential.credentialId === "string" && typeof credential.verifier === "string" && typeof credential.principalId === "string")
851
+ credentials.push(credential);
852
+ } catch {
853
+ }
854
+ }
855
+ } catch (error) {
856
+ const code = error.code;
857
+ if (code !== "ENOENT") throw error;
858
+ }
859
+ ctx.transaction(() => {
860
+ for (const credential of credentials) persistCredential(db, credential);
861
+ db.prepare("INSERT INTO mailbox_meta(key, value) VALUES (?, ?)").run(
862
+ "legacy_credentials_imported",
863
+ (/* @__PURE__ */ new Date()).toISOString()
864
+ );
865
+ });
866
+ }
867
+ function migrateLegacyFiles(ctx) {
868
+ const { db } = ctx;
869
+ const marker = db.prepare("SELECT value FROM mailbox_meta WHERE key = ?").get("legacy_files_imported");
870
+ if (marker !== void 0) return;
871
+ const messages = readLegacyMessages(ctx.projectDir);
872
+ const agents = readLegacyRegistry(
873
+ path2.join(ctx.projectDir, "_mailbox.registry.json"),
874
+ parseAgentRegistryEntry
875
+ );
876
+ const clients = readLegacyRegistry(
877
+ path2.join(ctx.projectDir, GLOBAL_MAILBOX_CLIENT_REGISTRY_FILE),
878
+ parseClientRegistryEntry
879
+ );
880
+ ctx.transaction(() => {
881
+ for (const message of messages) {
882
+ const projection = message;
883
+ persistMessage(db, message, projection.legacyGlobalCompletion === true);
884
+ for (const state of Object.values(projection.recipientState ?? {})) {
885
+ persistReceipt(db, message.id, state);
886
+ }
887
+ }
888
+ for (const agent of agents.values()) persistAgent(db, agent);
889
+ for (const client of clients.values()) persistClient(db, client);
890
+ db.prepare("INSERT INTO mailbox_meta(key, value) VALUES (?, ?)").run(
891
+ "legacy_files_imported",
892
+ (/* @__PURE__ */ new Date()).toISOString()
893
+ );
894
+ });
895
+ }
896
+ function readLegacyMessages(projectDir) {
897
+ try {
898
+ return parseMailboxFile(fs.readFileSync(path2.join(projectDir, GLOBAL_MAILBOX_FILE), "utf8"));
899
+ } catch (error) {
900
+ if (error.code === "ENOENT") return [];
901
+ throw error;
902
+ }
903
+ }
904
+ function readLegacyRegistry(filePath, parseEntry) {
905
+ try {
906
+ const raw = JSON.parse(fs.readFileSync(filePath, "utf8"));
907
+ const result = /* @__PURE__ */ new Map();
908
+ for (const [id, value] of Object.entries(raw)) {
909
+ const parsed = parseEntry(value);
910
+ if (parsed !== null) result.set(id, parsed);
911
+ }
912
+ return result;
913
+ } catch (error) {
914
+ if (error.code === "ENOENT") return /* @__PURE__ */ new Map();
915
+ throw error;
916
+ }
917
+ }
918
+
919
+ export {
920
+ AGENT_STALE_MS,
921
+ CLIENT_STALE_MS,
922
+ HEARTBEAT_THROTTLE_MS,
923
+ MAILBOX_AWARENESS_INTERVAL_MS,
924
+ MAILBOX_HEARTBEAT_INTERVAL_MS,
925
+ HQ_MAILBOX_SNAPSHOT_MIN_INTERVAL_MS,
926
+ PULSE_MIN_READ_INTERVAL_MS,
927
+ UNREAD_CHECK_MIN_INTERVAL_MS,
928
+ AUTO_COMPACT_INTERVAL_MS,
929
+ AUTO_COMPACT_READ_MAX_AGE_MS,
930
+ AUTO_COMPACT_DEFAULT_TTL_MS,
931
+ AUTO_COMPACT_TYPE_TTL_MS,
932
+ MAILBOX_MAX_QUERY_LIMIT,
933
+ MAILBOX_MAX_ACK_BATCH,
934
+ normalizeMailboxMessageType,
935
+ resolveSendType,
936
+ resolveSendTypeSafe,
937
+ isFanOutRecipient,
938
+ MAX_CREDENTIAL_TTL,
939
+ ROTATION_OVERLAP_MS,
940
+ createMailboxCredential,
941
+ redactMailboxCredential,
942
+ verifyMailboxCredential,
943
+ withoutAggregateCompletion,
944
+ persistMessage,
945
+ persistReceipt,
946
+ materializeMessageRows,
947
+ deleteMessages,
948
+ persistAgent,
949
+ readAgents,
950
+ pruneAgents,
951
+ persistClient,
952
+ readClients,
953
+ pruneClients,
954
+ persistCredential,
955
+ resolveProjectDir,
956
+ loadDatabaseSync,
957
+ initializeSchema,
958
+ migrateLegacyFiles
959
+ };
960
+ //# sourceMappingURL=chunk-IRUTEHCE.js.map