@desplega.ai/agent-swarm 2.4.4 → 2.5.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 (382) hide show
  1. package/README.md +4 -2
  2. package/dist/{acp-adapter-thq04adh.js → acp-adapter-11gp67nr.js} +8 -6
  3. package/dist/{actions-j6ywh6x5.js → actions-8p2kze8j.js} +24 -22
  4. package/dist/{amp-adapter-k8b5xmj8.js → amp-adapter-z4qvhacj.js} +2 -2
  5. package/dist/{anthropic-messages-g6pqmqk4.js → anthropic-messages-txs190dd.js} +17 -20
  6. package/dist/{app-rb7vc02s.js → app-0qp0a2gk.js} +3 -3
  7. package/dist/{assistant-ftta1zjf.js → assistant-jedd3ktm.js} +27 -25
  8. package/dist/{azure-openai-responses-9dbmj346.js → azure-openai-responses-9kfwhmn7.js} +18 -13
  9. package/dist/{boot-reembed-xns7h5h9.js → boot-reembed-4xwq5tg0.js} +1 -1
  10. package/dist/{boot-reembed-srp6v6af.js → boot-reembed-n4wq5dd2.js} +1 -1
  11. package/dist/{boot-scrub-sweep-3qqrh2mz.js → boot-scrub-sweep-69h90xcq.js} +4 -4
  12. package/dist/{boot-seeds-9ks8hce7.js → boot-seeds-3vn0m9sg.js} +4 -4
  13. package/dist/{claude-adapter-k5ksyres.js → claude-adapter-221mvad5.js} +8 -6
  14. package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-gt6pa35d.js} +2 -2
  15. package/dist/{claude-managed-setup-n5a5eqks.js → claude-managed-setup-c3hp36ph.js} +4 -4
  16. package/dist/{claude-sdk-session-2j3j4kwn.js → claude-sdk-session-8thjsk5e.js} +9729 -9628
  17. package/dist/{cli-b9fcxxev.js → cli-007cnhm1.js} +50 -4
  18. package/dist/{cli-j4rqdf2n.js → cli-03vpq45j.js} +2 -2
  19. package/dist/{cli-amyhm3gj.js → cli-0y6f0ckq.js} +1 -1
  20. package/dist/{cli-4dg55wsk.js → cli-0z3vjrpm.js} +1 -1
  21. package/dist/{cli-pccfmtb5.js → cli-179xcyky.js} +11 -11
  22. package/dist/{cli-3r8samv3.js → cli-1f0gp9vz.js} +3 -2
  23. package/dist/{cli-hj3debgw.js → cli-1pr672hz.js} +3 -3
  24. package/dist/{cli-0bqteszy.js → cli-2nf3b08t.js} +328 -25
  25. package/dist/{cli-t7cyef5g.js → cli-36j4jnk3.js} +4 -4
  26. package/dist/{cli-er83cjbn.js → cli-3qv8naq8.js} +527 -231
  27. package/dist/cli-3zwye9sn.js +1193 -0
  28. package/dist/{cli-60cgh1rv.js → cli-459fk97x.js} +7 -7
  29. package/dist/{cli-xj0re5tm.js → cli-4w24f7z3.js} +1 -1
  30. package/dist/{cli-v3yr2gbg.js → cli-5kzk3472.js} +2198 -968
  31. package/dist/{cli-h7gc0b4r.js → cli-5m84zd2k.js} +55 -18
  32. package/dist/{cli-w6nadkh4.js → cli-5rvg1ddk.js} +5 -5
  33. package/dist/{cli-dvkmp9bt.js → cli-6ctwrf1z.js} +20 -10
  34. package/dist/{cli-9qtjfd60.js → cli-6rg2jn2y.js} +3 -2
  35. package/dist/{cli-2v045xyf.js → cli-7bwtc6yx.js} +3 -3
  36. package/dist/{cli-3cgngyd8.js → cli-7g40g8hq.js} +35 -17
  37. package/dist/{cli-q6r7t299.js → cli-92mqenkc.js} +2379 -154
  38. package/dist/{cli-cynvc9fj.js → cli-9ce2xw98.js} +8 -8
  39. package/dist/{cli-gqvh8d8a.js → cli-bgdtv62r.js} +36 -22
  40. package/dist/{cli-wxbn3yfx.js → cli-cz5nmdxt.js} +2 -2
  41. package/dist/{cli-wt645v7q.js → cli-dabehxhp.js} +1 -1
  42. package/dist/{cli-vfha21c9.js → cli-e5bxnjps.js} +2 -2
  43. package/dist/{cli-p20r8w42.js → cli-fcc5qe3f.js} +763 -268
  44. package/dist/{cli-1ephgwnq.js → cli-fes51ya2.js} +3 -3
  45. package/dist/{cli-1d70crsy.js → cli-ftmq4nvk.js} +2 -2
  46. package/dist/{cli-qkhc5aqy.js → cli-fy1jyyym.js} +13 -13
  47. package/dist/{cli-s95dknxh.js → cli-g1cw7xtt.js} +1 -1
  48. package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
  49. package/dist/{cli-74c1wpm0.js → cli-gpv60278.js} +1 -1
  50. package/dist/{cli-pemywhfq.js → cli-ha9rmwgq.js} +2 -1
  51. package/dist/{cli-bnz0r3kc.js → cli-j1eghqfm.js} +5 -5
  52. package/dist/{cli-2zqpkvtt.js → cli-jpxsrxcb.js} +1 -1
  53. package/dist/{cli-ejs3m1sx.js → cli-kxpfx2xr.js} +1 -1
  54. package/dist/{cli-37yb7307.js → cli-mbfj11fq.js} +1 -1
  55. package/dist/{cli-pnp2j5zg.js → cli-mmhj8vd7.js} +2 -2
  56. package/dist/{cli-xf234ws8.js → cli-n4c8e3s5.js} +2 -0
  57. package/dist/{cli-a0kcty51.js → cli-n6kmqngw.js} +2 -2
  58. package/dist/{cli-te6b5wvg.js → cli-nnvjb17s.js} +3 -3
  59. package/dist/{cli-1dmcq2eh.js → cli-nzfnt2gs.js} +1 -1
  60. package/dist/{cli-625tb7aq.js → cli-p859hcc8.js} +2 -2
  61. package/dist/{cli-smvcw9z5.js → cli-pasyvjmm.js} +1 -1
  62. package/dist/cli-pkaqk57w.js +128 -0
  63. package/dist/{cli-8nyhf7za.js → cli-qqzmjxkf.js} +129 -105
  64. package/dist/{cli-zrwpctp4.js → cli-r25qpaxt.js} +161 -63
  65. package/dist/{cli-nc35pxb7.js → cli-rh5smt8t.js} +19 -4
  66. package/dist/{cli-qwkcwjdn.js → cli-rycdaj0a.js} +1 -1
  67. package/dist/{cli-esxerzg7.js → cli-s4sntwt4.js} +2 -2
  68. package/dist/{cli-b8k7epj1.js → cli-segs7hx9.js} +8 -8
  69. package/dist/{cli-36ckw0wx.js → cli-stxdrqs2.js} +2 -2
  70. package/dist/{cli-vdm20wej.js → cli-sy8f9705.js} +4 -4
  71. package/dist/{cli-1m17dc9d.js → cli-ta8bd7th.js} +2 -2
  72. package/dist/{cli-2y91wnbh.js → cli-we0ra057.js} +222 -10
  73. package/dist/{cli-55qmbp6z.js → cli-x21dqn18.js} +5 -5
  74. package/dist/{cli-dqb4n629.js → cli-x6vf4sad.js} +11 -11
  75. package/dist/{cli-d2mb5s8a.js → cli-x77gen2p.js} +680 -440
  76. package/dist/{cli-vq97g1jq.js → cli-xawhpgc9.js} +95 -195
  77. package/dist/{cli-82d3nkc3.js → cli-xd4eqtr2.js} +2 -2
  78. package/dist/{cli-9fhkkpj5.js → cli-xt768r5m.js} +2 -2
  79. package/dist/{cli-zrk6jxv8.js → cli-y4x8ww6s.js} +2 -2
  80. package/dist/{cli-xc27fwzg.js → cli-y9jvxfhk.js} +3 -3
  81. package/dist/{cli-44159k28.js → cli-z63a269p.js} +2 -2
  82. package/dist/{cli-sm8rses9.js → cli-zfdp01hn.js} +8 -5
  83. package/dist/cli.js +31 -29
  84. package/dist/{cloudflare-workers-ai-system-one-ch2wxfcp.js → cloudflare-workers-ai-system-one-43v9qkjk.js} +7 -2
  85. package/dist/{codex-adapter-968xwfy7.js → codex-adapter-tcg1q3jk.js} +6 -4
  86. package/dist/{codex-login-m819c41r.js → codex-login-rn7c5gxt.js} +1 -1
  87. package/dist/{codex-session-runner-ht4z99fa.js → codex-session-runner-xfx4wd9x.js} +7 -5
  88. package/dist/{commands-pcymaeg9.js → commands-ew83nj70.js} +2 -2
  89. package/dist/{controller-fpjyk46r.js → controller-gnq1k1mf.js} +4 -4
  90. package/dist/{controllers-connect-mwzx1fh6.js → controllers-connect-tw1dan9r.js} +26 -24
  91. package/dist/{cursor-adapter-cp4s2e2f.js → cursor-adapter-yq5xgfcg.js} +1 -1
  92. package/dist/{db-xsjg9jqq.js → db-7gbc53fd.js} +14 -2
  93. package/dist/{db-sgd12bt9.js → db-t86xrnes.js} +3 -3
  94. package/dist/{devin-adapter-zgqadvnm.js → devin-adapter-4ycy4vrf.js} +1 -1
  95. package/dist/{dispatcher-x0jfw2c9.js → dispatcher-64bdyhps.js} +23 -21
  96. package/dist/{docker-fkgtr75t.js → docker-nfy2gc8t.js} +2 -2
  97. package/dist/{dsh-adapter-jrq7ma7h.js → dsh-adapter-tvhc4k2d.js} +1 -1
  98. package/dist/{e2b-16d6ch39.js → e2b-9gkdhm3c.js} +2 -2
  99. package/dist/{e2b-zn0b4w5w.js → e2b-cjtf8k1z.js} +2 -2
  100. package/dist/{easter-egg-3d-5cgynaja.js → easter-egg-3d-e4qv8dxj.js} +1 -1
  101. package/dist/{event-bus-9vpk8gmq.js → event-bus-3z78ep5n.js} +1 -1
  102. package/dist/{execute-t4e6m3rw.js → execute-0xpz8950.js} +85 -23
  103. package/dist/{external-channel-8njj4h3b.js → external-channel-e9nw24zv.js} +2 -2
  104. package/dist/{google-generative-ai-bmq8gkf3.js → google-generative-ai-mk9vcpe1.js} +15 -15
  105. package/dist/{google-vertex-b1rvp52s.js → google-vertex-q580kz8k.js} +20 -20
  106. package/dist/{grok-adapter-kkr97v2f.js → grok-adapter-v82srhrx.js} +9 -7
  107. package/dist/handlers-c9ajzhbn.js +41 -0
  108. package/dist/{heartbeat-wd03zhn0.js → heartbeat-2vqs1319.js} +26 -24
  109. package/dist/{hook-xzj2ts2p.js → hook-01nk13wx.js} +7 -5
  110. package/dist/{hook-f0vghj42.js → hook-jzpheegg.js} +9 -7
  111. package/dist/{http-4hwxv62p.js → http-fc1k6ec8.js} +859 -252
  112. package/dist/index-07ef7nkm.js +42 -0
  113. package/dist/{index-g6tbb6ve.js → index-31ceyf42.js} +1 -1
  114. package/dist/index-7yts8n9s.js +43 -0
  115. package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
  116. package/dist/index-q3t40ryv.js +46 -0
  117. package/dist/{index-ww2vznkp.js → index-sepja052.js} +1 -1
  118. package/dist/{index-97q4xn03.js → index-zdycv3ja.js} +135 -79
  119. package/dist/{index-g216q6jr.js → index-zsyx51ap.js} +1 -4
  120. package/dist/{keepalive-hrh7xnr9.js → keepalive-5nh2rhmr.js} +4 -4
  121. package/dist/lead-aayq64jn.js +79 -0
  122. package/dist/{llama-cpp-classify-vv43gswy.js → llama-cpp-classify-ee7vmd7q.js} +4 -1
  123. package/dist/{maintenance-e8wnwnqx.js → maintenance-hjhzdt3k.js} +1 -1
  124. package/dist/{mistral-conversations-1medfwv7.js → mistral-conversations-sd0xf1tn.js} +13 -13
  125. package/dist/{node-3v3f08f7.js → node-jzjj7r9x.js} +10 -9
  126. package/dist/{oauth-refresh-sweep-zm0yj4sj.js → oauth-refresh-sweep-y3n1knmd.js} +3 -3
  127. package/dist/{onboard-dtwcq603.js → onboard-1zq3m7db.js} +2 -2
  128. package/dist/{openai-codex-responses-de9pvs4d.js → openai-codex-responses-79s8xnbh.js} +29 -23
  129. package/dist/{openai-completions-mtqge3nf.js → openai-completions-tdbyts0x.js} +21 -20
  130. package/dist/{openai-decisions-ygk4kkxd.js → openai-decisions-bqhnjyfz.js} +2 -1
  131. package/dist/{openai-responses-dkyng71g.js → openai-responses-dm3t5vqp.js} +26 -17
  132. package/dist/{opencode-adapter-x4tqzhkh.js → opencode-adapter-e56086m1.js} +7 -5
  133. package/dist/{openrouter-images-wvv7camj.js → openrouter-images-ssttr1y4.js} +6 -3
  134. package/dist/{otel-impl-w3fbhpn0.js → otel-impl-h9yyza47.js} +2 -2
  135. package/dist/{pi-messages-nhh1pkz2.js → pi-messages-3nf8bq1a.js} +6 -4
  136. package/dist/{pi-mono-adapter-mcfkn9vf.js → pi-mono-adapter-tzps8f38.js} +9 -37
  137. package/dist/{pricing-refresh-j38dehfs.js → pricing-refresh-nevhat8h.js} +3 -3
  138. package/dist/{rbac-roles-ae8yttq4.js → rbac-roles-4y6ngvzq.js} +1 -1
  139. package/dist/{rbac-roles-ejxx9b35.js → rbac-roles-exbg8xb6.js} +2 -2
  140. package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
  141. package/dist/{render-v2-n16n0phe.js → render-v2-cfsh13z3.js} +3 -3
  142. package/dist/{resume-z0fgjc38.js → resume-5s2t0dbs.js} +10 -8
  143. package/dist/{runtime-xe3aqy4x.js → runtime-bt5pkpm1.js} +1 -1
  144. package/dist/{session-access-cv3mq6mc.js → session-access-dnbyp3cn.js} +6 -4
  145. package/dist/{setup-mafhj3yt.js → setup-1wj1y77j.js} +1 -1
  146. package/dist/{typesafe-system-one-2hgpayzy.js → typesafe-system-one-bre38hvs.js} +4 -2
  147. package/dist/{virtual-modules-4r3zkc20.js → virtual-modules-mnfbh5mr.js} +8 -2
  148. package/dist/{work-objects-8b86mgjp.js → work-objects-7mg6216g.js} +26 -24
  149. package/dist/worker-nwb789mg.js +79 -0
  150. package/dist/{x-y45mthwn.js → x-pbpezr0s.js} +2 -2
  151. package/openapi.json +793 -6
  152. package/package.json +11 -11
  153. package/src/apps/catalog.generated.json +206 -4
  154. package/src/apps/page-validator.ts +13 -1
  155. package/src/assets/key.ts +17 -0
  156. package/src/azure-devops/handlers.ts +1 -1
  157. package/src/be/chunking.ts +42 -9
  158. package/src/be/db/approvals.ts +18 -0
  159. package/src/be/db/session-moves.ts +164 -0
  160. package/src/be/db/session-tree.ts +384 -0
  161. package/src/be/db/tasks/draft-text.ts +15 -0
  162. package/src/be/db/tasks/read.ts +54 -5
  163. package/src/be/db/workflow-runs.ts +96 -0
  164. package/src/be/db.ts +85 -237
  165. package/src/be/memory/index-content.ts +36 -17
  166. package/src/be/memory/providers/openai-embedding.ts +115 -61
  167. package/src/be/memory/providers/sqlite-store.ts +69 -23
  168. package/src/be/memory/reranker.ts +31 -1
  169. package/src/be/memory/search-candidates.ts +47 -0
  170. package/src/be/memory/types.ts +14 -0
  171. package/src/be/onboarding.ts +3 -0
  172. package/src/be/scripts/typecheck.ts +2 -0
  173. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +106 -54
  174. package/src/be/seed-scripts/index.ts +2 -2
  175. package/src/be/skill-sync.ts +43 -2
  176. package/src/be/swarm-config-guard.ts +25 -1
  177. package/src/be/task-attachment-store.ts +30 -0
  178. package/src/bitbucket/api.ts +81 -0
  179. package/src/bitbucket/auth.ts +64 -0
  180. package/src/bitbucket/handlers.ts +434 -0
  181. package/src/bitbucket/index.ts +28 -0
  182. package/src/bitbucket/templates.ts +134 -0
  183. package/src/bitbucket/types.ts +65 -0
  184. package/src/commands/runner.ts +55 -3
  185. package/src/e2b/env.ts +1 -0
  186. package/src/extensions/catalog.generated.json +4 -4
  187. package/src/extensions/contract-types.generated.ts +1 -1
  188. package/src/extensions/contract.ts +9 -2
  189. package/src/extensions/post-bridge.ts +1 -0
  190. package/src/fs/provider.ts +13 -1
  191. package/src/github/handlers.ts +6 -6
  192. package/src/gitlab/handlers.ts +5 -5
  193. package/src/heartbeat/heartbeat.ts +31 -11
  194. package/src/http/assets.ts +14 -2
  195. package/src/http/core.ts +12 -0
  196. package/src/http/fs.ts +54 -34
  197. package/src/http/index.ts +4 -0
  198. package/src/http/mcp-body.ts +37 -0
  199. package/src/http/mcp-user.ts +3 -5
  200. package/src/http/mcp.ts +6 -7
  201. package/src/http/memory.ts +26 -15
  202. package/src/http/onboarding.ts +1 -0
  203. package/src/http/page-proxy.ts +61 -5
  204. package/src/http/pages-public.ts +27 -44
  205. package/src/http/pages.ts +4 -4
  206. package/src/http/script-runs.ts +2 -0
  207. package/src/http/sessions.ts +366 -12
  208. package/src/http/skills.ts +48 -1
  209. package/src/http/tasks.ts +1 -1
  210. package/src/http/users.ts +13 -1
  211. package/src/http/webhooks.ts +141 -0
  212. package/src/integrations/chat-sdk/adapters.ts +24 -4
  213. package/src/integrations/chat-sdk/attachments.ts +90 -12
  214. package/src/integrations/chat-sdk/facts.ts +138 -0
  215. package/src/integrations/chat-sdk/inbound.ts +156 -8
  216. package/src/integrations/chat-sdk/limits.ts +24 -0
  217. package/src/integrations/chat-sdk/outbound-files.ts +186 -0
  218. package/src/integrations/chat-sdk/outbound.ts +272 -5
  219. package/src/integrations/chat-sdk/relay.ts +4 -1
  220. package/src/integrations/chat-sdk/router.ts +28 -2
  221. package/src/integrations/chat-sdk/steering.ts +9 -0
  222. package/src/integrations/chat-sdk/templates.ts +14 -0
  223. package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
  224. package/src/mcp-limits.ts +20 -0
  225. package/src/pages/browser-sdk.ts +8 -3
  226. package/src/pages/feedback-overlay.ts +1 -1
  227. package/src/providers/acp-targets.ts +1 -1
  228. package/src/providers/amp-adapter.ts +1 -1
  229. package/src/providers/codex-adapter.ts +106 -119
  230. package/src/providers/codex-agents-md.ts +35 -229
  231. package/src/providers/cursor-adapter.ts +1 -1
  232. package/src/providers/pi-mono-adapter.ts +5 -53
  233. package/src/realtime/transport.ts +1 -2
  234. package/src/script-workflows/workflow-ctx.ts +1 -0
  235. package/src/scripts-runtime/types/stdlib.d.ts +2 -0
  236. package/src/scripts-runtime/types/swarm-extension.d.ts +14 -4
  237. package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
  238. package/src/server-user.ts +2 -0
  239. package/src/server.ts +2 -0
  240. package/src/slack/assistant.ts +2 -2
  241. package/src/slack/files.ts +2 -0
  242. package/src/slack/handlers.test.ts +158 -0
  243. package/src/slack/handlers.ts +23 -32
  244. package/src/slack/inbound-files.ts +39 -6
  245. package/src/slack/thread-buffer.ts +2 -1
  246. package/src/tasks/context-key.ts +61 -1
  247. package/src/tasks/task-terminal-effects.ts +21 -17
  248. package/src/tests/apps-card-grid.test.ts +197 -0
  249. package/src/tests/apps-catalog-additions.test.ts +120 -0
  250. package/src/tests/apps-tree.test.ts +129 -0
  251. package/src/tests/bitbucket-auth.test.ts +156 -0
  252. package/src/tests/bitbucket-handlers.test.ts +425 -0
  253. package/src/tests/bitbucket-webhook.test.ts +220 -0
  254. package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
  255. package/src/tests/chat-sdk-config.test.ts +11 -0
  256. package/src/tests/chat-sdk-facts.test.ts +23 -0
  257. package/src/tests/chat-sdk-inbound.test.ts +597 -4
  258. package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
  259. package/src/tests/chat-sdk-telegram-markdown.test.ts +92 -0
  260. package/src/tests/codex-adapter.test.ts +167 -242
  261. package/src/tests/config-api-only-keys.test.ts +9 -0
  262. package/src/tests/context-key.test.ts +50 -0
  263. package/src/tests/core-auth.test.ts +5 -0
  264. package/src/tests/cors-allowlist.test.ts +1 -1
  265. package/src/tests/db-task-read-contract.test.ts +7 -0
  266. package/src/tests/db-task-write-contract.test.ts +6 -0
  267. package/src/tests/docs-index-footprint.test.js +3 -3
  268. package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
  269. package/src/tests/fixtures/bitbucket/pullrequest-comment-created-inline.json +174 -0
  270. package/src/tests/fixtures/bitbucket/pullrequest-comment-created.json +170 -0
  271. package/src/tests/fixtures/bitbucket/pullrequest-created-mention.json +132 -0
  272. package/src/tests/fixtures/bitbucket/pullrequest-created-reviewer.json +140 -0
  273. package/src/tests/fixtures/bitbucket/pullrequest-fulfilled.json +134 -0
  274. package/src/tests/fixtures/bitbucket/pullrequest-rejected.json +133 -0
  275. package/src/tests/generate-mcp-docs.test.ts +101 -0
  276. package/src/tests/gitlab-handlers.test.ts +3 -3
  277. package/src/tests/gitlab-vcs-db.test.ts +4 -4
  278. package/src/tests/heartbeat-checklist.test.ts +33 -0
  279. package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
  280. package/src/tests/heartbeat-jev-gate.test.ts +242 -1
  281. package/src/tests/integration-disable-flags.test.ts +36 -0
  282. package/src/tests/kv-page-proxy.test.ts +91 -5
  283. package/src/tests/launch-password-rejection.test.ts +2 -2
  284. package/src/tests/mcp-input-caps.test.ts +294 -0
  285. package/src/tests/mcp-tools.test.ts +1 -1
  286. package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
  287. package/src/tests/memory-embedding-input-cap.test.ts +114 -0
  288. package/src/tests/memory.test.ts +14 -0
  289. package/src/tests/onboarding.test.ts +12 -0
  290. package/src/tests/page-guest-session.test.ts +19 -8
  291. package/src/tests/page-proxy-authed.test.ts +1 -1
  292. package/src/tests/page-proxy.test.ts +17 -10
  293. package/src/tests/page-session.test.ts +102 -1
  294. package/src/tests/pages-authed-mode.test.ts +82 -12
  295. package/src/tests/pages-password-mode.test.ts +5 -5
  296. package/src/tests/pi-codemode.test.ts +8 -2
  297. package/src/tests/preload-env.test.ts +57 -0
  298. package/src/tests/preload.ts +21 -0
  299. package/src/tests/prompt-template-remaining.test.ts +38 -0
  300. package/src/tests/realtime-transport.test.ts +13 -7
  301. package/src/tests/run-root-coverage.test.ts +39 -0
  302. package/src/tests/runner-bitbucket-vcs.test.ts +191 -0
  303. package/src/tests/runner-skills-refresh.test.ts +58 -0
  304. package/src/tests/script-runs-http.test.ts +84 -0
  305. package/src/tests/scripts-http.test.ts +10 -1
  306. package/src/tests/secret-scrubber.test.ts +15 -0
  307. package/src/tests/sessions-move.test.ts +576 -0
  308. package/src/tests/sessions-tree.test.ts +493 -0
  309. package/src/tests/skill-files-http.test.ts +50 -0
  310. package/src/tests/skills-bundle.test.ts +99 -0
  311. package/src/tests/swarm-config-export-to-env.test.ts +23 -3
  312. package/src/tests/task-audio-transcription.test.ts +299 -0
  313. package/src/tests/task-completion-memory-chunking.test.ts +434 -0
  314. package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
  315. package/src/tests/transcription.test.ts +299 -0
  316. package/src/tests/vcs-bitbucket.test.ts +91 -0
  317. package/src/tests/vcs-provider-isolation.test.ts +123 -0
  318. package/src/tests/vcs-provider.test.ts +16 -1
  319. package/src/tests/vcs-tracking.test.ts +3 -3
  320. package/src/tests/workflow-foreach-bodies.test.ts +637 -0
  321. package/src/tests/workflow-foreach-concurrency.test.ts +342 -0
  322. package/src/tests/workflow-foreach-retry.test.ts +537 -0
  323. package/src/tests/workflow-foreach.test.ts +44 -23
  324. package/src/tests/workflow-step-claims.test.ts +6 -6
  325. package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
  326. package/src/tests/workflow-system-one-decision.test.ts +2 -1
  327. package/src/tests/workflow-tla-races.test.ts +2 -2
  328. package/src/tools/chat-access.ts +10 -0
  329. package/src/tools/chat-post.ts +31 -11
  330. package/src/tools/chat-reply.ts +32 -10
  331. package/src/tools/memory-search.ts +3 -1
  332. package/src/tools/script-delete.ts +1 -1
  333. package/src/tools/system-one-decide.ts +17 -4
  334. package/src/tools/workflows/create-workflow.ts +5 -3
  335. package/src/types.ts +9 -2
  336. package/src/utils/config-env-export.ts +4 -1
  337. package/src/utils/page-session.ts +133 -20
  338. package/src/utils/secret-scrubber.ts +4 -0
  339. package/src/utils/skills-refresh.ts +83 -43
  340. package/src/utils/transcription.ts +246 -0
  341. package/src/vcs/bitbucket.ts +58 -0
  342. package/src/vcs/index.ts +2 -0
  343. package/src/vcs/types.ts +2 -2
  344. package/src/workflows/approval-resolution.ts +4 -1
  345. package/src/workflows/checkpoint.ts +9 -1
  346. package/src/workflows/constants.ts +3 -0
  347. package/src/workflows/definition.ts +48 -17
  348. package/src/workflows/engine.ts +25 -15
  349. package/src/workflows/executors/foreach.ts +45 -99
  350. package/src/workflows/executors/system-one-decision.ts +28 -7
  351. package/src/workflows/executors/system-one-providers.ts +39 -4
  352. package/src/workflows/foreach-body.ts +146 -0
  353. package/src/workflows/foreach-driver.ts +552 -0
  354. package/src/workflows/foreach-join.ts +206 -7
  355. package/src/workflows/node-timeout.ts +21 -0
  356. package/src/workflows/recovery.ts +68 -3
  357. package/src/workflows/resume.ts +221 -43
  358. package/src/workflows/retry-poller.ts +39 -24
  359. package/src/workflows/step-input.ts +59 -0
  360. package/src/workflows/task-step-routing.ts +114 -56
  361. package/templates/extensions/slack-reply-gate/README.md +24 -22
  362. package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
  363. package/templates/extensions/slack-reply-gate/manifest.json +2 -2
  364. package/templates/skills/apps/SKILL.md +28 -6
  365. package/templates/skills/apps/content.md +28 -6
  366. package/templates/skills/chat-sdk/content.md +6 -2
  367. package/templates/skills/code-quality/content.md +2 -1
  368. package/templates/skills/heartbeat-runbook/content.md +5 -5
  369. package/templates/skills/pages/content.md +6 -4
  370. package/templates/skills/slack-interaction/content.md +5 -0
  371. package/templates/skills/swarm-scripts/SKILL.md +2 -2
  372. package/templates/skills/swarm-scripts/content.md +2 -2
  373. package/templates/skills/work-on-task/SKILL.md +1 -1
  374. package/templates/skills/work-on-task/content.md +1 -1
  375. package/dist/cli-51y09c6p.js +0 -2657
  376. package/dist/cli-yw91rnmw.js +0 -13
  377. package/dist/handlers-0pvee9nw.js +0 -39
  378. package/dist/index-gdh8jrdm.js +0 -43
  379. package/dist/index-hg0x2cdv.js +0 -40
  380. package/dist/index-thm0y6a8.js +0 -41
  381. package/dist/lead-ee8vazz2.js +0 -77
  382. package/dist/worker-16s75hm5.js +0 -77
@@ -1,6 +1,7 @@
1
1
  import { afterAll, beforeAll, beforeEach, describe, expect, test } from "bun:test";
2
2
  import { unlink } from "node:fs/promises";
3
3
  import { closeDb, getDbClient, initDb, upsertSwarmConfig } from "../be/db";
4
+ import { SYSTEM_ONE_DEFAULT_PROVIDER_OPTIONS, validateConfigValue } from "../be/swarm-config-guard";
4
5
  import type { WorkflowNode } from "../types";
5
6
  import { validateDefinition } from "../workflows/definition";
6
7
  import { InProcessEventBus } from "../workflows/event-bus";
@@ -11,6 +12,7 @@ import {
11
12
  SystemOneDecisionExecutor,
12
13
  type SystemOneDecisionExecutorOptions,
13
14
  } from "../workflows/executors/system-one-decision";
15
+ import { SYSTEM_ONE_PROVIDER_IDS } from "../workflows/executors/system-one-providers";
14
16
  import { interpolate } from "../workflows/template";
15
17
 
16
18
  const TEST_DB_PATH = "./test-workflow-system-one-decision-providers.sqlite";
@@ -50,7 +52,7 @@ afterAll(async () => {
50
52
 
51
53
  beforeEach(async () => {
52
54
  await getDbClient().run(
53
- "DELETE FROM swarm_config WHERE key IN ('OPENAI_API_KEY', 'OPENAI_DECISIONS_API_KEY', 'CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_API_TOKEN')",
55
+ "DELETE FROM swarm_config WHERE key IN ('OPENAI_API_KEY', 'OPENAI_DECISIONS_API_KEY', 'CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_API_TOKEN', 'SYSTEM_ONE_DEFAULT_PROVIDER')",
54
56
  );
55
57
  });
56
58
 
@@ -708,6 +710,101 @@ describe("system-one-decision openai provider", () => {
708
710
  });
709
711
  });
710
712
 
713
+ // ─── Default provider ───────────────────────────────────────
714
+
715
+ describe("system-one-decision default provider", () => {
716
+ const TYPESAFE_KEY = "typesafe-example-test-key-0123456789";
717
+ const jevBody = () =>
718
+ jsonResponse({
719
+ model: "jev",
720
+ answers: systemOneAnswers,
721
+ usage: { input_tokens: 1, output_tokens: 0 },
722
+ });
723
+ const setDefault = (value: string) =>
724
+ upsertSwarmConfig({ scope: "global", key: "SYSTEM_ONE_DEFAULT_PROVIDER", value });
725
+ const withTypesafeKey = {
726
+ getApiKey: async (id: string) =>
727
+ id === "typesafe" ? TYPESAFE_KEY : id === "cloudflare" ? CF_TOKEN : null,
728
+ };
729
+
730
+ test("unset, a node with no provider still calls typesafe", async () => {
731
+ const { executor, calls } = makeExecutor([jevBody()], withTypesafeKey);
732
+ const result = await run(executor, config());
733
+ expect(result.status).toBe("success");
734
+ expect(calls[0]?.url).toBe("https://api.typesafe.ai/v1/systemone");
735
+ expect(calls[0]?.body.model).toBe("jev-latest");
736
+ // The schema leaves the provider unset; the executor resolves it per run.
737
+ expect(SystemOneDecisionConfigSchema.parse(config()).provider).toBeUndefined();
738
+ });
739
+
740
+ test("set to cloudflare, a node with no provider calls Clef with no workflow edit", async () => {
741
+ await setDefault("cloudflare");
742
+ const { executor, calls } = makeExecutor([jsonResponse(clefEnvelope())], withTypesafeKey);
743
+ const result = await run(executor, config());
744
+ expect(result.status).toBe("success");
745
+ expect(calls[0]?.url).toBe(`${CF_BASE}/clef`);
746
+ expect((calls[0]?.init.headers as Record<string, string>).authorization).toBe(
747
+ `Bearer ${CF_TOKEN}`,
748
+ );
749
+ expect(result.output).toMatchObject({ model: "clef", answers: systemOneAnswers as never });
750
+ });
751
+
752
+ test("a node that names its provider keeps it", async () => {
753
+ await setDefault("cloudflare");
754
+ const { executor, calls } = makeExecutor([jevBody()], withTypesafeKey);
755
+ expect((await run(executor, config({ provider: "typesafe" }))).status).toBe("success");
756
+ expect(calls[0]?.url).toBe("https://api.typesafe.ai/v1/systemone");
757
+ });
758
+
759
+ test("readiness checks the default provider's credentials", async () => {
760
+ await setDefault("cloudflare");
761
+ const { executor } = makeExecutor([], { getApiKey: async () => null });
762
+ const problems = await executor.checkReadiness([{ id: "a", config: config() }]);
763
+ expect(problems).toHaveLength(1);
764
+ expect(problems[0]?.nodeIds).toEqual(["a"]);
765
+ expect(problems[0]?.message).toContain("CLOUDFLARE_API_TOKEN is not configured");
766
+ });
767
+
768
+ test("the environment is read when no row is stored; a stored row wins", async () => {
769
+ const env = { SYSTEM_ONE_DEFAULT_PROVIDER: "cloudflare" };
770
+ const fromEnv = makeExecutor([jsonResponse(clefEnvelope())], { ...withTypesafeKey, env });
771
+ expect((await run(fromEnv.executor, config())).status).toBe("success");
772
+ expect(fromEnv.calls[0]?.url).toBe(`${CF_BASE}/clef`);
773
+
774
+ await setDefault("typesafe");
775
+ const stored = makeExecutor([jevBody()], { ...withTypesafeKey, env });
776
+ expect((await run(stored.executor, config())).status).toBe("success");
777
+ expect(stored.calls[0]?.url).toBe("https://api.typesafe.ai/v1/systemone");
778
+ });
779
+
780
+ test("a defaulted provider's limits are checked at run, and nothing is sent", async () => {
781
+ await setDefault("cloudflare");
782
+ const qs: Record<string, unknown> = {};
783
+ const rs: Record<string, unknown> = {};
784
+ for (let i = 0; i < 65; i++) {
785
+ qs[`q${i}`] = { type: "noul", instructions: `Question ${i}?` };
786
+ rs[`q${i}`] = { type: "noul" };
787
+ }
788
+ const { executor, calls } = makeExecutor([jsonResponse(clefEnvelope())]);
789
+ const result = await run(executor, config({ questions: qs, returns: rs }));
790
+ expect(result.status).toBe("failed");
791
+ expect(result.error).toContain("at most 64 questions per node; this node has 65");
792
+ expect(calls).toHaveLength(0);
793
+ });
794
+
795
+ test("the config guard accepts exactly the decide hosts", () => {
796
+ expect([...SYSTEM_ONE_DEFAULT_PROVIDER_OPTIONS].sort()).toEqual(
797
+ [...SYSTEM_ONE_PROVIDER_IDS].sort(),
798
+ );
799
+ for (const id of SYSTEM_ONE_PROVIDER_IDS) {
800
+ expect(validateConfigValue("SYSTEM_ONE_DEFAULT_PROVIDER", id)).toBeNull();
801
+ }
802
+ expect(validateConfigValue("SYSTEM_ONE_DEFAULT_PROVIDER", "jev")).toContain(
803
+ "Invalid SYSTEM_ONE_DEFAULT_PROVIDER value",
804
+ );
805
+ });
806
+ });
807
+
711
808
  // ─── Existing providers ─────────────────────────────────────
712
809
 
713
810
  describe("system-one-decision SystemOne wire is unchanged", () => {
@@ -227,7 +227,8 @@ describe("system-one-decision config schema", () => {
227
227
  questions: { fit: { type: "noul", instructions: "Is it real?" } },
228
228
  returns: { fit: { type: "noul" } },
229
229
  });
230
- expect(parsed.provider).toBe("typesafe");
230
+ // Unset: the executor reads SYSTEM_ONE_DEFAULT_PROVIDER at run time (typesafe when unset).
231
+ expect(parsed.provider).toBeUndefined();
231
232
  // The model default belongs to the provider, so the schema leaves it unset.
232
233
  expect(parsed.model).toBeUndefined();
233
234
  expect(parsed.timeoutMs).toBe(30_000);
@@ -213,7 +213,7 @@ describe("TLA+ workflow counterexamples", () => {
213
213
  const stepB = await untilStatus(runId, "B", "waiting");
214
214
 
215
215
  // EF: B's task fails -> run failed.
216
- await failStepAndRunIfWaiting(stepB!.id, runId, "task failed");
216
+ await failStepAndRunIfWaiting(def, stepB!.id, runId, "task failed");
217
217
  expect((await getWorkflowRun(runId))?.status).toBe("failed");
218
218
 
219
219
  // U1/U2: the user retries; findReadyNodes returns A because it is not completed.
@@ -240,7 +240,7 @@ describe("TLA+ workflow counterexamples", () => {
240
240
 
241
241
  // EF: B's task fails -> run failed. XCkWait(A): the checkpoint CAS sees a
242
242
  // failed run, so A's row stays `running` with its task out.
243
- await failStepAndRunIfWaiting(stepB!.id, runId, "task failed");
243
+ await failStepAndRunIfWaiting(def, stepB!.id, runId, "task failed");
244
244
  holdA.release();
245
245
  await initial;
246
246
  expect((await stepsOf(runId, "A"))[0]?.status).toBe("running");
@@ -1,8 +1,18 @@
1
+ import * as z from "zod";
1
2
  import { getAgentById, getAgentCurrentTask, getTaskById } from "@/be/db";
2
3
  import { can } from "@/rbac";
3
4
  import { chatThreadOfContextKey } from "@/tasks/context-key";
4
5
  import type { RequestInfo } from "@/tools/utils";
5
6
 
7
+ /** The `attachments` input of `chat-reply` and `chat-post`. */
8
+ export const chatAttachmentsSchema = z
9
+ .array(z.string().min(1))
10
+ .max(10)
11
+ .optional()
12
+ .describe(
13
+ "Files to send after the text, up to 10: attachment ids of your current task (from get-task-details) or file paths in your agent-fs drive, such as thoughts/<agent-id>/report.pdf, read with your own agent-fs credential. Telegram shows JPEG and PNG as photos, MP4 as video, MP3 and M4A as audio, and anything else as a document. A file over the platform upload limit (Telegram 50 MB, Discord 10 MB) is not sent, and the thread gets a note naming it.",
14
+ );
15
+
6
16
  /** Chat SDK verbs; the legacy policy grants them to the lead only. */
7
17
  export type ChatVerb = "integration.chat.post" | "integration.chat.read" | "integration.chat.dm";
8
18
 
@@ -2,8 +2,13 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import * as z from "zod";
3
3
  import { CHAT_SDK_ADAPTER_NAMES } from "@/integrations/chat-sdk/config";
4
4
  import { errorMessage } from "@/integrations/chat-sdk/logger";
5
- import { adapterOfChatId, postChatMessage } from "@/integrations/chat-sdk/outbound";
6
- import { canUseChatVerb } from "@/tools/chat-access";
5
+ import {
6
+ adapterOfChatId,
7
+ postChatMessage,
8
+ unsentFilesSummary,
9
+ } from "@/integrations/chat-sdk/outbound";
10
+ import { resolveChatAttachmentRefs } from "@/integrations/chat-sdk/outbound-files";
11
+ import { canUseChatVerb, chatAttachmentsSchema } from "@/tools/chat-access";
7
12
  import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
8
13
 
9
14
  export const registerChatPostTool = (server: McpServer) => {
@@ -27,6 +32,7 @@ export const registerChatPostTool = (server: McpServer) => {
27
32
  .optional()
28
33
  .describe("Full SDK channel id, such as slack:C123. Ignored when threadId is set."),
29
34
  text: z.string().min(1).max(20_000).describe("Markdown text to post."),
35
+ attachments: chatAttachmentsSchema,
30
36
  }),
31
37
  outputSchema: swarmToolOutputSchema({
32
38
  yourAgentId: z.string().optional(),
@@ -34,9 +40,12 @@ export const registerChatPostTool = (server: McpServer) => {
34
40
  adapter: z.string().optional(),
35
41
  threadId: z.string().optional(),
36
42
  channelId: z.string().optional(),
43
+ unsentFiles: z
44
+ .array(z.looseObject({ name: z.string().optional(), reason: z.string().optional() }))
45
+ .optional(),
37
46
  }),
38
47
  },
39
- async ({ adapter, threadId, channelId, text }, requestInfo) => {
48
+ async ({ adapter, threadId, channelId, text, attachments }, requestInfo) => {
40
49
  const data = { yourAgentId: requestInfo.agentId };
41
50
  const target = threadId ?? channelId;
42
51
  if (!target) return toolErr("Give a threadId or a channelId.", { data });
@@ -49,22 +58,33 @@ export const registerChatPostTool = (server: McpServer) => {
49
58
  { data },
50
59
  );
51
60
  }
61
+ const resolved = await resolveChatAttachmentRefs(
62
+ attachments ?? [],
63
+ requestInfo.sourceTaskId,
64
+ requestInfo.agentId,
65
+ );
66
+ if ("error" in resolved) return toolErr(resolved.error, { data });
52
67
  try {
53
68
  const sent = await postChatMessage({
54
69
  adapter,
55
70
  ...(threadId ? { threadId } : { channelId }),
56
71
  text,
57
72
  taskId: requestInfo.sourceTaskId,
73
+ files: resolved.files,
58
74
  });
59
- return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}.`, {
60
- data: {
61
- ...data,
62
- messageId: sent.messageIds.at(-1),
63
- adapter: sent.adapter,
64
- threadId: sent.threadId,
65
- channelId: sent.channelId,
75
+ return toolOk(
76
+ `Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}.${unsentFilesSummary(sent.unsentFiles)}`,
77
+ {
78
+ data: {
79
+ ...data,
80
+ messageId: sent.messageIds.at(-1),
81
+ adapter: sent.adapter,
82
+ threadId: sent.threadId,
83
+ channelId: sent.channelId,
84
+ unsentFiles: sent.unsentFiles,
85
+ },
66
86
  },
67
- });
87
+ );
68
88
  } catch (error) {
69
89
  const message = errorMessage(error);
70
90
  return toolErr(`Could not post: ${message}`, { data });
@@ -2,8 +2,14 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import * as z from "zod";
3
3
  import { getAgentCurrentTask, getTaskById } from "@/be/db";
4
4
  import { errorMessage } from "@/integrations/chat-sdk/logger";
5
- import { ChatAdapterUnavailableError, postChatMessage } from "@/integrations/chat-sdk/outbound";
5
+ import {
6
+ ChatAdapterUnavailableError,
7
+ postChatMessage,
8
+ unsentFilesSummary,
9
+ } from "@/integrations/chat-sdk/outbound";
10
+ import { resolveChatAttachmentRefs } from "@/integrations/chat-sdk/outbound-files";
6
11
  import { chatThreadOfContextKey } from "@/tasks/context-key";
12
+ import { chatAttachmentsSchema } from "@/tools/chat-access";
7
13
  import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
8
14
 
9
15
  export const registerChatReplyTool = (server: McpServer) => {
@@ -12,19 +18,23 @@ export const registerChatReplyTool = (server: McpServer) => {
12
18
  {
13
19
  title: "Reply in the chat thread of this task",
14
20
  description:
15
- "Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user or a short progress note on long work. Markdown is supported; long text is split into several messages.",
21
+ "Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user, a short progress note on long work, or to send files (attachments). Markdown is supported; long text is split into several messages. When the final output of a task is posted, the files attached to that task go with it.",
16
22
  annotations: { openWorldHint: true },
17
23
  inputSchema: z.object({
18
24
  text: z.string().min(1).max(20_000).describe("Markdown text to post to the thread."),
25
+ attachments: chatAttachmentsSchema,
19
26
  }),
20
27
  outputSchema: swarmToolOutputSchema({
21
28
  yourAgentId: z.string().optional(),
22
29
  messageId: z.string().optional(),
23
30
  adapter: z.string().optional(),
24
31
  threadId: z.string().optional(),
32
+ unsentFiles: z
33
+ .array(z.looseObject({ name: z.string().optional(), reason: z.string().optional() }))
34
+ .optional(),
25
35
  }),
26
36
  },
27
- async ({ text }, requestInfo) => {
37
+ async ({ text, attachments }, requestInfo) => {
28
38
  if (!requestInfo.agentId) return toolErr("Agent ID not found.");
29
39
  const data = { yourAgentId: requestInfo.agentId };
30
40
 
@@ -46,21 +56,33 @@ export const registerChatReplyTool = (server: McpServer) => {
46
56
  );
47
57
  }
48
58
 
59
+ const resolved = await resolveChatAttachmentRefs(
60
+ attachments ?? [],
61
+ task.id,
62
+ requestInfo.agentId,
63
+ );
64
+ if ("error" in resolved) return toolErr(resolved.error, { data });
65
+
49
66
  try {
50
67
  const sent = await postChatMessage({
51
68
  adapter: thread.adapter,
52
69
  threadId: thread.threadId,
53
70
  text,
54
71
  taskId: task.id,
72
+ files: resolved.files,
55
73
  });
56
- return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}.`, {
57
- data: {
58
- ...data,
59
- messageId: sent.messageIds.at(-1),
60
- adapter: sent.adapter,
61
- threadId: sent.threadId,
74
+ return toolOk(
75
+ `Posted to ${thread.adapter} thread ${sent.threadId}.${unsentFilesSummary(sent.unsentFiles)}`,
76
+ {
77
+ data: {
78
+ ...data,
79
+ messageId: sent.messageIds.at(-1),
80
+ adapter: sent.adapter,
81
+ threadId: sent.threadId,
82
+ unsentFiles: sent.unsentFiles,
83
+ },
62
84
  },
63
- });
85
+ );
64
86
  } catch (error) {
65
87
  const message = errorMessage(error);
66
88
  return toolErr(
@@ -11,6 +11,7 @@ import {
11
11
  recordRetrievals,
12
12
  } from "@/be/memory/raters/retrieval";
13
13
  import { rerank } from "@/be/memory/reranker";
14
+ import { searchMemoryCandidates } from "@/be/memory/search-candidates";
14
15
  import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
15
16
  import type { AgentMemorySource } from "@/types";
16
17
  import { AgentMemoryScopeSchema, AgentMemorySourceSchema } from "@/types";
@@ -122,7 +123,8 @@ export const registerMemorySearchTool = (server: McpServer) => {
122
123
  const queryEmbedding = await provider.embed(query);
123
124
 
124
125
  const candidateLimit = limit * CANDIDATE_SET_MULTIPLIER;
125
- const candidates = await store.search(
126
+ const candidates = await searchMemoryCandidates(
127
+ store,
126
128
  queryEmbedding ?? new Float32Array(0),
127
129
  requestInfo.agentId,
128
130
  {
@@ -9,7 +9,7 @@ import {
9
9
  } from "./script-common";
10
10
 
11
11
  export const SCRIPT_DELETE_DESCRIPTION =
12
- "Remove a swarm-shared script from the catalog. Versions table preserves history.";
12
+ "Permanently remove a swarm-shared script and all its versions from the catalog. This cannot be undone.";
13
13
 
14
14
  export const registerScriptDeleteTool = (server: McpServer) => {
15
15
  createToolRegistrar(server)(
@@ -10,7 +10,7 @@ import {
10
10
  import { SYSTEM_ONE_PROVIDER_IDS } from "@/workflows/executors/system-one-providers";
11
11
 
12
12
  /**
13
- * One typed decision (Jev and the other SystemOne hosts) made in the API
13
+ * One typed decision (Jev, Clef and the other SystemOne hosts) made in the API
14
14
  * process, the same way a `system-one-decision` workflow node makes it. The
15
15
  * provider credential is read and sent here and never reaches the caller, so a
16
16
  * script can ask for a decision without a credential binding in its own realm.
@@ -22,14 +22,16 @@ export const registerSystemOneDecideTool = (server: McpServer) => {
22
22
  title: "Ask a SystemOne decision model",
23
23
  annotations: { destructiveHint: false, openWorldHint: true },
24
24
  description:
25
- "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev, and return the validated answers. " +
25
+ "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev or Clef, and return the validated answers. " +
26
26
  "Same request, provider list, credentials and validation as the `system-one-decision` workflow node, without its human review band. " +
27
27
  "The provider credential is a global secret that stays on the server; this tool never returns it.",
28
28
  inputSchema: z.object({
29
29
  provider: z
30
30
  .enum(SYSTEM_ONE_PROVIDER_IDS)
31
31
  .optional()
32
- .describe("Decision host (default typesafe)"),
32
+ .describe(
33
+ "Decision host (default: the SYSTEM_ONE_DEFAULT_PROVIDER global config, typesafe when unset)",
34
+ ),
33
35
  model: z.string().min(1).optional().describe("Provider model id (default: the provider's)"),
34
36
  state: z
35
37
  .union([z.string(), z.array(z.string()), z.record(z.string(), z.unknown())])
@@ -55,6 +57,12 @@ export const registerSystemOneDecideTool = (server: McpServer) => {
55
57
  answers: z.record(z.string(), z.unknown()).optional(),
56
58
  usage: z.record(z.string(), z.unknown()).optional(),
57
59
  requestId: z.string().optional(),
60
+ providerUnavailable: z
61
+ .boolean()
62
+ .optional()
63
+ .describe(
64
+ "On an error: true when this deployment refuses the provider (e.g. OpenRouter behind a gateway) and no request was sent, so a caller choosing automatically can try its next provider",
65
+ ),
58
66
  }),
59
67
  },
60
68
  async ({ provider, model, state, questions, timeoutMs, maxRetries }, requestInfo) => {
@@ -88,7 +96,12 @@ export const registerSystemOneDecideTool = (server: McpServer) => {
88
96
  return toolErr("The system-one-decision executor is not available");
89
97
  }
90
98
  const decided = await executor.decide(parsed.data);
91
- if (!decided.ok) return toolErr(decided.error);
99
+ if (!decided.ok) {
100
+ return toolErr(
101
+ decided.error,
102
+ decided.deploymentRefused ? { data: { providerUnavailable: true } } : {},
103
+ );
104
+ }
92
105
 
93
106
  const { output } = decided;
94
107
  return toolOk(`Decision from ${output.model}`, {
@@ -40,11 +40,13 @@ export const registerCreateWorkflowTool = (server: McpServer) => {
40
40
  "- STRUCTURED OUTPUT: For agent-task nodes, put outputSchema inside 'config' to validate the agent's raw JSON output. " +
41
41
  "Node-level outputSchema validates the executor's return ({taskId, taskOutput}), which is different.\n" +
42
42
  "- Agent-task config: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }.\n" +
43
- "- FOREACH NODE: type 'foreach' fans out one agent-task per item. Config: " +
44
- "{ over: <array or exact {{input}} token>, itemKey: <property name>, body: { type: 'agent-task', config: {...} } }. " +
43
+ "- FOREACH NODE: type 'foreach' runs its body once per item. Config: " +
44
+ "{ over: <array or exact {{input}} token>, itemKey: <property name>, body: { type: <any executor except foreach>, config: {...} }, " +
45
+ "concurrency?: <integer >= 1, items in flight; unbounded when absent>, failurePolicy?: 'fail-fast' | 'collect-outcomes' }. " +
45
46
  "The body config is interpolated once per item with {{item.*}} and {{index}}. Child steps use synthetic IDs " +
46
47
  "'<foreachNodeId>#<itemKey>'; the parent waits for every child and exposes one aggregate result to successors. " +
47
- "concurrency is not supported in v1; use definition-level onNodeFailure: 'continue' to aggregate failed children.\n" +
48
+ "failurePolicy defaults from onNodeFailure ('continue' = collect-outcomes, else fail-fast); fail-fast cancels queued items. " +
49
+ "retry-workflow-run on a failed fan-out reruns only failed and cancelled items.\n" +
48
50
  "- TRIGGER SCHEMA: Optional 'triggerSchema' is a JSON-Schema object that validates incoming trigger payloads. " +
49
51
  "Supported keywords: type, required, properties, enum, const, items (recursive into arrays). " +
50
52
  "Other JSON-Schema keywords (oneOf/anyOf/$ref/pattern/format/additionalProperties) are silently ignored.\n" +
package/src/types.ts CHANGED
@@ -384,6 +384,7 @@ export const AgentTaskSourceSchema = z.enum([
384
384
  "github",
385
385
  "gitlab",
386
386
  "azure-devops",
387
+ "bitbucket",
387
388
  "agentmail",
388
389
  "system",
389
390
  "schedule",
@@ -697,7 +698,7 @@ export const AgentTaskSchema = z
697
698
  slackTreeRootMessageTs: z.string().optional(),
698
699
 
699
700
  // VCS metadata (GitHub / GitLab / Azure DevOps — provider-agnostic)
700
- vcsProvider: z.enum(["github", "gitlab", "azure-devops"]).optional(),
701
+ vcsProvider: z.enum(["github", "gitlab", "azure-devops", "bitbucket"]).optional(),
701
702
  vcsRepo: z.string().optional(),
702
703
  vcsEventType: z.string().optional(),
703
704
  vcsNumber: z.number().int().optional(),
@@ -863,7 +864,7 @@ export const CreateTaskOptionsSchema = z.object({
863
864
  * this boundary must not let a caller silently persist a mismatch.
864
865
  */
865
866
  overrideSlackContext: z.boolean().optional(),
866
- vcsProvider: z.enum(["github", "gitlab", "azure-devops"]).optional(),
867
+ vcsProvider: z.enum(["github", "gitlab", "azure-devops", "bitbucket"]).optional(),
867
868
  vcsRepo: z.string().optional(),
868
869
  vcsEventType: z.string().optional(),
869
870
  vcsNumber: z.number().int().optional(),
@@ -905,6 +906,12 @@ export const CreateTaskOptionsSchema = z.object({
905
906
  * contract on completion (which would block the control task — DES-523).
906
907
  */
907
908
  inheritParentOutputSchema: z.boolean().optional(),
909
+ /**
910
+ * When a `parentTaskId` is set and `requestedByUserId` is not, the child
911
+ * inherits the parent's requester by default. Set this to `false` when the
912
+ * child answers a different person (a chat message whose sender is unknown).
913
+ */
914
+ inheritParentRequester: z.boolean().optional(),
908
915
  /**
909
916
  * Skip parent routing requirements only for a child with its own explicit
910
917
  * Lead-only control-plane authorization.
@@ -8,7 +8,8 @@
8
8
  * binding instead.
9
9
  *
10
10
  * Keys below are read only by the API server (integration signing secrets, app
11
- * private keys, OAuth client secrets, the API's own agent-fs key). They can
11
+ * private keys, OAuth client secrets, the API's own agent-fs and
12
+ * speech-to-text keys). They can
12
13
  * never be exported: the config API rejects `exportToEnv: true` for them and
13
14
  * every reader treats a stored true as false.
14
15
  */
@@ -23,8 +24,10 @@ export const ENV_EXPORT_RESTRICTED_KEYS: ReadonlySet<string> = new Set([
23
24
  "JIRA_CLIENT_SECRET",
24
25
  "JIRA_WEBHOOK_TOKEN",
25
26
  "AZURE_DEVOPS_WEBHOOK_SECRET",
27
+ "BITBUCKET_WEBHOOK_SECRET",
26
28
  "AGENTMAIL_WEBHOOK_SECRET",
27
29
  "API_AGENT_FS_API_KEY",
30
+ "TRANSCRIPTION_API_KEY",
28
31
  ]);
29
32
 
30
33
  /**