@desplega.ai/agent-swarm 1.173.0 → 2.1.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 (511) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-kr4abrsk.js} +17 -16
  3. package/dist/{actions-sgeyv08k.js → actions-eh4g6w2r.js} +39 -34
  4. package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-7h7wdt8q.js} +8 -7
  5. package/dist/{app-km9qnv2f.js → app-7k8s9w5p.js} +18 -14
  6. package/dist/{assistant-5r8tcvvd.js → assistant-wswt2y7p.js} +40 -35
  7. package/dist/{boot-reembed-16rv9843.js → boot-reembed-9apm9qw6.js} +10 -9
  8. package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-whzbdthj.js} +10 -9
  9. package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-ndzmvmgt.js} +11 -10
  10. package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-e9sta0yt.js} +16 -13
  11. package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-4mqd3r6r.js} +19 -18
  12. package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-9wswb52m.js} +7 -5
  13. package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-tpe1effx.js} +6 -4
  14. package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-q49ghmh9.js} +12402 -11850
  15. package/dist/{cli-ne7smj1b.js → cli-01xvj1rq.js} +10 -10
  16. package/dist/{cli-nwrdx840.js → cli-035vekcw.js} +3 -3
  17. package/dist/{cli-9xf7fdtp.js → cli-0pd8hzhc.js} +29 -6
  18. package/dist/{cli-tmhsxhb8.js → cli-0veb92a3.js} +28 -6
  19. package/dist/{cli-c3rk1v0x.js → cli-10jesr25.js} +3 -3
  20. package/dist/{cli-6thk4jz3.js → cli-1y7yywmj.js} +6 -6
  21. package/dist/{cli-6r2f7edk.js → cli-20krdhz5.js} +47 -19
  22. package/dist/{cli-rfs4vddv.js → cli-29rja109.js} +39 -20
  23. package/dist/cli-2m1ktfzz.js +17795 -0
  24. package/dist/{cli-na2pxe4f.js → cli-2pwa0q4d.js} +15 -4
  25. package/dist/{cli-7a93cv8c.js → cli-4mengw46.js} +441 -43
  26. package/dist/{cli-94b48jhk.js → cli-5twdke5x.js} +16 -14
  27. package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
  28. package/dist/cli-6cvfxs8r.js +47 -0
  29. package/dist/{cli-w1apjecb.js → cli-711vwbxn.js} +2 -2
  30. package/dist/{cli-r4fqfpwf.js → cli-78vv7446.js} +50 -27
  31. package/dist/{cli-srqq3gc5.js → cli-7n6s5man.js} +5 -5
  32. package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
  33. package/dist/{cli-2bw3w47j.js → cli-8wwxw8a3.js} +1 -1
  34. package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
  35. package/dist/{cli-ywm1azg9.js → cli-9jzdj90z.js} +8 -4
  36. package/dist/cli-9traj3dn.js +638 -0
  37. package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
  38. package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
  39. package/dist/cli-cvv9k0hh.js +10143 -0
  40. package/dist/{cli-anzdk0z4.js → cli-d9286m9h.js} +2 -2
  41. package/dist/cli-e3g5mbkz.js +776 -0
  42. package/dist/cli-f527ce74.js +781 -0
  43. package/dist/{cli-gmdajfw5.js → cli-gxzkg1de.js} +5020 -1729
  44. package/dist/{cli-451ks6aw.js → cli-h1arqn31.js} +1 -1
  45. package/dist/cli-hjwmhcg1.js +10622 -0
  46. package/dist/{cli-jpc4r224.js → cli-hqr88ew6.js} +19 -3
  47. package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
  48. package/dist/{cli-cd0hv9nh.js → cli-j67mh2vg.js} +2 -2
  49. package/dist/cli-jta2eyzc.js +619 -0
  50. package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
  51. package/dist/cli-kceah1eh.js +92 -0
  52. package/dist/{cli-d603qf86.js → cli-ksphgh48.js} +10 -8
  53. package/dist/{cli-3nxdmjrc.js → cli-mgz4nbgg.js} +4 -4
  54. package/dist/{cli-saqyage0.js → cli-mz5as5ha.js} +179 -27
  55. package/dist/cli-n2wq4j7m.js +6985 -0
  56. package/dist/{cli-ppy4nnnh.js → cli-n8ndw8j7.js} +2 -2
  57. package/dist/{cli-1w0vj3gw.js → cli-naqzr17j.js} +7 -7
  58. package/dist/{cli-0a7mm3zp.js → cli-nm1p8jfr.js} +25 -21
  59. package/dist/{cli-wrh08zjd.js → cli-p3zbc1rw.js} +5 -18
  60. package/dist/{cli-hsem16hb.js → cli-pe05f8yk.js} +29 -6
  61. package/dist/{cli-5wpw4rab.js → cli-qmzsbkvy.js} +5 -5
  62. package/dist/{cli-bv2etw2y.js → cli-qnm4e9e4.js} +99 -590
  63. package/dist/{cli-1x7da0de.js → cli-qqy4q48b.js} +8 -8
  64. package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
  65. package/dist/{cli-5er5gjbm.js → cli-r35rw5de.js} +15 -15
  66. package/dist/{cli-v3zhnxsb.js → cli-r610p9bs.js} +2 -2
  67. package/dist/{cli-7jykv7ef.js → cli-rc6pf5kv.js} +1 -1
  68. package/dist/{cli-x119kdba.js → cli-rdxm77k3.js} +1 -1
  69. package/dist/cli-rhs9pz33.js +294 -0
  70. package/dist/{cli-0p3enk35.js → cli-s69nfyeh.js} +9 -1
  71. package/dist/{cli-0kxf81jj.js → cli-sawv63e8.js} +2 -2
  72. package/dist/{cli-e3pmyt39.js → cli-sg19gbf0.js} +1 -1
  73. package/dist/{cli-d161g69q.js → cli-shk7r5cs.js} +57 -6
  74. package/dist/{cli-7pz3b7x5.js → cli-sksetb2q.js} +36 -1
  75. package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
  76. package/dist/{cli-db3m6zdt.js → cli-t02z59f2.js} +1 -1
  77. package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
  78. package/dist/{cli-s8z6x4b4.js → cli-v7g551te.js} +225 -113
  79. package/dist/{cli-rfz2ve55.js → cli-vgqzp4em.js} +3341 -955
  80. package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
  81. package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
  82. package/dist/cli-wfnemr1t.js +86 -0
  83. package/dist/cli-wmgrkscj.js +23254 -0
  84. package/dist/{cli-qm1448f9.js → cli-wms6x9db.js} +8 -8
  85. package/dist/{cli-tadfgd0t.js → cli-x1r545x8.js} +33 -4
  86. package/dist/{cli-xc7p7s3g.js → cli-xczsgshn.js} +6 -6
  87. package/dist/{cli-fmhj1ehj.js → cli-y3167wt1.js} +882 -271
  88. package/dist/{cli-r0byd61h.js → cli-yjmqpxt3.js} +17 -16
  89. package/dist/{cli-81r1wjyv.js → cli-z780ec7c.js} +1 -1
  90. package/dist/{cli-phcqp1b9.js → cli-zm9t2vde.js} +2 -2
  91. package/dist/cli.js +34 -49
  92. package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-4z16v9n0.js} +15 -14
  93. package/dist/{codex-login-841kv5fk.js → codex-login-pkepy2j1.js} +3 -2
  94. package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-rvms9y2x.js} +15 -14
  95. package/dist/{commands-z8fq9qna.js → commands-2a9rtyat.js} +11 -10
  96. package/dist/{controller-hq5ggpcp.js → controller-3k3madbn.js} +5 -4
  97. package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-v9yn8zb9.js} +42 -37
  98. package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-98gbhyzn.js} +7 -6
  99. package/dist/{db-qfpq4bt7.js → db-eywwsnjw.js} +30 -9
  100. package/dist/{db-yyhqqrbf.js → db-ncypk9np.js} +12 -11
  101. package/dist/{devin-adapter-xgtj680j.js → devin-adapter-zeq8b9gz.js} +3 -2
  102. package/dist/{dispatcher-x0x7qfcq.js → dispatcher-w94kc575.js} +38 -33
  103. package/dist/{docker-f503k9p0.js → docker-b1e4cqab.js} +3 -2
  104. package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-47ztej36.js} +7 -6
  105. package/dist/{e2b-66xra4az.js → e2b-bbt8ey45.js} +4 -3
  106. package/dist/{e2b-xwhyj8cw.js → e2b-dp804sen.js} +4 -3
  107. package/dist/{event-bus-vjtv82gm.js → event-bus-j2jdg3qb.js} +3 -2
  108. package/dist/{external-channel-h1fjecwe.js → external-channel-zrkg8ar9.js} +11 -10
  109. package/dist/{google-generative-ai-szdxbpqg.js → google-generative-ai-g8db7x0f.js} +4 -2
  110. package/dist/{google-vertex-qzw3p36d.js → google-vertex-r2692q0r.js} +4 -2
  111. package/dist/{grok-adapter-e7mr287e.js → grok-adapter-s9ncp9vy.js} +18 -17
  112. package/dist/{handlers-znb9n7d4.js → handlers-kqftvjgw.js} +41 -36
  113. package/dist/{heartbeat-bm4qkn8d.js → heartbeat-9q96p8v9.js} +43 -38
  114. package/dist/{hook-254r4mza.js → hook-56qe10dp.js} +11 -23
  115. package/dist/{hook-xaa3q80s.js → hook-yy6rw42k.js} +12 -11
  116. package/dist/{http-3dgrgp8y.js → http-r2dnb8f8.js} +2411 -275
  117. package/dist/{index-fx3jqq1e.js → index-3gtmkhc6.js} +38 -33
  118. package/dist/{index-bdsqa799.js → index-3k5hkz7r.js} +43 -38
  119. package/dist/index-52j1aja4.js +3465 -0
  120. package/dist/{index-g2byveez.js → index-5e101240.js} +38 -33
  121. package/dist/{index-2ybk7khy.js → index-5wyfjc2c.js} +845 -683
  122. package/dist/index-9gw58n4k.js +193 -0
  123. package/dist/index-9j87mcm8.js +56305 -0
  124. package/dist/index-bsmcresk.js +79424 -0
  125. package/dist/index-mh85qhec.js +475 -0
  126. package/dist/{index-jd7sejm2.js → index-vxvhxxbn.js} +10 -9
  127. package/dist/index-we27kd31.js +12810 -0
  128. package/dist/{keepalive-6ywhpja1.js → keepalive-psj6j54c.js} +12 -11
  129. package/dist/{lead-cw45n21s.js → lead-hajz4688.js} +61 -56
  130. package/dist/{maintenance-ss1a1ge9.js → maintenance-ps02sb5m.js} +10 -9
  131. package/dist/{node-fkajaq96.js → node-mwb5r697.js} +2 -1
  132. package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-0284h93b.js} +11 -10
  133. package/dist/{onboard-8hzdhc1k.js → onboard-rbf6bg01.js} +11 -3
  134. package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-13dcatgq.js} +18 -13
  135. package/dist/{otel-impl-e6mnvc4v.js → otel-impl-zvqcbhp7.js} +242 -868
  136. package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-xxy47q4v.js} +244 -106
  137. package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-kefx9v3t.js} +12 -11
  138. package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-3m36rxm2.js} +11 -10
  139. package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-z76xv0hq.js} +12 -11
  140. package/dist/{render-v2-907cy6sa.js → render-v2-wz73bs25.js} +18 -14
  141. package/dist/{resume-42stcaz0.js → resume-k4wzge8w.js} +25 -21
  142. package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
  143. package/dist/{setup-adbc1c10.js → setup-2fp2pypp.js} +2 -2
  144. package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
  145. package/dist/{work-objects-wpj8ck95.js → work-objects-6k0ywz3m.js} +41 -36
  146. package/dist/{worker-bzdra9rf.js → worker-5v3rxsdh.js} +61 -56
  147. package/dist/{x-qfmygqqv.js → x-4mtdeym1.js} +3 -2
  148. package/openapi.json +1279 -329
  149. package/package.json +15 -15
  150. package/src/agentmail/handlers.ts +21 -11
  151. package/src/apps/definition.ts +16 -0
  152. package/src/azure-devops/api.ts +52 -2
  153. package/src/azure-devops/boards-sync.ts +50 -20
  154. package/src/azure-devops/index.ts +1 -0
  155. package/src/azure-devops/outbound.ts +95 -0
  156. package/src/be/boot-seeds.ts +11 -0
  157. package/src/be/config-refs.ts +60 -0
  158. package/src/be/db/model-profiles.ts +315 -0
  159. package/src/be/db/page-versions.ts +15 -0
  160. package/src/be/db/runtime.ts +35 -8
  161. package/src/be/db/skill-name-resolution.ts +36 -0
  162. package/src/be/db/tasks/read.ts +237 -0
  163. package/src/be/db/tasks/write.ts +7 -0
  164. package/src/be/db.ts +87 -36
  165. package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
  166. package/src/be/migrations/216_task_resolved_effort.sql +5 -0
  167. package/src/be/migrations/217_chat_sdk_state.sql +104 -0
  168. package/src/be/migrations/219_relabel_pi_context_compactions.sql +22 -0
  169. package/src/be/migrations/220_model_profiles.sql +137 -0
  170. package/src/be/model-catalog-store.ts +5 -1
  171. package/src/be/model-tier-resolution.ts +155 -10
  172. package/src/be/model-validation.ts +12 -2
  173. package/src/be/models-catalog.ts +26 -1
  174. package/src/be/modelsdev-cache.json +198 -63
  175. package/src/be/modelsdev-cache.ts +9 -1
  176. package/src/be/script-credential-broker.ts +39 -2
  177. package/src/be/scripts/run-saved.ts +1 -0
  178. package/src/be/scripts/typecheck.ts +22 -8
  179. package/src/be/secret-registry.ts +6 -2
  180. package/src/be/seed/runner.ts +13 -1
  181. package/src/be/seed/state-db.ts +5 -0
  182. package/src/be/seed/types.ts +6 -0
  183. package/src/be/seed-model-profiles.ts +41 -0
  184. package/src/be/seed-pricing.ts +19 -2
  185. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +368 -0
  186. package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
  187. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
  188. package/src/be/seed-scripts/index.ts +9 -0
  189. package/src/be/seed-skills/bundled-files.generated.json +0 -18
  190. package/src/be/seed-skills/index.ts +104 -3
  191. package/src/be/swarm-config-guard.ts +53 -0
  192. package/src/cli.tsx +0 -16
  193. package/src/commands/onboard/non-interactive.ts +4 -2
  194. package/src/commands/provider-credentials.ts +52 -6
  195. package/src/commands/runner.ts +193 -71
  196. package/src/e2b/env.ts +5 -0
  197. package/src/extensions/catalog.generated.json +17 -0
  198. package/src/extensions/contract-types.generated.ts +1 -1
  199. package/src/extensions/contract.ts +45 -0
  200. package/src/extensions/dispatcher.ts +7 -0
  201. package/src/extensions/loader.ts +10 -5
  202. package/src/extensions/post-bridge.ts +40 -0
  203. package/src/github/handlers.ts +11 -4
  204. package/src/heartbeat/heartbeat.ts +2 -1
  205. package/src/heartbeat/templates.ts +8 -5
  206. package/src/hooks/hook.ts +0 -26
  207. package/src/http/agents.ts +49 -2
  208. package/src/http/all-routes.ts +1 -1
  209. package/src/http/apps.ts +30 -3
  210. package/src/http/config.ts +62 -19
  211. package/src/http/core.ts +8 -0
  212. package/src/http/index.ts +25 -3
  213. package/src/http/integrations.ts +88 -1
  214. package/src/http/mcp.ts +15 -5
  215. package/src/http/model-profiles.ts +303 -0
  216. package/src/http/page-proxy.ts +2 -4
  217. package/src/http/pages-public.ts +13 -7
  218. package/src/http/pages.ts +3 -13
  219. package/src/http/poll.ts +42 -71
  220. package/src/http/requested-by.ts +54 -0
  221. package/src/http/script-runs.ts +1 -1
  222. package/src/http/scripts.ts +26 -2
  223. package/src/http/stats.ts +1 -30
  224. package/src/http/tasks.ts +79 -5
  225. package/src/http/utils.ts +14 -0
  226. package/src/http/webhooks.ts +160 -3
  227. package/src/http/x.ts +1 -0
  228. package/src/integrations/chat-sdk/adapters.ts +129 -0
  229. package/src/integrations/chat-sdk/attachments.ts +232 -0
  230. package/src/integrations/chat-sdk/background.ts +36 -0
  231. package/src/integrations/chat-sdk/commands.ts +194 -0
  232. package/src/integrations/chat-sdk/config.ts +198 -0
  233. package/src/integrations/chat-sdk/discord-api.ts +63 -0
  234. package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
  235. package/src/integrations/chat-sdk/handlers.ts +28 -0
  236. package/src/integrations/chat-sdk/inbound.ts +426 -0
  237. package/src/integrations/chat-sdk/limits.ts +48 -0
  238. package/src/integrations/chat-sdk/logger.ts +81 -0
  239. package/src/integrations/chat-sdk/outbound.ts +123 -0
  240. package/src/integrations/chat-sdk/relay.ts +172 -0
  241. package/src/integrations/chat-sdk/router.ts +169 -0
  242. package/src/integrations/chat-sdk/runtime.ts +351 -0
  243. package/src/integrations/chat-sdk/schema.ts +245 -0
  244. package/src/integrations/chat-sdk/state.ts +243 -0
  245. package/src/integrations/chat-sdk/status.ts +244 -0
  246. package/src/integrations/chat-sdk/steering.ts +58 -0
  247. package/src/integrations/chat-sdk/teams-origin.ts +77 -0
  248. package/src/integrations/chat-sdk/telegram-api.ts +56 -0
  249. package/src/integrations/chat-sdk/templates.ts +16 -0
  250. package/src/integrations/chat-sdk/test-hooks.ts +37 -0
  251. package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
  252. package/src/integrations/chat-sdk/typing.ts +65 -0
  253. package/src/{artifact-sdk → pages}/feedback-overlay.ts +65 -6
  254. package/src/pages/version.ts +4 -5
  255. package/src/prompts/base-prompt.ts +111 -45
  256. package/src/providers/acp-target-catalog.ts +6 -0
  257. package/src/providers/acp-targets.ts +56 -3
  258. package/src/providers/amp-adapter.ts +1 -1
  259. package/src/providers/claude-adapter.ts +1 -1
  260. package/src/providers/claude-flag-settings.ts +17 -5
  261. package/src/providers/claude-managed-adapter.ts +1 -1
  262. package/src/providers/claude-session-events.ts +6 -1
  263. package/src/providers/dsh-adapter.ts +1 -1
  264. package/src/providers/opencode-adapter.ts +243 -26
  265. package/src/providers/opencode-swarm-plugin.ts +31 -0
  266. package/src/providers/pi-mono-adapter.ts +398 -153
  267. package/src/providers/pi-mono-extension.ts +17 -3
  268. package/src/providers/pricing-sources.md +33 -2
  269. package/src/providers/reasoning-effort.ts +37 -0
  270. package/src/providers/types.ts +6 -2
  271. package/src/rbac/legacy-policy.ts +16 -2
  272. package/src/rbac/permissions.ts +26 -0
  273. package/src/scheduler/deferred-task-waits.ts +18 -5
  274. package/src/scheduler/scheduler.ts +11 -3
  275. package/src/scripts-runtime/executors/quickjs-prelude.ts +75 -6
  276. package/src/scripts-runtime/executors/quickjs-runner.ts +85 -8
  277. package/src/scripts-runtime/executors/quickjs-web-shims.ts +1041 -0
  278. package/src/scripts-runtime/extract-args-schema.ts +9 -8
  279. package/src/scripts-runtime/loader.ts +19 -7
  280. package/src/scripts-runtime/quickjs-compat.ts +464 -0
  281. package/src/scripts-runtime/sdk-allowlist.ts +12 -6
  282. package/src/scripts-runtime/swarm-sdk.ts +0 -11
  283. package/src/scripts-runtime/types/stdlib.d.ts +39 -15
  284. package/src/scripts-runtime/types/swarm-extension.d.ts +66 -1
  285. package/src/scripts-runtime/types/swarm-sdk.d.ts +39 -15
  286. package/src/server.ts +62 -19
  287. package/src/slack/blocks.ts +4 -2
  288. package/src/slack/event-dedup.ts +1 -1
  289. package/src/slack/reaction-shortcode.ts +14 -0
  290. package/src/slack/render-v2.ts +12 -7
  291. package/src/slack/responses.ts +5 -4
  292. package/src/slack/thread-buffer.ts +41 -22
  293. package/src/tasks/additive-buffer.ts +4 -2
  294. package/src/tasks/context-key.ts +60 -1
  295. package/src/tasks/model-pin.ts +67 -0
  296. package/src/tasks/worker-follow-up.ts +15 -33
  297. package/src/tests/acp-adapter.test.ts +42 -0
  298. package/src/tests/agentmail-filters.test.ts +47 -0
  299. package/src/tests/api-drain-worker-e2e.test.ts +1 -6
  300. package/src/tests/apps-spike2.test.ts +35 -0
  301. package/src/tests/azure-devops-outbound.test.ts +420 -0
  302. package/src/tests/base-prompt.test.ts +58 -54
  303. package/src/tests/chat-sdk-commands.test.ts +191 -0
  304. package/src/tests/chat-sdk-config.test.ts +334 -0
  305. package/src/tests/chat-sdk-discord-api.test.ts +68 -0
  306. package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
  307. package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
  308. package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
  309. package/src/tests/chat-sdk-harness.ts +146 -0
  310. package/src/tests/chat-sdk-inbound.test.ts +363 -0
  311. package/src/tests/chat-sdk-relay.test.ts +470 -0
  312. package/src/tests/chat-sdk-reload.test.ts +128 -0
  313. package/src/tests/chat-sdk-shutdown.test.ts +220 -0
  314. package/src/tests/chat-sdk-slack.test.ts +268 -0
  315. package/src/tests/chat-sdk-state.test.ts +163 -0
  316. package/src/tests/chat-sdk-status-route.test.ts +382 -0
  317. package/src/tests/chat-sdk-teams.test.ts +277 -0
  318. package/src/tests/chat-sdk-tools.test.ts +520 -0
  319. package/src/tests/chat-sdk-typing.test.ts +120 -0
  320. package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
  321. package/src/tests/claude-adapter-binary.test.ts +9 -4
  322. package/src/tests/claude-flag-settings.test.ts +11 -3
  323. package/src/tests/claude-managed-adapter.test.ts +1 -1
  324. package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
  325. package/src/tests/claude-thinking-tokens.test.ts +57 -0
  326. package/src/tests/claude-worker-parity.test.ts +2 -7
  327. package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
  328. package/src/tests/config-refs.test.ts +66 -0
  329. package/src/tests/context-key.test.ts +19 -0
  330. package/src/tests/cors-allowlist.test.ts +25 -0
  331. package/src/tests/create-page-tool.test.ts +18 -0
  332. package/src/tests/credential-check.test.ts +139 -0
  333. package/src/tests/credentials.test.ts +21 -0
  334. package/src/tests/db-runtime.test.ts +61 -0
  335. package/src/tests/db-task-read-contract.test.ts +22 -0
  336. package/src/tests/db-task-write-contract.test.ts +11 -0
  337. package/src/tests/deferred-task-wake.test.ts +78 -1
  338. package/src/tests/docs-index-footprint.test.js +3 -3
  339. package/src/tests/dsh-adapter.test.ts +1 -1
  340. package/src/tests/enabled-capabilities.test.ts +20 -0
  341. package/src/tests/entrypoint-api-readiness.test.ts +14 -8
  342. package/src/tests/entrypoint-config-env-export.test.ts +5 -2
  343. package/src/tests/entrypoint-export-to-env.test.ts +78 -0
  344. package/src/tests/env-flag.test.ts +1 -0
  345. package/src/tests/explicit-model-validation.test.ts +105 -1
  346. package/src/tests/extensions-catalog.test.ts +1 -0
  347. package/src/tests/extensions-example-comms-adherence-gate.test.ts +413 -0
  348. package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
  349. package/src/tests/extensions-loader.test.ts +15 -0
  350. package/src/tests/extensions-post-bridge.test.ts +51 -0
  351. package/src/tests/fetch-resolved-env.test.ts +128 -0
  352. package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
  353. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
  354. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
  355. package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
  356. package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
  357. package/src/tests/github-handlers.test.ts +35 -0
  358. package/src/tests/harness-provider-resolution.test.ts +12 -0
  359. package/src/tests/heartbeat-checklist.test.ts +3 -2
  360. package/src/tests/heartbeat-jev-gate-credentials.test.ts +168 -0
  361. package/src/tests/heartbeat-jev-gate.test.ts +385 -0
  362. package/src/tests/hook-runtime-close.test.ts +0 -2
  363. package/src/tests/http-api-integration.test.ts +0 -25
  364. package/src/tests/migration-046-budgets.test.ts +17 -16
  365. package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
  366. package/src/tests/model-profile-backcompat.test.ts +327 -0
  367. package/src/tests/model-profile-providers.test.ts +302 -0
  368. package/src/tests/model-profile-runtime-secrets.test.ts +223 -0
  369. package/src/tests/model-profiles-api.test.ts +614 -0
  370. package/src/tests/model-tier-resolution.test.ts +93 -0
  371. package/src/tests/models-catalog.test.ts +42 -1
  372. package/src/tests/openai-compatible-providers.test.ts +134 -0
  373. package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
  374. package/src/tests/opencode-adapter.test.ts +216 -2
  375. package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
  376. package/src/tests/opencode-shell-env.test.ts +145 -0
  377. package/src/tests/openrouter-base-url.test.ts +101 -151
  378. package/src/tests/page-proxy.test.ts +1 -1
  379. package/src/tests/pages-browser-sdk.test.ts +76 -0
  380. package/src/tests/pages-feedback-keys.test.ts +121 -0
  381. package/src/tests/pages-feedback.test.ts +4 -1
  382. package/src/tests/paused-tasks-requested-by.test.ts +102 -0
  383. package/src/tests/pi-context-compaction.test.ts +193 -0
  384. package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
  385. package/src/tests/pi-mono-adapter.test.ts +385 -5
  386. package/src/tests/pi-shell-env.test.ts +170 -0
  387. package/src/tests/profile-claim.test.ts +269 -0
  388. package/src/tests/prompt-template-remaining.test.ts +35 -0
  389. package/src/tests/quickjs-compat.test.ts +213 -0
  390. package/src/tests/rbac-engine.test.ts +32 -3
  391. package/src/tests/runner-exit-after-tasks.test.ts +0 -4
  392. package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
  393. package/src/tests/script-connections.test.ts +6 -0
  394. package/src/tests/script-executor-conformance.test.ts +252 -1
  395. package/src/tests/script-executor-quickjs.test.ts +96 -0
  396. package/src/tests/script-runs-http.test.ts +89 -0
  397. package/src/tests/scripts-http.test.ts +217 -1
  398. package/src/tests/scripts-only-gating.test.ts +2 -3
  399. package/src/tests/scripts-runtime.test.ts +58 -40
  400. package/src/tests/secret-scrubber.test.ts +96 -0
  401. package/src/tests/seed-model-profiles.test.ts +174 -0
  402. package/src/tests/seed-scripts.test.ts +2 -2
  403. package/src/tests/seed-skills-bundled-files.test.ts +45 -53
  404. package/src/tests/seed-skills-retire.test.ts +182 -0
  405. package/src/tests/send-task-requester-gate.test.ts +58 -0
  406. package/src/tests/session-cost-recompute-unit.test.ts +46 -0
  407. package/src/tests/skill-get-name-resolution.test.ts +137 -0
  408. package/src/tests/skill-invocations.test.ts +4 -2
  409. package/src/tests/slack-blocks.test.ts +36 -0
  410. package/src/tests/slack-inline-output.test.ts +14 -0
  411. package/src/tests/slack-reaction-config.test.ts +20 -0
  412. package/src/tests/slack-render-v2.test.ts +37 -0
  413. package/src/tests/slack-thread-buffer.test.ts +98 -1
  414. package/src/tests/sonnet-5-5-registry.test.ts +9 -1
  415. package/src/tests/swarm-config-export-to-env.test.ts +267 -0
  416. package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
  417. package/src/tests/swarm-diff.test.ts +1 -1
  418. package/src/tests/task-model-effort-rerun.test.ts +164 -0
  419. package/src/tests/task-session-prompts.test.ts +132 -0
  420. package/src/tests/task-tool-manifest.test.ts +14 -0
  421. package/src/tests/task-tools-ctx.test.ts +2 -0
  422. package/src/tests/tool-annotations.test.ts +6 -6
  423. package/src/tests/ui-logs-parser.test.ts +43 -0
  424. package/src/tests/used-by-route.test.ts +6 -0
  425. package/src/tests/vercel-ai-gateway.test.ts +149 -0
  426. package/src/tests/workflow-llm.test.ts +61 -0
  427. package/src/tests/workflow-swarm-script.test.ts +38 -0
  428. package/src/tests/workflow-wait-filter.test.ts +5 -3
  429. package/src/tools/chat-access.ts +41 -0
  430. package/src/tools/chat-open-dm.ts +59 -0
  431. package/src/tools/chat-post.ts +74 -0
  432. package/src/tools/chat-read-thread.ts +100 -0
  433. package/src/tools/chat-reply.ts +75 -0
  434. package/src/tools/create-page.ts +3 -13
  435. package/src/tools/model-catalog/index.ts +2 -1
  436. package/src/tools/model-profiles/list-model-profiles.ts +54 -0
  437. package/src/tools/register-chat-channel.ts +139 -0
  438. package/src/tools/request-human-input.ts +11 -3
  439. package/src/tools/script-apis.ts +5 -1
  440. package/src/tools/script-upsert.ts +4 -1
  441. package/src/tools/send-task.ts +48 -1
  442. package/src/tools/skills/skill-get.ts +17 -9
  443. package/src/tools/swarm-config/get-config.ts +2 -1
  444. package/src/tools/swarm-config/list-config.ts +2 -1
  445. package/src/tools/swarm-config/set-config.ts +16 -3
  446. package/src/tools/system-one-decide.ts +104 -0
  447. package/src/tools/task-action.ts +22 -1
  448. package/src/tools/tool-config.ts +14 -6
  449. package/src/types.ts +48 -3
  450. package/src/utils/config-env-export.ts +74 -0
  451. package/src/utils/credentials.test.ts +92 -0
  452. package/src/utils/credentials.ts +52 -4
  453. package/src/utils/harness-provider.ts +15 -6
  454. package/src/utils/runtime-model-catalog.ts +11 -1
  455. package/src/utils/secret-scrubber.ts +86 -10
  456. package/src/utils/task-tool-manifest.ts +19 -2
  457. package/src/utils/vcs-repo-match.ts +29 -0
  458. package/src/workflows/executors/raw-llm.ts +8 -3
  459. package/src/workflows/executors/swarm-script.ts +1 -0
  460. package/src/workflows/executors/system-one-decision.ts +21 -11
  461. package/src/workflows/executors/workflow-llm.ts +22 -0
  462. package/src/workflows/index.ts +21 -12
  463. package/templates/extensions/README.md +1 -0
  464. package/templates/extensions/comms-adherence-gate/README.md +88 -0
  465. package/templates/extensions/comms-adherence-gate/hooks.ts +489 -0
  466. package/templates/extensions/comms-adherence-gate/manifest.json +8 -0
  467. package/templates/skills/agent-browser/SKILL.md +1 -1
  468. package/templates/skills/agent-browser/content.md +1 -1
  469. package/templates/skills/apps/SKILL.md +8 -1
  470. package/templates/skills/apps/content.md +8 -1
  471. package/templates/skills/chat-sdk/config.json +14 -0
  472. package/templates/skills/chat-sdk/content.md +84 -0
  473. package/templates/skills/composio-gmail/content.md +7 -0
  474. package/templates/skills/composio-google-docs/content.md +1 -1
  475. package/templates/skills/email-domain-health/config.json +14 -0
  476. package/templates/skills/email-domain-health/content.md +131 -0
  477. package/templates/skills/kv-storage/content.md +2 -2
  478. package/templates/skills/pages/content.md +8 -10
  479. package/templates/skills/swarm-extensions/content.md +2 -0
  480. package/templates/skills/swarm-scripts/SKILL.md +4 -2
  481. package/templates/skills/swarm-scripts/config.json +1 -1
  482. package/templates/skills/swarm-scripts/content.md +4 -2
  483. package/templates/skills/workflow-iterate/content.md +38 -0
  484. package/dist/artifact-eczsknc3.js +0 -3843
  485. package/dist/cli-42qhyvwx.js +0 -33
  486. package/dist/cli-bd957dgb.js +0 -153
  487. package/dist/cli-q51yprfq.js +0 -1104
  488. package/dist/cli-t1ze64h3.js +0 -811
  489. package/dist/cli-tcc4wd5d.js +0 -56471
  490. package/dist/index-9ch1n761.js +0 -1102
  491. package/src/artifact-sdk/index.ts +0 -2
  492. package/src/artifact-sdk/localtunnel.d.ts +0 -20
  493. package/src/artifact-sdk/port.ts +0 -12
  494. package/src/artifact-sdk/server.ts +0 -183
  495. package/src/artifact-sdk/tunnel.ts +0 -19
  496. package/src/commands/artifact.ts +0 -249
  497. package/src/http/ecosystem.ts +0 -77
  498. package/src/tests/artifact-commands.test.ts +0 -92
  499. package/src/tests/artifact-sdk.test.ts +0 -793
  500. package/src/tests/register-service-security.test.ts +0 -194
  501. package/src/tools/list-services.ts +0 -107
  502. package/src/tools/register-service.ts +0 -177
  503. package/src/tools/unregister-service.ts +0 -73
  504. package/src/tools/update-service-status.ts +0 -96
  505. package/templates/skills/artifacts/config.json +0 -14
  506. package/templates/skills/artifacts/content.md +0 -344
  507. package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
  508. package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
  509. package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
  510. package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
  511. /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
package/src/http/apps.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  parseAppDefinition,
13
13
  SORTABLE_SYSTEM_DATE_COLUMNS,
14
14
  SYSTEM_COLUMN_KINDS,
15
+ scriptCompatWarnings,
15
16
  } from "../apps/definition";
16
17
  import {
17
18
  type AppRow,
@@ -227,9 +228,14 @@ const AppUserConfigFieldSchema = z.object({
227
228
  /** Mirrors an app definition's `userConfig` declaration map. */
228
229
  const AppUserConfigSchema = z.record(AppNameSchema, AppUserConfigFieldSchema);
229
230
 
231
+ const compatWarningsSchema = z
232
+ .array(z.string())
233
+ .optional()
234
+ .describe("Advisory quickjs-executor compatibility findings for the app's scripts.");
230
235
  const appWriteResponseSchema = z.object({
231
236
  app: AppRecordSchema,
232
237
  migration: AppMigrationReportSchema,
238
+ warnings: compatWarningsSchema,
233
239
  });
234
240
  const userConfigBodySchema = z.object({ values: z.record(z.string(), z.unknown()) }).strict();
235
241
 
@@ -307,7 +313,10 @@ const createAppRoute = route({
307
313
  forceElementBreak: ForceElementBreakSchema.optional(),
308
314
  }),
309
315
  responses: {
310
- 201: { description: "Created app", schema: z.object({ app: AppRecordSchema }) },
316
+ 201: {
317
+ description: "Created app",
318
+ schema: z.object({ app: AppRecordSchema, warnings: compatWarningsSchema }),
319
+ },
311
320
  400: { description: "Invalid app definition" },
312
321
  403: { description: "Permission denied" },
313
322
  },
@@ -1020,12 +1029,14 @@ export async function handleApps(
1020
1029
  invalidDefinition(res, definition.issues);
1021
1030
  return true;
1022
1031
  }
1032
+ const warnings = await scriptCompatWarnings(definition.definition);
1023
1033
  createAppRoute.respond(res, 201, {
1024
1034
  app: await createApp({
1025
1035
  name: parsed.body.name,
1026
1036
  description: parsed.body.description,
1027
1037
  definition: definition.definition,
1028
1038
  }),
1039
+ ...(warnings.length > 0 ? { warnings } : {}),
1029
1040
  });
1030
1041
  return true;
1031
1042
  }
@@ -1482,6 +1493,7 @@ export async function handleApps(
1482
1493
  }
1483
1494
  let app: Awaited<ReturnType<typeof updateApp>> = null;
1484
1495
  let migration!: AppMigrationReport;
1496
+ let writtenDefinition: unknown;
1485
1497
  let responseHandled = false;
1486
1498
  try {
1487
1499
  await withAppDefinitionLock(parsed.params.id, async () => {
@@ -1513,6 +1525,7 @@ export async function handleApps(
1513
1525
  responseHandled = true;
1514
1526
  return;
1515
1527
  }
1528
+ if (parsed.body.definition !== undefined) writtenDefinition = definition.definition;
1516
1529
  const migrated = await migrateAppSchema({
1517
1530
  appId: parsed.params.id,
1518
1531
  previousDefinition: existing.definition,
@@ -1553,7 +1566,13 @@ export async function handleApps(
1553
1566
  jsonError(res, "app not found", 404);
1554
1567
  return true;
1555
1568
  }
1556
- patchAppRoute.respond(res, 200, { app, migration });
1569
+ const warnings =
1570
+ writtenDefinition === undefined ? [] : await scriptCompatWarnings(writtenDefinition);
1571
+ patchAppRoute.respond(res, 200, {
1572
+ app,
1573
+ migration,
1574
+ ...(warnings.length > 0 ? { warnings } : {}),
1575
+ });
1557
1576
  return true;
1558
1577
  }
1559
1578
 
@@ -1568,6 +1587,7 @@ export async function handleApps(
1568
1587
  }
1569
1588
  let app: Awaited<ReturnType<typeof updateApp>> = null;
1570
1589
  let migration!: AppMigrationReport;
1590
+ let writtenDefinition: unknown;
1571
1591
  let responseHandled = false;
1572
1592
  try {
1573
1593
  await withAppDefinitionLock(parsed.params.id, async () => {
@@ -1597,6 +1617,7 @@ export async function handleApps(
1597
1617
  return;
1598
1618
  }
1599
1619
  const nextDefinition = definition ?? existing.definition;
1620
+ writtenDefinition = definition;
1600
1621
  const migrated = await migrateAppSchema({
1601
1622
  appId: parsed.params.id,
1602
1623
  previousDefinition: appDefinitionNeedsRepair(existing) ? undefined : existing.definition,
@@ -1637,7 +1658,13 @@ export async function handleApps(
1637
1658
  jsonError(res, "app not found", 404);
1638
1659
  return true;
1639
1660
  }
1640
- updateAppRoute.respond(res, 200, { app, migration });
1661
+ const warnings =
1662
+ writtenDefinition === undefined ? [] : await scriptCompatWarnings(writtenDefinition);
1663
+ updateAppRoute.respond(res, 200, {
1664
+ app,
1665
+ migration,
1666
+ ...(warnings.length > 0 ? { warnings } : {}),
1667
+ });
1641
1668
  return true;
1642
1669
  }
1643
1670
 
@@ -9,6 +9,7 @@ import {
9
9
  getSwarmConfigs,
10
10
  maskSecrets,
11
11
  } from "../be/db";
12
+ import { modelProfileRefError } from "../be/db/model-profiles";
12
13
  import {
13
14
  AGENT_MAX_TASKS_CONFIG_KEY,
14
15
  resetAgentMaxTasksMirror,
@@ -18,14 +19,16 @@ import { fillOrgLogoFromWebsite } from "../be/org-profile";
18
19
  import { getUserGrant } from "../be/rbac-roles";
19
20
  import {
20
21
  internalConfigKeyError,
22
+ isApiOnlyConfigKey,
21
23
  isInternalConfigKey,
22
24
  isReservedConfigKey,
23
25
  reservedKeyError,
24
26
  validateConfigValue,
27
+ validateExportToEnv,
25
28
  } from "../be/swarm-config-guard";
26
29
  import { can, isRbacEnabled, type PermissionVerb } from "../rbac";
27
30
  import { SwarmConfigSchema } from "../types";
28
- import { getRequestAuth } from "../utils/request-auth-context";
31
+ import { getRequestAuth, type HttpRequestAuth } from "../utils/request-auth-context";
29
32
  import { registerVolatileSecret } from "../utils/secret-scrubber";
30
33
  import { reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload } from "./core";
31
34
  import { route } from "./route-def";
@@ -35,16 +38,9 @@ const MAX_ENV_PRESENCE_KEYS = 200;
35
38
  const SECRETS_FORCE_MASK_NOTE =
36
39
  " (secret values masked: this token cannot read secrets in this scope)";
37
40
 
38
- // Config keys the API server owns for its own use and must NEVER hand out over
39
- // HTTP — workers/entrypoints read config to build their env, and the agent-fs
40
- // bootstrap admin key would let a compromised worker administer the shared org.
41
- // The API materializes these into its own process.env at boot via
42
- // getInjectableGlobalConfigs, so no HTTP consumer legitimately needs them.
43
- const API_ONLY_CONFIG_KEYS = new Set(["API_AGENT_FS_API_KEY", "SLACK_SIGNING_SECRET"]);
44
-
45
41
  function stripApiOnlyKeys<T extends { key: string }>(configs: T[]): T[] {
46
42
  return configs.filter(
47
- (config) => !API_ONLY_CONFIG_KEYS.has(config.key) && !isInternalConfigKey(config.key),
43
+ (config) => !isApiOnlyConfigKey(config.key) && !isInternalConfigKey(config.key),
48
44
  );
49
45
  }
50
46
 
@@ -53,6 +49,25 @@ function singleHeader(req: IncomingMessage, name: string): string | undefined {
53
49
  return Array.isArray(raw) ? raw[0] : raw;
54
50
  }
55
51
 
52
+ /**
53
+ * Whether this caller's `/api/config/resolved` carries secret repo rows (the
54
+ * `includeRepoSecrets` of {@link resolveSecretsRead}): a runtime-token agent
55
+ * gets them only with `config.read.secrets`. Claim uses it so an agent's
56
+ * default profile yields only to repo rows that worker's env really gets.
57
+ */
58
+ export function readsRepoSecrets(
59
+ auth: HttpRequestAuth | null,
60
+ agent: { isLead?: boolean } | null | undefined,
61
+ ): boolean {
62
+ if (auth?.kind !== "agent" || !auth.runtimeId) return true;
63
+ return can({
64
+ principal: { kind: "agent", agentId: auth.agentId, isLead: agent?.isLead ?? false },
65
+ verb: "config.read.secrets",
66
+ resource: { kind: "none" },
67
+ source: "http",
68
+ }).allow;
69
+ }
70
+
56
71
  async function requestSecretReadScope(
57
72
  req: IncomingMessage,
58
73
  resolvedScope?: { agentId?: string; repoId?: string },
@@ -116,6 +131,28 @@ export async function ensureConfigAdmin(
116
131
  req: IncomingMessage,
117
132
  res: ServerResponse,
118
133
  verb: Extract<PermissionVerb, "config.write.any" | "config.delete.any">,
134
+ ): Promise<boolean> {
135
+ return ensureHttpPermission(
136
+ req,
137
+ res,
138
+ verb,
139
+ verb === "config.write.any"
140
+ ? "Writing swarm config requires the lead agent"
141
+ : "Deleting swarm config requires the lead agent",
142
+ );
143
+ }
144
+
145
+ /**
146
+ * The general form of `ensureConfigAdmin`: operators and users pass, guests
147
+ * get a plain 403, and an agent principal (session identity first, then the
148
+ * legacy X-Agent-ID header) must hold `verb`. On denial it writes a 403 with
149
+ * `forbiddenMessage` and returns false.
150
+ */
151
+ export async function ensureHttpPermission(
152
+ req: IncomingMessage,
153
+ res: ServerResponse,
154
+ verb: PermissionVerb,
155
+ forbiddenMessage: string,
119
156
  ): Promise<boolean> {
120
157
  const auth = getRequestAuth(req);
121
158
  if (auth?.kind === "operator" || auth?.kind === "user") return true;
@@ -132,13 +169,7 @@ export async function ensureConfigAdmin(
132
169
  source: "http",
133
170
  });
134
171
  if (!decision.allow) {
135
- jsonError(
136
- res,
137
- verb === "config.write.any"
138
- ? "Writing swarm config requires the lead agent"
139
- : "Deleting swarm config requires the lead agent",
140
- 403,
141
- );
172
+ jsonError(res, forbiddenMessage, 403);
142
173
  return false;
143
174
  }
144
175
  return true;
@@ -276,6 +307,12 @@ const upsertConfig = route({
276
307
  isSecret: z.boolean().optional(),
277
308
  envPath: z.string().nullish(),
278
309
  description: z.string().nullish(),
310
+ exportToEnv: z
311
+ .boolean()
312
+ .optional()
313
+ .describe(
314
+ "Export this row into agent process env (default true on create, false for a few server-side secrets; omitted on update keeps the stored flag). Rejected as true for keys only the API server reads.",
315
+ ),
279
316
  }),
280
317
  responses: {
281
318
  200: { description: "Config entry upserted", schema: SwarmConfigSchema },
@@ -442,7 +479,7 @@ export async function handleConfig(
442
479
  const parsed = await upsertConfig.parse(req, res, pathSegments, queryParams);
443
480
  if (!parsed) return true;
444
481
  if (!(await ensureConfigAdmin(req, res, "config.write.any"))) return true;
445
- const { scope, scopeId, key, value, isSecret, envPath, description } = parsed.body;
482
+ const { scope, scopeId, key, value, isSecret, envPath, description, exportToEnv } = parsed.body;
446
483
 
447
484
  if (scope === "global" && scopeId) {
448
485
  jsonError(res, "Global scope must not have scopeId", 400);
@@ -464,7 +501,8 @@ export async function handleConfig(
464
501
  return true;
465
502
  }
466
503
 
467
- const validationError = validateConfigValue(key, value);
504
+ const validationError =
505
+ validateConfigValue(key, value) ?? validateExportToEnv(key, exportToEnv);
468
506
  if (validationError) {
469
507
  jsonError(res, validationError, 400);
470
508
  return true;
@@ -480,6 +518,7 @@ export async function handleConfig(
480
518
  isSecret: isSecret || false,
481
519
  envPath: envPath || null,
482
520
  description: description || null,
521
+ exportToEnv,
483
522
  });
484
523
  // Auto-reload integrations when a global-scoped config changes so callers
485
524
  // (CLI, automation, dashboard) don't have to remember to hit /reload.
@@ -493,7 +532,11 @@ export async function handleConfig(
493
532
  }
494
533
  const result = includeSecrets || !config.isSecret ? config : maskSecrets([config])[0]!;
495
534
  upsertConfig.respond(res, 200, result);
496
- } catch (_error) {
535
+ } catch (error) {
536
+ if (modelProfileRefError(error) === "missing") {
537
+ jsonError(res, `Unknown model profile "${String(value)}"`, 400);
538
+ return true;
539
+ }
497
540
  jsonError(res, "Failed to upsert config", 500);
498
541
  }
499
542
  return true;
package/src/http/core.ts CHANGED
@@ -3,9 +3,11 @@ import { z } from "zod";
3
3
  import { initAgentMail, resetAgentMail } from "../agentmail";
4
4
  import {
5
5
  initAzureDevOps,
6
+ initAzureDevOpsOutbound,
6
7
  isAzureDevOpsEnabled,
7
8
  resetAzureDevOps,
8
9
  resetAzureDevOpsBotIdCache,
10
+ teardownAzureDevOpsOutbound,
9
11
  } from "../azure-devops";
10
12
  import {
11
13
  getAgentById,
@@ -29,6 +31,7 @@ import { getUserGrant } from "../be/rbac-roles";
29
31
  import { syncTelemetryEnabled } from "../be/telemetry-enable";
30
32
  import { initGitHub, resetGitHub } from "../github";
31
33
  import { initGitLab, isGitLabEnabled, resetGitLab } from "../gitlab";
34
+ import { restartChatSdkIfConfigChanged } from "../integrations/chat-sdk/runtime";
32
35
  import { initJira, resetJira } from "../jira";
33
36
  import { initLinear, resetLinear } from "../linear";
34
37
  import { can, decideAdmission, isRbacEnabled } from "../rbac";
@@ -234,6 +237,8 @@ async function reloadGlobalConfigsAndIntegrationsInner(): Promise<ReloadConfigRe
234
237
  resetAzureDevOpsBotIdCache();
235
238
  initAzureDevOps();
236
239
  if (isAzureDevOpsEnabled()) integrations.push("azure-devops");
240
+ teardownAzureDevOpsOutbound();
241
+ if (isAzureDevOpsEnabled()) initAzureDevOpsOutbound();
237
242
 
238
243
  resetLinear();
239
244
  if (await initLinear()) integrations.push("linear");
@@ -243,6 +248,9 @@ async function reloadGlobalConfigsAndIntegrationsInner(): Promise<ReloadConfigRe
243
248
 
244
249
  if (await startSlackApp()) integrations.push("slack");
245
250
 
251
+ // After Slack: the Chat SDK Slack clash check reads SLACK_DISABLE.
252
+ if (await restartChatSdkIfConfigChanged()) integrations.push("chat-sdk");
253
+
246
254
  return {
247
255
  configsLoaded: updated.length,
248
256
  keysUpdated: updated,
package/src/http/index.ts CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  import type { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
8
8
  import { getEnabledCapabilities, hasCapability } from "@/server";
9
9
  import { initAgentMail } from "../agentmail";
10
- import { initAzureDevOps } from "../azure-devops";
10
+ import { initAzureDevOps, initAzureDevOpsOutbound } from "../azure-devops";
11
11
  import { drainApi, isApiDraining } from "../be/api-drain";
12
12
  import {
13
13
  closeDb,
@@ -41,6 +41,7 @@ import {
41
41
  import { initGitHub } from "../github";
42
42
  import { initGitLab } from "../gitlab";
43
43
  import { stopHeartbeat } from "../heartbeat";
44
+ import { startChatSdk, stopChatSdk } from "../integrations/chat-sdk/runtime";
44
45
  import { initJira } from "../jira";
45
46
  import { initLinear } from "../linear";
46
47
  import {
@@ -81,7 +82,6 @@ import { handleConfig } from "./config";
81
82
  import { handleContext } from "./context";
82
83
  import { handleCore, loadGlobalConfigsIntoEnv } from "./core";
83
84
  import { handleDbQuery } from "./db-query";
84
- import { handleEcosystem } from "./ecosystem";
85
85
  import { handleEvents } from "./events";
86
86
  import { handleExtensions } from "./extensions";
87
87
  import { handleFavorites } from "./favorites";
@@ -104,6 +104,7 @@ import { handleMcpServers } from "./mcp-servers";
104
104
  import { closeIdleMcpUserTransports, handleMcpUser } from "./mcp-user";
105
105
  import { handleMemory, startMemoryGc, stopMemoryGc } from "./memory";
106
106
  import { handleMetrics } from "./metrics";
107
+ import { handleModelProfiles } from "./model-profiles";
107
108
  import { handleModelsCatalog } from "./models-catalog";
108
109
  import { handleOAuthCallback, startOAuthPendingGc, stopOAuthPendingGc } from "./oauth-callback";
109
110
  import { handleGenericOAuth } from "./oauth-generic";
@@ -345,7 +346,6 @@ const httpServer = createHttpServer(async (req, res) => {
345
346
  () => handleAgentRegister(req, res, pathSegments, myAgentId),
346
347
  () => handlePoll(req, res, pathSegments, queryParams, myAgentId),
347
348
  () => handleSessionData(req, res, pathSegments, queryParams, myAgentId),
348
- () => handleEcosystem(req, res, pathSegments, myAgentId),
349
349
  () => handleTrackers(req, res, pathSegments),
350
350
  () => handleWebhooks(req, res, pathSegments),
351
351
  () => handleAgentsRest(req, res, pathSegments, queryParams, myAgentId),
@@ -377,6 +377,7 @@ const httpServer = createHttpServer(async (req, res) => {
377
377
  () => handleDbQuery(req, res, pathSegments, queryParams),
378
378
  () => handleMetrics(req, res, pathSegments, queryParams, myAgentId),
379
379
  () => handleModelsCatalog(req, res, pathSegments, queryParams),
380
+ () => handleModelProfiles(req, res, pathSegments, queryParams, myAgentId),
380
381
  () => handleRepos(req, res, pathSegments, queryParams, myAgentId),
381
382
  () => handleSkills(req, res, pathSegments, queryParams, myAgentId),
382
383
  () => handleScriptConnections(req, res, pathSegments, queryParams, myAgentId),
@@ -503,6 +504,9 @@ async function shutdown() {
503
504
  // Stop Slack bot
504
505
  await stopSlackApp();
505
506
 
507
+ // Stop Chat SDK adapters and drain their background handlers before the DB closes
508
+ await stopChatSdk();
509
+
506
510
  // Stop OAuth keepalive
507
511
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
508
512
  const { stopOAuthKeepalive } = await import("../oauth/keepalive");
@@ -663,6 +667,13 @@ try {
663
667
  console.error("[startup] Failed to seed pricing rows:", err);
664
668
  }
665
669
 
670
+ try {
671
+ const { ensureModelProfilesSeeded } = await import("../be/boot-seeds");
672
+ await ensureModelProfilesSeeded();
673
+ } catch (err) {
674
+ console.error("[startup] Failed to seed model profiles:", err);
675
+ }
676
+
666
677
  try {
667
678
  const { ensureRbacSeeded } = await import("../be/boot-seeds");
668
679
  ensureRbacSeeded();
@@ -762,6 +773,16 @@ httpServer
762
773
  console.error("[Slack] Failed to start, continuing boot without Slack:", err);
763
774
  }
764
775
 
776
+ // Chat SDK channel: never the boot path, so not awaited. Adapter init
777
+ // makes network calls (Slack's auth.test retries for up to ~30 min), and
778
+ // the scheduler, heartbeat and supervisor below must start regardless.
779
+ void startChatSdk().catch((err: unknown) => {
780
+ console.error(
781
+ "[chat-sdk] Failed to start, continuing without Chat SDK:",
782
+ scrubSecrets(err instanceof Error ? err.message : String(err)),
783
+ );
784
+ });
785
+
765
786
  // Independent of workers, scheduler targets, and heartbeat agent tasks.
766
787
  startQueueStallAlarm();
767
788
 
@@ -773,6 +794,7 @@ httpServer
773
794
 
774
795
  // Initialize Azure DevOps service-hook handler (if configured)
775
796
  initAzureDevOps();
797
+ initAzureDevOpsOutbound();
776
798
 
777
799
  // Initialize AgentMail webhook handler (if configured)
778
800
  initAgentMail();
@@ -1,9 +1,17 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import Anthropic from "@anthropic-ai/sdk";
3
3
  import { z } from "zod";
4
+ import {
5
+ ChatSdkActionError,
6
+ ChatSdkStatusSchema,
7
+ getChatSdkStatus,
8
+ registerTelegramWebhook,
9
+ } from "../integrations/chat-sdk/status";
4
10
  import { buildSlackManifest } from "../slack/manifest";
11
+ import { ensureHttpPermission } from "./config";
5
12
  import { resolveConfigValue, resolveMcpBaseUrl } from "./config-values";
6
13
  import { route } from "./route-def";
14
+ import { jsonError } from "./utils";
7
15
 
8
16
  // ─── Types ───────────────────────────────────────────────────────────────────
9
17
 
@@ -48,6 +56,20 @@ const McpUserConfigSchema = z.object({
48
56
 
49
57
  const SlackManifestSchema = z.record(z.string(), z.unknown());
50
58
 
59
+ const TelegramRegisterWebhookSchema = z.object({
60
+ webhookUrl: z.string(),
61
+ webhookInfo: z.looseObject({
62
+ url: z.string(),
63
+ has_custom_certificate: z.boolean().optional(),
64
+ pending_update_count: z.number().optional(),
65
+ last_error_date: z.number().optional(),
66
+ last_error_message: z.string().optional(),
67
+ max_connections: z.number().optional(),
68
+ ip_address: z.string().optional(),
69
+ allowed_updates: z.array(z.string()).optional(),
70
+ }),
71
+ });
72
+
51
73
  // ─── Route Definition ────────────────────────────────────────────────────────
52
74
 
53
75
  const claudeManagedTestRoute = route({
@@ -94,7 +116,38 @@ const slackManifestRoute = route({
94
116
  },
95
117
  });
96
118
 
97
- // ─── Helpers ─────────────────────────────────────────────────────────────────
119
+ const chatSdkStatusRoute = route({
120
+ method: "get",
121
+ path: "/api/integrations/chat/status",
122
+ pattern: ["api", "integrations", "chat", "status"],
123
+ summary:
124
+ "Chat SDK channel status: enabled flag, Slack clash, per-adapter health and webhook URL.",
125
+ tags: ["Integrations"],
126
+ responses: {
127
+ 200: {
128
+ description:
129
+ "Per-adapter status. `health` is `disabled` for an adapter that is not running. Never contains secret values.",
130
+ schema: ChatSdkStatusSchema,
131
+ },
132
+ },
133
+ });
134
+
135
+ const chatSdkTelegramRegisterWebhookRoute = route({
136
+ method: "post",
137
+ path: "/api/integrations/chat/telegram/register-webhook",
138
+ pattern: ["api", "integrations", "chat", "telegram", "register-webhook"],
139
+ summary:
140
+ "Register this swarm's public Telegram webhook URL and secret token with the Bot API (setWebhook), then return getWebhookInfo.",
141
+ tags: ["Integrations"],
142
+ body: z.object({}).optional(),
143
+ responses: {
144
+ 200: { description: "Webhook registered", schema: TelegramRegisterWebhookSchema },
145
+ 400: { description: "Telegram is not configured for webhook mode" },
146
+ 403: { description: "Only the lead agent or a dashboard user can register the webhook" },
147
+ 502: { description: "The Telegram Bot API rejected the call" },
148
+ },
149
+ rbac: { permission: "integration.chat.manage" },
150
+ });
98
151
 
99
152
  // ─── Public handler factory ──────────────────────────────────────────────────
100
153
 
@@ -122,6 +175,40 @@ export function createIntegrationsHandler(deps: TestConnectionDeps = {}) {
122
175
  return true;
123
176
  }
124
177
 
178
+ if (chatSdkStatusRoute.match(req.method, pathSegments)) {
179
+ chatSdkStatusRoute.respond(res, 200, await getChatSdkStatus());
180
+ return true;
181
+ }
182
+
183
+ if (chatSdkTelegramRegisterWebhookRoute.match(req.method, pathSegments)) {
184
+ const parsed = await chatSdkTelegramRegisterWebhookRoute.parse(
185
+ req,
186
+ res,
187
+ pathSegments,
188
+ queryParams,
189
+ );
190
+ if (!parsed) return true;
191
+ // Operators and dashboard users pass; agents need the verb (lead-only
192
+ // under the legacy policy).
193
+ if (
194
+ !(await ensureHttpPermission(
195
+ req,
196
+ res,
197
+ "integration.chat.manage",
198
+ "Registering the Telegram webhook requires the lead agent",
199
+ ))
200
+ ) {
201
+ return true;
202
+ }
203
+ try {
204
+ chatSdkTelegramRegisterWebhookRoute.respond(res, 200, await registerTelegramWebhook());
205
+ } catch (error) {
206
+ if (!(error instanceof ChatSdkActionError)) throw error;
207
+ jsonError(res, error.message, error.status);
208
+ }
209
+ return true;
210
+ }
211
+
125
212
  if (mcpUserConfigRoute.match(req.method, pathSegments)) {
126
213
  const mcpBaseUrl = await resolveMcpBaseUrl();
127
214
  mcpUserConfigRoute.respond(res, 200, { mcpBaseUrl, mcpUserUrl: `${mcpBaseUrl}/mcp-user` });
package/src/http/mcp.ts CHANGED
@@ -7,7 +7,12 @@ import { createServer } from "@/server";
7
7
  import { parseEnvFlag } from "@/utils/env-flag";
8
8
  import { getRequestAuth } from "@/utils/request-auth-context";
9
9
  import { resolveScriptsOnlyMode } from "@/utils/scripts-only-mode";
10
- import { parseTaskToolManifest, selectTaskTools } from "@/utils/task-tool-manifest";
10
+ import {
11
+ CHAT_TASK_ONLY_TOOLS,
12
+ isChatSdkTask,
13
+ parseTaskToolManifest,
14
+ selectTaskTools,
15
+ } from "@/utils/task-tool-manifest";
11
16
 
12
17
  export type McpTransportActivity = Record<string, number>;
13
18
  export type McpSessionAgents = Record<string, string>;
@@ -218,18 +223,22 @@ export async function handleMcp(
218
223
  true,
219
224
  );
220
225
  let preloadedTools: string[] = [];
226
+ const sourceTaskId = headerValue(req.headers["x-source-task-id"]);
227
+ const sourceTask = sourceTaskId ? await getTaskById(sourceTaskId) : undefined;
228
+ // A session bound to a non-chat task never sees chat-reply. Without the
229
+ // header the tool stays, and resolves the agent's current task itself.
230
+ const excludedTools =
231
+ sourceTask && !isChatSdkTask(sourceTask) ? [...CHAT_TASK_ONLY_TOOLS] : [];
221
232
  if (preloadEnabled) {
222
- const taskId = headerValue(req.headers["x-source-task-id"]);
223
- const task = taskId ? await getTaskById(taskId) : undefined;
224
233
  // Never select a manifest using another agent's task. Session-token
225
234
  // identity is also checked above, before any MCP session is created.
226
- if (task?.agentId === agentId) {
235
+ if (sourceTask?.agentId === agentId) {
227
236
  const manifestValue =
228
237
  configs.find((config) => config.key === "TASK_TOOL_MANIFESTS")?.value ??
229
238
  process.env.TASK_TOOL_MANIFESTS ??
230
239
  "{}";
231
240
  try {
232
- preloadedTools = selectTaskTools(parseTaskToolManifest(manifestValue), task);
241
+ preloadedTools = selectTaskTools(parseTaskToolManifest(manifestValue), sourceTask);
233
242
  } catch {
234
243
  // An invalid deployment value must not prevent tool discovery.
235
244
  // Avoid logging its contents, which may contain misfiled secrets.
@@ -239,6 +248,7 @@ export async function handleMcp(
239
248
  }
240
249
  const server = await createServer({
241
250
  preloadedTools,
251
+ excludedTools,
242
252
  // Agent row, then global row, then deployment env. A blank agent row
243
253
  // resolves to "unset" for that agent.
244
254
  enabledTools: