@askexenow/exe-os 0.9.299 → 0.9.301

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 (499) hide show
  1. package/deploy/compose/.env.customer.example +1 -1
  2. package/deploy/compose/.env.example +1 -1
  3. package/deploy/compose/docker-compose.yml +31 -5
  4. package/deploy/compose/erp-nginx/nginx.conf +6 -3
  5. package/deploy/compose/generate-env.ts +1 -1
  6. package/deploy/compose/observability/otel-collector-config.yaml +10 -1
  7. package/deploy/compose/setup.sh +1 -1
  8. package/dist/active-agent-56J56WW5.js +27 -0
  9. package/dist/active-agent-UNJO6AJ2.js +27 -0
  10. package/dist/active-agent-VDWK7TES.js +28 -0
  11. package/dist/active-agent-Y5LSIMVC.js +28 -0
  12. package/dist/agentic-ontology-MZ4WHFDE.js +25 -0
  13. package/dist/agentic-ontology-QEV7GI3T.js +25 -0
  14. package/dist/assets/com.askexe.exed.plist +6 -5
  15. package/dist/backfill-metadata-IHKI5GXV.js +600 -0
  16. package/dist/backfill-metadata-RQZ4BN7G.js +600 -0
  17. package/dist/backfill-metadata-ZU3SZNBD.js +600 -0
  18. package/dist/behaviors-A3L5CWMK.js +46 -0
  19. package/dist/behaviors-G4KWGS24.js +46 -0
  20. package/dist/behaviors-WO67R6C4.js +46 -0
  21. package/dist/bin/agentic-ontology-backfill.js +5 -5
  22. package/dist/bin/agentic-reflection-backfill.js +6 -6
  23. package/dist/bin/agentic-semantic-label.js +5 -5
  24. package/dist/bin/backfill-conversations.js +6 -6
  25. package/dist/bin/backfill-responses.js +6 -6
  26. package/dist/bin/backfill-vectors.js +8 -8
  27. package/dist/bin/bulk-sync-postgres.js +13 -7
  28. package/dist/bin/cc-doctor.js +5 -5
  29. package/dist/bin/cleanup-stale-review-tasks.js +10 -10
  30. package/dist/bin/cli.js +16 -16
  31. package/dist/bin/deferred-daemon-restart.js +1 -1
  32. package/dist/bin/exe-agent-config.js +2 -2
  33. package/dist/bin/exe-agent.js +10 -10
  34. package/dist/bin/exe-assign.js +8 -8
  35. package/dist/bin/exe-boot.js +36 -21
  36. package/dist/bin/exe-call.js +4 -4
  37. package/dist/bin/exe-cloud.js +13 -7
  38. package/dist/bin/exe-dispatch.js +10 -10
  39. package/dist/bin/exe-doctor.js +2 -2
  40. package/dist/bin/exe-export-behaviors.js +7 -7
  41. package/dist/bin/exe-forget.js +6 -6
  42. package/dist/bin/exe-gateway.js +7 -7
  43. package/dist/bin/exe-healthcheck.js +5 -5
  44. package/dist/bin/exe-heartbeat.js +10 -10
  45. package/dist/bin/exe-kill.js +13 -13
  46. package/dist/bin/exe-launch-agent.js +29 -19
  47. package/dist/bin/exe-new-employee.js +6 -6
  48. package/dist/bin/exe-pending-messages.js +11 -11
  49. package/dist/bin/exe-pending-notifications.js +10 -10
  50. package/dist/bin/exe-pending-reviews.js +10 -10
  51. package/dist/bin/exe-rename.js +4 -4
  52. package/dist/bin/exe-review.js +12 -12
  53. package/dist/bin/exe-search.js +5 -5
  54. package/dist/bin/exe-session-cleanup.js +15 -15
  55. package/dist/bin/exe-settings.js +13 -7
  56. package/dist/bin/exe-start-codex.js +11 -11
  57. package/dist/bin/exe-start-opencode.js +8 -8
  58. package/dist/bin/exe-status.js +11 -11
  59. package/dist/bin/exe-team.js +3 -3
  60. package/dist/bin/exe-watchdog.js +3 -3
  61. package/dist/bin/git-sweep.js +11 -11
  62. package/dist/bin/graph-backfill.js +6 -6
  63. package/dist/bin/graph-export.js +5 -5
  64. package/dist/bin/import-history.js +9 -9
  65. package/dist/bin/install-launchd.js +7 -3
  66. package/dist/bin/install.js +19 -15
  67. package/dist/bin/intercom-check.js +4 -4
  68. package/dist/bin/mcp-sessions.js +2 -2
  69. package/dist/bin/orchestration-metrics.js +4 -4
  70. package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
  71. package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
  72. package/dist/bin/pre-publish.js +24 -1
  73. package/dist/bin/scan-tasks.js +10 -10
  74. package/dist/bin/setup.js +1 -1
  75. package/dist/bin/shard-migrate.js +4 -4
  76. package/dist/bin/stack-update.js +123 -3
  77. package/dist/bin/vps-health-gate.js +1 -1
  78. package/dist/capability-cards-VTGDTOZ4.js +89 -0
  79. package/dist/capability-cards-XAQSL26B.js +89 -0
  80. package/dist/capacity-monitor-6MQLFFQT.js +51 -0
  81. package/dist/capacity-monitor-BB3LKJLE.js +51 -0
  82. package/dist/capacity-monitor-G2MAJPRP.js +51 -0
  83. package/dist/catchup-brief-BQSL5M5S.js +175 -0
  84. package/dist/catchup-brief-COALBX6L.js +175 -0
  85. package/dist/catchup-brief-VBGEJQRS.js +175 -0
  86. package/dist/cc-binary-detect-B5JDCJ5J.js +19 -0
  87. package/dist/chunk-22LDUTY7.js +14597 -0
  88. package/dist/chunk-24JVDLQJ.js +345 -0
  89. package/dist/chunk-24M4AJPG.js +128 -0
  90. package/dist/chunk-2B7RCTPT.js +85 -0
  91. package/dist/chunk-2QBA6YE6.js +127 -0
  92. package/dist/chunk-2RGDEBZC.js +731 -0
  93. package/dist/chunk-2T3OYZMR.js +1158 -0
  94. package/dist/chunk-32DBQWR5.js +333 -0
  95. package/dist/chunk-3ABY3QDX.js +199 -0
  96. package/dist/chunk-3EOPMTG2.js +128 -0
  97. package/dist/chunk-3G3ECFB5.js +668 -0
  98. package/dist/chunk-3LHOFGHT.js +280 -0
  99. package/dist/chunk-3NS4V4JW.js +382 -0
  100. package/dist/chunk-3NYY2NZ3.js +836 -0
  101. package/dist/chunk-3RA62PNQ.js +58 -0
  102. package/dist/chunk-3ROUD5WA.js +97 -0
  103. package/dist/chunk-3RY2ARDN.js +129 -0
  104. package/dist/chunk-3XRS5AVV.js +567 -0
  105. package/dist/chunk-3Y5IRIRU.js +290 -0
  106. package/dist/chunk-3YK7X5FD.js +1186 -0
  107. package/dist/chunk-3ZWWUKBI.js +210 -0
  108. package/dist/chunk-463G3VAH.js +122 -0
  109. package/dist/chunk-4L6PVYFE.js +54 -0
  110. package/dist/chunk-4LC7BFI2.js +76 -0
  111. package/dist/chunk-4O67LBMK.js +377 -0
  112. package/dist/chunk-4OIU3N6U.js +167 -0
  113. package/dist/chunk-4Z3FWLOE.js +836 -0
  114. package/dist/chunk-5BAU4T5G.js +208 -0
  115. package/dist/chunk-5FP7YHCG.js +1158 -0
  116. package/dist/chunk-5SYYMNPE.js +30 -0
  117. package/dist/chunk-5TO5PH7O.js +304 -0
  118. package/dist/chunk-5U3JZP62.js +1352 -0
  119. package/dist/chunk-5VNFXIGF.js +85 -0
  120. package/dist/chunk-5XD2Y463.js +402 -0
  121. package/dist/chunk-63AENHJC.js +123 -0
  122. package/dist/chunk-673IFJYB.js +731 -0
  123. package/dist/chunk-6UVUJNLY.js +1186 -0
  124. package/dist/chunk-7AWH47AR.js +448 -0
  125. package/dist/chunk-7KPWYWYL.js +290 -0
  126. package/dist/chunk-7P4B6AEP.js +227 -0
  127. package/dist/chunk-7URNGDEY.js +2145 -0
  128. package/dist/chunk-7VHOALNC.js +244 -0
  129. package/dist/chunk-ADZQBZOX.js +122 -0
  130. package/dist/chunk-APSZAEDO.js +1186 -0
  131. package/dist/chunk-ASHF6VO4.js +2265 -0
  132. package/dist/chunk-ASJHCAVL.js +38 -0
  133. package/dist/chunk-BT2LEHIW.js +448 -0
  134. package/dist/chunk-BTS5QUWB.js +50 -0
  135. package/dist/chunk-BWJDJ3BS.js +604 -0
  136. package/dist/chunk-CME46VWP.js +150 -0
  137. package/dist/chunk-D3ICCKXY.js +54 -0
  138. package/dist/chunk-D3IOU3NO.js +377 -0
  139. package/dist/chunk-DFGXRKI2.js +221 -0
  140. package/dist/chunk-DICIFTCS.js +150 -0
  141. package/dist/chunk-DIFI5JDC.js +76 -0
  142. package/dist/chunk-DO65VHQZ.js +128 -0
  143. package/dist/chunk-DPOIJ5SM.js +284 -0
  144. package/dist/chunk-E2OMUBXQ.js +567 -0
  145. package/dist/chunk-ECMXIV6N.js +97 -0
  146. package/dist/chunk-EDMVA3PT.js +727 -0
  147. package/dist/chunk-F5OSXH4A.js +4388 -0
  148. package/dist/chunk-F5OWHPRG.js +236 -0
  149. package/dist/chunk-F7MZA3QP.js +199 -0
  150. package/dist/chunk-FAZNXNA5.js +33 -0
  151. package/dist/chunk-FCHG5RC4.js +197 -0
  152. package/dist/chunk-FFKSPZO2.js +157 -0
  153. package/dist/chunk-FNHYH5U6.js +331 -0
  154. package/dist/chunk-FRNXQSB4.js +134 -0
  155. package/dist/chunk-FTAASABV.js +362 -0
  156. package/dist/chunk-FWPDAQ6Q.js +1350 -0
  157. package/dist/chunk-FZB73QOI.js +210 -0
  158. package/dist/chunk-GBL5QSTM.js +197 -0
  159. package/dist/chunk-GJBR6QLD.js +630 -0
  160. package/dist/chunk-GRSYAHKI.js +535 -0
  161. package/dist/chunk-GRXWINOW.js +244 -0
  162. package/dist/chunk-GUPNVUG5.js +348 -0
  163. package/dist/chunk-GY66UPMX.js +167 -0
  164. package/dist/chunk-HCCG67BY.js +43 -0
  165. package/dist/chunk-HCSZZXZZ.js +197 -0
  166. package/dist/chunk-HNGNZU62.js +240 -0
  167. package/dist/chunk-HP2D5LIE.js +214 -0
  168. package/dist/chunk-HUABQHDC.js +1352 -0
  169. package/dist/chunk-HYKO2LNW.js +157 -0
  170. package/dist/chunk-IFL6DG2K.js +181 -0
  171. package/dist/chunk-IKPQRHVQ.js +304 -0
  172. package/dist/chunk-J5HFRVNW.js +362 -0
  173. package/dist/chunk-J6SD7LT2.js +171 -0
  174. package/dist/chunk-JCWA3X6A.js +402 -0
  175. package/dist/chunk-JHPK33IP.js +2162 -0
  176. package/dist/chunk-JURL2S27.js +128 -0
  177. package/dist/chunk-JWGDH5I2.js +127 -0
  178. package/dist/chunk-KBXQFXYM.js +567 -0
  179. package/dist/chunk-KGY5QIOJ.js +1350 -0
  180. package/dist/chunk-KLES22FB.js +1094 -0
  181. package/dist/chunk-KPUYYOFS.js +122 -0
  182. package/dist/chunk-KY43UELJ.js +331 -0
  183. package/dist/chunk-L32V4O5Z.js +58 -0
  184. package/dist/chunk-LAFARYU5.js +456 -0
  185. package/dist/chunk-LC7ETNTJ.js +1350 -0
  186. package/dist/chunk-LEJ5FKIK.js +55 -0
  187. package/dist/chunk-LNLLCAI4.js +377 -0
  188. package/dist/chunk-LQWZYMNU.js +448 -0
  189. package/dist/chunk-LSDXEHKL.js +381 -0
  190. package/dist/chunk-LY3SOO73.js +76 -0
  191. package/dist/chunk-M6CIHXXB.js +159 -0
  192. package/dist/chunk-MJOQ35DX.js +427 -0
  193. package/dist/chunk-MO5HER5Y.js +345 -0
  194. package/dist/chunk-MS2EOZJQ.js +290 -0
  195. package/dist/chunk-MUIMJGSQ.js +128 -0
  196. package/dist/chunk-MY4TGLT6.js +284 -0
  197. package/dist/chunk-N3ARGCVG.js +345 -0
  198. package/dist/chunk-N4XG2M2U.js +735 -0
  199. package/dist/chunk-N72JNFJ4.js +535 -0
  200. package/dist/chunk-NJMPNYBS.js +427 -0
  201. package/dist/chunk-NM3AUMFE.js +2145 -0
  202. package/dist/chunk-NPPQ3TR4.js +735 -0
  203. package/dist/chunk-NTWF4DAF.js +581 -0
  204. package/dist/chunk-NXL3VKXM.js +331 -0
  205. package/dist/chunk-OJACH2JF.js +128 -0
  206. package/dist/chunk-OMSLHEEF.js +456 -0
  207. package/dist/chunk-OO4IFABD.js +382 -0
  208. package/dist/chunk-OYIP3QVN.js +167 -0
  209. package/dist/chunk-P2IOW54H.js +668 -0
  210. package/dist/chunk-P5KXQ3RN.js +731 -0
  211. package/dist/chunk-P5UXP53T.js +81 -0
  212. package/dist/chunk-PH6VRRFR.js +395 -0
  213. package/dist/chunk-Q3GKOF7Z.js +85 -0
  214. package/dist/chunk-Q65NCNL4.js +1352 -0
  215. package/dist/chunk-QIGS2LRT.js +735 -0
  216. package/dist/chunk-QKBN3CY2.js +381 -0
  217. package/dist/chunk-QNNAVMQH.js +1094 -0
  218. package/dist/chunk-QODDW4YI.js +171 -0
  219. package/dist/chunk-QPAYPTSH.js +2162 -0
  220. package/dist/chunk-QRWDJ5RI.js +381 -0
  221. package/dist/chunk-RBFZCHVB.js +105 -0
  222. package/dist/chunk-RCEULTPF.js +185 -0
  223. package/dist/chunk-RCGHXBCX.js +630 -0
  224. package/dist/chunk-ROSCLRTH.js +204 -0
  225. package/dist/chunk-RYAOSGUW.js +227 -0
  226. package/dist/chunk-S2SPGHPY.js +38 -0
  227. package/dist/chunk-S73ZAJ2S.js +262 -0
  228. package/dist/chunk-SBPEWD7Z.js +171 -0
  229. package/dist/chunk-SDPUWZP5.js +333 -0
  230. package/dist/chunk-SJ4UF7YK.js +1094 -0
  231. package/dist/chunk-SOZ7D77I.js +204 -0
  232. package/dist/chunk-SVLSHDNL.js +54 -0
  233. package/dist/chunk-SVUYBT5N.js +262 -0
  234. package/dist/chunk-T7PTLVJV.js +284 -0
  235. package/dist/chunk-TDX2LK2M.js +240 -0
  236. package/dist/chunk-TGUSLO4B.js +50 -0
  237. package/dist/chunk-TPJH6PE6.js +1158 -0
  238. package/dist/chunk-TVW7EDOJ.js +382 -0
  239. package/dist/chunk-TYRUIE6P.js +58 -0
  240. package/dist/chunk-U5RKGLV6.js +50 -0
  241. package/dist/chunk-UFGTHBHP.js +127 -0
  242. package/dist/chunk-ULCYWCPI.js +1079 -0
  243. package/dist/chunk-UN5EPVBN.js +14597 -0
  244. package/dist/chunk-URLH7ZVR.js +70 -0
  245. package/dist/chunk-USYRTGR7.js +402 -0
  246. package/dist/chunk-V4ABCEHM.js +30 -0
  247. package/dist/chunk-V6LOEOXG.js +3372 -0
  248. package/dist/chunk-VAZOVAW4.js +2162 -0
  249. package/dist/chunk-VEUQVKKT.js +185 -0
  250. package/dist/chunk-VIDDJ5RF.js +214 -0
  251. package/dist/chunk-VKCNXOQ6.js +214 -0
  252. package/dist/chunk-VNB4ROYG.js +348 -0
  253. package/dist/chunk-VWUQFZFB.js +395 -0
  254. package/dist/chunk-W77GRCNA.js +85 -0
  255. package/dist/chunk-WB2B25UM.js +230 -0
  256. package/dist/chunk-WCUZX7F7.js +204 -0
  257. package/dist/chunk-WL5RMOZQ.js +362 -0
  258. package/dist/chunk-WPAXAOHD.js +1079 -0
  259. package/dist/chunk-WVMG4ZRH.js +14597 -0
  260. package/dist/chunk-WYVOTRRZ.js +129 -0
  261. package/dist/chunk-XABJRAUW.js +3346 -0
  262. package/dist/chunk-XQQ7D4I4.js +85 -0
  263. package/dist/chunk-YDFY6YCH.js +280 -0
  264. package/dist/chunk-YGUMRYCN.js +33 -0
  265. package/dist/chunk-YHJPTIPR.js +836 -0
  266. package/dist/chunk-YJSP5PPG.js +128 -0
  267. package/dist/chunk-YLKS7KKC.js +2145 -0
  268. package/dist/chunk-YOMETWOJ.js +4388 -0
  269. package/dist/chunk-YU3KEVCO.js +333 -0
  270. package/dist/chunk-Z4FVFSE3.js +81 -0
  271. package/dist/chunk-Z4TLSNUW.js +244 -0
  272. package/dist/chunk-ZDPU3JTF.js +221 -0
  273. package/dist/chunk-ZDY4LYAJ.js +81 -0
  274. package/dist/chunk-ZG33AACD.js +70 -0
  275. package/dist/chunk-ZKHPZ6KN.js +181 -0
  276. package/dist/chunk-ZO2TM5N5.js +97 -0
  277. package/dist/chunk-ZP6T5K6I.js +535 -0
  278. package/dist/chunk-ZR6ZJT32.js +123 -0
  279. package/dist/chunk-ZSUACDQC.js +4388 -0
  280. package/dist/co-activation-JGF5YIDU.js +74 -0
  281. package/dist/co-activation-XM25BLZM.js +74 -0
  282. package/dist/co-occurrence-CKEMDPWO.js +95 -0
  283. package/dist/co-occurrence-HLLC6GT2.js +95 -0
  284. package/dist/co-occurrence-W2LIAPHI.js +95 -0
  285. package/dist/code-context-index-FCL47WKE.js +30 -0
  286. package/dist/conversation-entity-extractor-WC2RU6RS.js +114 -0
  287. package/dist/core-memory-CRSR2PSL.js +110 -0
  288. package/dist/core-memory-VSKFRMEV.js +110 -0
  289. package/dist/core-memory-ZDA76EU3.js +110 -0
  290. package/dist/crdt-sync-6VH2YDVY.js +33 -0
  291. package/dist/crdt-sync-BJKZB6T6.js +33 -0
  292. package/dist/crm-webhook-E5PAFAUN.js +10 -0
  293. package/dist/crm-webhook-RXFPZJXP.js +10 -0
  294. package/dist/crm-webhook-Z26LEFKG.js +10 -0
  295. package/dist/cto-delegation-gate-45IBLPTK.js +280 -0
  296. package/dist/cto-delegation-gate-EMY6ZZ2F.js +280 -0
  297. package/dist/cto-delegation-gate-SF4EUB2Q.js +280 -0
  298. package/dist/daemon-orchestration-VB3BLYIT.js +143 -0
  299. package/dist/daemon-orchestration-W66UYGUD.js +143 -0
  300. package/dist/daemon-orchestration-Y5Y6YNE3.js +143 -0
  301. package/dist/db-backup-HFJ53IBU.js +43 -0
  302. package/dist/db-backup-NVUTS7L5.js +43 -0
  303. package/dist/doc-graph-extractor-ID45AQ2P.js +133 -0
  304. package/dist/doc-graph-extractor-MLYQYT4B.js +133 -0
  305. package/dist/doc-graph-extractor-SVFSXKL6.js +133 -0
  306. package/dist/dreaming-AZYRAGKA.js +34 -0
  307. package/dist/dreaming-N6B7KBIE.js +34 -0
  308. package/dist/dreaming-WG5CDUHX.js +34 -0
  309. package/dist/entity-boost-XAFCDDB6.js +375 -0
  310. package/dist/exe-drift-3SGA53CL.js +70 -0
  311. package/dist/exe-drift-CPUEAPIU.js +70 -0
  312. package/dist/exe-export-4RTGDV53.js +77 -0
  313. package/dist/exe-export-APUNLKWF.js +77 -0
  314. package/dist/exe-export-NM4SXB3P.js +77 -0
  315. package/dist/exe-import-6GLNCP62.js +80 -0
  316. package/dist/exe-import-AZMIF34Z.js +80 -0
  317. package/dist/exe-import-U4H4ES3Z.js +80 -0
  318. package/dist/exe-key-FIPXUTMF.js +673 -0
  319. package/dist/exe-key-LJV23AJI.js +673 -0
  320. package/dist/exe-key-WTLCMOYJ.js +673 -0
  321. package/dist/exe-snapshot-ILO3WSEC.js +338 -0
  322. package/dist/exe-snapshot-IODRQLBX.js +338 -0
  323. package/dist/exe-snapshot-ZOZBW7V6.js +338 -0
  324. package/dist/fast-db-init-7LYYUCSJ.js +7 -0
  325. package/dist/fast-db-init-ATRZGHOL.js +7 -0
  326. package/dist/fast-db-init-IU7GYFWB.js +7 -0
  327. package/dist/gateway/index.js +11 -11
  328. package/dist/git-staleness-GGCFPHQ5.js +112 -0
  329. package/dist/git-staleness-XNOKI4D3.js +112 -0
  330. package/dist/git-task-sweep-3MO4OVND.js +42 -0
  331. package/dist/git-task-sweep-M3SWXFKJ.js +42 -0
  332. package/dist/git-task-sweep-Y6KNWB67.js +42 -0
  333. package/dist/global-procedures-626WAU3I.js +22 -0
  334. package/dist/global-procedures-EBAPPWGZ.js +22 -0
  335. package/dist/graph-auto-extract-TKHQ4OR3.js +183 -0
  336. package/dist/graph-auto-extract-VGFEWFZX.js +183 -0
  337. package/dist/graph-auto-extract-VJOUQBPK.js +183 -0
  338. package/dist/graph-rag-KECA5TE4.js +35 -0
  339. package/dist/hooks/bug-report-worker.js +12 -12
  340. package/dist/hooks/codex-stop-task-finalizer.js +12 -12
  341. package/dist/hooks/commit-complete.js +12 -12
  342. package/dist/hooks/error-recall.js +6 -6
  343. package/dist/hooks/exe-heartbeat-hook.js +3 -3
  344. package/dist/hooks/ingest-worker.js +3 -3
  345. package/dist/hooks/ingest.js +6 -6
  346. package/dist/hooks/instructions-loaded.js +4 -4
  347. package/dist/hooks/manifest.json +20 -20
  348. package/dist/hooks/notification.js +4 -4
  349. package/dist/hooks/post-compact.js +12 -12
  350. package/dist/hooks/post-tool-combined.js +6 -6
  351. package/dist/hooks/pre-compact.js +16 -16
  352. package/dist/hooks/pre-tool-use.js +15 -15
  353. package/dist/hooks/prompt-submit.js +28 -26
  354. package/dist/hooks/session-end.js +20 -20
  355. package/dist/hooks/session-start.js +12 -12
  356. package/dist/hooks/stop.js +18 -18
  357. package/dist/hooks/subagent-stop.js +11 -11
  358. package/dist/hooks/summary-worker.js +18 -18
  359. package/dist/index.js +20 -20
  360. package/dist/installer-37KFNAWE.js +344 -0
  361. package/dist/installer-3FB5EMPB.js +40 -0
  362. package/dist/installer-BRQ42CPB.js +344 -0
  363. package/dist/installer-F55NR4E2.js +298 -0
  364. package/dist/installer-KOYBUS4J.js +40 -0
  365. package/dist/installer-PXZJG256.js +298 -0
  366. package/dist/lib/cloud-sync.js +13 -7
  367. package/dist/lib/consolidation.js +7 -7
  368. package/dist/lib/database.js +6 -4
  369. package/dist/lib/db-daemon-client.js +11 -202
  370. package/dist/lib/db.js +6 -4
  371. package/dist/lib/embedder.js +3 -3
  372. package/dist/lib/employee-templates.js +4 -4
  373. package/dist/lib/employees.js +2 -2
  374. package/dist/lib/exe-daemon-client.js +2 -2
  375. package/dist/lib/exe-daemon.js +53 -51
  376. package/dist/lib/hybrid-search.js +5 -5
  377. package/dist/lib/identity.js +2 -2
  378. package/dist/lib/messaging.js +10 -10
  379. package/dist/lib/reminders.js +3 -3
  380. package/dist/lib/schedules.js +5 -5
  381. package/dist/lib/session-registry.js +4 -4
  382. package/dist/lib/skill-learning.js +6 -6
  383. package/dist/lib/store.js +4 -4
  384. package/dist/lib/task-router.js +3 -3
  385. package/dist/lib/tasks.js +11 -11
  386. package/dist/lib/tmux-routing.js +9 -9
  387. package/dist/lib/token-spend.js +3 -3
  388. package/dist/mcp/register-tools.js +65 -63
  389. package/dist/mcp/server.js +66 -64
  390. package/dist/mcp/tools/complete-reminder.js +4 -4
  391. package/dist/mcp/tools/create-reminder.js +4 -4
  392. package/dist/mcp/tools/create-task.js +13 -13
  393. package/dist/mcp/tools/deactivate-behavior.js +7 -7
  394. package/dist/mcp/tools/list-reminders.js +4 -4
  395. package/dist/mcp/tools/list-tasks.js +13 -13
  396. package/dist/mcp/tools/send-message.js +12 -12
  397. package/dist/mcp/tools/update-task.js +12 -12
  398. package/dist/mcp-http-config-7KJZI7UD.js +31 -0
  399. package/dist/mcp-http-config-OF3MB7M5.js +31 -0
  400. package/dist/memory-cards-CPIZVXWI.js +180 -0
  401. package/dist/memory-cards-ZIT7ZKL5.js +180 -0
  402. package/dist/memory-graph-extractor-JIYWLBFF.js +22 -0
  403. package/dist/memory-graph-extractor-LY2VORZT.js +22 -0
  404. package/dist/memory-graph-extractor-MDPSLZDM.js +22 -0
  405. package/dist/memory-poisoning-defense-5UZT3WWA.js +224 -0
  406. package/dist/memory-poisoning-defense-SEM25TY5.js +224 -0
  407. package/dist/memory-queue-client-WKWRFERJ.js +16 -0
  408. package/dist/memory-reflection-J2W7CJ7C.js +244 -0
  409. package/dist/memory-reflection-TA2VQYPH.js +244 -0
  410. package/dist/message-queue-client-IFQQ2HI7.js +92 -0
  411. package/dist/notifications-CZBQ3H5T.js +47 -0
  412. package/dist/notifications-EIIL2EQV.js +47 -0
  413. package/dist/notifications-RLMSI4YE.js +47 -0
  414. package/dist/orchestration-events-TGQYA72K.js +27 -0
  415. package/dist/orchestration-events-VUYR6MXE.js +27 -0
  416. package/dist/orchestrator-JQD5G3CW.js +35 -0
  417. package/dist/orchestrator-MAMR4C37.js +35 -0
  418. package/dist/orchestrator-VE5WHEJH.js +35 -0
  419. package/dist/pipeline-router-3Q3YBYSM.js +15 -0
  420. package/dist/pipeline-router-DKXD6DJO.js +15 -0
  421. package/dist/pipeline-router-YNW63BY5.js +15 -0
  422. package/dist/plan-limits-YGXTYCW4.js +28 -0
  423. package/dist/plan-limits-ZM4MNZKY.js +28 -0
  424. package/dist/project-boot-E2TWYTAC.js +299 -0
  425. package/dist/project-boot-TDOZKKDR.js +299 -0
  426. package/dist/projection-worker-TMKUSVGD.js +1084 -0
  427. package/dist/projection-worker-WFPRM4AI.js +1084 -0
  428. package/dist/projection-worker-YKV3PFCV.js +1084 -0
  429. package/dist/prospective-memory-CNJDBNWF.js +232 -0
  430. package/dist/prospective-memory-OAFZUODU.js +232 -0
  431. package/dist/reranker-AFU75HEX.js +19 -0
  432. package/dist/reranker-RYNSJNDF.js +19 -0
  433. package/dist/reranker-YQIRNGDM.js +19 -0
  434. package/dist/retrieval-health-M5BVB7EV.js +12 -0
  435. package/dist/retrieval-health-RSQEIYIB.js +12 -0
  436. package/dist/review-polling-LGX7DUNT.js +126 -0
  437. package/dist/review-polling-MJBCYV4I.js +126 -0
  438. package/dist/review-polling-ZMB3OBPC.js +126 -0
  439. package/dist/runtime/index.js +16 -16
  440. package/dist/services/codex-reviewd/index.js +855 -0
  441. package/dist/session-events-5N47BRFK.js +38 -0
  442. package/dist/session-events-PT6SVS2P.js +38 -0
  443. package/dist/session-events-UTMCKDIN.js +38 -0
  444. package/dist/session-kill-telemetry-FRQA5MVD.js +31 -0
  445. package/dist/session-kill-telemetry-HKL2NQMR.js +31 -0
  446. package/dist/session-scope-2BD6QLNI.js +88 -0
  447. package/dist/session-scope-GQNCM6UQ.js +88 -0
  448. package/dist/session-scope-MMGM232A.js +88 -0
  449. package/dist/setup-wizard-SELXXVLD.js +12 -0
  450. package/dist/setup-wizard-W64I6SHC.js +12 -0
  451. package/dist/setup-wizard-X7YSRDNQ.js +12 -0
  452. package/dist/skill-refinement-CCP4ULZ3.js +159 -0
  453. package/dist/skill-refinement-FXCXTUS2.js +159 -0
  454. package/dist/skill-refinement-WCPDNHZ5.js +159 -0
  455. package/dist/stack-update-5VSGG36W.js +84 -0
  456. package/dist/steward-gate-JDR3SLH3.js +15 -0
  457. package/dist/steward-gate-PIXNK4BK.js +15 -0
  458. package/dist/task-enforcement-LEBWCYZT.js +506 -0
  459. package/dist/task-enforcement-VOSQRAQB.js +506 -0
  460. package/dist/task-enforcement-WCEA4FZI.js +506 -0
  461. package/dist/task-scope-CQZ33PRU.js +37 -0
  462. package/dist/task-scope-JTTEZKDU.js +37 -0
  463. package/dist/task-scope-L5GDL2AV.js +37 -0
  464. package/dist/tasks-crud-DC4GCXQQ.js +79 -0
  465. package/dist/tasks-crud-S36AFYYM.js +79 -0
  466. package/dist/tasks-crud-T32IRPXF.js +79 -0
  467. package/dist/tasks-notify-OBFVHJDP.js +40 -0
  468. package/dist/tasks-notify-OUQWUM6W.js +40 -0
  469. package/dist/tasks-notify-W2W2BJRB.js +40 -0
  470. package/dist/tasks-review-34WV7BX2.js +49 -0
  471. package/dist/tasks-review-N33MTHWJ.js +49 -0
  472. package/dist/tasks-review-OSBG2YN2.js +49 -0
  473. package/dist/telemetry-upload-3CSVO3J7.js +741 -0
  474. package/dist/telemetry-upload-EYHEWTKG.js +741 -0
  475. package/dist/telemetry-upload-XLBW4DRP.js +741 -0
  476. package/dist/token-budget-I6FMMDFX.js +86 -0
  477. package/dist/token-budget-ZG2MQ5GD.js +86 -0
  478. package/dist/tool-capability-index-IWQBQKM7.js +10 -0
  479. package/dist/tool-telemetry-2E3Z7CRV.js +17 -0
  480. package/dist/tool-telemetry-ODL4F2CW.js +17 -0
  481. package/dist/tui/App.js +17 -17
  482. package/dist/tui-data-VWT4Q5UT.js +260 -0
  483. package/dist/tui-data-XFBFBSBE.js +260 -0
  484. package/dist/tui-data-Z5UF7KEI.js +260 -0
  485. package/dist/wiki-acl-EUOPNUIQ.js +111 -0
  486. package/dist/wiki-acl-SZFHCEC4.js +111 -0
  487. package/dist/worker-gate-OOO6BWZ6.js +21 -0
  488. package/dist/worker-gate-OQMKAMP7.js +21 -0
  489. package/dist/worker-gate-ZPP3SZK6.js +21 -0
  490. package/dist/workflow-engine-P7WYJP2B.js +28 -0
  491. package/dist/workflow-engine-QY3IFFR2.js +28 -0
  492. package/dist/workflow-engine-UYNB5RTB.js +28 -0
  493. package/dist/worktree-CNOQZBNT.js +28 -0
  494. package/dist/worktree-H5C4LMQR.js +28 -0
  495. package/dist/worktree-sweep-KFWF3XZD.js +21 -0
  496. package/dist/worktree-sweep-SE7ITXC4.js +21 -0
  497. package/package.json +1 -1
  498. package/release-notes.json +117 -191
  499. package/src/commands/exe.md +18 -1
@@ -0,0 +1,1350 @@
1
+ import {
2
+ ingest
3
+ } from "./chunk-WCUZX7F7.js";
4
+ import {
5
+ listWorkflowDefinitions,
6
+ runWorkflow,
7
+ startWorkflow
8
+ } from "./chunk-SDPUWZP5.js";
9
+ import {
10
+ initCRMBridge
11
+ } from "./chunk-ONKIWA3R.js";
12
+ import {
13
+ orgBus
14
+ } from "./chunk-MP2AFCGL.js";
15
+
16
+ // src/gateway/router.ts
17
+ function matchesPlatform(msgPlatform, matchPlatform) {
18
+ if (!matchPlatform) return true;
19
+ const platforms = Array.isArray(matchPlatform) ? matchPlatform : [matchPlatform];
20
+ return platforms.includes(msgPlatform);
21
+ }
22
+ function matchesChannel(msgChannel, matchChannel) {
23
+ if (!matchChannel) return true;
24
+ const channels = Array.isArray(matchChannel) ? matchChannel : [matchChannel];
25
+ return channels.includes(msgChannel);
26
+ }
27
+ var MAX_REGEX_LENGTH = 200;
28
+ function safeRegExp(pattern, flags) {
29
+ if (pattern.length > MAX_REGEX_LENGTH) return null;
30
+ try {
31
+ return new RegExp(pattern, flags);
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ function matchesSender(msgSender, matchSender) {
37
+ if (!matchSender) return true;
38
+ const re = safeRegExp(matchSender);
39
+ return re ? re.test(msgSender) : false;
40
+ }
41
+ function matchesTextPattern(msgText, matchPattern) {
42
+ if (!matchPattern) return true;
43
+ const re = safeRegExp(matchPattern, "i");
44
+ return re ? re.test(msgText) : false;
45
+ }
46
+ function matchesRoute(msg, match) {
47
+ return matchesPlatform(msg.platform, match.platform) && matchesChannel(msg.channelId, match.channelId) && matchesSender(msg.senderId, match.senderId) && matchesTextPattern(msg.text, match.textPattern);
48
+ }
49
+ function routeMessage(msg, config) {
50
+ for (const route of config.routes) {
51
+ if (matchesRoute(msg, route.match)) {
52
+ return {
53
+ employee: route.target,
54
+ modelTier: route.modelTier,
55
+ permissions: route.permissions,
56
+ routeName: route.name
57
+ };
58
+ }
59
+ }
60
+ return {
61
+ employee: config.defaultRoute,
62
+ modelTier: config.defaultModelTier,
63
+ permissions: config.defaultPermissions,
64
+ routeName: "default"
65
+ };
66
+ }
67
+ function validateGatewayConfig(config) {
68
+ const warnings = [];
69
+ if (!config.routes.length) {
70
+ warnings.push("No routes configured \u2014 all messages will use default route");
71
+ }
72
+ if (!config.defaultRoute) {
73
+ warnings.push("No default route specified");
74
+ }
75
+ const names = /* @__PURE__ */ new Set();
76
+ for (const route of config.routes) {
77
+ if (names.has(route.name)) {
78
+ warnings.push(`Duplicate route name: "${route.name}"`);
79
+ }
80
+ names.add(route.name);
81
+ if (!route.target) {
82
+ warnings.push(`Route "${route.name}" has no target employee`);
83
+ }
84
+ if (route.match.senderId && !safeRegExp(route.match.senderId)) {
85
+ warnings.push(`Route "${route.name}" has invalid senderId regex: ${route.match.senderId}`);
86
+ }
87
+ if (route.match.textPattern && !safeRegExp(route.match.textPattern, "i")) {
88
+ warnings.push(`Route "${route.name}" has invalid textPattern regex: ${route.match.textPattern}`);
89
+ }
90
+ const isEmptyMatch = !route.match.platform && !route.match.channelId && !route.match.senderId && !route.match.textPattern;
91
+ if (isEmptyMatch && config.routes.indexOf(route) !== config.routes.length - 1) {
92
+ warnings.push(
93
+ `Route "${route.name}" matches everything but is not the last route \u2014 routes after it will never match`
94
+ );
95
+ }
96
+ }
97
+ return warnings;
98
+ }
99
+
100
+ // src/gateway/reliability.ts
101
+ var DEFAULT_RETRY = {
102
+ maxRetries: 3,
103
+ baseDelayMs: 1e3,
104
+ maxDelayMs: 4e3
105
+ };
106
+ async function retryWithBackoff(fn, config = {}) {
107
+ const { maxRetries, baseDelayMs, maxDelayMs } = {
108
+ ...DEFAULT_RETRY,
109
+ ...config
110
+ };
111
+ let lastError;
112
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
113
+ try {
114
+ return await fn();
115
+ } catch (err) {
116
+ lastError = err instanceof Error ? err : new Error(String(err));
117
+ if (attempt < maxRetries) {
118
+ const delay = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
119
+ await new Promise((r) => setTimeout(r, delay));
120
+ }
121
+ }
122
+ }
123
+ throw lastError;
124
+ }
125
+ var DEFAULT_CIRCUIT = {
126
+ windowMs: 6e4,
127
+ failureThreshold: 0.5,
128
+ minimumRequests: 5,
129
+ halfOpenAfterMs: 3e4
130
+ };
131
+ var CircuitBreaker = class {
132
+ state = "closed";
133
+ records = [];
134
+ lastStateChange = Date.now();
135
+ config;
136
+ name;
137
+ constructor(name, config = {}) {
138
+ this.name = name;
139
+ this.config = { ...DEFAULT_CIRCUIT, ...config };
140
+ }
141
+ /** Check if a request should be allowed through */
142
+ canRequest() {
143
+ this.pruneRecords();
144
+ if (this.state === "closed") return true;
145
+ if (this.state === "open") {
146
+ const elapsed = Date.now() - this.lastStateChange;
147
+ if (elapsed >= this.config.halfOpenAfterMs) {
148
+ this.transition("half-open");
149
+ return true;
150
+ }
151
+ return false;
152
+ }
153
+ return true;
154
+ }
155
+ /** Record a successful request */
156
+ recordSuccess() {
157
+ this.records.push({ timestamp: Date.now(), success: true });
158
+ if (this.state === "half-open") {
159
+ this.transition("closed");
160
+ }
161
+ }
162
+ /** Record a failed request */
163
+ recordFailure() {
164
+ this.records.push({ timestamp: Date.now(), success: false });
165
+ if (this.state === "half-open") {
166
+ this.transition("open");
167
+ return;
168
+ }
169
+ if (this.state === "closed") {
170
+ this.pruneRecords();
171
+ if (this.records.length >= this.config.minimumRequests) {
172
+ const failures = this.records.filter((r) => !r.success).length;
173
+ const rate = failures / this.records.length;
174
+ if (rate >= this.config.failureThreshold) {
175
+ this.transition("open");
176
+ }
177
+ }
178
+ }
179
+ }
180
+ /** Get current circuit state */
181
+ getState() {
182
+ if (this.state === "open") {
183
+ const elapsed = Date.now() - this.lastStateChange;
184
+ if (elapsed >= this.config.halfOpenAfterMs) {
185
+ this.transition("half-open");
186
+ }
187
+ }
188
+ return this.state;
189
+ }
190
+ /** Get failure rate in current window */
191
+ getFailureRate() {
192
+ this.pruneRecords();
193
+ if (this.records.length === 0) return 0;
194
+ const failures = this.records.filter((r) => !r.success).length;
195
+ return failures / this.records.length;
196
+ }
197
+ /** Reset the circuit breaker */
198
+ reset() {
199
+ this.records = [];
200
+ this.transition("closed");
201
+ }
202
+ transition(newState) {
203
+ this.state = newState;
204
+ this.lastStateChange = Date.now();
205
+ }
206
+ pruneRecords() {
207
+ const cutoff = Date.now() - this.config.windowMs;
208
+ while (this.records.length > 0 && this.records[0].timestamp < cutoff) {
209
+ this.records.shift();
210
+ }
211
+ }
212
+ };
213
+ function buildDegradationMessage() {
214
+ return "I'm having trouble right now. Let me get a human to help you.";
215
+ }
216
+
217
+ // src/gateway/types.ts
218
+ var FULL_ACCESS = {
219
+ canRead: true,
220
+ canWrite: true,
221
+ canExecute: true
222
+ };
223
+ var READ_ONLY = {
224
+ canRead: true,
225
+ canWrite: false,
226
+ canExecute: false
227
+ };
228
+ var READ_TOOLS = [
229
+ "ask_team_memory",
230
+ "recall_my_memory",
231
+ "list_tasks",
232
+ "get_session_context",
233
+ "get_memory_by_id",
234
+ "list_reminders",
235
+ "query_conversations"
236
+ ];
237
+ var WRITE_TOOLS = [
238
+ "create_task",
239
+ "update_task",
240
+ "send_message",
241
+ "store_memory",
242
+ "store_behavior",
243
+ "create_reminder",
244
+ "complete_reminder"
245
+ ];
246
+ var EXECUTE_TOOLS = ["close_task"];
247
+
248
+ // src/gateway/permission-guard.ts
249
+ var TOOL_CLASSIFICATION = /* @__PURE__ */ new Map();
250
+ for (const tool of READ_TOOLS) TOOL_CLASSIFICATION.set(tool, "canRead");
251
+ for (const tool of WRITE_TOOLS) TOOL_CLASSIFICATION.set(tool, "canWrite");
252
+ for (const tool of EXECUTE_TOOLS) TOOL_CLASSIFICATION.set(tool, "canExecute");
253
+ function classifyTool(toolName) {
254
+ return TOOL_CLASSIFICATION.get(toolName) ?? null;
255
+ }
256
+ function checkToolPermission(toolName, permissions) {
257
+ const classification = classifyTool(toolName);
258
+ if (!classification) {
259
+ return {
260
+ allowed: false,
261
+ tool: toolName,
262
+ requiredPermission: "canExecute",
263
+ reason: `Unknown tool "${toolName}" is not in the allowed tool list`
264
+ };
265
+ }
266
+ const allowed = permissions[classification];
267
+ return {
268
+ allowed,
269
+ tool: toolName,
270
+ requiredPermission: classification,
271
+ reason: allowed ? void 0 : `Tool "${toolName}" requires ${classification} permission, which is not granted on this channel`
272
+ };
273
+ }
274
+ function guardToolUseBlocks(blocks, permissions) {
275
+ const allowed = [];
276
+ const blocked = [];
277
+ for (const block of blocks) {
278
+ const result = checkToolPermission(block.name, permissions);
279
+ if (result.allowed) {
280
+ allowed.push(block);
281
+ } else {
282
+ blocked.push({ block, check: result });
283
+ }
284
+ }
285
+ return { allowed, blocked };
286
+ }
287
+ function checkSenderAllowlist(senderId, config) {
288
+ if (!config || config.allowlist.length === 0) {
289
+ return { allowed: true, mode: "none" };
290
+ }
291
+ const normalizedSender = senderId.trim().toLowerCase();
292
+ const isAllowed = config.allowlist.some(
293
+ (id) => id.trim().toLowerCase() === normalizedSender
294
+ );
295
+ if (isAllowed) {
296
+ return { allowed: true, mode: config.allowlist_mode };
297
+ }
298
+ if (config.allowlist_mode === "log") {
299
+ console.warn(
300
+ `[sender-allowlist] Unknown sender "${senderId}" \u2014 logging (mode=log)`
301
+ );
302
+ return { allowed: true, mode: "log", reason: "Unknown sender (logged)" };
303
+ }
304
+ return {
305
+ allowed: false,
306
+ mode: "strict",
307
+ reason: config.reject_message ?? "This service is not available to you."
308
+ };
309
+ }
310
+ var BOUNDARY_MARKER = "--- EXTERNAL USER MESSAGE (untrusted input) ---";
311
+ var INJECTION_PATTERNS = [
312
+ /ignore\s+(all\s+)?previous\s+instructions/gi,
313
+ /ignore\s+(all\s+)?prior\s+instructions/gi,
314
+ /you\s+are\s+now\b/gi,
315
+ /^system\s*:/gim,
316
+ /^ADMIN\s*:/gim,
317
+ /^DEVELOPER\s*:/gim,
318
+ /^ASSISTANT\s*:/gim,
319
+ /^HUMAN\s*:/gim,
320
+ /\bdo\s+not\s+follow\s+(your|the)\s+(rules|instructions|guidelines)\b/gi,
321
+ /\boverride\s+(your|all|the)\s+(rules|instructions|constraints)\b/gi,
322
+ /\bforget\s+(your|all|previous)\s+(rules|instructions|context)\b/gi,
323
+ /\bnew\s+instructions?\s*:/gi,
324
+ /\<\/?system\>/gi,
325
+ /\[\s*SYSTEM\s*\]/gi
326
+ ];
327
+ function sanitizeInboundMessage(text) {
328
+ let sanitized = text;
329
+ for (const pattern of INJECTION_PATTERNS) {
330
+ pattern.lastIndex = 0;
331
+ sanitized = sanitized.replace(pattern, "[FILTERED]");
332
+ }
333
+ return `${BOUNDARY_MARKER}
334
+ ${sanitized}`;
335
+ }
336
+ var OutboundRateLimiter = class {
337
+ contacts = /* @__PURE__ */ new Map();
338
+ maxPerMinute;
339
+ constructor(maxPerMinute = 5) {
340
+ this.maxPerMinute = maxPerMinute;
341
+ }
342
+ /**
343
+ * Check if an outbound message to this contact is allowed.
344
+ * Returns true if under the rate limit.
345
+ */
346
+ check(contactId) {
347
+ const now = Date.now();
348
+ const windowMs = 6e4;
349
+ let entry = this.contacts.get(contactId);
350
+ if (!entry) {
351
+ entry = { timestamps: [] };
352
+ this.contacts.set(contactId, entry);
353
+ }
354
+ entry.timestamps = entry.timestamps.filter((t) => now - t < windowMs);
355
+ if (entry.timestamps.length >= this.maxPerMinute) {
356
+ return { allowed: false, remaining: 0 };
357
+ }
358
+ entry.timestamps.push(now);
359
+ return {
360
+ allowed: true,
361
+ remaining: this.maxPerMinute - entry.timestamps.length
362
+ };
363
+ }
364
+ /** Reset limiter state (for testing) */
365
+ reset() {
366
+ this.contacts.clear();
367
+ }
368
+ };
369
+ function buildPermissionContext(platform, permissions) {
370
+ if (permissions.canRead && permissions.canWrite && permissions.canExecute) {
371
+ return `[FULL ACCESS \u2014 you can read, write, and execute via ${platform}]`;
372
+ }
373
+ if (permissions.canRead && !permissions.canWrite && !permissions.canExecute) {
374
+ return `[READ-ONLY \u2014 this ${platform} channel cannot create tasks, send messages, or execute commands. Tell the founder to use Signal for commands.]`;
375
+ }
376
+ const parts = [];
377
+ if (permissions.canRead) parts.push("read");
378
+ if (permissions.canWrite) parts.push("write");
379
+ if (permissions.canExecute) parts.push("execute");
380
+ return `[${platform.toUpperCase()} \u2014 allowed: ${parts.join(", ")}]`;
381
+ }
382
+
383
+ // src/gateway/workflow-triggers.ts
384
+ var _patterns = [];
385
+ function matchPatterns(msg, eventType = "message.inbound") {
386
+ return _patterns.filter((p) => {
387
+ if (!p.enabled) return false;
388
+ if (p.eventType !== eventType && p.eventType !== "*") return false;
389
+ if (p.platformMatch && p.platformMatch !== msg.platform) return false;
390
+ if (p.senderMatch && p.senderMatch !== msg.senderId) return false;
391
+ if (p.textMatch && !msg.text.toLowerCase().includes(p.textMatch.toLowerCase())) return false;
392
+ return true;
393
+ });
394
+ }
395
+ async function processWorkflowTriggers(msg, eventType = "message.inbound") {
396
+ if (_patterns.length === 0) return 0;
397
+ const matches = matchPatterns(msg, eventType);
398
+ if (matches.length === 0) return 0;
399
+ let started = 0;
400
+ for (const pattern of matches) {
401
+ const defs = listWorkflowDefinitions();
402
+ const def = defs.find((d) => d.id === pattern.workflowDefinitionId);
403
+ if (!def) {
404
+ console.error(
405
+ `[workflow-triggers] Pattern "${pattern.name}" references unknown definition: ${pattern.workflowDefinitionId}`
406
+ );
407
+ continue;
408
+ }
409
+ try {
410
+ const instance = startWorkflow(pattern.workflowDefinitionId, {
411
+ platform: msg.platform,
412
+ senderId: msg.senderId,
413
+ senderName: msg.senderName,
414
+ text: msg.text,
415
+ channelId: msg.channelId,
416
+ messageId: msg.messageId,
417
+ timestamp: msg.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
418
+ triggerId: pattern.id,
419
+ triggerName: pattern.name
420
+ });
421
+ await runWorkflow(instance.id);
422
+ started++;
423
+ console.log(
424
+ `[workflow-triggers] Started workflow "${def.name}" (${instance.id}) from trigger "${pattern.name}"`
425
+ );
426
+ } catch (err) {
427
+ console.error(
428
+ `[workflow-triggers] Failed to start workflow for trigger "${pattern.name}":`,
429
+ err instanceof Error ? err.message : err
430
+ );
431
+ }
432
+ }
433
+ return started;
434
+ }
435
+
436
+ // src/gateway/media-r2-bridge.ts
437
+ import { readFileSync } from "fs";
438
+
439
+ // src/lib/r2-media.ts
440
+ import {
441
+ S3Client,
442
+ PutObjectCommand,
443
+ GetObjectCommand,
444
+ DeleteObjectCommand,
445
+ HeadObjectCommand
446
+ } from "@aws-sdk/client-s3";
447
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
448
+ import { randomUUID } from "crypto";
449
+ import path from "path";
450
+ function loadR2Config() {
451
+ const bucket = process.env.R2_MEDIA_BUCKET?.trim();
452
+ const endpoint = process.env.R2_MEDIA_ENDPOINT?.trim();
453
+ const accessKeyId = process.env.R2_MEDIA_ACCESS_KEY?.trim();
454
+ const secretAccessKey = process.env.R2_MEDIA_SECRET_KEY?.trim();
455
+ if (!bucket || !endpoint || !accessKeyId || !secretAccessKey) return null;
456
+ return {
457
+ bucket,
458
+ endpoint,
459
+ accessKeyId,
460
+ secretAccessKey,
461
+ publicUrl: process.env.R2_MEDIA_PUBLIC_URL?.trim() || void 0
462
+ };
463
+ }
464
+ var _client = null;
465
+ var _config = null;
466
+ function getClient() {
467
+ if (_client && _config) return { client: _client, config: _config };
468
+ const config = loadR2Config();
469
+ if (!config) return null;
470
+ _client = new S3Client({
471
+ region: "auto",
472
+ endpoint: config.endpoint,
473
+ credentials: {
474
+ accessKeyId: config.accessKeyId,
475
+ secretAccessKey: config.secretAccessKey
476
+ }
477
+ });
478
+ _config = config;
479
+ return { client: _client, config: _config };
480
+ }
481
+ function isR2MediaConfigured() {
482
+ return loadR2Config() !== null;
483
+ }
484
+ async function uploadMedia(data, filename, product, contentType) {
485
+ const r2 = getClient();
486
+ if (!r2) return null;
487
+ const ext = path.extname(filename) || "";
488
+ const key = `media/${product}/${randomUUID()}${ext}`;
489
+ await r2.client.send(
490
+ new PutObjectCommand({
491
+ Bucket: r2.config.bucket,
492
+ Key: key,
493
+ Body: data,
494
+ ContentType: contentType || guessMimeType(ext)
495
+ })
496
+ );
497
+ const url = r2.config.publicUrl ? `${r2.config.publicUrl}/${key}` : await getPresignedUrl(key, 3600);
498
+ return { key, url, size: data.length };
499
+ }
500
+ async function getPresignedUrl(key, expiresIn = 3600) {
501
+ const r2 = getClient();
502
+ if (!r2) throw new Error("R2 media storage is not configured");
503
+ return getSignedUrl(
504
+ r2.client,
505
+ new GetObjectCommand({
506
+ Bucket: r2.config.bucket,
507
+ Key: key
508
+ }),
509
+ { expiresIn }
510
+ );
511
+ }
512
+ function guessMimeType(ext) {
513
+ const map = {
514
+ ".jpg": "image/jpeg",
515
+ ".jpeg": "image/jpeg",
516
+ ".png": "image/png",
517
+ ".gif": "image/gif",
518
+ ".webp": "image/webp",
519
+ ".svg": "image/svg+xml",
520
+ ".mp4": "video/mp4",
521
+ ".webm": "video/webm",
522
+ ".mp3": "audio/mpeg",
523
+ ".wav": "audio/wav",
524
+ ".pdf": "application/pdf",
525
+ ".json": "application/json",
526
+ ".txt": "text/plain"
527
+ };
528
+ return map[ext.toLowerCase()] || "application/octet-stream";
529
+ }
530
+
531
+ // src/gateway/media-r2-bridge.ts
532
+ async function uploadMediaAttachments(msg) {
533
+ if (!isR2MediaConfigured()) return 0;
534
+ if (!msg.media || msg.media.length === 0) return 0;
535
+ let uploaded = 0;
536
+ for (const attachment of msg.media) {
537
+ if (attachment.url) continue;
538
+ if (!attachment.localPath) continue;
539
+ try {
540
+ const data = readFileSync(attachment.localPath);
541
+ const filename = attachment.fileName ?? `media.${attachment.type}`;
542
+ const result = await uploadMedia(data, filename, msg.platform);
543
+ if (result) {
544
+ attachment.url = result.url;
545
+ uploaded++;
546
+ }
547
+ } catch (err) {
548
+ console.error(
549
+ `[media-r2-bridge] Failed to upload ${attachment.localPath}:`,
550
+ err instanceof Error ? err.message : err
551
+ );
552
+ }
553
+ }
554
+ return uploaded;
555
+ }
556
+
557
+ // src/gateway/gateway.ts
558
+ var Gateway = class {
559
+ config;
560
+ adapters = /* @__PURE__ */ new Map();
561
+ platformConfigs;
562
+ botRegistry;
563
+ rateLimiter;
564
+ sessionStore;
565
+ analytics;
566
+ alertMonitor;
567
+ failover;
568
+ customerStore;
569
+ startedAt = 0;
570
+ outboundLimiters = /* @__PURE__ */ new Map();
571
+ /** Queued outbound messages awaiting coordinator approval (Tier 3) */
572
+ outboundQueue = [];
573
+ constructor(options) {
574
+ this.config = options.config;
575
+ this.platformConfigs = options.platformConfigs;
576
+ this.botRegistry = options.botRegistry;
577
+ this.rateLimiter = options.rateLimiter;
578
+ this.sessionStore = options.sessionStore;
579
+ this.analytics = options.analytics;
580
+ this.alertMonitor = options.alertMonitor;
581
+ this.failover = options.failover;
582
+ this.customerStore = options.customerStore;
583
+ }
584
+ registerAdapter(adapter) {
585
+ this.adapters.set(adapter.platform, adapter);
586
+ adapter.onMessage((msg) => this.handleMessage(msg));
587
+ }
588
+ async start() {
589
+ this.startedAt = Date.now();
590
+ initCRMBridge();
591
+ const startPromises = [];
592
+ for (const [platform, adapter] of this.adapters) {
593
+ const config = this.platformConfigs.get(platform);
594
+ if (!config) {
595
+ console.error(`[gateway] No config for platform: ${platform}`);
596
+ continue;
597
+ }
598
+ console.log(`[gateway] Connecting ${platform}...`);
599
+ startPromises.push(
600
+ adapter.connect(config).then(() => {
601
+ console.log(`[gateway] ${platform} connected`);
602
+ }).catch((err) => {
603
+ console.error(`[gateway] ${platform} connection failed:`, err);
604
+ this.alertMonitor?.alertAdapterDisconnected(
605
+ platform,
606
+ err instanceof Error ? err.message : String(err)
607
+ );
608
+ })
609
+ );
610
+ }
611
+ await Promise.allSettled(startPromises);
612
+ console.log(
613
+ `[gateway] Started with ${this.botRegistry.list().length} bots: ${this.botRegistry.list().join(", ")}`
614
+ );
615
+ }
616
+ async stop() {
617
+ const stopPromises = [...this.adapters.values()].map(
618
+ (a) => a.disconnect()
619
+ );
620
+ await Promise.allSettled(stopPromises);
621
+ console.log("[gateway] Stopped");
622
+ }
623
+ async handleMessage(msg) {
624
+ const start = Date.now();
625
+ if (this.rateLimiter) {
626
+ const limitResult = this.rateLimiter.check(msg.senderId);
627
+ if (!limitResult.allowed) {
628
+ const adapter2 = this.adapters.get(msg.platform);
629
+ if (adapter2) {
630
+ await adapter2.sendText(msg.channelId, limitResult.reason ?? "Please slow down.");
631
+ }
632
+ return;
633
+ }
634
+ }
635
+ const platformConfig = this.platformConfigs.get(msg.platform);
636
+ const senderCheck = checkSenderAllowlist(
637
+ msg.senderId,
638
+ platformConfig?.senderAllowlist
639
+ );
640
+ if (!senderCheck.allowed) {
641
+ console.warn(
642
+ `[gateway] Sender rejected by allowlist: ${msg.senderId} on ${msg.platform}`
643
+ );
644
+ const adapter2 = this.adapters.get(msg.platform);
645
+ if (adapter2 && senderCheck.reason) {
646
+ await adapter2.sendText(msg.channelId, senderCheck.reason);
647
+ }
648
+ return;
649
+ }
650
+ msg.text = sanitizeInboundMessage(msg.text);
651
+ this.customerStore?.resolve(msg.platform, msg.senderId);
652
+ uploadMediaAttachments(msg).catch((err) => {
653
+ console.error("[gateway] Media R2 upload error:", err);
654
+ });
655
+ ingest(msg).catch((err) => {
656
+ console.error("[gateway] Pipeline inbound ingest error:", err);
657
+ });
658
+ processWorkflowTriggers(msg).catch((err) => {
659
+ console.error("[gateway] Workflow trigger error:", err);
660
+ });
661
+ const route = routeMessage(msg, this.config);
662
+ console.log(
663
+ `[gateway] ${msg.platform}/${msg.senderId} \u2192 ${route.employee} (${route.routeName})`
664
+ );
665
+ orgBus.emit({
666
+ type: "gateway_message",
667
+ platform: msg.platform,
668
+ senderId: msg.senderId,
669
+ botId: route.employee,
670
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
671
+ });
672
+ const bot = this.botRegistry.get(route.employee);
673
+ if (!bot) {
674
+ console.error(`[gateway] No bot registered for target: ${route.employee}`);
675
+ const adapter2 = this.adapters.get(msg.platform);
676
+ if (adapter2) {
677
+ await adapter2.sendText(msg.channelId, "Sorry, I'm not available right now.");
678
+ }
679
+ return;
680
+ }
681
+ const adapter = this.adapters.get(msg.platform);
682
+ if (!adapter) return;
683
+ await adapter.sendTyping(msg.channelId);
684
+ const session = this.sessionStore?.getOrCreate(
685
+ msg.senderId,
686
+ route.employee,
687
+ msg.platform
688
+ );
689
+ if (session) {
690
+ this.sessionStore.addMessage(session.sessionId, {
691
+ role: "user",
692
+ content: msg.text
693
+ });
694
+ }
695
+ if (session?.messageCount === 1) {
696
+ this.analytics?.conversationStarted(msg.platform, route.employee);
697
+ }
698
+ try {
699
+ const response = await bot.processMessage(msg, route.permissions);
700
+ const latencyMs = Date.now() - start;
701
+ if (session) {
702
+ this.sessionStore.addMessage(session.sessionId, {
703
+ role: "assistant",
704
+ content: response
705
+ });
706
+ }
707
+ this.analytics?.responseRecorded(
708
+ msg.platform,
709
+ route.employee,
710
+ latencyMs,
711
+ 0,
712
+ // Token counts not available from BotRuntime yet
713
+ 0,
714
+ "anthropic",
715
+ true
716
+ );
717
+ this.alertMonitor?.recordEvent(latencyMs, true);
718
+ const outboundConfig = platformConfig?.outboundConfirm;
719
+ if (outboundConfig?.enabled) {
720
+ this.outboundQueue.push({
721
+ platform: msg.platform,
722
+ channelId: msg.channelId,
723
+ text: response,
724
+ replyToMessageId: msg.messageId,
725
+ queuedAt: Date.now()
726
+ });
727
+ console.log(
728
+ `[gateway] Outbound queued for approval (${this.outboundQueue.length} pending): ${msg.platform}/${msg.channelId}`
729
+ );
730
+ } else {
731
+ let limiter = this.outboundLimiters.get(msg.platform);
732
+ if (!limiter) {
733
+ const maxPerMin = outboundConfig?.rate_limit_per_minute ?? 5;
734
+ limiter = new OutboundRateLimiter(maxPerMin);
735
+ this.outboundLimiters.set(msg.platform, limiter);
736
+ }
737
+ const rateCheck = limiter.check(msg.senderId);
738
+ if (!rateCheck.allowed) {
739
+ console.warn(
740
+ `[gateway] Outbound rate-limited for ${msg.senderId} on ${msg.platform}`
741
+ );
742
+ }
743
+ await adapter.sendText(msg.channelId, response, {
744
+ replyToMessageId: msg.messageId
745
+ });
746
+ }
747
+ ingest(msg, response, route.employee).catch((err) => {
748
+ console.error("[gateway] Pipeline conversation ingest error:", err);
749
+ });
750
+ } catch (err) {
751
+ const latencyMs = Date.now() - start;
752
+ this.alertMonitor?.recordEvent(latencyMs, false);
753
+ this.analytics?.responseRecorded(
754
+ msg.platform,
755
+ route.employee,
756
+ latencyMs,
757
+ 0,
758
+ 0,
759
+ "anthropic",
760
+ false
761
+ );
762
+ console.error(`[gateway] Error processing message:`, err);
763
+ await adapter.sendText(
764
+ msg.channelId,
765
+ buildDegradationMessage()
766
+ );
767
+ }
768
+ }
769
+ /** Get pending outbound messages awaiting approval (Tier 3) */
770
+ getOutboundQueue() {
771
+ return this.outboundQueue.map((item, index) => ({
772
+ platform: item.platform,
773
+ channelId: item.channelId,
774
+ text: item.text,
775
+ queuedAt: item.queuedAt,
776
+ index
777
+ }));
778
+ }
779
+ /** Approve and send a queued outbound message (Tier 3) */
780
+ async approveOutbound(index) {
781
+ if (index < 0 || index >= this.outboundQueue.length) return false;
782
+ const item = this.outboundQueue[index];
783
+ const adapter = this.adapters.get(item.platform);
784
+ if (!adapter) return false;
785
+ await adapter.sendText(item.channelId, item.text, {
786
+ replyToMessageId: item.replyToMessageId
787
+ });
788
+ this.outboundQueue.splice(index, 1);
789
+ return true;
790
+ }
791
+ /** Reject a queued outbound message (Tier 3) */
792
+ rejectOutbound(index) {
793
+ if (index < 0 || index >= this.outboundQueue.length) return false;
794
+ this.outboundQueue.splice(index, 1);
795
+ return true;
796
+ }
797
+ /** Health check all adapters + provider health */
798
+ async healthCheck() {
799
+ const adapterHealth = /* @__PURE__ */ new Map();
800
+ for (const [platform, adapter] of this.adapters) {
801
+ adapterHealth.set(platform, await adapter.healthCheck());
802
+ }
803
+ return {
804
+ adapters: adapterHealth,
805
+ providers: this.failover?.getProviderHealth(),
806
+ bots: this.botRegistry.list(),
807
+ uptime: this.startedAt > 0 ? Date.now() - this.startedAt : 0,
808
+ sessions: this.sessionStore?.stats(),
809
+ alerts: this.alertMonitor?.getActiveAlerts().length
810
+ };
811
+ }
812
+ };
813
+
814
+ // src/gateway/bot-errors.ts
815
+ var FatalBotError = class extends Error {
816
+ constructor(message, cause) {
817
+ super(message);
818
+ this.cause = cause;
819
+ this.name = "FatalBotError";
820
+ }
821
+ cause;
822
+ fatal = true;
823
+ };
824
+ var RecoverableBotError = class extends Error {
825
+ constructor(message, toolName, cause) {
826
+ super(message);
827
+ this.toolName = toolName;
828
+ this.cause = cause;
829
+ this.name = "RecoverableBotError";
830
+ }
831
+ toolName;
832
+ cause;
833
+ recoverable = true;
834
+ };
835
+ var MaxStepsError = class extends Error {
836
+ constructor(stepsTaken, maxSteps) {
837
+ super(
838
+ `Reached maximum steps (${stepsTaken}/${maxSteps}). Returning partial result.`
839
+ );
840
+ this.stepsTaken = stepsTaken;
841
+ this.maxSteps = maxSteps;
842
+ this.name = "MaxStepsError";
843
+ }
844
+ stepsTaken;
845
+ maxSteps;
846
+ };
847
+ function classifyError(err, toolName) {
848
+ if (err instanceof FatalBotError) return err;
849
+ if (err instanceof RecoverableBotError) return err;
850
+ const message = err instanceof Error ? err.message : String(err);
851
+ if (message.includes("401") || message.includes("403") || message.includes("authentication") || message.includes("rate_limit")) {
852
+ return new FatalBotError(message, err);
853
+ }
854
+ return new RecoverableBotError(message, toolName, err);
855
+ }
856
+
857
+ // src/gateway/bot-runtime.ts
858
+ import Anthropic from "@anthropic-ai/sdk";
859
+ var DEFAULT_MODEL = "claude-sonnet-4-20250514";
860
+ var MAX_TURNS = 10;
861
+ var MAX_HISTORY = 50;
862
+ var DEFAULT_PLANNING_INTERVAL = 3;
863
+ function buildExecAssistantSystemPrompt(platform, permissions) {
864
+ const permContext = buildPermissionContext(platform, permissions);
865
+ return `You are the founder's executive assistant (agent_id: "ea").
866
+
867
+ You are a relay between the founder and their AI team. You have access to team memories, task lists, and session context. Your job is to answer the founder's questions by querying the team and presenting clear, synthesized answers.
868
+
869
+ ${permContext}
870
+
871
+ Your personality:
872
+ - Direct and concise \u2014 the founder is busy
873
+ - Lead with the answer, not the process
874
+ - When summarizing team work, be specific: names, counts, what shipped
875
+ - If you don't know something, say so and suggest who might
876
+
877
+ Your tools:
878
+ - ask_team_memory: Query any employee's memories by their configured name
879
+ - recall_my_memory: Search your own past conversations with the founder
880
+ - list_tasks: See what's in progress across the org
881
+ - get_session_context: Get context from a specific session
882
+ - list_reminders: Check active reminders
883
+
884
+ ${permissions.canWrite ? "You also have write access: create_task, send_message, store_memory, etc." : "You are READ-ONLY on this channel. If the founder wants to create tasks or send commands, they should use Signal."}`;
885
+ }
886
+ function filterToolsForPermissions(tools, permissions) {
887
+ const allAllowed = /* @__PURE__ */ new Set();
888
+ if (permissions.canRead) {
889
+ for (const t of READ_TOOLS) allAllowed.add(t);
890
+ }
891
+ if (permissions.canWrite) {
892
+ for (const t of WRITE_TOOLS) allAllowed.add(t);
893
+ }
894
+ if (permissions.canExecute) {
895
+ for (const t of EXECUTE_TOOLS) allAllowed.add(t);
896
+ }
897
+ return tools.filter((t) => allAllowed.has(t.name));
898
+ }
899
+ var BotRuntime = class {
900
+ client;
901
+ config;
902
+ conversations = /* @__PURE__ */ new Map();
903
+ constructor(config) {
904
+ this.config = config;
905
+ this.client = new Anthropic({ apiKey: config.apiKey });
906
+ }
907
+ /**
908
+ * Process an incoming message and return the text response.
909
+ * Handles multi-turn tool use internally.
910
+ */
911
+ async processMessage(msg, permissions) {
912
+ const sessionKey = msg.chatType === "group" ? msg.channelId : msg.senderId;
913
+ const history = this.getHistory(sessionKey);
914
+ history.push({ role: "user", content: msg.text, frameType: "task" });
915
+ const systemPrompt = this.config.systemPrompt + "\n\n" + buildPermissionContext(msg.platform, permissions);
916
+ const allowedTools = filterToolsForPermissions(
917
+ this.config.tools,
918
+ permissions
919
+ );
920
+ const model = this.config.model ?? DEFAULT_MODEL;
921
+ const maxTurns = this.config.maxTurns ?? MAX_TURNS;
922
+ const planningInterval = this.config.planningInterval ?? DEFAULT_PLANNING_INTERVAL;
923
+ let turns = 0;
924
+ while (turns < maxTurns) {
925
+ turns++;
926
+ if (planningInterval > 0 && turns > 1 && turns % planningInterval === 1 && maxTurns - turns >= 2) {
927
+ history.push({
928
+ role: "user",
929
+ content: "[Planning checkpoint] Review what you know so far. What facts have you gathered? What is your plan for the remaining steps? Be concise.",
930
+ frameType: "planning"
931
+ });
932
+ }
933
+ let response;
934
+ try {
935
+ response = await this.client.messages.create({
936
+ model,
937
+ max_tokens: 4096,
938
+ system: systemPrompt,
939
+ messages: history.map((m) => ({
940
+ role: m.role,
941
+ content: m.content
942
+ })),
943
+ tools: allowedTools.map((t) => ({
944
+ name: t.name,
945
+ description: t.description,
946
+ input_schema: t.input_schema
947
+ }))
948
+ });
949
+ } catch (err) {
950
+ const classified = classifyError(err);
951
+ if (classified instanceof FatalBotError) {
952
+ const errorMsg = `Bot error: ${classified.message}`;
953
+ history.push({ role: "assistant", content: errorMsg, frameType: "error" });
954
+ this.trimHistory(sessionKey);
955
+ return errorMsg;
956
+ }
957
+ history.push({
958
+ role: "assistant",
959
+ content: `[API error \u2014 retrying] ${classified.message}`,
960
+ frameType: "error"
961
+ });
962
+ continue;
963
+ }
964
+ const toolUseBlocks = response.content.filter(
965
+ (b) => b.type === "tool_use"
966
+ );
967
+ if (toolUseBlocks.length === 0) {
968
+ const textContent = response.content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
969
+ history.push({ role: "assistant", content: textContent, frameType: "assistant" });
970
+ this.trimHistory(sessionKey);
971
+ return textContent;
972
+ }
973
+ const { allowed, blocked } = guardToolUseBlocks(
974
+ toolUseBlocks,
975
+ permissions
976
+ );
977
+ history.push({
978
+ role: "assistant",
979
+ content: response.content,
980
+ frameType: "assistant"
981
+ });
982
+ const toolResults = [];
983
+ let hadFatalError = false;
984
+ for (const block of allowed) {
985
+ try {
986
+ const result = await this.config.toolExecutor(
987
+ block.name,
988
+ block.input
989
+ );
990
+ toolResults.push({
991
+ type: "tool_result",
992
+ tool_use_id: block.id,
993
+ content: result
994
+ });
995
+ } catch (err) {
996
+ const classified = classifyError(err, block.name);
997
+ if (classified instanceof FatalBotError) {
998
+ toolResults.push({
999
+ type: "tool_result",
1000
+ tool_use_id: block.id,
1001
+ content: `Fatal error: ${classified.message}`,
1002
+ is_error: true
1003
+ });
1004
+ hadFatalError = true;
1005
+ } else {
1006
+ toolResults.push({
1007
+ type: "tool_result",
1008
+ tool_use_id: block.id,
1009
+ content: `Error (recoverable): ${classified.message}`,
1010
+ is_error: true
1011
+ });
1012
+ }
1013
+ }
1014
+ }
1015
+ for (const { block, check } of blocked) {
1016
+ toolResults.push({
1017
+ type: "tool_result",
1018
+ tool_use_id: block.id,
1019
+ content: `Permission denied: ${check.reason}`,
1020
+ is_error: true
1021
+ });
1022
+ }
1023
+ history.push({
1024
+ role: "user",
1025
+ content: toolResults,
1026
+ frameType: hadFatalError ? "error" : "tool_result"
1027
+ });
1028
+ if (hadFatalError) {
1029
+ this.trimHistory(sessionKey);
1030
+ return `A fatal error occurred during tool execution. The bot loop has been stopped.`;
1031
+ }
1032
+ }
1033
+ const maxErr = new MaxStepsError(turns, maxTurns);
1034
+ history.push({
1035
+ role: "assistant",
1036
+ content: maxErr.message,
1037
+ frameType: "error"
1038
+ });
1039
+ this.trimHistory(sessionKey);
1040
+ return maxErr.message;
1041
+ }
1042
+ getHistory(sessionKey) {
1043
+ if (!this.conversations.has(sessionKey)) {
1044
+ this.conversations.set(sessionKey, []);
1045
+ }
1046
+ return this.conversations.get(sessionKey);
1047
+ }
1048
+ trimHistory(sessionKey) {
1049
+ const history = this.conversations.get(sessionKey);
1050
+ if (!history || history.length <= MAX_HISTORY) return;
1051
+ const firstTaskIdx = history.findIndex((m) => m.frameType === "task");
1052
+ let trimmed = history.filter(
1053
+ (m, i) => m.frameType !== "planning" || i >= history.length - MAX_HISTORY
1054
+ );
1055
+ if (trimmed.length > MAX_HISTORY) {
1056
+ const tail = trimmed.slice(-MAX_HISTORY);
1057
+ if (firstTaskIdx >= 0 && !tail.includes(history[firstTaskIdx])) {
1058
+ tail[0] = history[firstTaskIdx];
1059
+ }
1060
+ trimmed = tail;
1061
+ }
1062
+ this.conversations.set(sessionKey, trimmed);
1063
+ }
1064
+ /** Clear conversation history for a session */
1065
+ clearHistory(sessionKey) {
1066
+ this.conversations.delete(sessionKey);
1067
+ }
1068
+ };
1069
+ function buildExecAssistantTools() {
1070
+ return [
1071
+ {
1072
+ name: "ask_team_memory",
1073
+ description: "Search another employee's memories. Use this to find what a team member worked on, learned, or solved.",
1074
+ input_schema: {
1075
+ type: "object",
1076
+ properties: {
1077
+ team_member: {
1078
+ type: "string",
1079
+ description: "Configured name of the team member"
1080
+ },
1081
+ query: { type: "string", description: "What to search for" },
1082
+ project_name: {
1083
+ type: "string",
1084
+ description: "Filter by project name"
1085
+ },
1086
+ limit: { type: "number", description: "Max results (default 10)" }
1087
+ },
1088
+ required: ["team_member", "query"]
1089
+ }
1090
+ },
1091
+ {
1092
+ name: "recall_my_memory",
1093
+ description: "Search your own past memories using semantic search. Returns memory IDs; use get_memory_by_id for full long records.",
1094
+ input_schema: {
1095
+ type: "object",
1096
+ properties: {
1097
+ query: { type: "string", description: "What to search for" },
1098
+ project_name: {
1099
+ type: "string",
1100
+ description: "Filter by project name"
1101
+ },
1102
+ limit: { type: "number", description: "Max results (default 10)" },
1103
+ body_chars: { type: "number", description: "Max characters per memory body, up to 50000" }
1104
+ },
1105
+ required: ["query"]
1106
+ }
1107
+ },
1108
+ {
1109
+ name: "get_memory_by_id",
1110
+ description: "Fetch one memory by ID with the full untruncated raw_text body.",
1111
+ input_schema: {
1112
+ type: "object",
1113
+ properties: {
1114
+ id: { type: "string", description: "Memory UUID from recall_my_memory" }
1115
+ },
1116
+ required: ["id"]
1117
+ }
1118
+ },
1119
+ {
1120
+ name: "list_tasks",
1121
+ description: "List tasks across the organization.",
1122
+ input_schema: {
1123
+ type: "object",
1124
+ properties: {
1125
+ assigned_to: {
1126
+ type: "string",
1127
+ description: "Filter by assignee"
1128
+ },
1129
+ status: {
1130
+ type: "string",
1131
+ description: "Filter by status (open, in_progress, done)"
1132
+ },
1133
+ project_name: {
1134
+ type: "string",
1135
+ description: "Filter by project"
1136
+ }
1137
+ }
1138
+ }
1139
+ },
1140
+ {
1141
+ name: "get_session_context",
1142
+ description: "Get context from a specific session.",
1143
+ input_schema: {
1144
+ type: "object",
1145
+ properties: {
1146
+ session_key: {
1147
+ type: "string",
1148
+ description: "Session key to look up"
1149
+ }
1150
+ },
1151
+ required: ["session_key"]
1152
+ }
1153
+ },
1154
+ {
1155
+ name: "list_reminders",
1156
+ description: "List active reminders.",
1157
+ input_schema: {
1158
+ type: "object",
1159
+ properties: {
1160
+ status: {
1161
+ type: "string",
1162
+ description: "Filter by status"
1163
+ }
1164
+ }
1165
+ }
1166
+ },
1167
+ // Write tools (only available on Signal with full access)
1168
+ {
1169
+ name: "create_task",
1170
+ description: "Create a new task and assign it to an employee.",
1171
+ input_schema: {
1172
+ type: "object",
1173
+ properties: {
1174
+ title: { type: "string", description: "Task title" },
1175
+ description: { type: "string", description: "Task description" },
1176
+ assigned_to: {
1177
+ type: "string",
1178
+ description: "Employee to assign to"
1179
+ },
1180
+ priority: {
1181
+ type: "string",
1182
+ enum: ["p0", "p1", "p2"],
1183
+ description: "Task priority"
1184
+ },
1185
+ project_name: { type: "string", description: "Project name" }
1186
+ },
1187
+ required: ["title", "assigned_to"]
1188
+ }
1189
+ },
1190
+ {
1191
+ name: "send_message",
1192
+ description: "Send a message to an employee.",
1193
+ input_schema: {
1194
+ type: "object",
1195
+ properties: {
1196
+ to: { type: "string", description: "Employee name" },
1197
+ message: { type: "string", description: "Message content" }
1198
+ },
1199
+ required: ["to", "message"]
1200
+ }
1201
+ },
1202
+ {
1203
+ name: "store_memory",
1204
+ description: "Store a memory for future reference.",
1205
+ input_schema: {
1206
+ type: "object",
1207
+ properties: {
1208
+ content: { type: "string", description: "Memory content" },
1209
+ project_name: { type: "string", description: "Project name" }
1210
+ },
1211
+ required: ["content"]
1212
+ }
1213
+ },
1214
+ {
1215
+ name: "store_behavior",
1216
+ description: "Store a behavioral directive.",
1217
+ input_schema: {
1218
+ type: "object",
1219
+ properties: {
1220
+ content: {
1221
+ type: "string",
1222
+ description: "Behavioral directive content"
1223
+ }
1224
+ },
1225
+ required: ["content"]
1226
+ }
1227
+ },
1228
+ {
1229
+ name: "update_task",
1230
+ description: "Update a task's status.",
1231
+ input_schema: {
1232
+ type: "object",
1233
+ properties: {
1234
+ task_id: { type: "string", description: "Task ID" },
1235
+ status: {
1236
+ type: "string",
1237
+ enum: ["open", "in_progress", "done", "blocked", "cancelled"],
1238
+ description: "New status"
1239
+ },
1240
+ result: { type: "string", description: "Result summary" }
1241
+ },
1242
+ required: ["task_id", "status"]
1243
+ }
1244
+ },
1245
+ {
1246
+ name: "create_reminder",
1247
+ description: "Create a reminder.",
1248
+ input_schema: {
1249
+ type: "object",
1250
+ properties: {
1251
+ content: { type: "string", description: "Reminder content" },
1252
+ due_at: { type: "string", description: "ISO 8601 due date" }
1253
+ },
1254
+ required: ["content"]
1255
+ }
1256
+ },
1257
+ {
1258
+ name: "complete_reminder",
1259
+ description: "Mark a reminder as complete.",
1260
+ input_schema: {
1261
+ type: "object",
1262
+ properties: {
1263
+ reminder_id: { type: "string", description: "Reminder ID" }
1264
+ },
1265
+ required: ["reminder_id"]
1266
+ }
1267
+ },
1268
+ {
1269
+ name: "close_task",
1270
+ description: "Reviewer-only: finalize a task after review. Only coordinators/reviewers can use this.",
1271
+ input_schema: {
1272
+ type: "object",
1273
+ properties: {
1274
+ task_id: { type: "string", description: "Task ID" },
1275
+ result: { type: "string", description: "Completion summary" }
1276
+ },
1277
+ required: ["task_id"]
1278
+ }
1279
+ }
1280
+ ];
1281
+ }
1282
+
1283
+ // src/gateway/bot-registry.ts
1284
+ var BotRegistry = class {
1285
+ bots = /* @__PURE__ */ new Map();
1286
+ /** Register a bot from a template */
1287
+ register(template, apiKey) {
1288
+ const config = {
1289
+ apiKey,
1290
+ model: template.model,
1291
+ agentId: template.agentId,
1292
+ systemPrompt: template.systemPrompt,
1293
+ tools: template.tools.map((t) => ({
1294
+ name: t.name,
1295
+ description: t.description ?? "",
1296
+ input_schema: t.input_schema
1297
+ })),
1298
+ toolExecutor: async (name, input) => {
1299
+ const handler = template.toolHandlers[name];
1300
+ if (!handler) {
1301
+ throw new Error(`No handler for tool "${name}"`);
1302
+ }
1303
+ const result = await handler(input);
1304
+ return typeof result === "string" ? result : JSON.stringify(result);
1305
+ },
1306
+ maxTurns: template.maxTurns
1307
+ };
1308
+ this.bots.set(template.name, new BotRuntime(config));
1309
+ }
1310
+ /** Register a pre-configured BotRuntime directly */
1311
+ registerRuntime(name, runtime) {
1312
+ this.bots.set(name, runtime);
1313
+ }
1314
+ /** Look up a bot by route target name */
1315
+ get(targetName) {
1316
+ return this.bots.get(targetName);
1317
+ }
1318
+ /** List registered bot names */
1319
+ list() {
1320
+ return [...this.bots.keys()];
1321
+ }
1322
+ /** Check if a bot is registered */
1323
+ has(targetName) {
1324
+ return this.bots.has(targetName);
1325
+ }
1326
+ };
1327
+
1328
+ export {
1329
+ routeMessage,
1330
+ validateGatewayConfig,
1331
+ retryWithBackoff,
1332
+ CircuitBreaker,
1333
+ FULL_ACCESS,
1334
+ READ_ONLY,
1335
+ READ_TOOLS,
1336
+ WRITE_TOOLS,
1337
+ EXECUTE_TOOLS,
1338
+ checkToolPermission,
1339
+ guardToolUseBlocks,
1340
+ buildPermissionContext,
1341
+ Gateway,
1342
+ FatalBotError,
1343
+ RecoverableBotError,
1344
+ MaxStepsError,
1345
+ classifyError,
1346
+ buildExecAssistantSystemPrompt,
1347
+ BotRuntime,
1348
+ buildExecAssistantTools,
1349
+ BotRegistry
1350
+ };