@desplega.ai/agent-swarm 2.5.4 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/README.md +4 -2
  2. package/dist/{acp-adapter-ek38cwsv.js → acp-adapter-ma1js5n7.js} +9 -9
  3. package/dist/{actions-92mepq03.js → actions-1vhmtvg9.js} +21 -21
  4. package/dist/{amp-adapter-9gaxg015.js → amp-adapter-sxqqvmdk.js} +4 -4
  5. package/dist/{app-ctn8gsgx.js → app-mwx1d5a9.js} +3 -3
  6. package/dist/{assistant-zyr5kz47.js → assistant-yx1p6g82.js} +30 -26
  7. package/dist/{boot-reembed-w75maga2.js → boot-reembed-5h37a2c2.js} +1 -1
  8. package/dist/{boot-reembed-dwzfttdr.js → boot-reembed-7h78vmvv.js} +2 -1
  9. package/dist/{boot-scrub-sweep-e9kq43kf.js → boot-scrub-sweep-8mawd4gw.js} +4 -4
  10. package/dist/{boot-seeds-x28v3fhb.js → boot-seeds-ca84dhnn.js} +4 -4
  11. package/dist/{claude-adapter-f0afqnne.js → claude-adapter-wqt4hfkq.js} +9 -9
  12. package/dist/{claude-managed-adapter-x81a7r65.js → claude-managed-adapter-6fjqtr2z.js} +2 -2
  13. package/dist/{claude-managed-setup-bqzwjd9x.js → claude-managed-setup-rqv98sea.js} +10 -3
  14. package/dist/{claude-sdk-session-7b7whkaq.js → claude-sdk-session-f29f3b2x.js} +11 -11
  15. package/dist/{cli-sxgtf5fw.js → cli-07q03xm2.js} +1 -1
  16. package/dist/{cli-kxpfx2xr.js → cli-0z1xjzwa.js} +2 -2
  17. package/dist/{cli-g9vd9ece.js → cli-1hhbzkbb.js} +14 -16
  18. package/dist/{cli-qqzmjxkf.js → cli-1m9x8dr5.js} +11 -6
  19. package/dist/{cli-jbnn4vxb.js → cli-2pvzmas1.js} +3 -3
  20. package/dist/{cli-x77gen2p.js → cli-2y7v133v.js} +7 -7
  21. package/dist/{cli-dew6x255.js → cli-39aet655.js} +2 -2
  22. package/dist/{cli-g1cw7xtt.js → cli-39rrw8yp.js} +1 -1
  23. package/dist/{cli-jb30dzvk.js → cli-48gxjmcz.js} +530 -190
  24. package/dist/{cli-pzatvw94.js → cli-54sj64fc.js} +2 -2
  25. package/dist/{cli-bvpgr9ny.js → cli-60sty27p.js} +5 -5
  26. package/dist/{cli-asq5ydm4.js → cli-6a9qfa8b.js} +411 -69
  27. package/dist/{cli-277c31dw.js → cli-6mgdba42.js} +225 -3
  28. package/dist/{cli-19202kew.js → cli-6srv653c.js} +5 -5
  29. package/dist/{cli-n4c8e3s5.js → cli-708wdy32.js} +1 -1
  30. package/dist/{cli-pasyvjmm.js → cli-737pyqxr.js} +1 -1
  31. package/dist/{cli-6x9ma5w5.js → cli-803188pb.js} +1 -1
  32. package/dist/{cli-hh5we352.js → cli-86ehn4s5.js} +7 -7
  33. package/dist/{cli-9s05422w.js → cli-8mbc9za9.js} +1 -1
  34. package/dist/{cli-ff1tm9n9.js → cli-8wmj18cz.js} +1 -1
  35. package/dist/{cli-1r5ad7j5.js → cli-9gsm2rzp.js} +12 -12
  36. package/dist/{cli-mz9afxxf.js → cli-9pshx6rd.js} +17 -3
  37. package/dist/{cli-s682zgqz.js → cli-a6ds2epe.js} +1 -1
  38. package/dist/{cli-6a1xg1p7.js → cli-a89zdqz9.js} +2 -2
  39. package/dist/{cli-03vpq45j.js → cli-ay40dnj3.js} +2 -2
  40. package/dist/{cli-tsma7p8v.js → cli-aypd09nf.js} +2 -2
  41. package/dist/{cli-ethgy7ha.js → cli-b3yzyc57.js} +2 -2
  42. package/dist/{cli-bn0rewsy.js → cli-c081bj3b.js} +2 -2
  43. package/dist/{cli-mmhj8vd7.js → cli-c668vvcf.js} +11 -2
  44. package/dist/{cli-sbwsxvtd.js → cli-d20qvpr2.js} +2 -2
  45. package/dist/{cli-c952c7ac.js → cli-e1595bgx.js} +3 -3
  46. package/dist/{cli-621ce7kw.js → cli-f12mr20z.js} +3 -3
  47. package/dist/{cli-dqygeeh5.js → cli-f1e0ptjj.js} +10 -1
  48. package/dist/{cli-xzfq4at3.js → cli-f4dbh7a5.js} +16 -12
  49. package/dist/{cli-ha9rmwgq.js → cli-fb8m699c.js} +2 -2
  50. package/dist/{cli-5bnsc0e1.js → cli-gsfk58nw.js} +5 -5
  51. package/dist/cli-gt4h8cxw.js +895 -0
  52. package/dist/{cli-nwyw3zhg.js → cli-gxee0bqa.js} +1 -1
  53. package/dist/{cli-25n3mv5d.js → cli-h5jeg46p.js} +6 -6
  54. package/dist/{cli-gn5af0x5.js → cli-he9gbdx0.js} +62 -12
  55. package/dist/{cli-gbfxp48k.js → cli-j0ppywdr.js} +42 -35
  56. package/dist/{cli-k4tjsdx9.js → cli-j3y0x2n4.js} +277 -199
  57. package/dist/{cli-7p4jxgtt.js → cli-j9bpmykh.js} +75 -27
  58. package/dist/{cli-dabehxhp.js → cli-kt907da6.js} +1 -1
  59. package/dist/{cli-wx2nj19m.js → cli-kv7sbc2c.js} +6 -6
  60. package/dist/{cli-abs8ndtr.js → cli-m30k9777.js} +26 -26
  61. package/dist/{cli-cz5nmdxt.js → cli-m5e802r7.js} +2 -2
  62. package/dist/{cli-0shx9j93.js → cli-pfk92eqz.js} +2 -2
  63. package/dist/{cli-xtrz6bzs.js → cli-ptfq202x.js} +5 -3
  64. package/dist/{cli-6n8axjv1.js → cli-qj442fws.js} +2 -2
  65. package/dist/{cli-c61mbdds.js → cli-rd5m70gj.js} +4 -4
  66. package/dist/{cli-eftzyh9y.js → cli-s09j9vp5.js} +2 -2
  67. package/dist/{cli-m4ecdxvz.js → cli-s0mgx214.js} +7 -7
  68. package/dist/{cli-wghjkr0e.js → cli-sgqm2582.js} +10 -7
  69. package/dist/{cli-2655k16q.js → cli-sjctjr48.js} +2 -2
  70. package/dist/{cli-nzfnt2gs.js → cli-tf1n0r0b.js} +1 -1
  71. package/dist/{cli-x0f2v69c.js → cli-twctnkng.js} +12 -7
  72. package/dist/{cli-j6rktc91.js → cli-v6shg7na.js} +1 -1
  73. package/dist/{cli-gx4rm0qx.js → cli-vz78s5wm.js} +1 -1
  74. package/dist/{cli-gwhjmh8g.js → cli-wqr7cea4.js} +5 -5
  75. package/dist/{cli-e42vss7b.js → cli-x37r7qwf.js} +16 -8
  76. package/dist/{cli-4b2z6n0m.js → cli-yd2nreqw.js} +17 -8
  77. package/dist/{cli-64mh9mf3.js → cli-ymjpkxgn.js} +69 -17
  78. package/dist/{cli-5kqnemen.js → cli-yvy48785.js} +1 -1
  79. package/dist/{cli-9j129brq.js → cli-yxbsmx56.js} +6 -6
  80. package/dist/cli.js +22 -20
  81. package/dist/{codex-adapter-wch12q99.js → codex-adapter-zk59x2zh.js} +7 -7
  82. package/dist/{codex-hook-brpnycn5.js → codex-hook-xyjhvxwd.js} +1 -1
  83. package/dist/{codex-login-rn7c5gxt.js → codex-login-8cg0vhf2.js} +1 -1
  84. package/dist/{codex-session-runner-41pfcr95.js → codex-session-runner-kh6s4j3n.js} +8 -8
  85. package/dist/{commands-9849dkj6.js → commands-68et1qv2.js} +2 -2
  86. package/dist/{controller-ja0sd95p.js → controller-fyrbnzg4.js} +4 -4
  87. package/dist/{controllers-connect-xp05dj6x.js → controllers-connect-nep9h2xv.js} +23 -23
  88. package/dist/{cursor-adapter-623qxqew.js → cursor-adapter-yss3pg7t.js} +2 -2
  89. package/dist/{db-w759qmx0.js → db-28gjyvxj.js} +4 -2
  90. package/dist/{db-47vj40dy.js → db-8ftwvzba.js} +3 -3
  91. package/dist/{devin-adapter-4ycy4vrf.js → devin-adapter-byen2cxt.js} +1 -1
  92. package/dist/{dispatcher-7b8e4z2j.js → dispatcher-hayexmkr.js} +20 -20
  93. package/dist/{docker-s84hjs91.js → docker-fdzyewpz.js} +2 -2
  94. package/dist/{dsh-adapter-2ezw3xea.js → dsh-adapter-46wawff9.js} +2 -2
  95. package/dist/{e2b-9gkdhm3c.js → e2b-222hsajc.js} +2 -2
  96. package/dist/{e2b-cjtf8k1z.js → e2b-fn3zacvt.js} +2 -2
  97. package/dist/{easter-egg-3d-e4qv8dxj.js → easter-egg-3d-8d1e0h4m.js} +1 -1
  98. package/dist/{event-bus-3z78ep5n.js → event-bus-pghg8hqy.js} +1 -1
  99. package/dist/{execute-0xpz8950.js → execute-cjrfxfnm.js} +1 -1
  100. package/dist/{external-channel-e2s028da.js → external-channel-xbmxcg09.js} +2 -2
  101. package/dist/{grok-adapter-ys7gaqee.js → grok-adapter-ag4wks2a.js} +10 -10
  102. package/dist/handlers-tzmevqb5.js +41 -0
  103. package/dist/{heartbeat-w3mntghj.js → heartbeat-psfvcgwp.js} +23 -23
  104. package/dist/{hook-g7kvv6x9.js → hook-8pz04697.js} +6 -6
  105. package/dist/{hook-3jjywnpb.js → hook-cyq4mryn.js} +8 -8
  106. package/dist/{http-tkp7d4kb.js → http-haj1nd6k.js} +921 -169
  107. package/dist/{index-q7m26kvs.js → index-jwt2bj6f.js} +265 -97
  108. package/dist/{index-3n8m9ea2.js → index-q52f47pe.js} +1 -1
  109. package/dist/{index-31ceyf42.js → index-syvhnvtw.js} +1 -1
  110. package/dist/index-y1ajx04a.js +43 -0
  111. package/dist/{index-1ef1myq2.js → index-z5h22pes.js} +20 -20
  112. package/dist/{index-xdaahthb.js → index-zyq8ct52.js} +20 -20
  113. package/dist/{keepalive-v4ta8wgg.js → keepalive-xdvsamvj.js} +4 -4
  114. package/dist/lead-hqg57kdp.js +79 -0
  115. package/dist/{maintenance-84n1ex21.js → maintenance-4y2xzh3a.js} +1 -1
  116. package/dist/{oauth-refresh-sweep-vjnnandw.js → oauth-refresh-sweep-jd4r7zbs.js} +9 -4
  117. package/dist/{onboard-sfmpe4np.js → onboard-18447q9q.js} +6 -6
  118. package/dist/{opencode-adapter-jmpst4q4.js → opencode-adapter-26b2frdf.js} +7 -7
  119. package/dist/{otel-impl-v6cc0zve.js → otel-impl-f9tgr8yw.js} +2 -2
  120. package/dist/{pi-mono-adapter-fk8fkcf6.js → pi-mono-adapter-qn6qbga1.js} +38 -17
  121. package/dist/{pricing-refresh-fsk1e1zc.js → pricing-refresh-dw2tgb53.js} +3 -3
  122. package/dist/{rbac-roles-prmkdnkw.js → rbac-roles-aygm2760.js} +2 -2
  123. package/dist/{rbac-roles-zxmxqa39.js → rbac-roles-s4nwj2m3.js} +1 -1
  124. package/dist/render-v2-yfvdfr0x.js +16 -0
  125. package/dist/{resume-frdtgfa0.js → resume-1bmvjbf3.js} +9 -9
  126. package/dist/{runtime-bt5pkpm1.js → runtime-f7tpzedy.js} +1 -1
  127. package/dist/{session-access-fpez4y5q.js → session-access-r5garej6.js} +4 -4
  128. package/dist/session-source-backfill-424wzv0r.js +110 -0
  129. package/dist/{setup-mq6m3m8q.js → setup-8tygvxkq.js} +1 -1
  130. package/dist/{virtual-modules-mnfbh5mr.js → virtual-modules-xsw323b3.js} +2 -2
  131. package/dist/{work-objects-kfahhjsq.js → work-objects-ggnghpgf.js} +23 -23
  132. package/dist/worker-sqjd1nqf.js +79 -0
  133. package/dist/{x-pbpezr0s.js → x-wxrzvzx8.js} +2 -2
  134. package/openapi.json +1324 -14
  135. package/package.json +5 -3
  136. package/src/assets/source-key.ts +95 -0
  137. package/src/be/automation-preflight.ts +2 -0
  138. package/src/be/db/api-keys.ts +89 -0
  139. package/src/be/db/session-labels.ts +28 -0
  140. package/src/be/db/session-moves.ts +5 -6
  141. package/src/be/db/session-tree.ts +153 -14
  142. package/src/be/db/tasks/read.ts +11 -0
  143. package/src/be/db/tasks/write.ts +6 -1
  144. package/src/be/db/workflow-runs.ts +219 -6
  145. package/src/be/db-retention.ts +61 -6
  146. package/src/be/db.ts +135 -132
  147. package/src/be/memory/providers/openai-embedding.ts +5 -1
  148. package/src/be/memory/task-learning.ts +155 -0
  149. package/src/be/migrations/244_api_key_validation.sql +4 -0
  150. package/src/be/migrations/245_script_executor.sql +3 -0
  151. package/src/be/oauth-refresh-sweep.ts +2 -1
  152. package/src/be/onboarding.ts +4 -0
  153. package/src/be/scripts/boot-reembed.ts +2 -0
  154. package/src/be/scripts/db.ts +14 -4
  155. package/src/be/scripts/embeddings.ts +2 -0
  156. package/src/be/scripts/run-saved.ts +1 -0
  157. package/src/be/scripts/typecheck.ts +10 -4
  158. package/src/be/seed-skills/index.ts +7 -0
  159. package/src/be/session-source-backfill.ts +163 -0
  160. package/src/be/swarm-config-guard.ts +1 -0
  161. package/src/comb/review-batch.ts +28 -1
  162. package/src/comb/templates.ts +7 -2
  163. package/src/commands/claude-managed-setup.ts +7 -1
  164. package/src/commands/credential-refresh.ts +76 -1
  165. package/src/commands/credential-wait.ts +2 -2
  166. package/src/commands/onboard/compose-generator.ts +5 -3
  167. package/src/commands/provider-credentials.ts +212 -171
  168. package/src/commands/runner.ts +25 -4
  169. package/src/extensions/apply-task-create.ts +8 -1
  170. package/src/extensions/contract-types.generated.ts +1 -1
  171. package/src/extensions/contract.ts +5 -0
  172. package/src/heartbeat/heartbeat.ts +14 -1
  173. package/src/heartbeat/script-runner-probe.ts +47 -0
  174. package/src/http/all-routes.ts +2 -0
  175. package/src/http/api-keys.ts +77 -9
  176. package/src/http/assets.ts +15 -0
  177. package/src/http/codex-oauth-accounts.ts +191 -0
  178. package/src/http/comb.ts +15 -2
  179. package/src/http/config.ts +1 -1
  180. package/src/http/core.ts +6 -0
  181. package/src/http/fleet-benchmark.ts +5 -2
  182. package/src/http/idempotency-key.ts +1 -1
  183. package/src/http/index.ts +14 -3
  184. package/src/http/integrations.ts +5 -1
  185. package/src/http/kv.ts +8 -3
  186. package/src/http/onboarding.ts +6 -1
  187. package/src/http/pages-public.ts +38 -5
  188. package/src/http/pool-keys.ts +354 -0
  189. package/src/http/scripts.ts +27 -0
  190. package/src/http/sessions.ts +37 -12
  191. package/src/http/stats.ts +1 -0
  192. package/src/http/status.ts +26 -12
  193. package/src/http/tasks.ts +3 -0
  194. package/src/http/used-by.ts +7 -2
  195. package/src/http/workflows.ts +88 -9
  196. package/src/http/x.ts +5 -0
  197. package/src/integrations/chat-sdk/inbound.ts +27 -0
  198. package/src/kv-reserved-namespaces.ts +19 -0
  199. package/src/prompts/base-prompt.ts +21 -1
  200. package/src/prompts/session-templates.ts +17 -3
  201. package/src/providers/acp-targets.ts +1 -1
  202. package/src/providers/amp-adapter.ts +1 -1
  203. package/src/providers/claude-adapter.ts +5 -1
  204. package/src/providers/claude-managed-adapter.ts +16 -9
  205. package/src/providers/codex-adapter.ts +71 -11
  206. package/src/providers/dsh-adapter.ts +1 -1
  207. package/src/providers/pi-mono-adapter.ts +41 -11
  208. package/src/scheduler/scheduler.ts +5 -3
  209. package/src/scripts-runtime/eval-harness.ts +8 -1
  210. package/src/scripts-runtime/executors/native.ts +22 -16
  211. package/src/scripts-runtime/executors/quickjs-prelude.ts +103 -1
  212. package/src/scripts-runtime/executors/quickjs-runner.ts +2 -1
  213. package/src/scripts-runtime/executors/quickjs.ts +7 -0
  214. package/src/scripts-runtime/executors/registry.ts +32 -0
  215. package/src/scripts-runtime/executors/types.ts +7 -0
  216. package/src/scripts-runtime/host-validated-args.ts +133 -0
  217. package/src/scripts-runtime/loader.ts +30 -3
  218. package/src/scripts-runtime/swarm-sdk.ts +16 -3
  219. package/src/scripts-runtime/types/stdlib.d.ts +10 -2
  220. package/src/scripts-runtime/types/swarm-extension.d.ts +17 -8
  221. package/src/scripts-runtime/types/swarm-sdk.d.ts +10 -2
  222. package/src/slack/assistant.ts +7 -0
  223. package/src/slack/channel-labels.ts +74 -0
  224. package/src/slack/handlers.ts +8 -0
  225. package/src/slack/inbound-files.ts +5 -2
  226. package/src/slack/thread-buffer.ts +4 -0
  227. package/src/tasks/sibling-awareness.ts +12 -3
  228. package/src/telemetry-context.ts +5 -6
  229. package/src/telemetry-identity.ts +3 -3
  230. package/src/tests/api-key-status-by-suffix.test.ts +242 -0
  231. package/src/tests/api-keys-validation.test.ts +170 -0
  232. package/src/tests/base-prompt.test.ts +70 -2
  233. package/src/tests/claude-managed-adapter.test.ts +46 -0
  234. package/src/tests/claude-routes-e2e.test.ts +7 -2
  235. package/src/tests/codex-credential-pools.test.ts +120 -0
  236. package/src/tests/codex-gateway-route.test.ts +165 -0
  237. package/src/tests/codex-oauth-accounts.test.ts +357 -0
  238. package/src/tests/comb-review-batch.test.ts +63 -2
  239. package/src/tests/community-linear-delivery-loop.test.ts +2099 -0
  240. package/src/tests/config-pool-keys.test.ts +533 -0
  241. package/src/tests/credential-check.test.ts +294 -4
  242. package/src/tests/credential-refresh.test.ts +172 -1
  243. package/src/tests/db-retention.test.ts +9 -3
  244. package/src/tests/db-task-read-contract.test.ts +1 -0
  245. package/src/tests/db-task-write-contract.test.ts +1 -3
  246. package/src/tests/docs-index-footprint.test.js +3 -3
  247. package/src/tests/docs-index.test.ts +135 -0
  248. package/src/tests/dsh-adapter.test.ts +1 -1
  249. package/src/tests/extensions-pre-task.test.ts +53 -1
  250. package/src/tests/fetch-resolved-env.test.ts +16 -2
  251. package/src/tests/fixtures/extensions/record-task-create/hooks.ts +9 -0
  252. package/src/tests/fixtures/extensions/record-task-create/manifest.json +7 -0
  253. package/src/tests/fleet-benchmark.test.ts +8 -0
  254. package/src/tests/get-workflow-run-tool.test.ts +98 -0
  255. package/src/tests/heartbeat-checklist.test.ts +89 -0
  256. package/src/tests/heartbeat-script-runner-probe.test.ts +83 -0
  257. package/src/tests/integrations-http.test.ts +32 -2
  258. package/src/tests/internal-ai/complete-structured.test.ts +37 -1
  259. package/src/tests/internal-ai/credentials.test.ts +23 -0
  260. package/src/tests/kv-http.test.ts +32 -0
  261. package/src/tests/kv-tool.test.ts +25 -0
  262. package/src/tests/multi-runtime-registration.test.ts +12 -12
  263. package/src/tests/oauth-refresh-sweep.test.ts +34 -1
  264. package/src/tests/onboard-compose.test.ts +20 -0
  265. package/src/tests/onboarding.test.ts +108 -1
  266. package/src/tests/openai-embedding-credentials.test.ts +35 -0
  267. package/src/tests/opencode-adapter.test.ts +2 -1
  268. package/src/tests/openrouter-attribution-call-sites.test.ts +2 -2
  269. package/src/tests/org-website.test.ts +36 -0
  270. package/src/tests/pages-frame-ancestors.test.ts +162 -0
  271. package/src/tests/pi-codemode.test.ts +2 -1
  272. package/src/tests/pi-mono-adapter.test.ts +54 -0
  273. package/src/tests/pi-native-mcp.test.ts +13 -1
  274. package/src/tests/pi-tool-exposure.test.ts +8 -8
  275. package/src/tests/probe-tool-schema-tokens.test.ts +144 -0
  276. package/src/tests/prompt-template-session.test.ts +4 -3
  277. package/src/tests/provider-key-probes.test.ts +181 -0
  278. package/src/tests/rbac-e2e-helpers.test.ts +88 -1
  279. package/src/tests/rbac-e2e-helpers.ts +36 -11
  280. package/src/tests/request-composition-derive.test.ts +329 -0
  281. package/src/tests/script-connections.test.ts +4 -0
  282. package/src/tests/script-executor-conformance.test.ts +36 -1
  283. package/src/tests/script-executor-quickjs-pool.test.ts +50 -0
  284. package/src/tests/script-executor-quickjs.test.ts +140 -0
  285. package/src/tests/script-host-validated-args-native.test.ts +196 -0
  286. package/src/tests/script-per-script-executor.test.ts +415 -0
  287. package/src/tests/script-runs-retention.test.ts +212 -0
  288. package/src/tests/scripts-external-api.test.ts +45 -0
  289. package/src/tests/sdk-allowlist.test.ts +42 -2
  290. package/src/tests/self-improvement.test.ts +4 -4
  291. package/src/tests/session-source-backfill.test.ts +429 -0
  292. package/src/tests/session-source-keys.test.ts +236 -0
  293. package/src/tests/session-source-labels.test.ts +419 -0
  294. package/src/tests/sessions-detail-batch.test.ts +2 -0
  295. package/src/tests/sessions-move.test.ts +131 -0
  296. package/src/tests/sessions-tree.test.ts +299 -2
  297. package/src/tests/slack-inbound-files.test.ts +103 -23
  298. package/src/tests/status.test.ts +101 -18
  299. package/src/tests/store-progress-learning.test.ts +288 -0
  300. package/src/tests/tasks-workflow-run-filter.test.ts +146 -0
  301. package/src/tests/test-net.ts +31 -0
  302. package/src/tests/transcription.test.ts +8 -0
  303. package/src/tests/ui-logs-parser.test.ts +180 -0
  304. package/src/tests/used-by-route.test.ts +11 -0
  305. package/src/tests/workflow-cascade-cancel.test.ts +172 -0
  306. package/src/tests/workflow-engine-v2.test.ts +116 -1
  307. package/src/tests/workflow-http-v2.test.ts +131 -0
  308. package/src/tests/workflow-mcp-trigger-schema.test.ts +209 -0
  309. package/src/tests/workflow-run-finished-event.test.ts +263 -0
  310. package/src/tests/workflow-step-order.test.ts +92 -0
  311. package/src/tests/workflow-sub-workflow.test.ts +30 -0
  312. package/src/tests/workflow-swarm-script.test.ts +34 -0
  313. package/src/tools/get-tasks.ts +8 -0
  314. package/src/tools/kv/kv-read-auth.ts +4 -2
  315. package/src/tools/script-common.ts +1 -0
  316. package/src/tools/script-run.ts +7 -0
  317. package/src/tools/script-upsert.ts +7 -0
  318. package/src/tools/store-progress.ts +67 -1
  319. package/src/tools/task-action.ts +1 -1
  320. package/src/tools/workflows/get-workflow-run.ts +14 -4
  321. package/src/tools/workflows/trigger-workflow.ts +104 -10
  322. package/src/types.ts +36 -1
  323. package/src/utils/company-profile.ts +51 -1
  324. package/src/utils/credentials.ts +10 -4
  325. package/src/utils/internal-ai/complete-structured.ts +5 -0
  326. package/src/utils/internal-ai/credentials.ts +4 -3
  327. package/src/utils/provider-key-probes.ts +328 -0
  328. package/src/utils/transcription.ts +4 -1
  329. package/src/workflows/engine.ts +18 -16
  330. package/src/workflows/executors/sub-workflow.ts +8 -1
  331. package/src/workflows/executors/swarm-script.ts +5 -0
  332. package/src/workflows/foreach-driver.ts +5 -11
  333. package/src/workflows/node-timeout.ts +30 -0
  334. package/templates/ai-toolbox.manifest.json +2 -2
  335. package/templates/community/linear-delivery-loop/PLAYBOOK.md +323 -0
  336. package/templates/community/linear-delivery-loop/README.md +38 -0
  337. package/templates/community/linear-delivery-loop/config.example.json +31 -0
  338. package/templates/community/linear-delivery-loop/lead-prompt.md +34 -0
  339. package/templates/community/linear-delivery-loop/schedule.json +10 -0
  340. package/templates/community/linear-delivery-loop/scripts/linear-delivery-setup.ts +148 -0
  341. package/templates/community/linear-delivery-loop/scripts/linear-delivery-tick.ts +1781 -0
  342. package/templates/skills/researching/content.md +2 -0
  343. package/templates/skills/swarm-docs/config.json +14 -0
  344. package/templates/skills/swarm-docs/content.md +144 -0
  345. package/templates/skills/swarm-scripts/SKILL.md +1 -0
  346. package/templates/skills/swarm-scripts/content.md +1 -0
  347. package/dist/cli-7421jzsw.js +0 -84
  348. package/dist/cli-e45e4m6b.js +0 -413
  349. package/dist/cli-zw88zjba.js +0 -307
  350. package/dist/handlers-wy1dr6ja.js +0 -41
  351. package/dist/index-nmm79qgr.js +0 -43
  352. package/dist/lead-sawnyqxk.js +0 -79
  353. package/dist/render-v2-pjwxvnkw.js +0 -12
  354. package/dist/worker-v5e5rxj3.js +0 -79
@@ -1,12 +1,161 @@
1
- import { TERMINAL_TASK_STATUSES, type WorkflowRunStatus } from "../../types";
1
+ import {
2
+ TERMINAL_TASK_STATUSES,
3
+ type WorkflowRun,
4
+ type WorkflowRunStatus,
5
+ type WorkflowRunStep,
6
+ type WorkflowRunStepSlim,
7
+ type WorkflowRunStepStatus,
8
+ type WorkflowRunSummary,
9
+ } from "../../types";
2
10
  import { scrubSecrets } from "../../utils/secret-scrubber";
11
+ import { normalizeDate, normalizeDateRequired } from "../date-utils";
3
12
  import { scrubJsonValue } from "../scrub-json";
13
+ import { defineWorkflowPayload, type WorkflowPayloadView } from "../workflow-replay";
4
14
  import { getDbClient } from "./runtime";
5
15
 
6
16
  // Parent/child links between workflow runs (migration 203): a `sub-workflow`
7
17
  // step starts a child run that records the step in `parentStepId`, and the
8
18
  // step's `retryCount` at that time in `parentStepAttempt` (migration 240).
9
19
 
20
+ export type WorkflowRunRow = {
21
+ id: string;
22
+ workflowId: string;
23
+ status: string;
24
+ triggerType: string;
25
+ triggerData: string | null;
26
+ /** Absent from list rows: see `WORKFLOW_RUN_SUMMARY_COLUMNS`. */
27
+ context?: string | null;
28
+ /** Sealed exact `context` (migration 201). Absent from list rows. */
29
+ context_replay?: string | null;
30
+ error: string | null;
31
+ created_by: string | null;
32
+ startedAt: string;
33
+ lastUpdatedAt: string;
34
+ finishedAt: string | null;
35
+ /** The `sub-workflow` step that started this run (migration 203). */
36
+ parentStepId?: string | null;
37
+ /** That step's attempt (`retryCount`) when it started this run (migration 240). */
38
+ parentStepAttempt?: number | null;
39
+ };
40
+
41
+ /**
42
+ * `view` picks the `context` copy: `replay` (default) is the exact sealed value
43
+ * the engine resumes from; `display` is the scrubbed column for API, MCP and UI
44
+ * responses. See `src/be/workflow-replay.ts`.
45
+ */
46
+ export function rowToWorkflowRun(
47
+ row: WorkflowRunRow,
48
+ view: WorkflowPayloadView = "replay",
49
+ ): WorkflowRun {
50
+ const run: WorkflowRun = {
51
+ id: row.id,
52
+ workflowId: row.workflowId,
53
+ status: row.status as WorkflowRunStatus,
54
+ triggerData: row.triggerData ? JSON.parse(row.triggerData) : undefined,
55
+ context: undefined,
56
+ error: row.error ?? undefined,
57
+ createdBy: row.created_by ?? undefined,
58
+ startedAt: normalizeDateRequired(row.startedAt),
59
+ lastUpdatedAt: normalizeDateRequired(row.lastUpdatedAt),
60
+ finishedAt: normalizeDate(row.finishedAt) ?? undefined,
61
+ parentStepId: row.parentStepId ?? undefined,
62
+ parentStepAttempt: row.parentStepId ? (row.parentStepAttempt ?? 0) : undefined,
63
+ };
64
+ return defineWorkflowPayload(run, "context", row.context, row.context_replay, view, {
65
+ runId: row.id,
66
+ target: "its context",
67
+ });
68
+ }
69
+
70
+ // Everything but `context`. `triggerData` stays: it is small, and stored
71
+ // scripts read it off list rows (dedupe by trigger, failure reports). The
72
+ // parent link and attempt stay so a list row identifies a child's invocation.
73
+ export const WORKFLOW_RUN_SUMMARY_COLUMNS =
74
+ "id, workflowId, status, triggerType, triggerData, error, created_by, startedAt, lastUpdatedAt, finishedAt, parentStepId, parentStepAttempt";
75
+
76
+ export type WorkflowRunStepRow = {
77
+ id: string;
78
+ runId: string;
79
+ nodeId: string;
80
+ nodeType: string;
81
+ status: string;
82
+ /** Absent from slim rows: see `WORKFLOW_RUN_STEP_SLIM_COLUMNS`. */
83
+ input?: string | null;
84
+ output: string | null;
85
+ /** Sealed exact `output` (migration 201). Absent from slim rows. */
86
+ output_replay?: string | null;
87
+ error: string | null;
88
+ startedAt: string;
89
+ finishedAt: string | null;
90
+ retryCount: number;
91
+ maxRetries: number;
92
+ nextRetryAt: string | null;
93
+ idempotencyKey: string | null;
94
+ diagnostics: string | null;
95
+ nextPort: string | null;
96
+ };
97
+
98
+ /** `view` picks the `output` copy, as in `rowToWorkflowRun`. */
99
+ export function rowToWorkflowRunStep(
100
+ row: WorkflowRunStepRow,
101
+ view: WorkflowPayloadView = "replay",
102
+ ): WorkflowRunStep {
103
+ const step: WorkflowRunStep = {
104
+ id: row.id,
105
+ runId: row.runId,
106
+ nodeId: row.nodeId,
107
+ nodeType: row.nodeType,
108
+ status: row.status as WorkflowRunStepStatus,
109
+ input: row.input ? JSON.parse(row.input) : undefined,
110
+ output: undefined,
111
+ error: row.error ?? undefined,
112
+ startedAt: normalizeDateRequired(row.startedAt),
113
+ finishedAt: normalizeDate(row.finishedAt) ?? undefined,
114
+ retryCount: row.retryCount,
115
+ maxRetries: row.maxRetries,
116
+ nextRetryAt: normalizeDate(row.nextRetryAt) ?? undefined,
117
+ idempotencyKey: row.idempotencyKey ?? undefined,
118
+ diagnostics: row.diagnostics ?? undefined,
119
+ nextPort: row.nextPort ?? undefined,
120
+ };
121
+ return defineWorkflowPayload(step, "output", row.output, row.output_replay, view, {
122
+ runId: row.runId,
123
+ target: `the output of step ${row.id} (node ${row.nodeId})`,
124
+ });
125
+ }
126
+
127
+ // Everything but `input` (a context snapshot per step, so loops grow it with
128
+ // every iteration) and `output_replay` (the display view never opens it).
129
+ const WORKFLOW_RUN_STEP_SLIM_COLUMNS =
130
+ "id, runId, nodeId, nodeType, status, output, error, startedAt, finishedAt, retryCount, maxRetries, nextRetryAt, idempotencyKey, diagnostics, nextPort";
131
+
132
+ /**
133
+ * `getWorkflowRun` without `context`, in the display view. Backs
134
+ * `GET /api/workflow-runs/{id}?fields=slim`: the large column is neither read
135
+ * nor parsed.
136
+ */
137
+ export async function getWorkflowRunSummary(id: string): Promise<WorkflowRunSummary | null> {
138
+ const row = await getDbClient().get<WorkflowRunRow>(
139
+ `SELECT ${WORKFLOW_RUN_SUMMARY_COLUMNS} FROM workflow_runs WHERE id = ?`,
140
+ [id],
141
+ );
142
+ return row ? rowToWorkflowRun(row, "display") : null;
143
+ }
144
+
145
+ /**
146
+ * `getWorkflowRunStepsByRunId` without `input`, in the display view. Same
147
+ * order, including the rowid tie-break for steps that share `startedAt`.
148
+ */
149
+ export async function getWorkflowRunStepsSlimByRunId(
150
+ runId: string,
151
+ ): Promise<WorkflowRunStepSlim[]> {
152
+ const rows = await getDbClient().query<WorkflowRunStepRow>(
153
+ `SELECT ${WORKFLOW_RUN_STEP_SLIM_COLUMNS} FROM workflow_run_steps WHERE runId = ? ORDER BY startedAt ASC, rowid ASC`,
154
+ [runId],
155
+ );
156
+ return rows.map((row) => rowToWorkflowRunStep(row, "display"));
157
+ }
158
+
10
159
  const TERMINAL_STATUSES = new Set<WorkflowRunStatus>([
11
160
  "completed",
12
161
  "failed",
@@ -242,6 +391,39 @@ export async function workflowRunTreeHasOpenWork(runIds: string[]): Promise<bool
242
391
  return open;
243
392
  }
244
393
 
394
+ export type WorkflowRunTree = {
395
+ rootRunId: string;
396
+ /** Root first, in `getWorkflowRunTreeIds` order. List rows: no `context`. */
397
+ runs: WorkflowRun[];
398
+ hasOpenWork: boolean;
399
+ };
400
+
401
+ /**
402
+ * The run and every run below it, with whether any of them still has open
403
+ * work (see `workflowRunTreeHasOpenWork`). One read transaction, so `runs` and
404
+ * `hasOpenWork` come from the same snapshot. Null when the root is missing.
405
+ * Throws WorkflowRunTreeError on a cycle or a chain past the depth bound.
406
+ */
407
+ export async function getWorkflowRunTree(rootRunId: string): Promise<WorkflowRunTree | null> {
408
+ return getDbClient().transaction(
409
+ async () => {
410
+ if ((await getWorkflowRunStatus(rootRunId)) === null) return null;
411
+ const ids = await getWorkflowRunTreeIds(rootRunId);
412
+ const byId = new Map<string, WorkflowRun>();
413
+ await forEachChunk(ids, async (chunk, placeholders) => {
414
+ const rows = await getDbClient().query<WorkflowRunRow>(
415
+ `SELECT ${WORKFLOW_RUN_SUMMARY_COLUMNS} FROM workflow_runs WHERE id IN (${placeholders})`,
416
+ chunk,
417
+ );
418
+ for (const row of rows) byId.set(row.id, rowToWorkflowRun(row, "display"));
419
+ });
420
+ const runs = ids.flatMap((id) => byId.get(id) ?? []);
421
+ return { rootRunId, runs, hasOpenWork: await workflowRunTreeHasOpenWork(ids) };
422
+ },
423
+ { readOnly: true },
424
+ );
425
+ }
426
+
245
427
  /**
246
428
  * Cancel the pending, running and waiting steps of the given runs. The
247
429
  * migration-140 trigger closes each cancelled step's pending approval.
@@ -283,7 +465,8 @@ export async function disarmWorkflowTreeRetries(
283
465
  /**
284
466
  * Mark the given runs that are still running or waiting `cancelled`, without
285
467
  * the per-run `workflow.child.finished` wake-up: it is for runs whose parent
286
- * step the same cancel closes. A terminal run keeps its status and reason.
468
+ * step the same cancel closes. Each run it cancels still emits
469
+ * `workflow.run.finished`. A terminal run keeps its status and reason.
287
470
  */
288
471
  export async function cancelLiveWorkflowTreeRuns(
289
472
  runIds: string[],
@@ -291,12 +474,14 @@ export async function cancelLiveWorkflowTreeRuns(
291
474
  finishedAt: string,
292
475
  ): Promise<void> {
293
476
  await forEachChunk(runIds, async (chunk, placeholders) => {
294
- await getDbClient().run(
477
+ const cancelled = await getDbClient().query<{ id: string; workflowId: string }>(
295
478
  `UPDATE workflow_runs
296
479
  SET status = 'cancelled', error = ?, finishedAt = ?, lastUpdatedAt = ?
297
- WHERE id IN (${placeholders}) AND status IN ('running', 'waiting')`,
480
+ WHERE id IN (${placeholders}) AND status IN ('running', 'waiting')
481
+ RETURNING id, workflowId`,
298
482
  [scrubSecrets(reason), finishedAt, finishedAt, ...chunk],
299
483
  );
484
+ for (const run of cancelled) emitRunFinished(run.id, run.workflowId, "cancelled");
300
485
  });
301
486
  }
302
487
 
@@ -461,14 +646,42 @@ export function emitChildRunFinished(
461
646
  }
462
647
 
463
648
  function emitAfterCommit(childRunId: string, parentStepId: string): void {
649
+ emitBusEventAfterCommit("workflow.child.finished", { childRunId, parentStepId });
650
+ }
651
+
652
+ /** Bus event every run emits once when it turns terminal. */
653
+ export const WORKFLOW_RUN_FINISHED_EVENT = "workflow.run.finished";
654
+
655
+ export function isTerminalWorkflowRunStatus(status: WorkflowRunStatus): boolean {
656
+ return TERMINAL_STATUSES.has(status);
657
+ }
658
+
659
+ /**
660
+ * Announce after commit that a run turned terminal, top-level and child runs
661
+ * alike, so an event-mode `wait` can resume when any run ends. Callers emit
662
+ * only when a live run (running or waiting) turns terminal, never on a later
663
+ * update of a run that is already terminal. The id is `runId`, never `workflowRunId` or
664
+ * `_runId`: those would put the finished run in the waiting run's own `run`
665
+ * scope, so waiters use scope `global` and filter on `runId`.
666
+ */
667
+ export function emitRunFinished(
668
+ runId: string,
669
+ workflowId: string,
670
+ status: WorkflowRunStatus,
671
+ ): void {
672
+ if (!TERMINAL_STATUSES.has(status)) return;
673
+ emitBusEventAfterCommit(WORKFLOW_RUN_FINISHED_EVENT, { runId, workflowId, status });
674
+ }
675
+
676
+ function emitBusEventAfterCommit(event: string, payload: Record<string, unknown>): void {
464
677
  getDbClient().afterCommit(() => {
465
678
  import("../../workflows/event-bus")
466
679
  .then(({ workflowEventBus }) => {
467
- workflowEventBus.emit("workflow.child.finished", { childRunId, parentStepId });
680
+ workflowEventBus.emit(event, payload);
468
681
  })
469
682
  .catch((err) =>
470
683
  console.error(
471
- "[db] workflow.child.finished event not emitted:",
684
+ `[db] ${event} event not emitted:`,
472
685
  scrubSecrets(err instanceof Error ? err.message : String(err)),
473
686
  ),
474
687
  );
@@ -1,6 +1,7 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import type { Attributes, DbRetentionSweepMetric, SpanStatus, SwarmSpan } from "../otel";
3
3
  import { recordDbRetentionStatement, recordDbRetentionSweep, startSpan, withSpan } from "../otel";
4
+ import { TERMINAL_SCRIPT_RUN_STATUSES } from "../types";
4
5
  import { isEnvFlagEnabled } from "../utils/env-flag";
5
6
  import { scrubSecrets } from "../utils/secret-scrubber";
6
7
  import { getDbClient } from "./db";
@@ -23,7 +24,11 @@ const YIELD_MS = 25;
23
24
  *
24
25
  * Two policies exist:
25
26
  * - `age`: the env value is a number of days; rows whose `timeColumn` is older
26
- * than that horizon are deleted.
27
+ * than that horizon are deleted. Optional narrowing: `terminalStatuses`
28
+ * deletes only rows whose `statusColumn` is in that list, `keepWhenSet`
29
+ * keeps every row where that column is non-NULL, and
30
+ * `cutoffFormat: "sqliteDatetime"` compares against a `YYYY-MM-DD HH:MM:SS`
31
+ * cutoff for a column that mixes that format with ISO strings.
27
32
  * - `keepLatest`: the env value is a count; within each `partitionBy` group,
28
33
  * only the newest `rankBy` rows are kept. The newest row of a group is
29
34
  * never deleted, because the smallest accepted count is 1.
@@ -65,6 +70,29 @@ export const DB_RETENTION_TABLES = [
65
70
  initialBatchSize: 50,
66
71
  maxBatchSize: 100,
67
72
  },
73
+ {
74
+ // Every inline script run stores its full source, args and output. Only
75
+ // terminal runs are eligible: a running or paused durable run must survive
76
+ // to be resumed. Runs with an idempotencyKey are kept, so a retried launch
77
+ // still gets its 409 instead of executing twice. The status filter, the
78
+ // time range and the key exclusion all resolve on indexes
79
+ // (idx_script_runs_status_startedAt, idx_script_runs_idempotencyKey).
80
+ // Workflow runs write `datetime('now')` (space separator) while inline runs
81
+ // write ISO strings, hence the sqliteDatetime cutoff. script_run_journal
82
+ // rows go with their run through ON DELETE CASCADE on idx_srj_runId.
83
+ // Rows average ~30 KB and reach ~1.3 MB, so batches stay small.
84
+ table: "script_runs",
85
+ policy: "age",
86
+ timeColumn: "startedAt",
87
+ cutoffFormat: "sqliteDatetime",
88
+ statusColumn: "status",
89
+ terminalStatuses: TERMINAL_SCRIPT_RUN_STATUSES,
90
+ keepWhenSet: "idempotencyKey",
91
+ envKey: "SCRIPT_RUNS_RETENTION_DAYS",
92
+ metricsKey: "scriptRuns",
93
+ initialBatchSize: 100,
94
+ maxBatchSize: 500,
95
+ },
68
96
  ] as const satisfies ReadonlyArray<
69
97
  {
70
98
  table: string;
@@ -73,7 +101,14 @@ export const DB_RETENTION_TABLES = [
73
101
  initialBatchSize?: number;
74
102
  maxBatchSize?: number;
75
103
  } & (
76
- | { policy: "age"; timeColumn: string }
104
+ | {
105
+ policy: "age";
106
+ timeColumn: string;
107
+ cutoffFormat?: "sqliteDatetime";
108
+ statusColumn?: string;
109
+ terminalStatuses?: readonly string[];
110
+ keepWhenSet?: string;
111
+ }
77
112
  | { policy: "keepLatest"; partitionBy: string; rankBy: string }
78
113
  )
79
114
  >;
@@ -326,13 +361,33 @@ export function sweepStatements(table: RetentionTable, value: number, now: Date)
326
361
  params: [value],
327
362
  };
328
363
  }
329
- const cutoff = new Date(now.getTime() - value * DAY_MS).toISOString();
364
+ const iso = new Date(now.getTime() - value * DAY_MS).toISOString();
365
+ // Text comparison of the two formats: ' ' sorts before 'T', so against a
366
+ // space-separated cutoff an ISO row on the cutoff's own date is kept, never
367
+ // deleted early. It is swept on the next day's ticks instead.
368
+ const cutoff = "cutoffFormat" in table ? `${iso.slice(0, 10)} ${iso.slice(11, 19)}` : iso;
369
+ const conditions: string[] = [];
370
+ const params: Array<string | number> = [];
371
+ if ("terminalStatuses" in table) {
372
+ conditions.push(
373
+ `${table.statusColumn} IN (${table.terminalStatuses.map(() => "?").join(", ")})`,
374
+ );
375
+ params.push(...table.terminalStatuses);
376
+ }
377
+ conditions.push(`${table.timeColumn} < ?`);
378
+ params.push(cutoff);
379
+ if ("keepWhenSet" in table) {
380
+ conditions.push(
381
+ `rowid NOT IN (SELECT rowid FROM ${table.table} WHERE ${table.keepWhenSet} IS NOT NULL)`,
382
+ );
383
+ }
384
+ const where = conditions.join(" AND ");
330
385
  return {
331
- backlogSql: `SELECT COUNT(*) AS n FROM ${table.table} WHERE ${table.timeColumn} < ?`,
386
+ backlogSql: `SELECT COUNT(*) AS n FROM ${table.table} WHERE ${where}`,
332
387
  deleteSql: `DELETE FROM ${table.table} WHERE rowid IN (
333
- SELECT rowid FROM ${table.table} WHERE ${table.timeColumn} < ? ORDER BY ${table.timeColumn} LIMIT ?
388
+ SELECT rowid FROM ${table.table} WHERE ${where} ORDER BY ${table.timeColumn} LIMIT ?
334
389
  )`,
335
- params: [cutoff],
390
+ params,
336
391
  };
337
392
  }
338
393