@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
@@ -56,6 +56,12 @@ export const registerRequestHumanInputTool = (server: McpServer) => {
56
56
  .describe(
57
57
  "Seconds until the request expires. After that the request becomes 'timeout' and you get a hitl-follow-up task. A request with no timeout is cancelled after APPROVAL_REQUEST_AUTO_CANCELLATION_DAYS days (default 7).",
58
58
  ),
59
+ detached: z
60
+ .boolean()
61
+ .optional()
62
+ .describe(
63
+ "Do not attach the request to your current task, so no hitl-follow-up task is created. For scripts that read the request's status themselves.",
64
+ ),
59
65
  }),
60
66
  outputSchema: swarmToolOutputSchema({
61
67
  yourAgentId: z.string().optional(),
@@ -63,7 +69,7 @@ export const registerRequestHumanInputTool = (server: McpServer) => {
63
69
  url: z.string().optional(),
64
70
  }),
65
71
  },
66
- async ({ title, questions, timeoutSeconds }, requestInfo) => {
72
+ async ({ title, questions, timeoutSeconds, detached }, requestInfo) => {
67
73
  if (!requestInfo.agentId) {
68
74
  return toolErr(
69
75
  'Agent ID not found. The MCP client should define the "X-Agent-ID" header.',
@@ -74,8 +80,10 @@ export const registerRequestHumanInputTool = (server: McpServer) => {
74
80
  // Resolve sourceTaskId: prefer header, fall back to agent's current in-progress task.
75
81
  // The X-Source-Task-Id header may be missing when the per-session MCP config wasn't
76
82
  // created (e.g. .mcp.json not found, session resumed, or lead agent on a non-task trigger).
77
- let sourceTaskId = requestInfo.sourceTaskId;
78
- if (!sourceTaskId && requestInfo.agentId) {
83
+ // A detached request has no source task: a script call carries no task
84
+ // header, and the agent's current task is unrelated to the script.
85
+ let sourceTaskId = detached ? undefined : requestInfo.sourceTaskId;
86
+ if (!sourceTaskId && !detached && requestInfo.agentId) {
79
87
  const currentTask = await getAgentCurrentTask(requestInfo.agentId);
80
88
  if (currentTask) {
81
89
  sourceTaskId = currentTask.id;
@@ -149,7 +149,11 @@ export const registerScriptApisTool = (server: McpServer) => {
149
149
  agentId: args.agentId,
150
150
  },
151
151
  requestInfo,
152
- successMessage: (data) => `Endpoint ${(data as ScriptApiWithSecret).id} created.`,
152
+ successMessage: (data) => {
153
+ const warnings = (data as { warnings?: string[] }).warnings ?? [];
154
+ const note = warnings.length > 0 ? `\n${warnings.join("\n")}` : "";
155
+ return `Endpoint ${(data as ScriptApiWithSecret).id} created.${note}`;
156
+ },
153
157
  successDetails: (data) => {
154
158
  const token = (data as ScriptApiWithSecret).token;
155
159
  return token ? `Bearer token (shown once — save it now): ${token}` : undefined;
@@ -47,11 +47,14 @@ export const registerScriptUpsertTool = (server: McpServer) => {
47
47
  name?: unknown;
48
48
  version?: unknown;
49
49
  contentDeduped?: unknown;
50
+ warnings?: unknown;
50
51
  };
51
52
  const name = typeof body.name === "string" ? body.name : args.name;
52
53
  const version = typeof body.version === "number" ? ` v${body.version}` : "";
53
54
  const deduped = body.contentDeduped ? " (content unchanged — deduped)" : "";
54
- return `Script \`${name}\`${version} saved.${deduped}`;
55
+ const warnings = Array.isArray(body.warnings) ? body.warnings.map(String) : [];
56
+ const note = warnings.length > 0 ? `\n${warnings.join("\n")}` : "";
57
+ return `Script \`${name}\`${version} saved.${deduped}${note}`;
55
58
  },
56
59
  }),
57
60
  );
@@ -18,6 +18,7 @@ import {
18
18
  isExtensionAgent,
19
19
  isLinearTrackerContextKey,
20
20
  } from "@/be/db";
21
+ import { modelProfileRefError, taskProfileError } from "@/be/db/model-profiles";
21
22
  import { repointTrackerSyncBySwarmId } from "@/be/db-queries/tracker";
22
23
  import { explicitModelErrorForAgent } from "@/be/model-validation";
23
24
  import { applyPreTaskCreate } from "@/extensions/apply-task-create";
@@ -150,6 +151,14 @@ export const sendTaskInputSchema = z
150
151
  effort: ReasoningEffortSchema.optional().describe(
151
152
  "Reasoning effort for this task: 'off', 'low', 'medium', 'high', 'xhigh', or 'max'. If omitted, the assignee's REASONING_EFFORT_OVERRIDE/default applies.",
152
153
  ),
154
+ profile: z
155
+ .string()
156
+ .trim()
157
+ .min(1)
158
+ .optional()
159
+ .describe(
160
+ "Model profile name (see list-model-profiles): a named harness + model + effort, applied when the task is claimed. Must run on the assignee's harness. Exclusive with model and modelTier. A set `effort` still wins over the profile's.",
161
+ ),
153
162
  allowDuplicate: z
154
163
  .boolean()
155
164
  .default(false)
@@ -281,6 +290,7 @@ export async function sendTaskHandler(
281
290
  modelTier,
282
291
  allowCustomModel,
283
292
  effort,
293
+ profile,
284
294
  allowDuplicate,
285
295
  slackChannelId,
286
296
  slackThreadTs,
@@ -378,6 +388,30 @@ export async function sendTaskHandler(
378
388
  const effectiveParentTask = effectiveParentTaskId
379
389
  ? await getTaskById(effectiveParentTaskId)
380
390
  : null;
391
+ // The child inherits the parent's contextKey (its Slack or chat thread) and requester, and
392
+ // thread-scoped tools trust that binding. An agent can only build on a parent it owns or
393
+ // created; otherwise a worker could mint access to a foreign thread.
394
+ if (ctx.kind === "owner" && creatorAgentId && effectiveParentTask) {
395
+ const caller = await getAgentById(creatorAgentId);
396
+ const decision = can({
397
+ principal: { kind: "agent", agentId: creatorAgentId, isLead: caller?.isLead ?? false },
398
+ verb: "task.parent.attach",
399
+ resource: {
400
+ kind: "task",
401
+ taskId: effectiveParentTask.id,
402
+ requestedByUserId: effectiveParentTask.requestedByUserId,
403
+ creatorAgentId: effectiveParentTask.creatorAgentId,
404
+ agentId: effectiveParentTask.agentId,
405
+ },
406
+ source: "mcp",
407
+ });
408
+ if (!decision.allow) {
409
+ return toolErr(
410
+ `You don't have context for parent task ${effectiveParentTask.id}. Only its assignee, its creator, or a lead can create a child task under it.`,
411
+ { data: { yourAgentId: creatorAgentId } },
412
+ );
413
+ }
414
+ }
381
415
  if (effectiveParentTask?.routingAffinityInvalid) {
382
416
  return toolErr("Cannot continue a task with an invalid routing affinity.", {
383
417
  data: { yourAgentId: creatorAgentId },
@@ -450,6 +484,13 @@ export async function sendTaskHandler(
450
484
  agentId: effectiveAgentId,
451
485
  });
452
486
  if (modelError) return toolErr(modelError, { data: { yourAgentId: creatorAgentId } });
487
+ const profileError = await taskProfileError({
488
+ profile,
489
+ model: normalizedModel.model,
490
+ modelTier: normalizedModel.modelTier,
491
+ agentId: effectiveAgentId,
492
+ });
493
+ if (profileError) return toolErr(profileError, { data: { yourAgentId: creatorAgentId } });
453
494
  const effectiveRoutingReason =
454
495
  requestedAgentId !== undefined
455
496
  ? requestedRoutingReason
@@ -484,6 +525,7 @@ export async function sendTaskHandler(
484
525
  model: normalizedModel.model,
485
526
  modelTier: normalizedModel.modelTier,
486
527
  effort,
528
+ profile,
487
529
  slackChannelId,
488
530
  slackThreadTs,
489
531
  slackUserId,
@@ -623,7 +665,7 @@ export async function sendTaskHandler(
623
665
  : toolErr(guard.message, { data: guardData });
624
666
  }
625
667
 
626
- const result = await getDbClient().transaction(async () => {
668
+ const created = getDbClient().transaction(async () => {
627
669
  // Authoritative re-check: the reads above are separated from the INSERT by
628
670
  // the whole handler, so only a guard inside this transaction can see a
629
671
  // concurrent send-task's committed task.
@@ -719,6 +761,11 @@ export async function sendTaskHandler(
719
761
  task: newTask,
720
762
  };
721
763
  });
764
+ const result = await created.catch((error: unknown) => {
765
+ // The profile was deleted between taskProfileError and the insert.
766
+ if (modelProfileRefError(error) !== "missing") throw error;
767
+ return { success: false, message: `Unknown model profile "${profile}".`, task: undefined };
768
+ });
722
769
 
723
770
  const data = {
724
771
  yourAgentId: creatorAgentId,
@@ -1,6 +1,7 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import * as z from "zod";
3
3
  import { getSkillById, getSkillByName } from "@/be/db";
4
+ import { resolveSwarmSkillByName } from "@/be/db/skill-name-resolution";
4
5
  import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
5
6
 
6
7
  export const registerSkillGetTool = (server: McpServer) => {
@@ -10,7 +11,7 @@ export const registerSkillGetTool = (server: McpServer) => {
10
11
  title: "Get Skill",
11
12
  annotations: { destructiveHint: false },
12
13
  description:
13
- "Get full skill content by ID or name. Name resolution checks agent scope first, then swarm, then global.",
14
+ "Get full skill content by ID or name. Name resolution checks agent scope first, then swarm, then global. In swarm scope the ownerless skill wins, then your own, then the only agent-owned one; when several other agents own that name, it errors with their IDs: pass skillId instead.",
14
15
  inputSchema: z.object({
15
16
  skillId: z.string().optional().describe("Skill ID"),
16
17
  name: z.string().optional().describe("Skill name (resolved with precedence)"),
@@ -29,15 +30,22 @@ export const registerSkillGetTool = (server: McpServer) => {
29
30
 
30
31
  if (args.skillId) {
31
32
  skill = await getSkillById(args.skillId);
32
- } else if (args.name && requestInfo.agentId) {
33
- // Precedence: agent (personal) → swarm → global
34
- skill =
35
- (await getSkillByName(args.name, "agent", requestInfo.agentId)) ||
36
- (await getSkillByName(args.name, "swarm")) ||
37
- (await getSkillByName(args.name, "global"));
38
33
  } else if (args.name) {
39
- skill =
40
- (await getSkillByName(args.name, "swarm")) || (await getSkillByName(args.name, "global"));
34
+ // Precedence: agent (personal) → swarm → global
35
+ if (requestInfo.agentId) {
36
+ skill = await getSkillByName(args.name, "agent", requestInfo.agentId);
37
+ }
38
+ if (!skill) {
39
+ const swarm = await resolveSwarmSkillByName(args.name, requestInfo.agentId);
40
+ if (swarm.kind === "ambiguous") {
41
+ return toolErr(
42
+ `Skill name "${args.name}" matches ${swarm.skillIds.length} swarm skills owned by other agents: ${swarm.skillIds.join(", ")}. Call skill-get with skillId instead.`,
43
+ { data: { yourAgentId: requestInfo.agentId } },
44
+ );
45
+ }
46
+ if (swarm.kind === "found") skill = await getSkillById(swarm.skillId);
47
+ }
48
+ if (!skill) skill = await getSkillByName(args.name, "global");
41
49
  }
42
50
 
43
51
  if (!skill) {
@@ -19,6 +19,7 @@ const configEntryShape = z.looseObject({
19
19
  createdAt: z.string().optional(),
20
20
  lastUpdatedAt: z.string().optional(),
21
21
  encrypted: z.boolean().optional(),
22
+ exportToEnv: z.boolean().optional(),
22
23
  });
23
24
 
24
25
  export const registerGetConfigTool = (server: McpServer) => {
@@ -110,7 +111,7 @@ export const registerGetConfigTool = (server: McpServer) => {
110
111
  : result
111
112
  .map(
112
113
  (c) =>
113
- `- ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""})`,
114
+ `- ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""}${c.exportToEnv ? "" : ", not in agent env"})`,
114
115
  )
115
116
  .join("\n");
116
117
 
@@ -19,6 +19,7 @@ const configEntryShape = z.looseObject({
19
19
  createdAt: z.string().optional(),
20
20
  lastUpdatedAt: z.string().optional(),
21
21
  encrypted: z.boolean().optional(),
22
+ exportToEnv: z.boolean().optional(),
22
23
  });
23
24
 
24
25
  export const registerListConfigTool = (server: McpServer) => {
@@ -102,7 +103,7 @@ export const registerListConfigTool = (server: McpServer) => {
102
103
  : result
103
104
  .map(
104
105
  (c) =>
105
- `- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value}${c.description ? ` — ${c.description}` : ""}`,
106
+ `- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value}${c.exportToEnv ? "" : " [not in agent env]"}${c.description ? ` — ${c.description}` : ""}`,
106
107
  )
107
108
  .join("\n");
108
109
 
@@ -8,6 +8,7 @@ import {
8
8
  isReservedConfigKey,
9
9
  reservedKeyError,
10
10
  validateConfigValue,
11
+ validateExportToEnv,
11
12
  } from "@/be/swarm-config-guard";
12
13
  import { scheduleIntegrationsReload } from "@/http/core";
13
14
  import { can } from "@/rbac";
@@ -26,6 +27,7 @@ const configEntryShape = z.looseObject({
26
27
  createdAt: z.string().optional(),
27
28
  lastUpdatedAt: z.string().optional(),
28
29
  encrypted: z.boolean().optional(),
30
+ exportToEnv: z.boolean().optional(),
29
31
  });
30
32
 
31
33
  export const registerSetConfigTool = (server: McpServer) => {
@@ -34,7 +36,7 @@ export const registerSetConfigTool = (server: McpServer) => {
34
36
  {
35
37
  title: "Set Config",
36
38
  description:
37
- "Set or update a swarm configuration value. Upserts by (scope, scopeId, key). Use scope='global' for server-wide settings, 'agent' for agent-specific, or 'repo' for repo-specific. Set isSecret=true to mask the value in API responses.",
39
+ "Set or update a swarm configuration value. Upserts by (scope, scopeId, key). Use scope='global' for server-wide settings, 'agent' for agent-specific, or 'repo' for repo-specific. Set isSecret=true to mask the value in API responses. Set exportToEnv=false to keep the row out of agent process env (agents then reach it through a connection or script credential binding).",
38
40
  annotations: { idempotentHint: true },
39
41
 
40
42
  inputSchema: z.object({
@@ -63,13 +65,22 @@ export const registerSetConfigTool = (server: McpServer) => {
63
65
  .string()
64
66
  .optional()
65
67
  .describe("Optional human-readable description of this config entry."),
68
+ exportToEnv: z
69
+ .boolean()
70
+ .optional()
71
+ .describe(
72
+ "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.",
73
+ ),
66
74
  }),
67
75
  outputSchema: swarmToolOutputSchema({
68
76
  yourAgentId: z.string().optional(),
69
77
  config: configEntryShape.optional(),
70
78
  }),
71
79
  },
72
- async ({ scope, scopeId, key, value, isSecret, envPath, description }, requestInfo) => {
80
+ async (
81
+ { scope, scopeId, key, value, isSecret, envPath, description, exportToEnv },
82
+ requestInfo,
83
+ ) => {
73
84
  if (!requestInfo.agentId) {
74
85
  return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
75
86
  }
@@ -114,7 +125,8 @@ export const registerSetConfigTool = (server: McpServer) => {
114
125
  });
115
126
  }
116
127
 
117
- const validationError = validateConfigValue(key, value);
128
+ const validationError =
129
+ validateConfigValue(key, value) ?? validateExportToEnv(key, exportToEnv);
118
130
  if (validationError) {
119
131
  return toolErr(validationError, { data: { yourAgentId: requestInfo.agentId } });
120
132
  }
@@ -127,6 +139,7 @@ export const registerSetConfigTool = (server: McpServer) => {
127
139
  isSecret,
128
140
  envPath,
129
141
  description,
142
+ exportToEnv,
130
143
  });
131
144
 
132
145
  if (scope === "global") {
@@ -0,0 +1,104 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import * as z from "zod";
3
+ import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
4
+ import { getExecutorRegistry } from "@/workflows";
5
+ import {
6
+ SYSTEM_ONE_DECISION_NODE_TYPE,
7
+ SystemOneDecisionConfigSchema,
8
+ SystemOneDecisionExecutor,
9
+ } from "@/workflows/executors/system-one-decision";
10
+ import { SYSTEM_ONE_PROVIDER_IDS } from "@/workflows/executors/system-one-providers";
11
+
12
+ /**
13
+ * One typed decision (Jev and the other SystemOne hosts) made in the API
14
+ * process, the same way a `system-one-decision` workflow node makes it. The
15
+ * provider credential is read and sent here and never reaches the caller, so a
16
+ * script can ask for a decision without a credential binding in its own realm.
17
+ */
18
+ export const registerSystemOneDecideTool = (server: McpServer) => {
19
+ createToolRegistrar(server)(
20
+ "system-one-decide",
21
+ {
22
+ title: "Ask a SystemOne decision model",
23
+ annotations: { destructiveHint: false, openWorldHint: true },
24
+ description:
25
+ "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev, and return the validated answers. " +
26
+ "Same request, provider list, credentials and validation as the `system-one-decision` workflow node, without its human review band. " +
27
+ "The provider credential is a global secret that stays on the server; this tool never returns it.",
28
+ inputSchema: z.object({
29
+ provider: z
30
+ .enum(SYSTEM_ONE_PROVIDER_IDS)
31
+ .optional()
32
+ .describe("Decision host (default typesafe)"),
33
+ model: z.string().min(1).optional().describe("Provider model id (default: the provider's)"),
34
+ state: z
35
+ .union([z.string(), z.array(z.string()), z.record(z.string(), z.unknown())])
36
+ .describe("The state to decide on"),
37
+ questions: z
38
+ .record(z.string(), z.record(z.string(), z.unknown()))
39
+ .describe(
40
+ "Questions by id, each `{ type: 'noul' | 'choice' | 'score', instructions, criteria }`",
41
+ ),
42
+ timeoutMs: z
43
+ .number()
44
+ .int()
45
+ .optional()
46
+ .describe("Time budget for the call, retries included (default 30000)"),
47
+ maxRetries: z
48
+ .number()
49
+ .int()
50
+ .optional()
51
+ .describe("Retries on transient failures inside the time budget (default 2)"),
52
+ }),
53
+ outputSchema: swarmToolOutputSchema({
54
+ model: z.string().optional(),
55
+ answers: z.record(z.string(), z.unknown()).optional(),
56
+ usage: z.record(z.string(), z.unknown()).optional(),
57
+ requestId: z.string().optional(),
58
+ }),
59
+ },
60
+ async ({ provider, model, state, questions, timeoutMs, maxRetries }, requestInfo) => {
61
+ if (!requestInfo.agentId) {
62
+ return toolErr('Agent ID not found. The MCP client should define the "X-Agent-ID" header.');
63
+ }
64
+
65
+ // `returns` mirrors the questions: the caller reads answers directly, so
66
+ // there is no downstream port to declare.
67
+ const returns = Object.fromEntries(
68
+ Object.entries(questions).map(([id, question]) => [id, { type: question.type }]),
69
+ );
70
+ const parsed = SystemOneDecisionConfigSchema.safeParse({
71
+ provider,
72
+ model,
73
+ state,
74
+ questions,
75
+ returns,
76
+ timeoutMs,
77
+ maxRetries,
78
+ });
79
+ if (!parsed.success) {
80
+ const issues = parsed.error.issues
81
+ .map((issue) => `${issue.path.join(".") || "(root)"}: ${issue.message}`)
82
+ .join("; ");
83
+ return toolErr(`Invalid decision request: ${issues}`.slice(0, 1000));
84
+ }
85
+
86
+ const executor = getExecutorRegistry().get(SYSTEM_ONE_DECISION_NODE_TYPE);
87
+ if (!(executor instanceof SystemOneDecisionExecutor)) {
88
+ return toolErr("The system-one-decision executor is not available");
89
+ }
90
+ const decided = await executor.decide(parsed.data);
91
+ if (!decided.ok) return toolErr(decided.error);
92
+
93
+ const { output } = decided;
94
+ return toolOk(`Decision from ${output.model}`, {
95
+ data: {
96
+ model: output.model,
97
+ answers: output.answers,
98
+ usage: output.usage,
99
+ requestId: output.requestId,
100
+ },
101
+ });
102
+ },
103
+ );
104
+ };
@@ -28,6 +28,7 @@ import {
28
28
  releaseTask,
29
29
  updateTaskClaudeSessionId,
30
30
  } from "@/be/db";
31
+ import { modelProfileRefError, taskProfileError } from "@/be/db/model-profiles";
31
32
  import { explicitModelErrorForAgent } from "@/be/model-validation";
32
33
  import { touchRuntimeInstance } from "@/be/multi-runtime";
33
34
  import { applyPreTaskCreate } from "@/extensions/apply-task-create";
@@ -109,6 +110,14 @@ export const taskActionInputSchema = z.object({
109
110
  effort: ReasoningEffortSchema.optional().describe(
110
111
  "Reasoning effort for the created task: 'off', 'low', 'medium', 'high', 'xhigh', or 'max'. Only used with 'create' action.",
111
112
  ),
113
+ profile: z
114
+ .string()
115
+ .trim()
116
+ .min(1)
117
+ .optional()
118
+ .describe(
119
+ "Model profile name for the created pool task (see list-model-profiles); only workers on its harness claim it. Exclusive with model and modelTier. Only used with 'create' action.",
120
+ ),
112
121
  requiredCapabilities: z
113
122
  .array(z.string())
114
123
  .optional()
@@ -296,6 +305,12 @@ export async function taskActionHandler(
296
305
  allowCustomModel: input.allowCustomModel,
297
306
  });
298
307
  if (modelError) return taskActionResult({ success: false, message: modelError }, agentId);
308
+ const profileError = await taskProfileError({
309
+ profile: input.profile,
310
+ model: normalizedModel.model,
311
+ modelTier: normalizedModel.modelTier,
312
+ });
313
+ if (profileError) return taskActionResult({ success: false, message: profileError }, agentId);
299
314
  try {
300
315
  assetKey = key
301
316
  ? await authorizeAssetKeyWrite(key, await resolveTaskAuditUserId(ctx.sourceTaskId, agentId))
@@ -324,6 +339,7 @@ export async function taskActionHandler(
324
339
  model: normalizedModel.model,
325
340
  modelTier: normalizedModel.modelTier,
326
341
  effort: input.effort,
342
+ profile: input.profile,
327
343
  routingAffinity:
328
344
  leadOnly || requiredCapabilities?.length
329
345
  ? { leadOnly, capabilities: requiredCapabilities ?? [] }
@@ -342,7 +358,7 @@ export async function taskActionHandler(
342
358
  };
343
359
  }
344
360
 
345
- const result = await getDbClient().transaction(async (): Promise<TaskActionResult> => {
361
+ const transacted = getDbClient().transaction(async (): Promise<TaskActionResult> => {
346
362
  switch (action) {
347
363
  case "create": {
348
364
  const newTask = await createTaskExtended(
@@ -644,6 +660,11 @@ export async function taskActionHandler(
644
660
  return { success: false, message: `Unknown action: ${action}` };
645
661
  }
646
662
  });
663
+ const result = await transacted.catch((error: unknown): TaskActionResult => {
664
+ // A create whose profile was deleted between taskProfileError and the insert.
665
+ if (modelProfileRefError(error) !== "missing") throw error;
666
+ return { success: false, message: `Unknown model profile "${input.profile}".` };
667
+ });
647
668
 
648
669
  // Phase 5: when the accept gate refused, run after-commit side
649
670
  // effects (lead follow-up + workflow bus). The dedup row was recorded
@@ -72,12 +72,6 @@ export const DEFERRED_TOOLS = new Set([
72
72
  "retry-workflow-run",
73
73
  "cancel-workflow-run",
74
74
 
75
- // Services (4)
76
- "register-service",
77
- "unregister-service",
78
- "list-services",
79
- "update-service-status",
80
-
81
75
  // Config (7)
82
76
  "set-config",
83
77
  "list-config",
@@ -87,6 +81,9 @@ export const DEFERRED_TOOLS = new Set([
87
81
  "model-catalog-refresh",
88
82
  "model-catalog-overlay-upsert",
89
83
 
84
+ // Model profiles (1)
85
+ "list-model-profiles",
86
+
90
87
  // Repos (1)
91
88
  "update-repo",
92
89
 
@@ -127,6 +124,14 @@ export const DEFERRED_TOOLS = new Set([
127
124
  "send-whatsapp-message",
128
125
  "reply-whatsapp-message",
129
126
 
127
+ // Chat SDK (6)
128
+ "chat-reply",
129
+ "chat-post",
130
+ "chat-open-dm",
131
+ "chat-read-thread",
132
+ "register-chat-channel",
133
+ "unregister-chat-channel",
134
+
130
135
  // Tracker (7)
131
136
  "tracker-status",
132
137
  "get-oauth-access-token",
@@ -149,6 +154,9 @@ export const DEFERRED_TOOLS = new Set([
149
154
  "request-human-input",
150
155
  "cancel-approval-request",
151
156
 
157
+ // Decisions (1)
158
+ "system-one-decide",
159
+
152
160
  // Skills (12)
153
161
  "skill-create",
154
162
  "skill-update",
package/src/types.ts CHANGED
@@ -391,6 +391,7 @@ export const AgentTaskSourceSchema = z.enum([
391
391
  "linear",
392
392
  "jira",
393
393
  "comb",
394
+ "chat",
394
395
  ]);
395
396
  export type AgentTaskSource = z.infer<typeof AgentTaskSourceSchema>;
396
397
 
@@ -427,6 +428,31 @@ export const ProviderNameSchema = z.enum([
427
428
  ]);
428
429
  export type ProviderName = z.infer<typeof ProviderNameSchema>;
429
430
 
431
+ // ============================================================================
432
+ // Model Profiles (runbooks/model-tiers.md § Model profiles)
433
+ // ============================================================================
434
+
435
+ /** Lowercase, starts with a letter or digit; dots, dashes and underscores allowed. */
436
+ export const ModelProfileNameSchema = z
437
+ .string()
438
+ .trim()
439
+ .regex(/^[a-z0-9][a-z0-9._-]{0,99}$/, "lowercase letters, digits, '.', '_' or '-', max 100");
440
+
441
+ export const ModelProfileSchema = z.object({
442
+ id: z.string(),
443
+ name: z.string(),
444
+ harness: ProviderNameSchema,
445
+ model: z.string(),
446
+ effort: ReasoningEffortSchema.nullable(),
447
+ allowCustomModel: z.boolean(),
448
+ description: z.string().nullable(),
449
+ /** `tier:<tier>` (boot seed), `agent-config` (made from an agent's MODEL_OVERRIDE), or null. */
450
+ seededFrom: z.string().nullable(),
451
+ createdAt: z.string(),
452
+ lastUpdatedAt: z.string(),
453
+ });
454
+ export type ModelProfile = z.infer<typeof ModelProfileSchema>;
455
+
430
456
  // ============================================================================
431
457
  // Task Steering Messages
432
458
  // ============================================================================
@@ -446,7 +472,7 @@ export const SteeringStatusSchema = z.enum([
446
472
  ]);
447
473
  export type SteeringStatus = z.infer<typeof SteeringStatusSchema>;
448
474
 
449
- export const SteeringSourceSchema = z.enum(["ui", "mcp", "script", "slack", "api"]);
475
+ export const SteeringSourceSchema = z.enum(["ui", "mcp", "script", "slack", "api", "chat"]);
450
476
  export type SteeringSource = z.infer<typeof SteeringSourceSchema>;
451
477
 
452
478
  export const SteeringMessageSchema = z
@@ -681,6 +707,15 @@ export const AgentTaskSchema = z
681
707
  resolvedModel: z.string().optional(),
682
708
  modelSource: z.string().optional(),
683
709
  modelAlias: z.string().optional(),
710
+ // The effort the session ran at (task effort, else the agent's
711
+ // REASONING_EFFORT_OVERRIDE, dropped when the harness/model cannot take
712
+ // it). Reported at session start; unset when the harness default applied.
713
+ resolvedEffort: ReasoningEffortSchema.optional(),
714
+ // Model profile (runbooks/model-tiers.md § Model profiles): `profile` is
715
+ // the creator's ask, `resolvedProfile` the name claim applied (the ask or
716
+ // the agent's default). Unset when no profile applied.
717
+ profile: z.string().optional(),
718
+ resolvedProfile: z.string().optional(),
684
719
 
685
720
  // Schedule linking (optional — set when task was created by a schedule).
686
721
  // z.string(): also reachable verbatim from the create-task query param.
@@ -812,6 +847,7 @@ export const CreateTaskOptionsSchema = z.object({
812
847
  model: z.string().optional(),
813
848
  modelTier: ModelTierSchema.optional(),
814
849
  effort: ReasoningEffortSchema.optional(),
850
+ profile: z.string().optional(),
815
851
  scheduleId: z.string().optional(),
816
852
  workflowRunId: z.string().optional(),
817
853
  workflowRunStepId: z.string().optional(),
@@ -1458,7 +1494,7 @@ export type ChannelType = z.infer<typeof ChannelTypeSchema>;
1458
1494
  export type Channel = z.infer<typeof ChannelSchema>;
1459
1495
  export type ChannelMessage = z.infer<typeof ChannelMessageSchema>;
1460
1496
 
1461
- // Service Types (for PM2/background services)
1497
+ // Service Types (removed PM2 service registry; kept with the services table)
1462
1498
  export const ServiceStatusSchema = z.enum(["starting", "healthy", "unhealthy", "stopped"]);
1463
1499
 
1464
1500
  export const ServiceSchema = z
@@ -1834,6 +1870,10 @@ export const SwarmConfigSchema = z
1834
1870
  // auto-encrypted during initDb; if that fails, boot aborts before normal API
1835
1871
  // reads occur.
1836
1872
  encrypted: z.boolean(),
1873
+ // Whether workers export this row into agent process env. False keeps it
1874
+ // server-side (connections, script credential bindings). Always false for
1875
+ // keys only the API server reads (src/utils/config-env-export.ts).
1876
+ exportToEnv: z.boolean(),
1837
1877
  })
1838
1878
  .openapi("SwarmConfig");
1839
1879
 
@@ -2394,7 +2434,11 @@ export const TriggerConfigSchema = z
2394
2434
  }),
2395
2435
  z.object({
2396
2436
  type: z.literal("event"),
2397
- eventName: z.literal("slack.message"),
2437
+ eventName: z.enum([
2438
+ "slack.message",
2439
+ "azure-devops.work_item.assigned",
2440
+ "azure-devops.work_item.commented",
2441
+ ]),
2398
2442
  }),
2399
2443
  ])
2400
2444
  .superRefine((trigger, ctx) => {
@@ -2625,6 +2669,7 @@ export type AgentTaskSummary = Pick<
2625
2669
  | "modelSource"
2626
2670
  | "modelAlias"
2627
2671
  | "effort"
2672
+ | "resolvedEffort"
2628
2673
  | "provider"
2629
2674
  | "requestedByUserId"
2630
2675
  | "progress"