@askexenow/exe-os 0.9.274 → 0.9.276

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 (378) hide show
  1. package/deploy/stack-manifests/v0.9.json +1329 -1206
  2. package/dist/active-agent-ELN34YCO.js +25 -0
  3. package/dist/active-agent-S6HAT63V.js +26 -0
  4. package/dist/agentic-ontology-WD7UT2GP.js +25 -0
  5. package/dist/backfill-metadata-D64TBGCN.js +597 -0
  6. package/dist/backfill-metadata-TIG7BGLY.js +597 -0
  7. package/dist/background-jobs-3UCY6XQ6.js +25 -0
  8. package/dist/behaviors-KS2QYUOI.js +25 -0
  9. package/dist/bin/age-ontology-load.js +2 -2
  10. package/dist/bin/agentic-ontology-backfill.js +8 -8
  11. package/dist/bin/agentic-reflection-backfill.js +9 -9
  12. package/dist/bin/agentic-semantic-label.js +8 -8
  13. package/dist/bin/backfill-conversations.js +8 -8
  14. package/dist/bin/backfill-responses.js +8 -8
  15. package/dist/bin/backfill-vectors.js +10 -10
  16. package/dist/bin/bulk-sync-postgres.js +9 -9
  17. package/dist/bin/cc-doctor.js +6 -6
  18. package/dist/bin/cleanup-stale-review-tasks.js +12 -12
  19. package/dist/bin/cli.js +20 -20
  20. package/dist/bin/exe-agent-config.js +4 -4
  21. package/dist/bin/exe-agent.js +5 -5
  22. package/dist/bin/exe-assign.js +10 -10
  23. package/dist/bin/exe-boot.js +20 -20
  24. package/dist/bin/exe-call.js +5 -5
  25. package/dist/bin/exe-cloud.js +8 -8
  26. package/dist/bin/exe-dispatch.js +12 -12
  27. package/dist/bin/exe-doctor.js +1 -1
  28. package/dist/bin/exe-export-behaviors.js +9 -9
  29. package/dist/bin/exe-forget.js +8 -8
  30. package/dist/bin/exe-gateway.js +8 -8
  31. package/dist/bin/exe-healthcheck.js +6 -6
  32. package/dist/bin/exe-heartbeat.js +12 -12
  33. package/dist/bin/exe-kill.js +16 -16
  34. package/dist/bin/exe-launch-agent.js +20 -20
  35. package/dist/bin/exe-new-employee.js +8 -8
  36. package/dist/bin/exe-pending-messages.js +13 -13
  37. package/dist/bin/exe-pending-notifications.js +12 -12
  38. package/dist/bin/exe-pending-reviews.js +12 -12
  39. package/dist/bin/exe-rename.js +5 -5
  40. package/dist/bin/exe-review.js +15 -15
  41. package/dist/bin/exe-search.js +7 -7
  42. package/dist/bin/exe-session-cleanup.js +18 -18
  43. package/dist/bin/exe-settings.js +7 -7
  44. package/dist/bin/exe-start-codex.js +13 -13
  45. package/dist/bin/exe-start-opencode.js +10 -10
  46. package/dist/bin/exe-status.js +13 -13
  47. package/dist/bin/exe-support.js +3 -3
  48. package/dist/bin/exe-team.js +4 -4
  49. package/dist/bin/git-sweep.js +13 -13
  50. package/dist/bin/graph-backfill.js +7 -7
  51. package/dist/bin/graph-export.js +7 -7
  52. package/dist/bin/import-history.js +9 -9
  53. package/dist/bin/install.js +7 -7
  54. package/dist/bin/intercom-check.js +4 -4
  55. package/dist/bin/mcp-sessions.js +2 -2
  56. package/dist/bin/orchestration-metrics.js +5 -5
  57. package/dist/bin/postgres-agentic-reflection-backfill.js +4 -4
  58. package/dist/bin/postgres-agentic-semantic-backfill.js +3 -3
  59. package/dist/bin/scan-tasks.js +12 -12
  60. package/dist/bin/setup.js +3 -3
  61. package/dist/bin/shard-migrate.js +7 -7
  62. package/dist/bin/stack-update.js +4 -4
  63. package/dist/bin/vps-health-gate.js +1 -1
  64. package/dist/branding-D253COCP.js +97 -0
  65. package/dist/capacity-monitor-LLGZM6GA.js +49 -0
  66. package/dist/capacity-monitor-WS7VVJTC.js +49 -0
  67. package/dist/catchup-brief-43X5J7BL.js +151 -0
  68. package/dist/catchup-brief-FAT5H2KH.js +151 -0
  69. package/dist/catchup-brief-MUWABIEX.js +151 -0
  70. package/dist/catchup-brief-PWWDZ4Z7.js +151 -0
  71. package/dist/catchup-brief-YZQU7LD3.js +151 -0
  72. package/dist/chunk-22N6BNXV.js +258 -0
  73. package/dist/chunk-2EDMJBSO.js +348 -0
  74. package/dist/chunk-36RHPMRM.js +13745 -0
  75. package/dist/chunk-3BYBAINX.js +818 -0
  76. package/dist/chunk-3FBDNOKA.js +97 -0
  77. package/dist/chunk-3O4KU3EA.js +54 -0
  78. package/dist/chunk-3RHPSZKF.js +1345 -0
  79. package/dist/chunk-3UZ2B4KE.js +526 -0
  80. package/dist/chunk-3Z2PJC6V.js +127 -0
  81. package/dist/chunk-4LQ5UGMM.js +85 -0
  82. package/dist/chunk-4TJV2SX5.js +227 -0
  83. package/dist/chunk-4UQZGZSF.js +159 -0
  84. package/dist/chunk-56OM6QLF.js +1051 -0
  85. package/dist/chunk-5BTZK345.js +448 -0
  86. package/dist/chunk-5ECWRU7F.js +58 -0
  87. package/dist/chunk-5FQNEKXL.js +50 -0
  88. package/dist/chunk-5JGYPU2V.js +13745 -0
  89. package/dist/chunk-5KIAMZBK.js +260 -0
  90. package/dist/chunk-5PVYMFK5.js +171 -0
  91. package/dist/chunk-5SDX3UAG.js +1021 -0
  92. package/dist/chunk-6GTMXZU2.js +197 -0
  93. package/dist/chunk-6KRJGGKJ.js +159 -0
  94. package/dist/chunk-7DXFPBRN.js +204 -0
  95. package/dist/chunk-7K32KHDT.js +50 -0
  96. package/dist/chunk-7NRLZQRM.js +1148 -0
  97. package/dist/chunk-A7XIRWM5.js +128 -0
  98. package/dist/chunk-AJSJWNI7.js +1148 -0
  99. package/dist/chunk-AN2NL33X.js +89 -0
  100. package/dist/chunk-ATWV5FER.js +157 -0
  101. package/dist/chunk-AU6Q5K6I.js +630 -0
  102. package/dist/chunk-BE6K6HT7.js +13745 -0
  103. package/dist/chunk-BER57L7R.js +244 -0
  104. package/dist/chunk-BHCGGKF7.js +2091 -0
  105. package/dist/chunk-BLB3MOXN.js +333 -0
  106. package/dist/chunk-BNZTW5DK.js +55 -0
  107. package/dist/chunk-C2IR4OGO.js +214 -0
  108. package/dist/chunk-CBO7FJQB.js +214 -0
  109. package/dist/chunk-CEPXBGAS.js +151 -0
  110. package/dist/chunk-CHXJT7O6.js +70 -0
  111. package/dist/chunk-CXIAU327.js +204 -0
  112. package/dist/chunk-DOHKUD26.js +366 -0
  113. package/dist/chunk-DPFGT2T5.js +1021 -0
  114. package/dist/chunk-DXGPGQTZ.js +551 -0
  115. package/dist/chunk-DYRRJNZG.js +818 -0
  116. package/dist/chunk-EP5PKTCF.js +76 -0
  117. package/dist/chunk-F5XWYDFE.js +1090 -0
  118. package/dist/chunk-FA4Y72TL.js +128 -0
  119. package/dist/chunk-FJE6RCPS.js +382 -0
  120. package/dist/chunk-FS6MBDRJ.js +190 -0
  121. package/dist/chunk-FZIRUCE5.js +297 -0
  122. package/dist/chunk-G3U2D2JR.js +1345 -0
  123. package/dist/chunk-G77I73CN.js +394 -0
  124. package/dist/chunk-GSN2CFE7.js +13745 -0
  125. package/dist/chunk-GTYRLDPF.js +128 -0
  126. package/dist/chunk-H3YWMLS4.js +132 -0
  127. package/dist/chunk-H4SQZEKD.js +41 -0
  128. package/dist/chunk-I772PYW4.js +2091 -0
  129. package/dist/chunk-ICVC6XC6.js +1073 -0
  130. package/dist/chunk-IGJOFP3V.js +81 -0
  131. package/dist/chunk-IJUH47AA.js +244 -0
  132. package/dist/chunk-IQFVWZQS.js +346 -0
  133. package/dist/chunk-JAP2N5ES.js +135 -0
  134. package/dist/chunk-JCKOUD7S.js +284 -0
  135. package/dist/chunk-JF5424J7.js +345 -0
  136. package/dist/chunk-JQJXWWTR.js +244 -0
  137. package/dist/chunk-JWLRS5AU.js +203 -0
  138. package/dist/chunk-JZZILUVN.js +69 -0
  139. package/dist/chunk-KETX4YMU.js +58 -0
  140. package/dist/chunk-KFKUY2MZ.js +240 -0
  141. package/dist/chunk-KLTHMXVE.js +280 -0
  142. package/dist/chunk-KMYMTYTF.js +262 -0
  143. package/dist/chunk-L7COBTV7.js +382 -0
  144. package/dist/chunk-L7KZLRHO.js +13745 -0
  145. package/dist/chunk-LWGW2QHP.js +75 -0
  146. package/dist/chunk-LYTIZLNF.js +129 -0
  147. package/dist/chunk-M34NJW4K.js +210 -0
  148. package/dist/chunk-M3CM5B4G.js +294 -0
  149. package/dist/chunk-M3FD44E5.js +38 -0
  150. package/dist/chunk-MN7UJSHM.js +363 -0
  151. package/dist/chunk-MTADEZ3J.js +58 -0
  152. package/dist/chunk-N3VRJKQX.js +54 -0
  153. package/dist/chunk-N532MB2W.js +290 -0
  154. package/dist/chunk-NEMNIJTY.js +333 -0
  155. package/dist/chunk-NFTOTZKL.js +617 -0
  156. package/dist/chunk-NQSHCAOH.js +163 -0
  157. package/dist/chunk-NQZKWG5S.js +604 -0
  158. package/dist/chunk-OFLNYGXJ.js +185 -0
  159. package/dist/chunk-OSKI5ZE5.js +346 -0
  160. package/dist/chunk-OUK53LFC.js +1073 -0
  161. package/dist/chunk-OW2W5DRQ.js +1148 -0
  162. package/dist/chunk-PLRCR6LW.js +1090 -0
  163. package/dist/chunk-QGNGAV5B.js +197 -0
  164. package/dist/chunk-QOV3CU2M.js +604 -0
  165. package/dist/chunk-QZBT6EXJ.js +1148 -0
  166. package/dist/chunk-R7HLLTIK.js +3961 -0
  167. package/dist/chunk-RDGF4T5S.js +377 -0
  168. package/dist/chunk-RIXOCFDZ.js +731 -0
  169. package/dist/chunk-RJB4IHY7.js +58 -0
  170. package/dist/chunk-RNJAQPVM.js +56 -0
  171. package/dist/chunk-RR2CD6CU.js +58 -0
  172. package/dist/chunk-RUHLTVW3.js +495 -0
  173. package/dist/chunk-RVPF7Q7X.js +1921 -0
  174. package/dist/chunk-RZQOKND6.js +76 -0
  175. package/dist/chunk-SE34CRK2.js +731 -0
  176. package/dist/chunk-SMDQTTDB.js +97 -0
  177. package/dist/chunk-SVAIOGPN.js +89 -0
  178. package/dist/chunk-SYLT5QCZ.js +127 -0
  179. package/dist/chunk-TPS5AMGN.js +448 -0
  180. package/dist/chunk-TQZLV2QV.js +1921 -0
  181. package/dist/chunk-UIJKWLFF.js +371 -0
  182. package/dist/chunk-UKQE4PGH.js +345 -0
  183. package/dist/chunk-VA5OPEGY.js +230 -0
  184. package/dist/chunk-VS7ZTWQR.js +3556 -0
  185. package/dist/chunk-VSHDYYHP.js +42 -0
  186. package/dist/chunk-WGDBENJ4.js +81 -0
  187. package/dist/chunk-WREI3KQR.js +377 -0
  188. package/dist/chunk-WVEKZU72.js +495 -0
  189. package/dist/chunk-WXQ6QK43.js +171 -0
  190. package/dist/chunk-X2SGZXVW.js +106 -0
  191. package/dist/chunk-XCX26PCH.js +1148 -0
  192. package/dist/chunk-XEBAKR2J.js +33 -0
  193. package/dist/chunk-XOZSYP7Y.js +562 -0
  194. package/dist/chunk-Y7OVCCAR.js +284 -0
  195. package/dist/chunk-YBF67NNY.js +377 -0
  196. package/dist/chunk-YSHYJGSL.js +1512 -0
  197. package/dist/chunk-YU3IMLUG.js +526 -0
  198. package/dist/chunk-YWZNRTOQ.js +221 -0
  199. package/dist/chunk-Z2NBGCIM.js +159 -0
  200. package/dist/chunk-Z73TGBDX.js +3961 -0
  201. package/dist/chunk-ZBC652FM.js +369 -0
  202. package/dist/chunk-ZCODOJ4Z.js +668 -0
  203. package/dist/chunk-ZITD4HLW.js +123 -0
  204. package/dist/chunk-ZM7SX4M4.js +30 -0
  205. package/dist/chunk-ZQUEZTFC.js +551 -0
  206. package/dist/co-activation-JCTPCXHF.js +72 -0
  207. package/dist/co-occurrence-BP6B3BH2.js +74 -0
  208. package/dist/code-context-index-F4OEDXA6.js +30 -0
  209. package/dist/conversation-wiki-populator-DIUJ4C7D.js +105 -0
  210. package/dist/core-memory-4FDW36TP.js +110 -0
  211. package/dist/core-memory-YVBILSBM.js +110 -0
  212. package/dist/crdt-sync-2ZFB3TNZ.js +33 -0
  213. package/dist/crm-webhook-4RZ7IS4B.js +10 -0
  214. package/dist/crm-webhook-JBOBSQ6W.js +10 -0
  215. package/dist/cto-delegation-gate-TKZXHJML.js +206 -0
  216. package/dist/cto-delegation-gate-WIETRXE3.js +206 -0
  217. package/dist/daemon-auth-WTRR4PDV.js +13 -0
  218. package/dist/daemon-orchestration-A4RCUQT3.js +135 -0
  219. package/dist/daemon-orchestration-O4DY5V52.js +135 -0
  220. package/dist/db-backup-JFTPWA6J.js +33 -0
  221. package/dist/dreaming-I3LRB7RF.js +32 -0
  222. package/dist/dreaming-K7OU7K6W.js +32 -0
  223. package/dist/entity-boost-6UYJZP6V.js +356 -0
  224. package/dist/exe-drift-UMKWLKS4.js +68 -0
  225. package/dist/exe-export-OW3JPYV5.js +73 -0
  226. package/dist/exe-export-VIACNSGD.js +73 -0
  227. package/dist/exe-import-UJS3KJSP.js +76 -0
  228. package/dist/exe-import-XUTWGVPM.js +76 -0
  229. package/dist/exe-key-HFQH2DSQ.js +579 -0
  230. package/dist/exe-key-MLC7AKR4.js +579 -0
  231. package/dist/exe-org-S52HWZS2.js +73 -0
  232. package/dist/exe-snapshot-DCDQ5U3N.js +164 -0
  233. package/dist/exe-snapshot-OUDGSSWH.js +164 -0
  234. package/dist/fast-db-init-23QWBHZU.js +7 -0
  235. package/dist/fast-db-init-ACRROC3C.js +7 -0
  236. package/dist/founder-context-XLQG5AO5.js +96 -0
  237. package/dist/gateway/index.js +9 -9
  238. package/dist/gateway-client-QMW3MECR.js +11 -0
  239. package/dist/git-staleness-IUY4PWYN.js +110 -0
  240. package/dist/git-task-sweep-DRRHHYSD.js +40 -0
  241. package/dist/git-task-sweep-OPZC6VJX.js +40 -0
  242. package/dist/global-procedures-HMPC5HAG.js +20 -0
  243. package/dist/graph-auto-extract-344QRTFR.js +162 -0
  244. package/dist/hook-integrity-2UWBTLHA.js +89 -0
  245. package/dist/hooks/bug-report-worker.js +14 -14
  246. package/dist/hooks/codex-stop-task-finalizer.js +14 -14
  247. package/dist/hooks/commit-complete.js +15 -15
  248. package/dist/hooks/error-recall.js +9 -9
  249. package/dist/hooks/exe-heartbeat-hook.js +5 -5
  250. package/dist/hooks/ingest-worker.js +5 -5
  251. package/dist/hooks/ingest.js +12 -12
  252. package/dist/hooks/instructions-loaded.js +6 -6
  253. package/dist/hooks/manifest.json +20 -20
  254. package/dist/hooks/notification.js +6 -6
  255. package/dist/hooks/post-compact.js +14 -14
  256. package/dist/hooks/post-tool-combined.js +7 -7
  257. package/dist/hooks/pre-compact.js +19 -19
  258. package/dist/hooks/pre-tool-use.js +18 -18
  259. package/dist/hooks/prompt-submit.js +26 -26
  260. package/dist/hooks/session-end.js +24 -24
  261. package/dist/hooks/session-start.js +13 -13
  262. package/dist/hooks/stop.js +21 -21
  263. package/dist/hooks/subagent-stop.js +14 -14
  264. package/dist/hooks/summary-worker.js +22 -22
  265. package/dist/index.js +20 -20
  266. package/dist/installer-7HYL4DSU.js +342 -0
  267. package/dist/installer-J5BOCLUE.js +38 -0
  268. package/dist/installer-SQLXCGJ6.js +296 -0
  269. package/dist/key-backup-status-RNRP2PMU.js +39 -0
  270. package/dist/lib/agent-config.js +2 -2
  271. package/dist/lib/cloud-sync.js +6 -6
  272. package/dist/lib/config.js +1 -1
  273. package/dist/lib/consolidation.js +7 -7
  274. package/dist/lib/database.js +3 -3
  275. package/dist/lib/db-daemon-client.js +3 -3
  276. package/dist/lib/db.js +3 -3
  277. package/dist/lib/device-registry.js +1 -1
  278. package/dist/lib/embedder.js +4 -4
  279. package/dist/lib/employee-templates.js +5 -5
  280. package/dist/lib/employees.js +3 -3
  281. package/dist/lib/exe-daemon-client.js +3 -3
  282. package/dist/lib/exe-daemon.js +208 -147
  283. package/dist/lib/hybrid-search.js +7 -7
  284. package/dist/lib/identity.js +3 -3
  285. package/dist/lib/keychain.js +1 -1
  286. package/dist/lib/license.js +2 -2
  287. package/dist/lib/messaging.js +12 -12
  288. package/dist/lib/reminders.js +4 -4
  289. package/dist/lib/schedules.js +7 -7
  290. package/dist/lib/session-registry.js +5 -5
  291. package/dist/lib/skill-learning.js +5 -5
  292. package/dist/lib/store.js +6 -6
  293. package/dist/lib/task-router.js +4 -4
  294. package/dist/lib/tasks.js +13 -13
  295. package/dist/lib/tmux-routing.js +11 -11
  296. package/dist/lib/token-spend.js +4 -4
  297. package/dist/lib/ws-client.js +1 -1
  298. package/dist/license-gate-NAHPUAGW.js +14 -0
  299. package/dist/mcp/register-tools.js +66 -66
  300. package/dist/mcp/server.js +67 -67
  301. package/dist/mcp/tools/complete-reminder.js +5 -5
  302. package/dist/mcp/tools/create-reminder.js +5 -5
  303. package/dist/mcp/tools/create-task.js +15 -15
  304. package/dist/mcp/tools/deactivate-behavior.js +6 -6
  305. package/dist/mcp/tools/list-reminders.js +5 -5
  306. package/dist/mcp/tools/list-tasks.js +15 -15
  307. package/dist/mcp/tools/send-message.js +14 -14
  308. package/dist/mcp/tools/update-task.js +14 -14
  309. package/dist/mcp-http-config-MEKBWYML.js +27 -0
  310. package/dist/memory-cards-72HLPWUY.js +174 -0
  311. package/dist/memory-graph-extractor-J74IK3P3.js +17 -0
  312. package/dist/memory-poisoning-defense-7MDWJBHC.js +225 -0
  313. package/dist/memory-queue-4MGXHMK4.js +19 -0
  314. package/dist/memory-queue-client-M3KDLB46.js +16 -0
  315. package/dist/memory-reflection-FMGMGVGM.js +238 -0
  316. package/dist/message-queue-client-ZHRKKF4X.js +92 -0
  317. package/dist/notifications-J4OWCFPF.js +45 -0
  318. package/dist/notifications-K3BH2RHN.js +45 -0
  319. package/dist/oauth-server-NVANCCC2.js +437 -0
  320. package/dist/orchestration-events-NDI4WT5H.js +25 -0
  321. package/dist/orchestration-phase-TVIMFZKY.js +23 -0
  322. package/dist/orchestrator-TPDFNGUF.js +33 -0
  323. package/dist/orchestrator-WR3Q2RVZ.js +33 -0
  324. package/dist/pipeline-router-DLYLQQSN.js +13 -0
  325. package/dist/pipeline-router-WV2XPQSN.js +13 -0
  326. package/dist/plan-limits-S55HNF7B.js +26 -0
  327. package/dist/project-boot-DRERMCYK.js +299 -0
  328. package/dist/projection-worker-4Z6XFRVE.js +964 -0
  329. package/dist/push-notifications-5DPGUL54.js +15 -0
  330. package/dist/reranker-BXUNHAKW.js +19 -0
  331. package/dist/reranker-DCFKXPKJ.js +19 -0
  332. package/dist/reranker-EW5P46UD.js +19 -0
  333. package/dist/reranker-L5CYCTOR.js +19 -0
  334. package/dist/reranker-U7VNOZJZ.js +19 -0
  335. package/dist/review-polling-UCYIW2F4.js +124 -0
  336. package/dist/review-polling-WF74N4VL.js +124 -0
  337. package/dist/runtime/index.js +14 -14
  338. package/dist/session-events-HZTHRSZG.js +36 -0
  339. package/dist/session-events-WFUE6EAD.js +36 -0
  340. package/dist/session-kill-telemetry-SI33W6SX.js +29 -0
  341. package/dist/session-scope-2AB6GDVE.js +86 -0
  342. package/dist/session-scope-IG4CZPQN.js +86 -0
  343. package/dist/setup-wizard-REWKS6RV.js +12 -0
  344. package/dist/setup-wizard-Y5JXBKU7.js +12 -0
  345. package/dist/shard-manager-43E5PUK7.js +30 -0
  346. package/dist/skill-refinement-ID35SRPO.js +157 -0
  347. package/dist/skill-refinement-WETHQUPD.js +157 -0
  348. package/dist/stack-update-HQCFXISV.js +52 -0
  349. package/dist/steward-gate-OZNNC5IU.js +13 -0
  350. package/dist/task-enforcement-4S6G5YE5.js +391 -0
  351. package/dist/task-enforcement-BR7RESTW.js +391 -0
  352. package/dist/task-scope-4ROTMKKW.js +35 -0
  353. package/dist/task-scope-MZFUEJY2.js +35 -0
  354. package/dist/tasks-crud-2TRZEJZE.js +77 -0
  355. package/dist/tasks-crud-LULZSG24.js +77 -0
  356. package/dist/tasks-notify-2AQ5Y5D3.js +38 -0
  357. package/dist/tasks-notify-EQFZENZS.js +38 -0
  358. package/dist/tasks-review-AOIDCIA7.js +47 -0
  359. package/dist/tasks-review-F6SMWQGU.js +47 -0
  360. package/dist/telemetry-upload-63FJDSTM.js +739 -0
  361. package/dist/telemetry-upload-UQ7362LE.js +739 -0
  362. package/dist/token-budget-KAVJ5VXR.js +84 -0
  363. package/dist/tool-capability-index-TSCBQMXU.js +10 -0
  364. package/dist/tool-telemetry-3XHI5RXV.js +17 -0
  365. package/dist/tui/App.js +25 -25
  366. package/dist/tui-data-4TIP5Y2C.js +258 -0
  367. package/dist/tui-data-DLUU73NT.js +258 -0
  368. package/dist/webhook-pipe-7ORU6VUL.js +114 -0
  369. package/dist/wiki-acl-KMRWMPUG.js +111 -0
  370. package/dist/wiki-client-TQVT6W43.js +157 -0
  371. package/dist/worker-gate-EUWOYKF4.js +21 -0
  372. package/dist/worker-gate-KTV4HWI4.js +21 -0
  373. package/dist/workflow-engine-AA27JRZY.js +28 -0
  374. package/dist/workflow-engine-ETHM77NC.js +28 -0
  375. package/dist/worktree-YQ2ZY6C2.js +26 -0
  376. package/dist/worktree-sweep-B3MI42LI.js +19 -0
  377. package/package.json +4 -3
  378. package/release-notes.json +50 -40
@@ -0,0 +1,128 @@
1
+ import {
2
+ getCurrentSessionScope,
3
+ strictSessionScopeFilter
4
+ } from "./chunk-Z73TGBDX.js";
5
+ import {
6
+ getProjectName
7
+ } from "./chunk-OPU3NYOO.js";
8
+
9
+ // src/lib/session-events.ts
10
+ import { randomUUID } from "crypto";
11
+ async function ensureSessionEventsTable(client) {
12
+ await client.execute(`
13
+ CREATE TABLE IF NOT EXISTS session_events (
14
+ id TEXT PRIMARY KEY,
15
+ agent_id TEXT NOT NULL,
16
+ agent_role TEXT NOT NULL,
17
+ session_id TEXT NOT NULL,
18
+ session_scope TEXT,
19
+ project_name TEXT NOT NULL,
20
+ event_index INTEGER NOT NULL,
21
+ event_type TEXT NOT NULL,
22
+ tool_name TEXT,
23
+ tool_use_id TEXT,
24
+ content TEXT NOT NULL,
25
+ payload_json TEXT,
26
+ has_error INTEGER NOT NULL DEFAULT 0,
27
+ created_at TEXT NOT NULL
28
+ )
29
+ `);
30
+ await client.execute(`
31
+ CREATE INDEX IF NOT EXISTS idx_session_events_agent_time
32
+ ON session_events(agent_id, created_at DESC)
33
+ `);
34
+ await client.execute(`
35
+ CREATE INDEX IF NOT EXISTS idx_session_events_session_index
36
+ ON session_events(session_id, event_index)
37
+ `);
38
+ await client.execute(`
39
+ CREATE INDEX IF NOT EXISTS idx_session_events_scope_agent_time
40
+ ON session_events(session_scope, agent_id, created_at DESC)
41
+ `);
42
+ }
43
+ async function recordSessionEvent(client, input) {
44
+ if (!input.content || input.content.trim().length === 0) return;
45
+ await ensureSessionEventsTable(client);
46
+ const maxResult = await client.execute({
47
+ sql: "SELECT COALESCE(MAX(event_index), 0) AS max_index FROM session_events WHERE session_id = ?",
48
+ args: [input.sessionId]
49
+ });
50
+ const currentMax = Number(maxResult.rows[0]?.max_index ?? 0);
51
+ const eventIndex = Number.isFinite(currentMax) ? currentMax + 1 : 1;
52
+ await client.execute({
53
+ sql: `INSERT INTO session_events (
54
+ id, agent_id, agent_role, session_id, session_scope, project_name,
55
+ event_index, event_type, tool_name, tool_use_id, content,
56
+ payload_json, has_error, created_at
57
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
58
+ args: [
59
+ randomUUID(),
60
+ input.agentId,
61
+ input.agentRole,
62
+ input.sessionId,
63
+ input.sessionScope ?? getCurrentSessionScope(),
64
+ input.projectName ?? getProjectName(input.cwd),
65
+ eventIndex,
66
+ input.eventType,
67
+ input.toolName ?? null,
68
+ input.toolUseId ?? null,
69
+ input.content,
70
+ input.payloadJson ?? null,
71
+ input.hasError ? 1 : 0,
72
+ input.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
73
+ ]
74
+ });
75
+ }
76
+ async function listRecentSessionEvents(client, options) {
77
+ await ensureSessionEventsTable(client);
78
+ const conditions = ["agent_id = ?"];
79
+ const args = [options.agentId];
80
+ if (options.sessionId) {
81
+ conditions.push("session_id = ?");
82
+ args.push(options.sessionId);
83
+ }
84
+ if (options.eventType) {
85
+ conditions.push("event_type = ?");
86
+ args.push(options.eventType);
87
+ }
88
+ if (options.projectName && options.projectName !== "all") {
89
+ conditions.push("project_name = ?");
90
+ args.push(options.projectName);
91
+ }
92
+ const scope = strictSessionScopeFilter(options.sessionScope);
93
+ const where = `WHERE ${conditions.join(" AND ")}${scope.sql}`;
94
+ args.push(...scope.args);
95
+ args.push(Math.min(Math.max(options.limit ?? 20, 1), 100));
96
+ const result = await client.execute({
97
+ sql: `SELECT id, agent_id, agent_role, session_id, session_scope,
98
+ project_name, event_index, event_type, tool_name, tool_use_id,
99
+ content, payload_json, has_error, created_at
100
+ FROM session_events
101
+ ${where}
102
+ ORDER BY created_at DESC, event_index DESC
103
+ LIMIT ?`,
104
+ args
105
+ });
106
+ return result.rows.map((row) => ({
107
+ id: String(row.id),
108
+ agentId: String(row.agent_id),
109
+ agentRole: String(row.agent_role),
110
+ sessionId: String(row.session_id),
111
+ sessionScope: row.session_scope == null ? null : String(row.session_scope),
112
+ projectName: String(row.project_name),
113
+ eventIndex: Number(row.event_index),
114
+ eventType: String(row.event_type),
115
+ toolName: row.tool_name == null ? null : String(row.tool_name),
116
+ toolUseId: row.tool_use_id == null ? null : String(row.tool_use_id),
117
+ content: String(row.content),
118
+ payloadJson: row.payload_json == null ? null : String(row.payload_json),
119
+ hasError: Number(row.has_error) === 1,
120
+ createdAt: String(row.created_at)
121
+ }));
122
+ }
123
+
124
+ export {
125
+ ensureSessionEventsTable,
126
+ recordSessionEvent,
127
+ listRecentSessionEvents
128
+ };
@@ -0,0 +1,382 @@
1
+ // src/automation/trigger-engine.ts
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
3
+ import { randomUUID } from "crypto";
4
+ import path from "path";
5
+ import os from "os";
6
+ var TRIGGERS_PATH = path.join(os.homedir(), ".exe-os", "triggers.json");
7
+ var GRAPH_API_VERSION = "v21.0";
8
+ var MAX_PARAM_LENGTH = 2e3;
9
+ var MAX_TRIGGER_DEPTH = 3;
10
+ var _currentTriggerDepth = 0;
11
+ var OUTBOUND_RATE_LIMIT_PER_HOUR = 100;
12
+ var _outboundWindows = /* @__PURE__ */ new Map();
13
+ function checkOutboundRateLimit(channel) {
14
+ const now = Date.now();
15
+ const cutoff = now - 36e5;
16
+ if (!_outboundWindows.has(channel)) _outboundWindows.set(channel, []);
17
+ const window = _outboundWindows.get(channel);
18
+ while (window.length > 0 && window[0] < cutoff) window.shift();
19
+ if (window.length >= OUTBOUND_RATE_LIMIT_PER_HOUR) return false;
20
+ window.push(now);
21
+ return true;
22
+ }
23
+ function sanitizeParam(value, maxLen = MAX_PARAM_LENGTH) {
24
+ const cleaned = value.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
25
+ return cleaned.length > maxLen ? cleaned.slice(0, maxLen) : cleaned;
26
+ }
27
+ function sanitizeExternalPayload(text) {
28
+ let sanitized = text;
29
+ sanitized = sanitized.replace(/^(system|SYSTEM|System)\s*:/gm, "[filtered]:");
30
+ sanitized = sanitized.replace(/<\/?system[^>]*>/gi, "[filtered]");
31
+ sanitized = sanitized.replace(/ignore\s+(all\s+)?previous\s+(instructions|prompts|rules)/gi, "[filtered]");
32
+ sanitized = sanitized.replace(/you\s+are\s+now\s+/gi, "[filtered] ");
33
+ return sanitized;
34
+ }
35
+ function substituteTemplate(template, record, sanitizeExternal = false) {
36
+ return template.replace(
37
+ /\{\{(\w+(?:\.\w+)*)\}\}/g,
38
+ (_match, dotPath) => {
39
+ const segments = dotPath.split(".");
40
+ if (segments[0] === "record") segments.shift();
41
+ let current = record;
42
+ for (const seg of segments) {
43
+ if (current == null || typeof current !== "object") return "";
44
+ current = current[seg];
45
+ }
46
+ if (current == null) return "";
47
+ const value = String(current);
48
+ return sanitizeExternal ? sanitizeExternalPayload(value) : value;
49
+ }
50
+ );
51
+ }
52
+ function resolveFieldValue(record, field) {
53
+ let current = record;
54
+ for (const segment of field.split(".")) {
55
+ if (current == null || typeof current !== "object") return void 0;
56
+ current = current[segment];
57
+ }
58
+ return current;
59
+ }
60
+ function evaluateCondition(condition, record) {
61
+ const fieldValue = resolveFieldValue(record, condition.field);
62
+ const target = condition.value;
63
+ switch (condition.op) {
64
+ case "eq":
65
+ return String(fieldValue) === String(target);
66
+ case "neq":
67
+ return String(fieldValue) !== String(target);
68
+ case "gt":
69
+ return Number(fieldValue) > Number(target);
70
+ case "lt":
71
+ return Number(fieldValue) < Number(target);
72
+ case "gte":
73
+ return Number(fieldValue) >= Number(target);
74
+ case "lte":
75
+ return Number(fieldValue) <= Number(target);
76
+ case "contains":
77
+ return String(fieldValue).toLowerCase().includes(String(target).toLowerCase());
78
+ case "not_contains":
79
+ return !String(fieldValue).toLowerCase().includes(String(target).toLowerCase());
80
+ default:
81
+ return false;
82
+ }
83
+ }
84
+ function evaluateConditions(conditions, record) {
85
+ if (conditions.length === 0) return true;
86
+ return conditions.every((c) => evaluateCondition(c, record));
87
+ }
88
+ function loadTriggers(project) {
89
+ if (!existsSync(TRIGGERS_PATH)) return [];
90
+ try {
91
+ const raw = readFileSync(TRIGGERS_PATH, "utf-8");
92
+ const all = JSON.parse(raw);
93
+ if (!Array.isArray(all)) return [];
94
+ if (project) {
95
+ return all.filter((t) => !t.project || t.project === project);
96
+ }
97
+ return all;
98
+ } catch {
99
+ return [];
100
+ }
101
+ }
102
+ function saveTriggers(triggers) {
103
+ const dir = path.dirname(TRIGGERS_PATH);
104
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
105
+ writeFileSync(TRIGGERS_PATH, JSON.stringify(triggers, null, 2), "utf-8");
106
+ }
107
+ function createNewTrigger(input) {
108
+ const triggers = loadTriggers();
109
+ const trigger = {
110
+ id: randomUUID().slice(0, 8),
111
+ ...input
112
+ };
113
+ triggers.push(trigger);
114
+ saveTriggers(triggers);
115
+ return trigger;
116
+ }
117
+ async function executeSendWhatsapp(params) {
118
+ if (!checkOutboundRateLimit("whatsapp")) {
119
+ throw new Error(`Outbound rate limit exceeded for WhatsApp (max ${OUTBOUND_RATE_LIMIT_PER_HOUR}/hour)`);
120
+ }
121
+ const { getAccountByName, getDefaultAccount } = await import("./whatsapp-accounts-BWRZUY23.js");
122
+ const account = params.account ? getAccountByName(params.account) : getDefaultAccount();
123
+ if (!account) {
124
+ throw new Error(
125
+ `No WhatsApp account found${params.account ? ` (${params.account})` : ""}`
126
+ );
127
+ }
128
+ const to = params.to ?? params.recipient;
129
+ const message = params.message ?? params.text;
130
+ if (!to || !message)
131
+ throw new Error("send_whatsapp requires 'to' and 'message' params");
132
+ const url = `https://graph.facebook.com/${GRAPH_API_VERSION}/${account.phoneNumberId}/messages`;
133
+ const res = await fetch(url, {
134
+ method: "POST",
135
+ headers: {
136
+ "Content-Type": "application/json",
137
+ Authorization: `Bearer ${account.accessToken}`
138
+ },
139
+ body: JSON.stringify({
140
+ messaging_product: "whatsapp",
141
+ to,
142
+ type: "text",
143
+ text: { body: message }
144
+ }),
145
+ signal: AbortSignal.timeout(3e4)
146
+ });
147
+ if (!res.ok) {
148
+ const errBody = await res.text();
149
+ throw new Error(`WhatsApp send failed (${res.status}): ${errBody}`);
150
+ }
151
+ }
152
+ async function executeSendMessage(params) {
153
+ const { sendMessage } = await import("./lib/messaging.js");
154
+ const { getCoordinatorName } = await import("./lib/employees.js");
155
+ const rawTo = params.to ?? params.recipient;
156
+ const to = rawTo === "coordinator" ? getCoordinatorName() : rawTo;
157
+ const content = params.message ?? params.content ?? params.text;
158
+ if (!to || !content)
159
+ throw new Error("send_message requires 'to' and 'message' params");
160
+ await sendMessage({
161
+ fromAgent: params.from ?? "trigger-engine",
162
+ targetAgent: to,
163
+ content,
164
+ priority: params.priority ?? "normal"
165
+ });
166
+ }
167
+ async function executeCreateTask(params) {
168
+ const { createTask } = await import("./lib/tasks.js");
169
+ const { getCoordinatorName } = await import("./lib/employees.js");
170
+ const rawAssignedTo = params.assigned_to;
171
+ await createTask({
172
+ title: params.title ?? "Triggered task",
173
+ assignedTo: !rawAssignedTo || rawAssignedTo === "coordinator" ? getCoordinatorName() : rawAssignedTo,
174
+ assignedBy: "trigger-engine",
175
+ projectName: params.project ?? "exe-os",
176
+ priority: params.priority ?? "p1",
177
+ context: params.context ?? params.description ?? "",
178
+ baseDir: process.cwd()
179
+ });
180
+ }
181
+ async function executeUpdateWiki(params) {
182
+ const apiUrl = process.env.EXE_WIKI_API_URL;
183
+ const apiKey = process.env.EXE_WIKI_API_KEY;
184
+ if (!apiUrl || !apiKey) {
185
+ throw new Error("Wiki not configured: EXE_WIKI_API_URL / EXE_WIKI_API_KEY not set");
186
+ }
187
+ const workspace = params.workspace;
188
+ const content = params.content ?? params.text;
189
+ const mode = params.mode ?? "append";
190
+ const section = params.section;
191
+ if (!workspace || !content) {
192
+ throw new Error("update_wiki requires 'workspace' and 'content' params");
193
+ }
194
+ const documentId = params.document_id;
195
+ if (documentId && mode === "append") {
196
+ const readRes = await fetch(`${apiUrl}/v1/document/${documentId}`, {
197
+ headers: { Authorization: `Bearer ${apiKey}` },
198
+ signal: AbortSignal.timeout(15e3)
199
+ });
200
+ if (!readRes.ok) {
201
+ throw new Error(`Wiki read failed (${readRes.status})`);
202
+ }
203
+ const doc = await readRes.json();
204
+ const existingContent = String(doc.content ?? "");
205
+ const title = String(doc.title ?? "Untitled");
206
+ await fetch(`${apiUrl}/v1/document/${documentId}`, {
207
+ method: "DELETE",
208
+ headers: { Authorization: `Bearer ${apiKey}` },
209
+ signal: AbortSignal.timeout(15e3)
210
+ }).catch((err) => {
211
+ process.stderr.write(`[trigger-engine] wiki purge failed: ${err instanceof Error ? err.message : String(err)}
212
+ `);
213
+ });
214
+ const uploadRes = await fetch(`${apiUrl}/v1/document/raw-text`, {
215
+ method: "POST",
216
+ headers: {
217
+ "Content-Type": "application/json",
218
+ Authorization: `Bearer ${apiKey}`
219
+ },
220
+ body: JSON.stringify({
221
+ textContent: section ? existingContent + `
222
+
223
+ ## ${section}
224
+ ${content}` : existingContent + "\n\n" + content,
225
+ metadata: { title },
226
+ workspaceSlugs: [workspace]
227
+ }),
228
+ signal: AbortSignal.timeout(15e3)
229
+ });
230
+ if (!uploadRes.ok) throw new Error(`Wiki upload failed (${uploadRes.status})`);
231
+ } else {
232
+ const title = params.title ?? "Auto-generated";
233
+ const res = await fetch(`${apiUrl}/v1/document/raw-text`, {
234
+ method: "POST",
235
+ headers: {
236
+ "Content-Type": "application/json",
237
+ Authorization: `Bearer ${apiKey}`
238
+ },
239
+ body: JSON.stringify({
240
+ textContent: content,
241
+ metadata: { title },
242
+ workspaceSlugs: [workspace]
243
+ }),
244
+ signal: AbortSignal.timeout(15e3)
245
+ });
246
+ if (!res.ok) throw new Error(`Wiki create failed (${res.status})`);
247
+ }
248
+ }
249
+ async function routeToApproval(action, resolvedParams, triggerName) {
250
+ const { createTask } = await import("./lib/tasks.js");
251
+ const { getCoordinatorName } = await import("./lib/employees.js");
252
+ const actionSummary = action.type === "send_whatsapp" ? `Send WhatsApp to ${resolvedParams.to ?? resolvedParams.recipient ?? "unknown"}: "${(resolvedParams.message ?? resolvedParams.text ?? "").slice(0, 100)}"` : `${action.type}: ${JSON.stringify(resolvedParams).slice(0, 200)}`;
253
+ await createTask({
254
+ title: `[Approval Required] ${triggerName}: ${action.type}`,
255
+ assignedTo: getCoordinatorName(),
256
+ assignedBy: "trigger-engine",
257
+ projectName: resolvedParams.project ?? "exe-os",
258
+ priority: "p1",
259
+ context: `Trigger "${triggerName}" wants to execute this action but requires approval.
260
+
261
+ **Action:** ${action.type}
262
+ **Summary:** ${actionSummary}
263
+ **Full params:** ${JSON.stringify(resolvedParams, null, 2)}
264
+
265
+ To approve, manually run the action via MCP tools.`,
266
+ baseDir: process.cwd()
267
+ });
268
+ }
269
+ async function executeAction(action, record, executor, triggerName) {
270
+ if (executor) {
271
+ return executor(action, record);
272
+ }
273
+ const resolvedParams = {};
274
+ for (const [key, val] of Object.entries(action.params)) {
275
+ resolvedParams[key] = sanitizeParam(substituteTemplate(val, record));
276
+ }
277
+ if (action.requires_approval) {
278
+ try {
279
+ await routeToApproval(action, resolvedParams, triggerName ?? "Unknown trigger");
280
+ return { success: true };
281
+ } catch (err) {
282
+ return {
283
+ success: false,
284
+ error: `Approval routing failed: ${err instanceof Error ? err.message : String(err)}`
285
+ };
286
+ }
287
+ }
288
+ try {
289
+ switch (action.type) {
290
+ case "send_whatsapp":
291
+ await executeSendWhatsapp(resolvedParams);
292
+ break;
293
+ case "send_message":
294
+ await executeSendMessage(resolvedParams);
295
+ break;
296
+ case "create_task":
297
+ await executeCreateTask(resolvedParams);
298
+ break;
299
+ case "update_wiki":
300
+ await executeUpdateWiki(resolvedParams);
301
+ break;
302
+ case "asana": {
303
+ const { loadAsanaConfig, executeAsanaOperation } = await import("./asana-MRQ2OQMJ.js");
304
+ const asanaConfig = loadAsanaConfig();
305
+ if (!asanaConfig) throw new Error("Asana not configured: set ASANA_API_TOKEN env var");
306
+ const operation = resolvedParams.operation ?? resolvedParams._operation;
307
+ if (!operation) throw new Error("asana action requires 'operation' param");
308
+ await executeAsanaOperation(asanaConfig, operation, resolvedParams);
309
+ break;
310
+ }
311
+ case "mcp_tool":
312
+ console.log(
313
+ `[trigger-engine] mcp_tool action: ${JSON.stringify(resolvedParams)}`
314
+ );
315
+ break;
316
+ }
317
+ return { success: true };
318
+ } catch (err) {
319
+ return {
320
+ success: false,
321
+ error: err instanceof Error ? err.message : String(err)
322
+ };
323
+ }
324
+ }
325
+ async function processCRMEvent(event, executor, triggersOverride) {
326
+ if (_currentTriggerDepth >= MAX_TRIGGER_DEPTH) {
327
+ console.error(
328
+ `[trigger-engine] Recursion limit (${MAX_TRIGGER_DEPTH}) reached \u2014 skipping event ${event.objectType}.${event.eventType}`
329
+ );
330
+ return [];
331
+ }
332
+ _currentTriggerDepth++;
333
+ try {
334
+ return await _processCRMEventInner(event, executor, triggersOverride);
335
+ } finally {
336
+ _currentTriggerDepth--;
337
+ }
338
+ }
339
+ async function _processCRMEventInner(event, executor, triggersOverride) {
340
+ const eventString = `${event.objectType}.${event.eventType}`;
341
+ const triggers = triggersOverride ?? loadTriggers();
342
+ const logs = [];
343
+ for (const trigger of triggers) {
344
+ if (!trigger.enabled) continue;
345
+ if (trigger.event !== eventString && trigger.event !== "*") continue;
346
+ if (!evaluateConditions(trigger.conditions, event.record)) continue;
347
+ const actionResults = [];
348
+ for (const action of trigger.actions) {
349
+ const result = await executeAction(action, event.record, executor, trigger.name);
350
+ actionResults.push({
351
+ type: action.type,
352
+ success: result.success,
353
+ error: result.error
354
+ });
355
+ }
356
+ const log = {
357
+ triggerId: trigger.id,
358
+ triggerName: trigger.name,
359
+ event: eventString,
360
+ firedAt: (/* @__PURE__ */ new Date()).toISOString(),
361
+ actionsExecuted: actionResults
362
+ };
363
+ logs.push(log);
364
+ console.log(
365
+ `[trigger-engine] Fired "${trigger.name}" on ${eventString}: ${actionResults.filter((a) => a.success).length}/${actionResults.length} actions succeeded`
366
+ );
367
+ }
368
+ return logs;
369
+ }
370
+ function isScheduledTrigger(trigger) {
371
+ return "schedule" in trigger && "query" in trigger;
372
+ }
373
+
374
+ export {
375
+ sanitizeParam,
376
+ substituteTemplate,
377
+ loadTriggers,
378
+ createNewTrigger,
379
+ executeAction,
380
+ processCRMEvent,
381
+ isScheduledTrigger
382
+ };
@@ -0,0 +1,190 @@
1
+ import {
2
+ EXE_AI_DIR
3
+ } from "./chunk-DOHKUD26.js";
4
+
5
+ // src/lib/memory-queue.ts
6
+ import {
7
+ appendFileSync,
8
+ mkdirSync,
9
+ readFileSync,
10
+ readdirSync,
11
+ renameSync,
12
+ unlinkSync,
13
+ existsSync,
14
+ statSync,
15
+ writeFileSync
16
+ } from "fs";
17
+ import path from "path";
18
+ import crypto from "crypto";
19
+ var QUEUE_PATH = path.join(EXE_AI_DIR, "memory-queue.jsonl");
20
+ var PROCESSING_PATH = QUEUE_PATH + ".processing";
21
+ var PROCESSING_PREFIX = path.basename(PROCESSING_PATH);
22
+ var TTL_MS = 24 * 60 * 60 * 1e3;
23
+ var DEFAULT_STALE_LEASE_MS = 5 * 60 * 1e3;
24
+ function enqueueMemory(entry) {
25
+ mkdirSync(path.dirname(QUEUE_PATH), { recursive: true });
26
+ appendFileSync(QUEUE_PATH, JSON.stringify(entry) + "\n");
27
+ }
28
+ function claimQueue(options = {}) {
29
+ const staleLeaseMs = options.staleLeaseMs ?? DEFAULT_STALE_LEASE_MS;
30
+ const staleLease = claimStaleLease(staleLeaseMs);
31
+ if (staleLease) return staleLease;
32
+ if (!existsSync(QUEUE_PATH)) return null;
33
+ try {
34
+ const stat = statSync(QUEUE_PATH);
35
+ if (stat.size === 0) {
36
+ try {
37
+ unlinkSync(QUEUE_PATH);
38
+ } catch {
39
+ }
40
+ return null;
41
+ }
42
+ } catch {
43
+ return null;
44
+ }
45
+ const leasePath = newLeasePath();
46
+ try {
47
+ renameSync(QUEUE_PATH, leasePath);
48
+ } catch {
49
+ return null;
50
+ }
51
+ const entries = parseQueueFile(leasePath);
52
+ if (entries.length === 0) {
53
+ try {
54
+ unlinkSync(leasePath);
55
+ } catch {
56
+ }
57
+ return null;
58
+ }
59
+ return { leasePath, entries };
60
+ }
61
+ function ackQueue(leasePath) {
62
+ assertQueueLeasePath(leasePath);
63
+ try {
64
+ unlinkSync(leasePath);
65
+ } catch {
66
+ }
67
+ }
68
+ function retryQueueEntries(leasePath, entries) {
69
+ assertQueueLeasePath(leasePath);
70
+ if (entries.length === 0) {
71
+ ackQueue(leasePath);
72
+ return;
73
+ }
74
+ writeFileSync(leasePath, entries.map((entry) => JSON.stringify(entry)).join("\n") + "\n");
75
+ }
76
+ function drainQueue() {
77
+ const entries = [];
78
+ while (true) {
79
+ const lease = claimQueue({ staleLeaseMs: 0 });
80
+ if (!lease) break;
81
+ entries.push(...lease.entries);
82
+ ackQueue(lease.leasePath);
83
+ }
84
+ return entries;
85
+ }
86
+ function queueDepth() {
87
+ const queueFiles = [QUEUE_PATH, ...listLeasePaths()];
88
+ let count = 0;
89
+ for (const filePath of queueFiles) {
90
+ if (!existsSync(filePath)) continue;
91
+ try {
92
+ const content = readFileSync(filePath, "utf8");
93
+ count += content.split("\n").filter((line) => line.trim().length > 0).length;
94
+ } catch {
95
+ }
96
+ }
97
+ return count;
98
+ }
99
+ function newLeasePath() {
100
+ const unique = `${process.pid}.${Date.now()}.${crypto.randomBytes(6).toString("hex")}`;
101
+ return `${PROCESSING_PATH}.${unique}`;
102
+ }
103
+ function listLeasePaths() {
104
+ const dir = path.dirname(QUEUE_PATH);
105
+ const files = [];
106
+ try {
107
+ for (const name of readdirSync(dir)) {
108
+ if (name === PROCESSING_PREFIX || name.startsWith(`${PROCESSING_PREFIX}.`)) {
109
+ files.push(path.join(dir, name));
110
+ }
111
+ }
112
+ } catch {
113
+ }
114
+ return files.sort();
115
+ }
116
+ function claimStaleLease(staleLeaseMs) {
117
+ const now = Date.now();
118
+ for (const existingLeasePath of listLeasePaths()) {
119
+ let stat;
120
+ try {
121
+ stat = statSync(existingLeasePath);
122
+ } catch {
123
+ continue;
124
+ }
125
+ const ageMs = Math.max(0, now - stat.mtimeMs);
126
+ if (ageMs < staleLeaseMs) continue;
127
+ let leasePath = existingLeasePath;
128
+ if (path.basename(existingLeasePath) === PROCESSING_PREFIX) {
129
+ leasePath = newLeasePath();
130
+ try {
131
+ renameSync(existingLeasePath, leasePath);
132
+ } catch {
133
+ continue;
134
+ }
135
+ }
136
+ const entries = parseQueueFile(leasePath);
137
+ if (entries.length === 0) {
138
+ try {
139
+ unlinkSync(leasePath);
140
+ } catch {
141
+ }
142
+ continue;
143
+ }
144
+ return { leasePath, entries };
145
+ }
146
+ return null;
147
+ }
148
+ function assertQueueLeasePath(leasePath) {
149
+ const resolved = path.resolve(leasePath);
150
+ const dir = path.resolve(path.dirname(QUEUE_PATH));
151
+ const base = path.basename(resolved);
152
+ if (path.dirname(resolved) !== dir || base !== PROCESSING_PREFIX && !base.startsWith(`${PROCESSING_PREFIX}.`)) {
153
+ throw new Error(`Refusing to operate on non-memory-queue lease path: ${leasePath}`);
154
+ }
155
+ }
156
+ function parseQueueFile(filePath) {
157
+ const now = Date.now();
158
+ const entries = [];
159
+ let content;
160
+ try {
161
+ content = readFileSync(filePath, "utf8");
162
+ } catch {
163
+ return entries;
164
+ }
165
+ for (const line of content.split("\n")) {
166
+ const trimmed = line.trim();
167
+ if (!trimmed) continue;
168
+ try {
169
+ const entry = JSON.parse(trimmed);
170
+ if (entry.timestamp) {
171
+ const age = now - new Date(entry.timestamp).getTime();
172
+ if (age > TTL_MS) continue;
173
+ }
174
+ entries.push(entry);
175
+ } catch {
176
+ process.stderr.write(`[memory-queue] Skipping corrupt line: ${trimmed.slice(0, 80)}
177
+ `);
178
+ }
179
+ }
180
+ return entries;
181
+ }
182
+
183
+ export {
184
+ enqueueMemory,
185
+ claimQueue,
186
+ ackQueue,
187
+ retryQueueEntries,
188
+ drainQueue,
189
+ queueDepth
190
+ };