@desplega.ai/agent-swarm 1.131.1 → 1.134.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 (360) hide show
  1. package/README.md +3 -3
  2. package/dist/{actions-jgcy477k.js → actions-7kast243.js} +20 -18
  3. package/dist/{anthropic-messages-rjmd2e7n.js → anthropic-messages-706yad38.js} +33 -17
  4. package/dist/app-0g84t8wf.js +28 -0
  5. package/dist/{artifact-jysj3wrg.js → artifact-dje5ke4h.js} +37 -131
  6. package/dist/{assistant-f2vkk1hj.js → assistant-ac4htcky.js} +25 -22
  7. package/dist/{azure-openai-responses-c0yjmbfd.js → azure-openai-responses-be59fbsz.js} +13 -13
  8. package/dist/{boot-reembed-q7mp8hcr.js → boot-reembed-b1rcqn85.js} +13 -11
  9. package/dist/{boot-reembed-xmw8wcx6.js → boot-reembed-kw2541c4.js} +14 -12
  10. package/dist/{boot-scrub-logs-dsqrv79n.js → boot-scrub-logs-ja29t92g.js} +11 -9
  11. package/dist/{claude-adapter-q6x7yspx.js → claude-adapter-5cg1fv8s.js} +33 -29
  12. package/dist/{claude-managed-adapter-wsg37bt8.js → claude-managed-adapter-9z9sdytx.js} +9 -9
  13. package/dist/{claude-managed-setup-52z4mq9w.js → claude-managed-setup-3zqp51cr.js} +5 -5
  14. package/dist/{claude-1ex232fc.js → claude-wqn3dtca.js} +1 -1
  15. package/dist/{cli-4wgngmwv.js → cli-00w4hbam.js} +1 -1
  16. package/dist/{cli-er3a4bb0.js → cli-15429qdw.js} +6 -1
  17. package/dist/{cli-e5dabkx0.js → cli-1cwhyvta.js} +4 -4
  18. package/dist/{cli-zsspvvm2.js → cli-1ybr6vw2.js} +237 -237
  19. package/dist/{cli-xpxde7rm.js → cli-2wv4kj0e.js} +60 -31
  20. package/dist/cli-34w2584r.js +530 -0
  21. package/dist/{cli-se2p6rkb.js → cli-38taxznr.js} +6 -6
  22. package/dist/{cli-9sbhdpvb.js → cli-3cgfyfzm.js} +14 -14
  23. package/dist/{cli-5n6e5yfn.js → cli-3zmdzfjf.js} +79 -74
  24. package/dist/{cli-3ty0t082.js → cli-43x36mty.js} +197 -8
  25. package/dist/{cli-ycrnynpw.js → cli-480nehnh.js} +29 -22
  26. package/dist/{cli-0258203w.js → cli-492e7ap5.js} +140 -20
  27. package/dist/{cli-3fj60etf.js → cli-497b685t.js} +3 -3
  28. package/dist/{cli-pxfxkx5m.js → cli-4bap00k0.js} +1 -1
  29. package/dist/{cli-w2wxd56v.js → cli-4bc8vmhm.js} +848 -770
  30. package/dist/{cli-aca5pz9f.js → cli-589599p9.js} +1 -1
  31. package/dist/{cli-t930g0xh.js → cli-5tnr64pm.js} +1 -1
  32. package/dist/{cli-jxg3s9ey.js → cli-65d93ves.js} +7 -7
  33. package/dist/{cli-6dpytdr2.js → cli-6x363v1z.js} +2 -2
  34. package/dist/{cli-dxak0fqd.js → cli-787ph852.js} +11 -11
  35. package/dist/{cli-793jvbsh.js → cli-7bv8nckk.js} +16 -11
  36. package/dist/{cli-zyxs93y9.js → cli-7jcc9y1r.js} +3 -3
  37. package/dist/{cli-f1am9szv.js → cli-87t2gstf.js} +1 -1
  38. package/dist/{cli-9aryf9tv.js → cli-95m51ztz.js} +1 -1
  39. package/dist/{cli-4w4fmq9x.js → cli-9w49enmh.js} +2 -2
  40. package/dist/{cli-v69vk5h0.js → cli-9y5b02vr.js} +13 -13
  41. package/dist/{cli-x23me2mg.js → cli-a1rrkrb4.js} +1 -1
  42. package/dist/{cli-psrqtw2m.js → cli-a3pkfpqs.js} +2 -2
  43. package/dist/{cli-h0rgxd24.js → cli-a4ajmfvp.js} +6 -6
  44. package/dist/{cli-ygrbmjja.js → cli-aw8bb6sf.js} +6 -6
  45. package/dist/{cli-g74vpjp2.js → cli-brm3et47.js} +55 -22
  46. package/dist/{cli-czkae1fp.js → cli-c5ddbdfj.js} +9 -9
  47. package/dist/{cli-114fvtmj.js → cli-c79a9zrc.js} +1 -1
  48. package/dist/{cli-49n9f49x.js → cli-dx3dz0ms.js} +3 -3
  49. package/dist/{cli-6dp3ydxa.js → cli-e07exmsb.js} +18 -14
  50. package/dist/cli-et1bbwqf.js +13 -0
  51. package/dist/{cli-yazx6hap.js → cli-f3s9dry0.js} +14 -14
  52. package/dist/{cli-t8d349cy.js → cli-f4wj0s3m.js} +3 -3
  53. package/dist/{cli-d6n0thxw.js → cli-f64gdfxc.js} +1 -1
  54. package/dist/{cli-pwfsqc2x.js → cli-fyd58xgb.js} +55 -55
  55. package/dist/{cli-7dm2zqy2.js → cli-g0j14czv.js} +2 -2
  56. package/dist/{cli-b0p7rfnd.js → cli-g2p9bd1z.js} +14 -14
  57. package/dist/{cli-z905tvmm.js → cli-g814jbst.js} +2 -2
  58. package/dist/{cli-5dsbcjjw.js → cli-ghexzd2d.js} +970 -970
  59. package/dist/{cli-jvv0g8bh.js → cli-gpt9kf01.js} +15 -15
  60. package/dist/{cli-rgrfzg8z.js → cli-grt6qv91.js} +380 -380
  61. package/dist/{cli-wz9115x0.js → cli-gtafvdy0.js} +8 -8
  62. package/dist/{cli-q5dzzak0.js → cli-gy07xk4s.js} +2 -2
  63. package/dist/{cli-sy7jk3tx.js → cli-h0djenzm.js} +2 -2
  64. package/dist/{cli-nrkkknat.js → cli-h37gbjbf.js} +2 -281
  65. package/dist/{cli-jevgrb4w.js → cli-h39xxnq6.js} +1200 -491
  66. package/dist/{cli-gz9sbyk3.js → cli-jepmgn7r.js} +1 -1
  67. package/dist/{cli-ccf9vy7q.js → cli-jmvk6et8.js} +7 -7
  68. package/dist/{cli-2rk0cx7s.js → cli-jxj92gkt.js} +51 -41
  69. package/dist/{cli-bqw0mt1n.js → cli-k46t4664.js} +18 -3
  70. package/dist/{cli-50vbt00w.js → cli-m07313tr.js} +1153 -696
  71. package/dist/{cli-4j2mrzag.js → cli-mkq1rk7b.js} +1 -1
  72. package/dist/{cli-1z7048dy.js → cli-mnm7w46e.js} +1 -1
  73. package/dist/{cli-kd1ck4rx.js → cli-mp9sg4cg.js} +14 -8
  74. package/dist/{cli-jbcva0xj.js → cli-mrammd8c.js} +60 -35
  75. package/dist/cli-nanaxrz6.js +27 -0
  76. package/dist/{cli-p9swy5t3.js → cli-pq2ee5ja.js} +8 -6
  77. package/dist/{cli-2wadx7p2.js → cli-pt43pdp1.js} +2 -2
  78. package/dist/{cli-7sgrxg9a.js → cli-q6d0vvey.js} +4 -4
  79. package/dist/{cli-k9qkf1hw.js → cli-qf9kpsve.js} +9 -9
  80. package/dist/cli-qh4sqfws.js +15 -0
  81. package/dist/{cli-e15jhafb.js → cli-qntkxysp.js} +14 -14
  82. package/dist/{cli-sajgpkqg.js → cli-qs9hhsvb.js} +1723 -325
  83. package/dist/{cli-z2zcxes1.js → cli-qt5bt3vk.js} +1 -1
  84. package/dist/{cli-wx82tw1k.js → cli-qtekrty1.js} +3 -3
  85. package/dist/{cli-g1re8r05.js → cli-rh6f3s9n.js} +3 -3
  86. package/dist/{cli-n0krnc6d.js → cli-rzhcrw2p.js} +2 -2
  87. package/dist/{cli-gecy3z2s.js → cli-snw62ze5.js} +4 -4
  88. package/dist/{cli-n6h8qt8n.js → cli-snz3p4yf.js} +15 -10
  89. package/dist/{cli-r6kqqbj0.js → cli-tkf8n6cw.js} +11 -11
  90. package/dist/{cli-4rkfg1wx.js → cli-tkrr24mz.js} +14 -9
  91. package/dist/{cli-9dr5qzc0.js → cli-tv9f1kyb.js} +54 -43
  92. package/dist/{cli-gm9cbhbq.js → cli-vtz6yj3v.js} +28 -9
  93. package/dist/{cli-2f07m0xr.js → cli-wf86d5t7.js} +1 -1
  94. package/dist/{cli-7zd05xb4.js → cli-whrvct19.js} +45 -45
  95. package/dist/{cli-ap1czx8f.js → cli-wrrea8xm.js} +3 -3
  96. package/dist/{cli-57khth04.js → cli-xmyqv00z.js} +120 -4
  97. package/dist/{cli-cwy5hqbq.js → cli-yjmk7tzc.js} +1 -1
  98. package/dist/{cli-6pcz9h15.js → cli-zykjrwcx.js} +180 -394
  99. package/dist/cli.js +45 -45
  100. package/dist/{codex-adapter-htjkn22b.js → codex-adapter-hsq6mz3m.js} +21 -19
  101. package/dist/{codex-hook-hq54t9ft.js → codex-hook-8c500gq8.js} +8 -7
  102. package/dist/{codex-login-z6yhbkmk.js → codex-login-x7603481.js} +3 -3
  103. package/dist/{codex-session-runner-wjfc7smz.js → codex-session-runner-c1x3x143.js} +15 -13
  104. package/dist/{commands-xhrfwqsk.js → commands-rwtddtst.js} +11 -9
  105. package/dist/{db-anvwb22f.js → db-j2b355vz.js} +458 -444
  106. package/dist/{devin-adapter-v1sarqtw.js → devin-adapter-8qmhqpy3.js} +3 -3
  107. package/dist/{devtools-2y1r7yqk.js → devtools-j2rnj8w7.js} +4 -4
  108. package/dist/{e2b-jdkwemv2.js → e2b-znpx78eg.js} +16 -16
  109. package/dist/{es5-vjgtkgp6.js → es5-fmqrjzy3.js} +2 -2
  110. package/dist/{event-bus-axn823e9.js → event-bus-n8sb35pw.js} +4 -4
  111. package/dist/{getMachineId-bsd-6tc9wxdj.js → getMachineId-bsd-wpzbhkm6.js} +4 -4
  112. package/dist/{getMachineId-darwin-sjt9sgnc.js → getMachineId-darwin-45zabjy0.js} +4 -4
  113. package/dist/{getMachineId-linux-v5n18y9p.js → getMachineId-linux-warnp5pd.js} +3 -3
  114. package/dist/{getMachineId-unsupported-yrjyqw3d.js → getMachineId-unsupported-5spent2a.js} +3 -3
  115. package/dist/{getMachineId-win-w3r8063c.js → getMachineId-win-v4bvcw7a.js} +4 -4
  116. package/dist/{google-generative-ai-hysrd8qx.js → google-generative-ai-b0wzss55.js} +17 -14
  117. package/dist/{google-vertex-p5arrga0.js → google-vertex-e8q4dpya.js} +18 -15
  118. package/dist/{handlers-b9kbc621.js → handlers-hchgrxkh.js} +32 -29
  119. package/dist/{hook-xkvn6c5h.js → hook-p49egqc0.js} +66 -52
  120. package/dist/hook-spb00w76.js +34 -0
  121. package/dist/{http-9xh6ta4r.js → http-nh14kkms.js} +663 -181
  122. package/dist/index-1qthq7vc.js +6 -0
  123. package/dist/{index-0g68f0p6.js → index-20xqmn3v.js} +3 -3
  124. package/dist/{index-vdkr5z2w.js → index-3e03k6e4.js} +114 -114
  125. package/dist/{index-ywds4812.js → index-4cbyhq2g.js} +43 -41
  126. package/dist/index-67pzqfrb.js +36 -0
  127. package/dist/{index-bccrkdkn.js → index-7m8yxkw5.js} +16 -16
  128. package/dist/{index-eaxyqcmj.js → index-dvsk64sm.js} +163 -83
  129. package/dist/{index-dqkpnmqm.js → index-e19s2m8k.js} +18 -18
  130. package/dist/{index-j30k5zxn.js → index-emvxcy98.js} +16 -16
  131. package/dist/{index-7ndw6ecy.js → index-gqnmr60d.js} +9 -9
  132. package/dist/{index-9znhar3x.js → index-j02xvjtd.js} +184 -185
  133. package/dist/{index-1s2442yw.js → index-ns5kksc1.js} +7 -7
  134. package/dist/{index-dpy2hth8.js → index-pdxc8kfh.js} +71 -71
  135. package/dist/{index-z1m7pw0v.js → index-ptcqm8bc.js} +107 -107
  136. package/dist/{index-070v4eyb.js → index-pyp7rexm.js} +5 -6
  137. package/dist/{index-86znjz1p.js → index-shne41sd.js} +13 -13
  138. package/dist/{index-2qn2qndv.js → index-t36q2v4t.js} +183 -183
  139. package/dist/index-tcnvv8w6.js +7 -0
  140. package/dist/index-w91qbfv1.js +7 -0
  141. package/dist/{index-fzc0mwvj.js → index-yqweff5n.js} +32 -32
  142. package/dist/index-yrfphye1.js +39 -0
  143. package/dist/{keepalive-vc7s2aa6.js → keepalive-9k51nqhc.js} +21 -15
  144. package/dist/lead-2xq3dxbz.js +88 -0
  145. package/dist/maintenance-0c0g6nym.js +28 -0
  146. package/dist/mistral-conversations-2njwdwhj.js +717 -0
  147. package/dist/{multipart-parser-qaktc7p8.js → multipart-parser-6gftesw0.js} +2 -2
  148. package/dist/{oauth-refresh-sweep-yecgjpk4.js → oauth-refresh-sweep-273a64r2.js} +14 -12
  149. package/dist/{onboard-xj0f73f9.js → onboard-tsv9wwhz.js} +12 -12
  150. package/dist/{openai-codex-responses-5g27pd6f.js → openai-codex-responses-kt84eq86.js} +26 -26
  151. package/dist/{openai-completions-3vkmfz2a.js → openai-completions-mrypq7qp.js} +17 -16
  152. package/dist/{openai-responses-dg4t7j7a.js → openai-responses-qhrk21ez.js} +20 -17
  153. package/dist/{opencode-adapter-1gm38aba.js → opencode-adapter-rar9676j.js} +13 -11
  154. package/dist/{openrouter-images-g3gm8931.js → openrouter-images-684fysx9.js} +5 -5
  155. package/dist/{otel-impl-nxg0n0b3.js → otel-impl-wp1mfzd2.js} +752 -537
  156. package/dist/{photon_rs-ky7dj5qw.js → photon_rs-8dwt2pzy.js} +581 -581
  157. package/dist/{pi-messages-tqj8q6b9.js → pi-messages-txp9f97r.js} +7 -7
  158. package/dist/{pi-mono-adapter-4g5kby31.js → pi-mono-adapter-yz47kk8e.js} +1910 -1180
  159. package/dist/pricing-refresh-jw1yw2fn.js +22 -0
  160. package/dist/rbac-roles-dg964c8p.js +32 -0
  161. package/dist/{rbac-roles-1hcxdtg7.js → rbac-roles-p53cg5cv.js} +19 -17
  162. package/dist/{registry-02cy9z5z.js → registry-mh12y17v.js} +4 -4
  163. package/dist/render-v2-56vn2rk9.js +36 -0
  164. package/dist/seed-pricing-52xx6z63.js +19 -0
  165. package/dist/{setup-46xtgq3c.js → setup-e8gp79sy.js} +7 -7
  166. package/dist/token-util-zy908s1a.js +6 -0
  167. package/dist/{token-fxkn2zf2.js → token-xg5711x5.js} +4 -4
  168. package/dist/worker-s17f1g46.js +88 -0
  169. package/dist/{x-6mg4kfpe.js → x-xkfh0w0v.js} +5 -5
  170. package/openapi.json +566 -22
  171. package/package.json +6 -6
  172. package/src/be/budget-refusal-notify.ts +14 -7
  173. package/src/be/db-queries/task-artifacts.ts +182 -0
  174. package/src/be/db.ts +834 -171
  175. package/src/be/events.ts +5 -0
  176. package/src/be/migrations/131_session_logs_created_at_index.sql +2 -0
  177. package/src/be/migrations/132_multi_runtime_instances.sql +44 -0
  178. package/src/be/migrations/133_workflow_run_trigger_type.sql +12 -0
  179. package/src/be/migrations/135_backfill_task_pull_request_attachments.sql +228 -0
  180. package/src/be/migrations/136_task_requester_provenance.sql +37 -0
  181. package/src/be/migrations/137_memory_retrieval_composite_index.sql +1 -0
  182. package/src/be/migrations/runner.ts +17 -11
  183. package/src/be/multi-runtime.ts +430 -0
  184. package/src/be/scripts/extract-schema.ts +3 -1
  185. package/src/be/scripts/typecheck.ts +6 -2
  186. package/src/be/seed-prompt-templates.ts +25 -2
  187. package/src/be/seed-skills/index.ts +7 -0
  188. package/src/be/steering.ts +1 -1
  189. package/src/be/swarm-config-guard.ts +18 -0
  190. package/src/commands/credential-wait.ts +54 -0
  191. package/src/commands/onboard/steps/core-credentials.tsx +1 -1
  192. package/src/commands/onboard/steps/custom-templates.tsx +1 -1
  193. package/src/commands/onboard/steps/harness-credentials.tsx +1 -1
  194. package/src/commands/onboard/steps/health-check.tsx +1 -1
  195. package/src/commands/onboard/steps/start.tsx +1 -1
  196. package/src/commands/profile-sync-audit.ts +56 -0
  197. package/src/commands/profile-sync.ts +287 -15
  198. package/src/commands/provider-credentials.ts +46 -19
  199. package/src/commands/runner.ts +199 -33
  200. package/src/commands/templates.ts +22 -0
  201. package/src/github/handlers.ts +55 -9
  202. package/src/heartbeat/heartbeat.ts +109 -17
  203. package/src/hooks/hook.ts +49 -33
  204. package/src/http/active-sessions.ts +11 -1
  205. package/src/http/agents.ts +261 -30
  206. package/src/http/all-routes.ts +1 -0
  207. package/src/http/config.ts +13 -2
  208. package/src/http/core.ts +102 -4
  209. package/src/http/db-query-bounded.ts +313 -0
  210. package/src/http/db-query-shared.ts +249 -0
  211. package/src/http/db-query.ts +54 -42
  212. package/src/http/events.ts +2 -0
  213. package/src/http/index.ts +23 -2
  214. package/src/http/mcp-bridge.ts +37 -3
  215. package/src/http/mcp.ts +12 -0
  216. package/src/http/memory.ts +13 -2
  217. package/src/http/openapi.ts +1 -0
  218. package/src/http/poll.ts +70 -27
  219. package/src/http/prompt-templates.ts +36 -13
  220. package/src/http/route-def.ts +43 -9
  221. package/src/http/schedules.ts +2 -2
  222. package/src/http/scripts.ts +10 -1
  223. package/src/http/session-data.ts +44 -0
  224. package/src/http/tasks.ts +2 -2
  225. package/src/http/users.ts +74 -52
  226. package/src/http/webhooks.ts +5 -2
  227. package/src/http/workflows.ts +1 -4
  228. package/src/integrations/kapso/inbound.ts +1 -1
  229. package/src/jira/outbound.ts +39 -8
  230. package/src/jira/webhook-lifecycle.ts +13 -2
  231. package/src/linear/outbound.ts +43 -10
  232. package/src/oauth/keepalive.ts +13 -2
  233. package/src/prompts/base-prompt.ts +1 -1
  234. package/src/prompts/default-drift.ts +21 -0
  235. package/src/prompts/session-templates.ts +56 -7
  236. package/src/providers/claude-adapter.ts +6 -0
  237. package/src/providers/codex-adapter.ts +6 -0
  238. package/src/providers/opencode-adapter.ts +6 -0
  239. package/src/providers/pi-mono-adapter.ts +8 -0
  240. package/src/providers/pricing-sources.md +24 -0
  241. package/src/queue-stall-alarm.ts +216 -0
  242. package/src/rbac/legacy-policy.ts +3 -0
  243. package/src/rbac/permissions.ts +12 -0
  244. package/src/scheduler/scheduler.ts +7 -0
  245. package/src/script-workflows/executor.ts +2 -1
  246. package/src/scripts-runtime/executors/native.ts +2 -1
  247. package/src/scripts-runtime/executors/types.ts +5 -0
  248. package/src/scripts-runtime/loader.ts +5 -0
  249. package/src/scripts-runtime/sdk-allowlist.ts +3 -0
  250. package/src/scripts-runtime/swarm-config.ts +8 -0
  251. package/src/scripts-runtime/swarm-sdk.ts +7 -0
  252. package/src/scripts-runtime/types/stdlib.d.ts +4 -0
  253. package/src/scripts-runtime/types/swarm-sdk.d.ts +4 -0
  254. package/src/server.ts +6 -0
  255. package/src/slack/channel-join.ts +22 -3
  256. package/src/slack/channel-lifecycle.ts +114 -0
  257. package/src/tests/budget-claim-gate.test.ts +20 -0
  258. package/src/tests/claude-adapter.test.ts +32 -0
  259. package/src/tests/codex-adapter.test.ts +30 -0
  260. package/src/tests/create-task-validation.test.ts +128 -0
  261. package/src/tests/credential-wait.test.ts +67 -1
  262. package/src/tests/db-query.test.ts +711 -2
  263. package/src/tests/heartbeat-checklist.test.ts +28 -0
  264. package/src/tests/http-api-integration.test.ts +81 -0
  265. package/src/tests/http-users.test.ts +166 -1
  266. package/src/tests/identity-field-budget.test.ts +176 -0
  267. package/src/tests/mcp-tools-user.test.ts +34 -0
  268. package/src/tests/mcp-user-route.test.ts +17 -0
  269. package/src/tests/metrics-http.test.ts +44 -0
  270. package/src/tests/migration-failure.test.ts +86 -0
  271. package/src/tests/multi-runtime-registration.test.ts +2810 -0
  272. package/src/tests/openapi-response-contract.test.ts +24 -0
  273. package/src/tests/openapi-route-headers.test.ts +83 -0
  274. package/src/tests/opencode-adapter.test.ts +40 -0
  275. package/src/tests/outbound-listener-rejection.test.ts +138 -0
  276. package/src/tests/pi-mono-adapter.test.ts +98 -0
  277. package/src/tests/preload.ts +2 -0
  278. package/src/tests/profile-sync-warning.test.ts +277 -0
  279. package/src/tests/profile-sync.test.ts +232 -6
  280. package/src/tests/prompt-template-resolver.test.ts +177 -6
  281. package/src/tests/prompt-template-session.test.ts +39 -3
  282. package/src/tests/queue-stall-alarm.test.ts +226 -0
  283. package/src/tests/rbac-charact-slack.test.ts +29 -0
  284. package/src/tests/rbac-engine.test.ts +3 -0
  285. package/src/tests/requester-comms.test.ts +32 -0
  286. package/src/tests/runner-requester-profile.test.ts +38 -0
  287. package/src/tests/schedule-target-type.test.ts +38 -0
  288. package/src/tests/script-connections.test.ts +13 -1
  289. package/src/tests/scripts-runtime-identity.test.ts +375 -0
  290. package/src/tests/scripts-runtime.test.ts +4 -3
  291. package/src/tests/sdk-allowlist.test.ts +47 -0
  292. package/src/tests/send-task-requested-by.test.ts +9 -0
  293. package/src/tests/session-costs.test.ts +506 -1
  294. package/src/tests/shutdown-error-scrubbing.test.ts +92 -0
  295. package/src/tests/slack-channel-lifecycle.test.ts +241 -0
  296. package/src/tests/slack-render-v2.test.ts +43 -0
  297. package/src/tests/steering-core.test.ts +28 -0
  298. package/src/tests/swarm-config-reserved-keys.test.ts +22 -0
  299. package/src/tests/task-artifacts.test.ts +386 -0
  300. package/src/tests/task-attachments-schema.test.ts +17 -1
  301. package/src/tests/task-completion-idempotency.test.ts +57 -0
  302. package/src/tests/task-pull-request-backfill-migration.test.ts +321 -0
  303. package/src/tests/tool-annotations.test.ts +4 -0
  304. package/src/tests/update-profile-api.test.ts +67 -39
  305. package/src/tests/update-profile-auth.test.ts +48 -4
  306. package/src/tests/user-attribution-migration.test.ts +54 -0
  307. package/src/tests/user-identity.test.ts +72 -0
  308. package/src/tests/workflow-async-v2.test.ts +39 -1
  309. package/src/tests/workflow-http-v2.test.ts +3 -2
  310. package/src/tests/workflow-mcp-trigger-schema.test.ts +52 -3
  311. package/src/tests/workflow-retry-v2.test.ts +45 -1
  312. package/src/tools/db-query.ts +18 -8
  313. package/src/tools/get-task-details.ts +24 -3
  314. package/src/tools/manage-user.ts +36 -3
  315. package/src/tools/poll-task.ts +93 -14
  316. package/src/tools/script-common.ts +5 -0
  317. package/src/tools/send-task.ts +1 -4
  318. package/src/tools/slack-archive-channel.ts +70 -0
  319. package/src/tools/slack-create-channel.ts +74 -0
  320. package/src/tools/slack-invite-to-channel.ts +78 -0
  321. package/src/tools/store-progress.ts +13 -2
  322. package/src/tools/swarm-config/delete-config.ts +9 -0
  323. package/src/tools/swarm-config/set-config.ts +3 -2
  324. package/src/tools/task-action.ts +30 -0
  325. package/src/tools/task-tool-ctx.ts +8 -1
  326. package/src/tools/tool-config.ts +4 -1
  327. package/src/tools/update-profile.ts +16 -21
  328. package/src/tools/utils.ts +5 -0
  329. package/src/tools/workflows/trigger-workflow.ts +7 -1
  330. package/src/types.ts +165 -1
  331. package/src/utils/github-pull-request.ts +76 -0
  332. package/src/utils/identity-field-budget.ts +73 -0
  333. package/src/utils/multi-runtime.ts +20 -0
  334. package/src/utils/requester-comms.ts +24 -0
  335. package/src/workflows/engine.ts +22 -2
  336. package/src/workflows/resume.ts +19 -11
  337. package/src/workflows/retry-poller.ts +1 -0
  338. package/src/workflows/triggers.ts +4 -0
  339. package/templates/skills/db-query-guidance/config.json +14 -0
  340. package/templates/skills/db-query-guidance/content.md +57 -0
  341. package/dist/app-5da78bd4.js +0 -26
  342. package/dist/cli-3te4jdkm.js +0 -225
  343. package/dist/cli-bmze986d.js +0 -7
  344. package/dist/cli-kh3ba2zf.js +0 -607
  345. package/dist/hook-cgk4wxmx.js +0 -31
  346. package/dist/index-25wjsdv2.js +0 -34
  347. package/dist/index-76at2ymp.js +0 -7
  348. package/dist/index-hase6zbe.js +0 -6
  349. package/dist/index-vg4snay4.js +0 -36
  350. package/dist/index-vy8edt27.js +0 -7
  351. package/dist/lead-r2yqfmx7.js +0 -85
  352. package/dist/maintenance-mw70k468.js +0 -26
  353. package/dist/mistral-conversations-81fwav0j.js +0 -30578
  354. package/dist/otel-nqa12wf3.js +0 -3149
  355. package/dist/pricing-refresh-2cn6effr.js +0 -20
  356. package/dist/rbac-roles-vynday5g.js +0 -30
  357. package/dist/render-v2-tc0bh8kk.js +0 -34
  358. package/dist/seed-pricing-8kceb43f.js +0 -17
  359. package/dist/token-util-pqyc8kng.js +0 -6
  360. package/dist/worker-qrbz6hmv.js +0 -85
@@ -0,0 +1,241 @@
1
+ import { afterAll, beforeAll, describe, expect, mock, test } from "bun:test";
2
+ import { unlink } from "node:fs/promises";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import type { WebClient } from "@slack/web-api";
5
+ import { closeDb, createAgent, initDb } from "../be/db";
6
+ import {
7
+ archiveChannel,
8
+ createChannel,
9
+ inviteToChannel,
10
+ normalizeChannelName,
11
+ } from "../slack/channel-lifecycle";
12
+ import { registerSlackArchiveChannelTool } from "../tools/slack-archive-channel";
13
+ import { registerSlackCreateChannelTool } from "../tools/slack-create-channel";
14
+ import { registerSlackInviteToChannelTool } from "../tools/slack-invite-to-channel";
15
+
16
+ const TEST_DB_PATH = "./test-slack-channel-lifecycle.sqlite";
17
+ const LEAD_ID = "aaaaaaaa-0000-4000-8000-000000000121";
18
+
19
+ const mockCreate = mock(() => Promise.resolve({ channel: { id: "C123", name: "project-alpha" } }));
20
+ const mockInvite = mock(() => Promise.resolve({ ok: true }));
21
+ const mockArchive = mock(() => Promise.resolve({ ok: true }));
22
+
23
+ mock.module("../slack/app", () => ({
24
+ getSlackApp: () => ({
25
+ client: {
26
+ conversations: {
27
+ create: mockCreate,
28
+ invite: mockInvite,
29
+ archive: mockArchive,
30
+ },
31
+ },
32
+ }),
33
+ }));
34
+
35
+ function makePlatformError(code: string, needed?: string): Error {
36
+ const error = new Error(`An API error occurred: ${code}`);
37
+ (error as unknown as { data: { error: string; needed?: string } }).data = { error: code, needed };
38
+ return error;
39
+ }
40
+
41
+ function makeClient(
42
+ overrides: { create?: () => unknown; invite?: () => unknown; archive?: () => unknown } = {},
43
+ ) {
44
+ const create = mock(
45
+ overrides.create ?? (() => Promise.resolve({ channel: { id: "C123", name: "project-alpha" } })),
46
+ );
47
+ const invite = mock(overrides.invite ?? (() => Promise.resolve({ ok: true })));
48
+ const archive = mock(overrides.archive ?? (() => Promise.resolve({ ok: true })));
49
+ const client = { conversations: { create, invite, archive } } as unknown as WebClient;
50
+
51
+ return { client, create, invite, archive };
52
+ }
53
+
54
+ type RegisteredTool = {
55
+ handler: (
56
+ args: unknown,
57
+ extra: unknown,
58
+ ) => Promise<{ isError?: boolean; structuredContent: { success: boolean; message: string } }>;
59
+ };
60
+
61
+ let tools: Record<string, RegisteredTool>;
62
+
63
+ async function removeDbFiles(): Promise<void> {
64
+ for (const suffix of ["", "-wal", "-shm"]) {
65
+ try {
66
+ await unlink(TEST_DB_PATH + suffix);
67
+ } catch (error) {
68
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
69
+ }
70
+ }
71
+ }
72
+
73
+ async function callTool(name: string, args: Record<string, unknown>) {
74
+ const tool = tools[name];
75
+ if (!tool) throw new Error(`Tool not registered: ${name}`);
76
+
77
+ return tool.handler(args, {
78
+ sessionId: "slack-channel-lifecycle-test",
79
+ requestInfo: { headers: { "x-agent-id": LEAD_ID } },
80
+ });
81
+ }
82
+
83
+ beforeAll(async () => {
84
+ await removeDbFiles();
85
+ closeDb();
86
+ initDb(TEST_DB_PATH);
87
+ createAgent({ id: LEAD_ID, name: "Slack Lifecycle Lead", isLead: true, status: "idle" });
88
+
89
+ const server = new McpServer({ name: "slack-channel-lifecycle-test", version: "1.0.0" });
90
+ registerSlackCreateChannelTool(server);
91
+ registerSlackInviteToChannelTool(server);
92
+ registerSlackArchiveChannelTool(server);
93
+ tools = (server as unknown as { _registeredTools: Record<string, RegisteredTool> })
94
+ ._registeredTools;
95
+ });
96
+
97
+ afterAll(async () => {
98
+ closeDb();
99
+ await removeDbFiles();
100
+ });
101
+
102
+ describe("Slack channel lifecycle", () => {
103
+ test("normalizes channel names to Slack's naming rules", () => {
104
+ expect(normalizeChannelName(" Project.Alpha / Launch! ")).toBe("project-alpha-launch");
105
+ expect(normalizeChannelName(`A${"B".repeat(100)}`)).toHaveLength(80);
106
+ });
107
+
108
+ test("rejects a name that normalizes to an empty value", () => {
109
+ expect(() => normalizeChannelName("... !!!")).toThrow("at least one letter or number");
110
+ });
111
+
112
+ test("creates a channel with the normalized name and returns it", async () => {
113
+ const { client, create } = makeClient();
114
+
115
+ const result = await createChannel(client, { name: "Project.Alpha", isPrivate: true });
116
+
117
+ expect(result).toEqual({ channelId: "C123", name: "project-alpha" });
118
+ expect(create).toHaveBeenCalledWith({ name: "project-alpha", is_private: true });
119
+ });
120
+
121
+ test("surfaces name_taken with the normalized name", async () => {
122
+ const { client } = makeClient({
123
+ create: () => {
124
+ throw makePlatformError("name_taken");
125
+ },
126
+ });
127
+
128
+ await expect(createChannel(client, { name: "Project.Alpha" })).rejects.toThrow(
129
+ 'Slack channel name "project-alpha" is already taken.',
130
+ );
131
+ });
132
+
133
+ test("treats already_in_channel as invite success", async () => {
134
+ const { client, invite } = makeClient({
135
+ invite: () => {
136
+ throw makePlatformError("already_in_channel");
137
+ },
138
+ });
139
+
140
+ const result = await inviteToChannel(client, "C123", ["U1", "U2"]);
141
+
142
+ expect(result).toEqual({ alreadyInChannel: true });
143
+ expect(invite).toHaveBeenCalledTimes(3);
144
+ expect(invite).toHaveBeenNthCalledWith(1, { channel: "C123", users: "U1,U2" });
145
+ expect(invite).toHaveBeenNthCalledWith(2, { channel: "C123", users: "U1" });
146
+ expect(invite).toHaveBeenNthCalledWith(3, { channel: "C123", users: "U2" });
147
+ });
148
+
149
+ test("retries a mixed already_in_channel batch so new users are still invited", async () => {
150
+ const inviteResults = [
151
+ () => {
152
+ throw makePlatformError("already_in_channel");
153
+ },
154
+ () => {
155
+ throw makePlatformError("already_in_channel");
156
+ },
157
+ () => Promise.resolve({ ok: true }),
158
+ ];
159
+ const { client, invite } = makeClient({
160
+ invite: () => inviteResults.shift()?.(),
161
+ });
162
+
163
+ const result = await inviteToChannel(client, "C123", ["U1", "U2"]);
164
+
165
+ expect(result).toEqual({ alreadyInChannel: false });
166
+ expect(invite).toHaveBeenNthCalledWith(2, { channel: "C123", users: "U1" });
167
+ expect(invite).toHaveBeenNthCalledWith(3, { channel: "C123", users: "U2" });
168
+ });
169
+
170
+ test("treats already_archived as archive success", async () => {
171
+ const { client, archive } = makeClient({
172
+ archive: () => {
173
+ throw makePlatformError("already_archived");
174
+ },
175
+ });
176
+
177
+ const result = await archiveChannel(client, "C123");
178
+
179
+ expect(result).toEqual({ alreadyArchived: true });
180
+ expect(archive).toHaveBeenCalledWith({ channel: "C123" });
181
+ });
182
+
183
+ test("explains that Slack's general channel cannot be archived", async () => {
184
+ const { client } = makeClient({
185
+ archive: () => {
186
+ throw makePlatformError("cant_archive_general");
187
+ },
188
+ });
189
+
190
+ await expect(archiveChannel(client, "CGENERAL")).rejects.toThrow(
191
+ "Slack's general channel cannot be archived.",
192
+ );
193
+ });
194
+ });
195
+
196
+ describe("Slack channel lifecycle tool scope errors", () => {
197
+ test("create names Slack's required scope and the reinstall step", async () => {
198
+ mockCreate.mockImplementationOnce(() =>
199
+ Promise.reject(makePlatformError("missing_scope", "channels:manage")),
200
+ );
201
+
202
+ const result = await callTool("slack-create-channel", { name: "project-alpha" });
203
+
204
+ expect(result.isError).toBe(true);
205
+ expect(result.structuredContent.success).toBe(false);
206
+ expect(result.structuredContent.message).toBe(
207
+ "Failed to create Slack channel: Slack requires the `channels:manage` scope. Add it to slack-manifest.json, apply the updated manifest to the Slack app, then reinstall the app to the workspace for the change to take effect.",
208
+ );
209
+ });
210
+
211
+ test("invite names Slack's required scope and the reinstall step", async () => {
212
+ mockInvite.mockImplementationOnce(() =>
213
+ Promise.reject(makePlatformError("missing_scope", "groups:write")),
214
+ );
215
+
216
+ const result = await callTool("slack-invite-to-channel", {
217
+ channelId: "G123",
218
+ userIds: ["U123"],
219
+ });
220
+
221
+ expect(result.isError).toBe(true);
222
+ expect(result.structuredContent.success).toBe(false);
223
+ expect(result.structuredContent.message).toBe(
224
+ "Failed to invite users to Slack channel: Slack requires the `groups:write` scope. Add it to slack-manifest.json, apply the updated manifest to the Slack app, then reinstall the app to the workspace for the change to take effect.",
225
+ );
226
+ });
227
+
228
+ test("archive names Slack's required scope and the reinstall step", async () => {
229
+ mockArchive.mockImplementationOnce(() =>
230
+ Promise.reject(makePlatformError("missing_scope", "channels:manage")),
231
+ );
232
+
233
+ const result = await callTool("slack-archive-channel", { channelId: "C123" });
234
+
235
+ expect(result.isError).toBe(true);
236
+ expect(result.structuredContent.success).toBe(false);
237
+ expect(result.structuredContent.message).toBe(
238
+ "Failed to archive Slack channel: Slack requires the `channels:manage` scope. Add it to slack-manifest.json, apply the updated manifest to the Slack app, then reinstall the app to the workspace for the change to take effect.",
239
+ );
240
+ });
241
+ });
@@ -19,6 +19,7 @@ import {
19
19
  isPendingSlackMessage,
20
20
  markTaskSlackReplySent,
21
21
  startTask,
22
+ upsertSwarmConfig,
22
23
  } from "../be/db";
23
24
  import { getTaskLink, MAX_SECTION_LENGTH } from "../slack/blocks";
24
25
  import {
@@ -33,6 +34,7 @@ import {
33
34
  } from "../slack/render-v2";
34
35
  import { getAgentDisplayName, getAgentEmoji } from "../slack/responses";
35
36
  import { slackContextKey } from "../tasks/context-key";
37
+ import { clearVolatileSecretsForTesting } from "../utils/secret-scrubber";
36
38
 
37
39
  const TEST_DB_PATH = "./test-slack-render-v2.sqlite";
38
40
  const calls: Array<{ method: string; payload: Record<string, unknown> }> = [];
@@ -224,6 +226,7 @@ beforeAll(() => {
224
226
  });
225
227
 
226
228
  beforeEach(async () => {
229
+ clearVolatileSecretsForTesting();
227
230
  closeDb();
228
231
  await removeDbFiles();
229
232
  initDb(TEST_DB_PATH);
@@ -1412,6 +1415,46 @@ describe("Slack renderer v2", () => {
1412
1415
  );
1413
1416
  });
1414
1417
 
1418
+ test("redacts a runtime-rotated config secret from persisted output and its Slack outcome", async () => {
1419
+ const lead = createAgent({ name: "Rotating Secret Lead", isLead: true, status: "idle" });
1420
+ const { channelId, threadTs } = uniqueSlackAddress("C_RENDER_ROTATED_SECRET");
1421
+ const ask = createTaskExtended("rotate a secret before completing", {
1422
+ agentId: lead.id,
1423
+ source: "slack",
1424
+ slackChannelId: channelId,
1425
+ slackThreadTs: threadTs,
1426
+ contextKey: slackContextKey({ channelId, threadTs }),
1427
+ });
1428
+ const secret = `rotated-directory-token-${crypto.randomUUID()}`;
1429
+ const redacted = "[REDACTED:config:AUTOINFRA_DIRECTORY_ACCESS_VALUE]";
1430
+
1431
+ upsertSwarmConfig({
1432
+ scope: "global",
1433
+ key: "AUTOINFRA_DIRECTORY_ACCESS_VALUE",
1434
+ value: secret,
1435
+ isSecret: true,
1436
+ });
1437
+ startTask(ask.id);
1438
+ await ensureSlackThreadTree([ask.id]);
1439
+ completeTask(ask.id, `Artifact: https://example.test/downloads/${secret}/result.json`);
1440
+
1441
+ const persistedOutput = getTaskById(ask.id)?.output;
1442
+ expect(persistedOutput).toBe(
1443
+ `Artifact: https://example.test/downloads/${redacted}/result.json`,
1444
+ );
1445
+ expect(persistedOutput).not.toContain(secret);
1446
+
1447
+ calls.length = 0;
1448
+ _resetSlackRenderV2ForTests();
1449
+ await processSlackRenderV2();
1450
+
1451
+ const started = calls.find((call) => call.method === "chat.startStream");
1452
+ expect(started?.payload.markdown_text).toBe(
1453
+ `✅\n\nArtifact: https://example.test/downloads/${redacted}/result.json`,
1454
+ );
1455
+ expect(started?.payload.markdown_text).not.toContain(secret);
1456
+ });
1457
+
1415
1458
  test("re-reads slackReplySent inside streamOutcomeCard to avoid a stale caller snapshot", async () => {
1416
1459
  const lead = createAgent({ name: "Stale Snapshot Lead", isLead: true, status: "idle" });
1417
1460
  const { channelId, threadTs } = uniqueSlackAddress("C_RENDER_STALE_SNAPSHOT");
@@ -12,7 +12,9 @@ import {
12
12
  createAgent,
13
13
  createSteeringMessage,
14
14
  createTaskExtended,
15
+ createUser,
15
16
  getChildTasks,
17
+ getDb,
16
18
  getLatestLeadTaskInThread,
17
19
  getPendingSteeringForAgent,
18
20
  getSteeringMessageById,
@@ -246,6 +248,32 @@ describe("task steering core", () => {
246
248
  });
247
249
  });
248
250
 
251
+ test("automatic promotion preserves inherited requester provenance", () => {
252
+ const user = createUser({ name: "Steering provenance requester" });
253
+ const parent = createTaskExtended("heartbeat steering parent", {
254
+ agentId: agentIds.get("codex"),
255
+ taskType: "heartbeat-checklist",
256
+ requestedByUserId: user.id,
257
+ });
258
+ expect(startTask(parent.id)?.status).toBe("in_progress");
259
+
260
+ const result = requestSteering({
261
+ taskId: parent.id,
262
+ message: "promote autonomous steering",
263
+ source: "api",
264
+ createdByKind: "agent",
265
+ createdByAgentId: agentIds.get("lead"),
266
+ });
267
+ const promoted = markSteeringUndeliverable(result.steeringMessageId, "session died");
268
+ expect(getTaskById(promoted.promotedTaskId!)?.requestedByUserId).toBe(user.id);
269
+ const provenance = getDb()
270
+ .query<{ inherited: number }, [string]>(
271
+ "SELECT requestedByUserIdInherited AS inherited FROM agent_tasks WHERE id = ?",
272
+ )
273
+ .get(promoted.promotedTaskId!);
274
+ expect(provenance?.inherited).toBe(1);
275
+ });
276
+
249
277
  test("claude steer requests degrade to queue while preserving requested mode", () => {
250
278
  const task = runningTask("claude", "claude degrade");
251
279
  const result = requestSteering({
@@ -19,6 +19,7 @@ import { registerDeleteConfigTool } from "../tools/swarm-config/delete-config";
19
19
  import { registerListConfigTool } from "../tools/swarm-config/list-config";
20
20
  import { registerSetConfigTool } from "../tools/swarm-config/set-config";
21
21
  import { setRequestAuth } from "../utils/request-auth-context";
22
+ import { clearVolatileSecretsForTesting, scrubSecrets } from "../utils/secret-scrubber";
22
23
 
23
24
  const TEST_DB_PATH = "./test-swarm-config-reserved-keys.sqlite";
24
25
  const TEST_PORT = 13047;
@@ -126,6 +127,7 @@ describe("swarm-config reserved keys guard", () => {
126
127
  });
127
128
 
128
129
  afterAll(async () => {
130
+ clearVolatileSecretsForTesting();
129
131
  server.close();
130
132
  closeDb();
131
133
  await unlink(TEST_DB_PATH).catch(() => {});
@@ -282,6 +284,26 @@ describe("swarm-config reserved keys guard", () => {
282
284
  expect(result.structuredContent.success).toBe(true);
283
285
  });
284
286
 
287
+ test("immediately redacts a newly set secret config value", async () => {
288
+ clearVolatileSecretsForTesting();
289
+ const handler = mcpServer.handlers.get("set-config");
290
+ const value = `rotated-directory-token-${crypto.randomUUID()}`;
291
+ const result = (await handler!(
292
+ {
293
+ scope: "global",
294
+ key: "AUTOINFRA_DIRECTORY_ACCESS_VALUE",
295
+ value,
296
+ isSecret: true,
297
+ },
298
+ makeRequestInfo(),
299
+ )) as { structuredContent: { success: boolean } };
300
+
301
+ expect(result.structuredContent.success).toBe(true);
302
+ expect(scrubSecrets(`https://example.test/downloads/${value}/artifact`)).toBe(
303
+ "https://example.test/downloads/[REDACTED:config:AUTOINFRA_DIRECTORY_ACCESS_VALUE]/artifact",
304
+ );
305
+ });
306
+
285
307
  test("rejects arbitrary config writes from non-lead set-config callers", async () => {
286
308
  const worker = createAgent({
287
309
  name: "config-worker",