@desplega.ai/agent-swarm 1.173.0 → 2.0.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 (432) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-sj2g0m84.js} +17 -16
  3. package/dist/{actions-sgeyv08k.js → actions-fegk44gr.js} +39 -34
  4. package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-ad8ft89x.js} +8 -7
  5. package/dist/{app-km9qnv2f.js → app-kfvgbvzy.js} +18 -14
  6. package/dist/{assistant-5r8tcvvd.js → assistant-z7zdy9ja.js} +40 -35
  7. package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-5c2z0mbe.js} +10 -9
  8. package/dist/{boot-reembed-16rv9843.js → boot-reembed-j8xa181e.js} +10 -9
  9. package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-hnkn3rgt.js} +11 -10
  10. package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-kwjq4d2z.js} +14 -13
  11. package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-9vmvpvgd.js} +19 -18
  12. package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-k9qae05j.js} +7 -5
  13. package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-q54zx5q2.js} +6 -4
  14. package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-9jye6cxr.js} +11881 -11472
  15. package/dist/{cli-94b48jhk.js → cli-03gedhng.js} +16 -14
  16. package/dist/{cli-1w0vj3gw.js → cli-1e4b6bzh.js} +7 -7
  17. package/dist/{cli-d603qf86.js → cli-29jc5q7w.js} +10 -8
  18. package/dist/cli-2m1ktfzz.js +17795 -0
  19. package/dist/{cli-x119kdba.js → cli-3dj8k4vy.js} +1 -1
  20. package/dist/{cli-srqq3gc5.js → cli-3fbmmawm.js} +5 -5
  21. package/dist/{cli-gmdajfw5.js → cli-4jxm2qtz.js} +4987 -1708
  22. package/dist/{cli-tadfgd0t.js → cli-5hkm7whv.js} +33 -4
  23. package/dist/{cli-42qhyvwx.js → cli-5t4f29ez.js} +3 -3
  24. package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
  25. package/dist/cli-6cvfxs8r.js +47 -0
  26. package/dist/{cli-0kxf81jj.js → cli-6jyj59nb.js} +2 -2
  27. package/dist/{cli-w1apjecb.js → cli-6razj6t4.js} +2 -2
  28. package/dist/{cli-anzdk0z4.js → cli-74ahz61x.js} +2 -2
  29. package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
  30. package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
  31. package/dist/{cli-81r1wjyv.js → cli-9nfx44eh.js} +1 -1
  32. package/dist/cli-9traj3dn.js +638 -0
  33. package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
  34. package/dist/{cli-na2pxe4f.js → cli-apx87jne.js} +2 -2
  35. package/dist/{cli-rfz2ve55.js → cli-bzszjf2p.js} +2855 -862
  36. package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
  37. package/dist/{cli-hsem16hb.js → cli-cgtksawx.js} +7 -4
  38. package/dist/{cli-db3m6zdt.js → cli-d2qr7aj4.js} +1 -1
  39. package/dist/{cli-rfs4vddv.js → cli-d5f9ed5c.js} +5 -5
  40. package/dist/cli-e3g5mbkz.js +776 -0
  41. package/dist/{cli-7jykv7ef.js → cli-e6mpjhed.js} +1 -1
  42. package/dist/{cli-7a93cv8c.js → cli-ee9gtz70.js} +98 -23
  43. package/dist/{cli-3nxdmjrc.js → cli-eejsgvm4.js} +4 -4
  44. package/dist/{cli-fmhj1ehj.js → cli-ef1hg1wv.js} +470 -51
  45. package/dist/cli-f527ce74.js +781 -0
  46. package/dist/{cli-ppy4nnnh.js → cli-f7kr7svz.js} +2 -2
  47. package/dist/cli-hjwmhcg1.js +10622 -0
  48. package/dist/{cli-2bw3w47j.js → cli-hnhtk6cj.js} +1 -1
  49. package/dist/{cli-ywm1azg9.js → cli-hnmhtzvh.js} +6 -4
  50. package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
  51. package/dist/{cli-s8z6x4b4.js → cli-j0pfptdp.js} +218 -102
  52. package/dist/cli-jta2eyzc.js +619 -0
  53. package/dist/{cli-5er5gjbm.js → cli-k382tshb.js} +10 -11
  54. package/dist/{cli-v3zhnxsb.js → cli-k3dp5tpf.js} +2 -2
  55. package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
  56. package/dist/cli-kceah1eh.js +92 -0
  57. package/dist/{cli-ne7smj1b.js → cli-ke896fcf.js} +10 -10
  58. package/dist/{cli-xc7p7s3g.js → cli-kt6zqg0e.js} +6 -6
  59. package/dist/{cli-wrh08zjd.js → cli-m50t4309.js} +5 -18
  60. package/dist/cli-n2wq4j7m.js +6985 -0
  61. package/dist/{cli-bv2etw2y.js → cli-n3hzg89b.js} +46 -15
  62. package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
  63. package/dist/{cli-qm1448f9.js → cli-ne236afy.js} +8 -8
  64. package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
  65. package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
  66. package/dist/{cli-0a7mm3zp.js → cli-q0ke1yww.js} +25 -21
  67. package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
  68. package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
  69. package/dist/{cli-phcqp1b9.js → cli-r2pnvj8g.js} +2 -2
  70. package/dist/{cli-jpc4r224.js → cli-r62a35ea.js} +19 -3
  71. package/dist/{cli-cd0hv9nh.js → cli-ra0xzggj.js} +2 -2
  72. package/dist/cli-rhs9pz33.js +294 -0
  73. package/dist/{cli-r4fqfpwf.js → cli-s2sp957d.js} +50 -27
  74. package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
  75. package/dist/{cli-6thk4jz3.js → cli-se8w6wny.js} +6 -6
  76. package/dist/cli-skxvvpap.js +10140 -0
  77. package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
  78. package/dist/{cli-0p3enk35.js → cli-tqaazemc.js} +9 -1
  79. package/dist/{cli-nwrdx840.js → cli-tr4sxp68.js} +3 -3
  80. package/dist/{cli-r0byd61h.js → cli-tsde1hdr.js} +15 -15
  81. package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
  82. package/dist/{cli-6r2f7edk.js → cli-v1yb0rqb.js} +6 -6
  83. package/dist/{cli-saqyage0.js → cli-vatyhshy.js} +179 -27
  84. package/dist/{cli-5wpw4rab.js → cli-vdach5a9.js} +5 -5
  85. package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
  86. package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
  87. package/dist/{cli-c3rk1v0x.js → cli-wayw93nt.js} +3 -3
  88. package/dist/cli-wmgrkscj.js +23254 -0
  89. package/dist/{cli-9xf7fdtp.js → cli-z5jjpaxw.js} +29 -6
  90. package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
  91. package/dist/cli.js +29 -45
  92. package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-y81sssk0.js} +15 -14
  93. package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
  94. package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-8vx4j6a9.js} +15 -14
  95. package/dist/{commands-z8fq9qna.js → commands-kcpvpcrr.js} +11 -10
  96. package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
  97. package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-kwpvj3rf.js} +42 -37
  98. package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
  99. package/dist/{db-yyhqqrbf.js → db-k8ankj20.js} +12 -11
  100. package/dist/{db-qfpq4bt7.js → db-ww5d7jq3.js} +28 -9
  101. package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
  102. package/dist/{dispatcher-x0x7qfcq.js → dispatcher-e8gq5m68.js} +38 -33
  103. package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
  104. package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-3epjm3af.js} +7 -6
  105. package/dist/{e2b-66xra4az.js → e2b-8ygwhg0f.js} +4 -3
  106. package/dist/{e2b-xwhyj8cw.js → e2b-swhnpw3n.js} +4 -3
  107. package/dist/{event-bus-vjtv82gm.js → event-bus-6axnngdj.js} +3 -2
  108. package/dist/{external-channel-h1fjecwe.js → external-channel-h3359cwn.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-0d4x7gkx.js} +18 -17
  112. package/dist/{handlers-znb9n7d4.js → handlers-an1gzv21.js} +41 -36
  113. package/dist/{heartbeat-bm4qkn8d.js → heartbeat-6dakeb61.js} +43 -38
  114. package/dist/{hook-254r4mza.js → hook-6v6cv6d5.js} +11 -23
  115. package/dist/{hook-xaa3q80s.js → hook-sa5xye4y.js} +12 -11
  116. package/dist/{http-3dgrgp8y.js → http-r7f3eky0.js} +1499 -251
  117. package/dist/index-52j1aja4.js +3465 -0
  118. package/dist/{index-fx3jqq1e.js → index-7ep4gzdk.js} +38 -33
  119. package/dist/index-9gw58n4k.js +193 -0
  120. package/dist/index-9j87mcm8.js +56305 -0
  121. package/dist/index-bsmcresk.js +79424 -0
  122. package/dist/index-mh85qhec.js +475 -0
  123. package/dist/{index-g2byveez.js → index-rmpw9a8q.js} +38 -33
  124. package/dist/{index-2ybk7khy.js → index-s2wxgzr0.js} +468 -683
  125. package/dist/{index-bdsqa799.js → index-v1v6n7hg.js} +43 -38
  126. package/dist/index-we27kd31.js +12810 -0
  127. package/dist/{index-jd7sejm2.js → index-zk96aq1k.js} +10 -9
  128. package/dist/{keepalive-6ywhpja1.js → keepalive-be9vwy5h.js} +12 -11
  129. package/dist/{lead-cw45n21s.js → lead-0861cwrf.js} +61 -56
  130. package/dist/{maintenance-ss1a1ge9.js → maintenance-mzzgc8bn.js} +10 -9
  131. package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
  132. package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-cpdnfwdj.js} +11 -10
  133. package/dist/{onboard-8hzdhc1k.js → onboard-fh8qs4r3.js} +11 -3
  134. package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-nm42wwj8.js} +18 -13
  135. package/dist/{otel-impl-e6mnvc4v.js → otel-impl-x6c1c9g4.js} +242 -868
  136. package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-9n2ya240.js} +244 -106
  137. package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-qb0rv0ap.js} +12 -11
  138. package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-1gzdwbh1.js} +11 -10
  139. package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-3mraey52.js} +12 -11
  140. package/dist/{render-v2-907cy6sa.js → render-v2-agpa45zz.js} +18 -14
  141. package/dist/{resume-42stcaz0.js → resume-x0ydy9s9.js} +25 -21
  142. package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
  143. package/dist/{setup-adbc1c10.js → setup-as9ga0d6.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-y5g1y7ev.js} +41 -36
  146. package/dist/{worker-bzdra9rf.js → worker-860c3e38.js} +61 -56
  147. package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
  148. package/openapi.json +523 -344
  149. package/package.json +10 -11
  150. package/src/be/config-refs.ts +60 -0
  151. package/src/be/db/page-versions.ts +15 -0
  152. package/src/be/db/runtime.ts +35 -8
  153. package/src/be/db/skill-name-resolution.ts +36 -0
  154. package/src/be/db/tasks/read.ts +230 -0
  155. package/src/be/db/tasks/write.ts +7 -0
  156. package/src/be/db.ts +52 -7
  157. package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
  158. package/src/be/migrations/216_task_resolved_effort.sql +5 -0
  159. package/src/be/migrations/217_chat_sdk_state.sql +104 -0
  160. package/src/be/model-catalog-store.ts +5 -1
  161. package/src/be/model-tier-resolution.ts +12 -1
  162. package/src/be/model-validation.ts +5 -2
  163. package/src/be/models-catalog.ts +26 -1
  164. package/src/be/modelsdev-cache.json +198 -63
  165. package/src/be/modelsdev-cache.ts +9 -1
  166. package/src/be/script-credential-broker.ts +39 -2
  167. package/src/be/scripts/run-saved.ts +1 -0
  168. package/src/be/scripts/typecheck.ts +10 -8
  169. package/src/be/seed/runner.ts +13 -1
  170. package/src/be/seed/state-db.ts +5 -0
  171. package/src/be/seed/types.ts +6 -0
  172. package/src/be/seed-pricing.ts +19 -2
  173. package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
  174. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
  175. package/src/be/seed-skills/bundled-files.generated.json +0 -18
  176. package/src/be/seed-skills/index.ts +104 -3
  177. package/src/be/swarm-config-guard.ts +52 -0
  178. package/src/cli.tsx +0 -16
  179. package/src/commands/onboard/non-interactive.ts +4 -2
  180. package/src/commands/provider-credentials.ts +52 -6
  181. package/src/commands/runner.ts +190 -54
  182. package/src/e2b/env.ts +5 -0
  183. package/src/extensions/contract-types.generated.ts +1 -1
  184. package/src/extensions/contract.ts +45 -0
  185. package/src/extensions/dispatcher.ts +7 -0
  186. package/src/extensions/post-bridge.ts +40 -0
  187. package/src/github/handlers.ts +11 -4
  188. package/src/heartbeat/templates.ts +8 -5
  189. package/src/hooks/hook.ts +0 -26
  190. package/src/http/all-routes.ts +0 -1
  191. package/src/http/config.ts +36 -17
  192. package/src/http/core.ts +4 -0
  193. package/src/http/index.ts +14 -2
  194. package/src/http/integrations.ts +88 -1
  195. package/src/http/mcp.ts +15 -5
  196. package/src/http/page-proxy.ts +2 -4
  197. package/src/http/pages-public.ts +3 -3
  198. package/src/http/pages.ts +3 -13
  199. package/src/http/poll.ts +28 -68
  200. package/src/http/requested-by.ts +54 -0
  201. package/src/http/scripts.ts +1 -0
  202. package/src/http/stats.ts +1 -30
  203. package/src/http/tasks.ts +61 -5
  204. package/src/http/utils.ts +14 -0
  205. package/src/http/webhooks.ts +159 -1
  206. package/src/http/x.ts +1 -0
  207. package/src/integrations/chat-sdk/adapters.ts +129 -0
  208. package/src/integrations/chat-sdk/attachments.ts +232 -0
  209. package/src/integrations/chat-sdk/background.ts +36 -0
  210. package/src/integrations/chat-sdk/commands.ts +194 -0
  211. package/src/integrations/chat-sdk/config.ts +198 -0
  212. package/src/integrations/chat-sdk/discord-api.ts +63 -0
  213. package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
  214. package/src/integrations/chat-sdk/handlers.ts +28 -0
  215. package/src/integrations/chat-sdk/inbound.ts +426 -0
  216. package/src/integrations/chat-sdk/limits.ts +48 -0
  217. package/src/integrations/chat-sdk/logger.ts +81 -0
  218. package/src/integrations/chat-sdk/outbound.ts +123 -0
  219. package/src/integrations/chat-sdk/relay.ts +172 -0
  220. package/src/integrations/chat-sdk/router.ts +169 -0
  221. package/src/integrations/chat-sdk/runtime.ts +351 -0
  222. package/src/integrations/chat-sdk/schema.ts +245 -0
  223. package/src/integrations/chat-sdk/state.ts +243 -0
  224. package/src/integrations/chat-sdk/status.ts +244 -0
  225. package/src/integrations/chat-sdk/steering.ts +58 -0
  226. package/src/integrations/chat-sdk/teams-origin.ts +77 -0
  227. package/src/integrations/chat-sdk/telegram-api.ts +56 -0
  228. package/src/integrations/chat-sdk/templates.ts +16 -0
  229. package/src/integrations/chat-sdk/test-hooks.ts +37 -0
  230. package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
  231. package/src/integrations/chat-sdk/typing.ts +65 -0
  232. package/src/pages/version.ts +4 -5
  233. package/src/prompts/base-prompt.ts +111 -45
  234. package/src/providers/acp-target-catalog.ts +6 -0
  235. package/src/providers/acp-targets.ts +55 -2
  236. package/src/providers/amp-adapter.ts +1 -1
  237. package/src/providers/claude-adapter.ts +1 -1
  238. package/src/providers/claude-flag-settings.ts +17 -5
  239. package/src/providers/claude-managed-adapter.ts +1 -1
  240. package/src/providers/claude-session-events.ts +6 -1
  241. package/src/providers/dsh-adapter.ts +1 -1
  242. package/src/providers/opencode-adapter.ts +243 -26
  243. package/src/providers/opencode-swarm-plugin.ts +31 -0
  244. package/src/providers/pi-mono-adapter.ts +398 -153
  245. package/src/providers/pricing-sources.md +33 -2
  246. package/src/providers/reasoning-effort.ts +27 -0
  247. package/src/providers/types.ts +6 -2
  248. package/src/rbac/legacy-policy.ts +8 -2
  249. package/src/rbac/permissions.ts +21 -0
  250. package/src/scheduler/scheduler.ts +4 -2
  251. package/src/scripts-runtime/loader.ts +19 -7
  252. package/src/scripts-runtime/sdk-allowlist.ts +8 -6
  253. package/src/scripts-runtime/swarm-sdk.ts +0 -11
  254. package/src/scripts-runtime/types/stdlib.d.ts +27 -15
  255. package/src/scripts-runtime/types/swarm-extension.d.ts +63 -1
  256. package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -15
  257. package/src/server.ts +52 -18
  258. package/src/slack/event-dedup.ts +1 -1
  259. package/src/tasks/additive-buffer.ts +4 -2
  260. package/src/tasks/context-key.ts +60 -1
  261. package/src/tasks/model-pin.ts +67 -0
  262. package/src/tasks/worker-follow-up.ts +4 -31
  263. package/src/tests/acp-adapter.test.ts +42 -0
  264. package/src/tests/api-drain-worker-e2e.test.ts +1 -6
  265. package/src/tests/base-prompt.test.ts +58 -54
  266. package/src/tests/chat-sdk-commands.test.ts +191 -0
  267. package/src/tests/chat-sdk-config.test.ts +334 -0
  268. package/src/tests/chat-sdk-discord-api.test.ts +68 -0
  269. package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
  270. package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
  271. package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
  272. package/src/tests/chat-sdk-harness.ts +146 -0
  273. package/src/tests/chat-sdk-inbound.test.ts +363 -0
  274. package/src/tests/chat-sdk-relay.test.ts +470 -0
  275. package/src/tests/chat-sdk-reload.test.ts +128 -0
  276. package/src/tests/chat-sdk-shutdown.test.ts +220 -0
  277. package/src/tests/chat-sdk-slack.test.ts +268 -0
  278. package/src/tests/chat-sdk-state.test.ts +163 -0
  279. package/src/tests/chat-sdk-status-route.test.ts +382 -0
  280. package/src/tests/chat-sdk-teams.test.ts +277 -0
  281. package/src/tests/chat-sdk-tools.test.ts +520 -0
  282. package/src/tests/chat-sdk-typing.test.ts +120 -0
  283. package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
  284. package/src/tests/claude-adapter-binary.test.ts +9 -4
  285. package/src/tests/claude-flag-settings.test.ts +11 -3
  286. package/src/tests/claude-managed-adapter.test.ts +1 -1
  287. package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
  288. package/src/tests/claude-thinking-tokens.test.ts +57 -0
  289. package/src/tests/claude-worker-parity.test.ts +2 -7
  290. package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
  291. package/src/tests/config-refs.test.ts +66 -0
  292. package/src/tests/context-key.test.ts +19 -0
  293. package/src/tests/cors-allowlist.test.ts +25 -0
  294. package/src/tests/create-page-tool.test.ts +18 -0
  295. package/src/tests/credential-check.test.ts +139 -0
  296. package/src/tests/credentials.test.ts +21 -0
  297. package/src/tests/db-runtime.test.ts +61 -0
  298. package/src/tests/db-task-read-contract.test.ts +20 -0
  299. package/src/tests/db-task-write-contract.test.ts +10 -0
  300. package/src/tests/docs-index-footprint.test.js +3 -3
  301. package/src/tests/dsh-adapter.test.ts +1 -1
  302. package/src/tests/enabled-capabilities.test.ts +20 -0
  303. package/src/tests/entrypoint-api-readiness.test.ts +14 -8
  304. package/src/tests/entrypoint-config-env-export.test.ts +5 -2
  305. package/src/tests/entrypoint-export-to-env.test.ts +78 -0
  306. package/src/tests/explicit-model-validation.test.ts +105 -1
  307. package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
  308. package/src/tests/extensions-post-bridge.test.ts +51 -0
  309. package/src/tests/fetch-resolved-env.test.ts +128 -0
  310. package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
  311. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
  312. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
  313. package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
  314. package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
  315. package/src/tests/github-handlers.test.ts +35 -0
  316. package/src/tests/harness-provider-resolution.test.ts +12 -0
  317. package/src/tests/heartbeat-checklist.test.ts +3 -2
  318. package/src/tests/hook-runtime-close.test.ts +0 -2
  319. package/src/tests/http-api-integration.test.ts +0 -25
  320. package/src/tests/migration-046-budgets.test.ts +17 -16
  321. package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
  322. package/src/tests/model-tier-resolution.test.ts +93 -0
  323. package/src/tests/models-catalog.test.ts +42 -1
  324. package/src/tests/openai-compatible-providers.test.ts +134 -0
  325. package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
  326. package/src/tests/opencode-adapter.test.ts +216 -2
  327. package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
  328. package/src/tests/opencode-shell-env.test.ts +145 -0
  329. package/src/tests/openrouter-base-url.test.ts +101 -151
  330. package/src/tests/page-proxy.test.ts +1 -1
  331. package/src/tests/pages-browser-sdk.test.ts +76 -0
  332. package/src/tests/pages-feedback.test.ts +1 -1
  333. package/src/tests/paused-tasks-requested-by.test.ts +102 -0
  334. package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
  335. package/src/tests/pi-mono-adapter.test.ts +385 -5
  336. package/src/tests/pi-shell-env.test.ts +170 -0
  337. package/src/tests/prompt-template-remaining.test.ts +35 -0
  338. package/src/tests/rbac-engine.test.ts +11 -3
  339. package/src/tests/runner-exit-after-tasks.test.ts +0 -4
  340. package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
  341. package/src/tests/script-connections.test.ts +2 -0
  342. package/src/tests/scripts-http.test.ts +201 -1
  343. package/src/tests/scripts-only-gating.test.ts +2 -3
  344. package/src/tests/scripts-runtime.test.ts +58 -40
  345. package/src/tests/secret-scrubber.test.ts +86 -0
  346. package/src/tests/seed-skills-bundled-files.test.ts +45 -53
  347. package/src/tests/seed-skills-retire.test.ts +182 -0
  348. package/src/tests/send-task-requester-gate.test.ts +58 -0
  349. package/src/tests/session-cost-recompute-unit.test.ts +46 -0
  350. package/src/tests/skill-get-name-resolution.test.ts +137 -0
  351. package/src/tests/sonnet-5-5-registry.test.ts +9 -1
  352. package/src/tests/swarm-config-export-to-env.test.ts +267 -0
  353. package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
  354. package/src/tests/swarm-diff.test.ts +1 -1
  355. package/src/tests/task-model-effort-rerun.test.ts +164 -0
  356. package/src/tests/task-session-prompts.test.ts +132 -0
  357. package/src/tests/task-tool-manifest.test.ts +14 -0
  358. package/src/tests/task-tools-ctx.test.ts +2 -0
  359. package/src/tests/tool-annotations.test.ts +6 -6
  360. package/src/tests/ui-logs-parser.test.ts +43 -0
  361. package/src/tests/used-by-route.test.ts +6 -0
  362. package/src/tests/vercel-ai-gateway.test.ts +149 -0
  363. package/src/tests/workflow-swarm-script.test.ts +38 -0
  364. package/src/tests/workflow-wait-filter.test.ts +5 -3
  365. package/src/tools/chat-access.ts +41 -0
  366. package/src/tools/chat-open-dm.ts +59 -0
  367. package/src/tools/chat-post.ts +74 -0
  368. package/src/tools/chat-read-thread.ts +100 -0
  369. package/src/tools/chat-reply.ts +75 -0
  370. package/src/tools/create-page.ts +3 -13
  371. package/src/tools/model-catalog/index.ts +2 -1
  372. package/src/tools/register-chat-channel.ts +139 -0
  373. package/src/tools/send-task.ts +24 -0
  374. package/src/tools/skills/skill-get.ts +17 -9
  375. package/src/tools/swarm-config/get-config.ts +2 -1
  376. package/src/tools/swarm-config/list-config.ts +2 -1
  377. package/src/tools/swarm-config/set-config.ts +16 -3
  378. package/src/tools/tool-config.ts +8 -6
  379. package/src/types.ts +12 -2
  380. package/src/utils/config-env-export.ts +74 -0
  381. package/src/utils/credentials.test.ts +92 -0
  382. package/src/utils/credentials.ts +52 -4
  383. package/src/utils/harness-provider.ts +15 -6
  384. package/src/utils/runtime-model-catalog.ts +11 -1
  385. package/src/utils/secret-scrubber.ts +71 -2
  386. package/src/utils/task-tool-manifest.ts +19 -2
  387. package/src/workflows/executors/swarm-script.ts +1 -0
  388. package/templates/skills/agent-browser/SKILL.md +1 -1
  389. package/templates/skills/agent-browser/content.md +1 -1
  390. package/templates/skills/apps/SKILL.md +8 -1
  391. package/templates/skills/apps/content.md +8 -1
  392. package/templates/skills/chat-sdk/config.json +14 -0
  393. package/templates/skills/chat-sdk/content.md +84 -0
  394. package/templates/skills/composio-gmail/content.md +7 -0
  395. package/templates/skills/composio-google-docs/content.md +1 -1
  396. package/templates/skills/email-domain-health/config.json +14 -0
  397. package/templates/skills/email-domain-health/content.md +131 -0
  398. package/templates/skills/kv-storage/content.md +2 -2
  399. package/templates/skills/pages/content.md +8 -10
  400. package/templates/skills/swarm-extensions/content.md +2 -0
  401. package/templates/skills/swarm-scripts/SKILL.md +4 -2
  402. package/templates/skills/swarm-scripts/config.json +1 -1
  403. package/templates/skills/swarm-scripts/content.md +4 -2
  404. package/templates/skills/workflow-iterate/content.md +38 -0
  405. package/dist/artifact-eczsknc3.js +0 -3843
  406. package/dist/cli-bd957dgb.js +0 -153
  407. package/dist/cli-q51yprfq.js +0 -1104
  408. package/dist/cli-t1ze64h3.js +0 -811
  409. package/dist/cli-tcc4wd5d.js +0 -56471
  410. package/dist/index-9ch1n761.js +0 -1102
  411. package/src/artifact-sdk/index.ts +0 -2
  412. package/src/artifact-sdk/localtunnel.d.ts +0 -20
  413. package/src/artifact-sdk/port.ts +0 -12
  414. package/src/artifact-sdk/server.ts +0 -183
  415. package/src/artifact-sdk/tunnel.ts +0 -19
  416. package/src/commands/artifact.ts +0 -249
  417. package/src/http/ecosystem.ts +0 -77
  418. package/src/tests/artifact-commands.test.ts +0 -92
  419. package/src/tests/artifact-sdk.test.ts +0 -793
  420. package/src/tests/register-service-security.test.ts +0 -194
  421. package/src/tools/list-services.ts +0 -107
  422. package/src/tools/register-service.ts +0 -177
  423. package/src/tools/unregister-service.ts +0 -73
  424. package/src/tools/update-service-status.ts +0 -96
  425. package/templates/skills/artifacts/config.json +0 -14
  426. package/templates/skills/artifacts/content.md +0 -344
  427. package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
  428. package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
  429. package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
  430. package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
  431. /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
  432. /package/src/{artifact-sdk → pages}/feedback-overlay.ts +0 -0
@@ -0,0 +1,131 @@
1
+ # Email Domain Health
2
+
3
+ Build a monitor that tells a person, every working day, whether mail from their
4
+ domains authenticates, lands, and stays off blocklists. It has four parts: one
5
+ saved script (checks + test send), a Swarm App with run history, one or two
6
+ schedules, and an alert that fires only when something gets worse.
7
+
8
+ This skill decides **what** to build. The mechanics live in other skills; read
9
+ them, do not re-derive them:
10
+
11
+ - [[swarm-scripts]]: authoring, `script-upsert`, scope, connections, secrets.
12
+ - [[apps]]: models, named queries, pages, row writes.
13
+ - [[scheduling]]: `targetType: "script"` schedules, cron and timezone.
14
+ - [[composio-gmail]] (or the user's own mail integration): the test send and
15
+ the bounce search.
16
+
17
+ Full design notes and pitfalls: the "Email domain health" playbook on the docs
18
+ site.
19
+
20
+ ## 1. Ask for requirements first
21
+
22
+ Ask before building (one batched question, see [[ask-user]]). Do not guess any
23
+ of these; a wrong selector or From address makes every later check wrong.
24
+
25
+ | Ask | Why it matters |
26
+ |---|---|
27
+ | Domains to monitor, and which one is the envelope/bounce domain | One check set per domain; SPF is judged on the envelope domain. |
28
+ | Sending providers per domain (Google Workspace, Microsoft 365, an ESP such as Resend, SES, Postmark) and each DKIM selector | DKIM is looked up at `<selector>._domainkey.<domain>`; there is no way to list selectors. |
29
+ | The From address for the test send, and the integration that sends it (Composio Gmail, SMTP, ESP API) | The test must leave through the real path, alias included. |
30
+ | Test inbox: mail-tester (free tier has a small daily cap) or an inbox the user owns | Decides how the score is captured. |
31
+ | Schedule and timezone | Default: weekdays, morning, user's timezone. |
32
+ | Alert channel and thresholds (score floor, bounce rate) | Defaults: score < 6/10, bounces >= 5% on >= 10 sends. |
33
+ | History retention | Default 90 days of runs. |
34
+
35
+ Read the answers back in one short message before you write code.
36
+
37
+ ## 2. Build the checks script
38
+
39
+ One saved script with modes `send`, `check`, and optionally `backfill`. Keep
40
+ domains, selectors, thresholds and ids in a config block at the top or in
41
+ `args`, never scattered through the code.
42
+
43
+ **DNS over HTTPS, two resolvers.** Query every record on two public DoH
44
+ resolvers (for example dns.google and Cloudflare's JSON endpoint).
45
+ NOERROR and NXDOMAIN are answers; SERVFAIL, REFUSED and timeouts are not.
46
+ Same verdict on both: use it. Different verdicts: `warn` ("resolvers
47
+ disagree", often propagation). One failed: use the other, note it. Both
48
+ failed: `unknown`.
49
+
50
+ **Checks per domain:**
51
+
52
+ - SPF: exactly one `v=spf1` record, includes each provider, total DNS lookups
53
+ <= 10 (recurse `include:`/`redirect=`; warn at 9), ends `~all` or `-all`.
54
+ - DKIM: TXT at each selector (follow a CNAME), non-empty `p=` (empty means
55
+ revoked), key length.
56
+ - DMARC: exactly one `v=DMARC1` at `_dmarc.<domain>`, a `p=` tag, `rua=` (warn
57
+ without it).
58
+ - MX: present and pointing at the expected provider.
59
+ - Provider records the ESP documents (bounce subdomain SPF and MX, DKIM
60
+ CNAMEs).
61
+ - Blocklists: domain lists such as Spamhaus DBL, SURBL, URIBL (details below).
62
+ - Test-send result: score plus the SPF, DKIM and DMARC verdicts from the
63
+ receiver's headers.
64
+ - Bounce rate: sent vs bounced in the last 24h from the sending mailbox,
65
+ excluding test sends.
66
+
67
+ **Verdicts:** `ok`, `warn`, `red`, `unknown`. Overall = worst. `unknown` means
68
+ "could not read", and it is **never** reported as clean.
69
+
70
+ **Controls, not hope.** Every negative result needs a positive control in the
71
+ same run:
72
+
73
+ - Blocklists: before trusting a list, query its documented test entry
74
+ (`dbltest.com` on `dbl.spamhaus.org`, `test.surbl.org` on `multi.surbl.org`,
75
+ `test.uribl.com` on `multi.uribl.com`) on each resolver. Use the list only on
76
+ a resolver where the test entry answers "listed". Refusal codes
77
+ (`127.255.255.x` from Spamhaus, `127.0.0.1` from SURBL and URIBL) mean the
78
+ resolver is blocked: `unknown`.
79
+ - Bounce rate: a whole-mailbox 24h count of 0 means the search failed:
80
+ `unknown`, not "0 bounces".
81
+ - Test result page without a score yet: `unknown` for the first hour after the
82
+ send, then `red`.
83
+
84
+ Return a `controls.ok` flag with the result so a run that read nothing cannot
85
+ pass as green.
86
+
87
+ **Send mode.** Send one realistic message (the same template and links real
88
+ mail uses) to a fresh test address, through the user's integration. Read the
89
+ sent message back and confirm the From header kept the address the user asked
90
+ for. Store the pending test id in KV with a per-day key so a retry never
91
+ sends twice.
92
+
93
+ ## 3. Build the app
94
+
95
+ Use [[apps]]. Minimum models:
96
+
97
+ - `run`: one row per run (time, overall, red/warn/unknown counts, score,
98
+ bounces, sent).
99
+ - `check`: one row per check per run (history).
100
+ - `current`: one row per `domain|check`, updated in place, with `since` = when
101
+ the status last changed.
102
+
103
+ Optional per-domain views (`domainRun`, `domainCheck`) make tabs per domain
104
+ cheap to render. Page: one tab per domain (problems first, raw record on
105
+ hover), a score trend, and a collapsed "How it works". The script writes rows
106
+ through the row endpoints; prune `run` and `check` rows older than the
107
+ retention window.
108
+
109
+ ## 4. Schedule it
110
+
111
+ Use [[scheduling]] with `targetType: "script"`, not an agent task that says
112
+ "run the script". Two schedules: `send`, then `check` 10 to 15 minutes later
113
+ in the user's timezone, so the test inbox has the message before the check
114
+ reads it.
115
+
116
+ ## 5. Alert only on change
117
+
118
+ Compare with the previous `current` rows. Alert when a check **turns** red, or
119
+ the score drops below the floor after being above it. Never alert on a
120
+ steady-state warn or an unknown. The message lists each new red with its raw
121
+ detail and links the app. If the script's identity cannot post to the chosen
122
+ channel, have it hand the message to an agent that can.
123
+
124
+ ## Done when
125
+
126
+ - A manual `check` run returns every check, `controls.ok: true`, and writes
127
+ rows the app renders.
128
+ - Every blocklist shows either a passing control or `unknown`, never a bare
129
+ "not listed".
130
+ - One full scheduled send + check cycle has run and the score landed in `run`.
131
+ - You reported the app link, script name and scope, and schedule ids.
@@ -287,8 +287,8 @@ value so you can detect a clobber.
287
287
  ## See also
288
288
 
289
289
  - The **`pages`** skill — companion skill for authed pages and `swarmSdk.kv`.
290
- - The **`artifacts`** skill — for anything too big or too binary for KV.
290
+ - The **`agent-fs`** skill — for anything too big or too binary for KV.
291
291
  - `src/be/migrations/061_kv_store.sql` — schema (`kv_entries`)
292
292
  - `src/http/kv.ts` — REST handler + namespace resolution
293
293
  - `src/tools/kv/*` — MCP tool registrars
294
- - `src/artifact-sdk/browser-sdk.ts` — `swarmSdk.kv` for pages
294
+ - `src/pages/browser-sdk.ts` — `swarmSdk.kv` for pages
@@ -1,8 +1,8 @@
1
1
  # Pages — DB-backed Static Artifacts
2
2
 
3
3
  DB-backed static content (HTML or JSON) served by the API directly. Cheap,
4
- versioned, share-able by URL. The lighter-weight cousin of `artifacts` —
5
- no PM2, no tunnels, no port allocation, no `services` registry row.
4
+ versioned, share-able by URL. No server process, no tunnel, no port
5
+ allocation.
6
6
 
7
7
  A page should be a clean human-facing artifact, not a raw dump with a URL. This
8
8
  skill covers both halves: **how to publish** a page, and **the taste baseline**
@@ -13,7 +13,7 @@ every page should meet.
13
13
  > (e.g. `CAPABILITIES=core,task-pool,pages`). If the tool is missing from
14
14
  > your MCP list, this is why.
15
15
 
16
- ## When to use Pages vs Artifacts
16
+ ## When to use Pages vs Apps
17
17
 
18
18
  | You need… | Use |
19
19
  |---|---|
@@ -21,12 +21,11 @@ every page should meet.
21
21
  | A JSON status payload + a few buttons that call swarm APIs | **Pages** (`contentType: 'application/json'`) |
22
22
  | To share an output via a URL with no server logic | **Pages** |
23
23
  | Analysis that should be linkable and bookmarkable | **Pages** |
24
- | Custom routes, websockets, server-side logic | The **`artifacts`** skill |
25
- | File uploads or per-request computation | The **`artifacts`** skill |
24
+ | Persistent records, queries, and server-side actions | The **`apps`** skill |
25
+ | Large or binary files (PNG, MP4, exports) | The **`agent-fs`** skill |
26
26
 
27
27
  Rule of thumb: if the content is a snapshot (you can write the full HTML/JSON
28
- in a single call), use pages. If the content is a *running program*, use
29
- artifacts.
28
+ in a single call), use pages. If it needs stored data and actions, use apps.
30
29
 
31
30
  Do **not** use pages for:
32
31
 
@@ -533,9 +532,8 @@ human-facing summary.
533
532
 
534
533
  ## See Also
535
534
 
536
- - The **`artifacts`** skill — durable storage (agent-fs, shared workspace) plus
537
- full custom Hono apps with PM2 + a tunneled subdomain. Use it for interactive
538
- servers, not static content.
535
+ - The **`apps`** skill — schema-backed records, named queries, and actions.
536
+ - The **`agent-fs`** skill — durable file storage and share links.
539
537
  - The **`kv-storage`** skill — page-scoped state via `swarmSdk.kv`.
540
538
  - `runbooks/secret-scrubbing.md` — egress scrubbing details.
541
539
  - SPA listing: `${APP_URL}/pages` — the same `APP_URL` used for share links above.
@@ -47,10 +47,12 @@ curl -s "$MCP_BASE_URL/api/extensions/type-defs" \
47
47
  | `pre.task.create` | before any task is stored (REST, MCP, Slack, schedule, workflow, webhook, follow-up) | `block(reason)`, `modify({ priority, agentId, tags, description, ... })`, or nothing |
48
48
  | `pre.task.followUp` | before the lead follow-up task for a finished worker task | `block`, `modify({ description, priority, agentId })`, or nothing |
49
49
  | `pre.slack.route` | before a Slack message becomes a task | `modify({ target: { kind: "agent", agentId } })`, `{ kind: "lead" }`, `{ kind: "broadcast" }` |
50
+ | `pre.chat.route` | before buffered Chat SDK messages (Telegram, Slack, Discord, Teams) become a task | `block(reason)`, or `modify({ target: { kind: "agent", agentId } })`, `{ kind: "lead" }`, `{ kind: "broadcast" }`, `{ kind: "workflow", workflowId }` |
50
51
  | `pre.heartbeat.remediate` | after the heartbeat sweep finds a stalled task | `modify({ proposedAction: "record" | "fail" | "supersede-resume" })` |
51
52
  | `pre.tool.call` | before an agent MCP tool call runs | `block(reason)` or `modify({ args })` |
52
53
  | `post.task.created`, `post.task.completed`, `post.task.failed`, `post.task.cancelled`, `post.task.superseded`, `post.task.progress` | after the change is committed | none |
53
54
  | `post.slack.message`, `post.tool.call` | after the message or tool call finished | none |
55
+ | `post.chat.message` | after a Chat SDK message is received (before buffering) or sent; `direction` is `inbound` or `outbound` | none |
54
56
  | `post.approval.resolved` | after a person answers an approval request, workflow or standalone (not on timeout or cancel) | none |
55
57
  | `post.task.budgetRefused` | after a task is refused by a daily spend budget | none |
56
58
  | `post.email.received`, `post.kapso.message` | after an inbound AgentMail or Kapso message is received | none |
@@ -76,7 +76,7 @@ export default async function (args: z.infer<typeof argsSchema>, ctx: ScriptCont
76
76
 
77
77
  - `ctx.swarm.*`: the swarm SDK. `task_get`, `task_send`, `task_storeProgress`, `task_action`, `task_list`, `slack_reply`, `memory_search`, `memory_store`, `kv_get`, `kv_getOrNull`, `kv_set`, `kv_delete`, `kv_incr`, `kv_list`, `swarm_get`, `agent_info`, `db_query`, and more. `kv_getOrNull` returns the entry, `null` on a missing key, and throws on other errors.
78
78
  - `ctx.swarm.task_send` requires `routingReason` and `routingNote` whenever `agentId` is present. The note must explain the worker choice in at least 10 characters after trimming whitespace (maximum 200 characters). Use `human_pinned` for an explicit/configured choice, `skill` for a role or specialization match, `continuity` for the same worker/session, `reroute_fault` for a fault handoff, or `overflow` for capacity/pool escalation. Omit both `agentId` and routing fields for the pool.
79
- - `ctx.swarm.config`: `apiKey`, `agentId`, `mcpBaseUrl`, and `ctx.swarm.config.get("KEY")` for user config values. All are `Redacted` wrappers that stringify to `<redacted>`. Never unwrap one into a return value, a log line, or a request body you build by hand.
79
+ - `ctx.swarm.config`: `apiKey`, `agentId`, `mcpBaseUrl`, and `ctx.swarm.config.get("KEY")` for swarm config values, resolved for the agent running the script (agent scope over global, the same rows `get-config` returns for that agent). A key that is not set returns `undefined`, so `config.get("KEY") ?? fallback` works. All are `Redacted` wrappers that stringify to `<redacted>`. Never unwrap one into a return value, a log line, or a request body you build by hand.
80
80
  - `ctx.api.<slug>` and `ctx.mcp.<slug>`: typed clients for registered connections. They exist only for registered connections. Introspect with `Object.keys(ctx.api ?? {})` and `Object.keys(ctx.mcp ?? {})`.
81
81
  - `ctx.stdlib`: `fetch`, `fetchJson` (retries, 30 s timeout), `grep`, `glob`, `table`, `Redacted`.
82
82
  - `ctx.logger`: `log`, `warn`, `error`. Keep logs short.
@@ -107,11 +107,13 @@ export default async function main(args: { status?: string; limit?: number } | u
107
107
 
108
108
  ## Secrets
109
109
 
110
+ A config row reaches your shell env only when its `exportToEnv` flag is on. If `$KEY` is empty in your shell but `get-config` or `list-config` shows the row marked `not in agent env`, the row stays server-side on purpose: do not copy the value into a file, an env var, or a command. Use it from a script instead, through one of the paths below. Harness, git, and agent-fs credentials stay exported. Keys only the API server reads (Slack app token and signing secret, GitHub App private key, webhook and OAuth client secrets) can never be exported. If a recipe genuinely needs the variable in a shell, ask the lead to turn `exportToEnv` on for that row (`set-config` with `exportToEnv: true`); it applies to your next task.
111
+
110
112
  Order of preference:
111
113
 
112
114
  1. A registered connection: `ctx.api.<slug>.<operationId>({ path, query, header, body })` (OpenAPI), `ctx.api.<slug>.graphql(query, variables)` (GraphQL), `ctx.mcp.<slug>.<toolName>(args)` (MCP, proxied server-side, returns the raw MCP envelope: read `res.structuredContent ?? res.content?.[0]?.text`). Credentials attach at egress. The script never sees them. OAuth tokens refresh on their own.
113
115
  2. A credential binding placeholder in a hand-written request: `Authorization: Bearer [REDACTED:GITHUB_TOKEN]`. The runtime substitutes the value at egress, only for the binding's allowed hosts.
114
- 3. `ctx.swarm.config.get("KEY")` for a config value you pass to `ctx.stdlib.fetch` as a header value. Still `Redacted`; never log it.
116
+ 3. `ctx.swarm.config.get("KEY")` for a config value you pass to `ctx.stdlib.fetch` as a header value. Unwrap it with `ctx.stdlib.Redacted.value(...)` inside the header itself (a wrapped value sends the literal `<redacted>`), and never log it. Secret values are scrubbed from run output.
115
117
 
116
118
  A raw secret, or the output of `get-config` with `includeSecrets: true`, must not appear in script source, script `args`, a schedule's `taskTemplate` or `scriptArgs`, or a task description. Those are stored as plain text and replayed on every run.
117
119
 
@@ -5,7 +5,7 @@
5
5
  "slug": "swarm-scripts",
6
6
  "title": "Swarm Scripts",
7
7
  "description": "Bulk, repeat, fan-out, or data-heavy work: write and run swarm scripts (inline `script-run`, named `script-upsert`, durable `launch-script-run`). Covers the script-vs-tool rubric, the authoring contract (`args` first, `ctx` second), the seed catalog, connections and secrets, `db_query`, and exposing a script as an API.",
8
- "version": "1.1.0",
8
+ "version": "1.2.0",
9
9
  "category": "skills",
10
10
  "placeholders": [],
11
11
  "runAllSeedersCandidate": true,
@@ -71,7 +71,7 @@ export default async function (args: z.infer<typeof argsSchema>, ctx: ScriptCont
71
71
 
72
72
  - `ctx.swarm.*`: the swarm SDK. `task_get`, `task_send`, `task_storeProgress`, `task_action`, `task_list`, `slack_reply`, `memory_search`, `memory_store`, `kv_get`, `kv_getOrNull`, `kv_set`, `kv_delete`, `kv_incr`, `kv_list`, `swarm_get`, `agent_info`, `db_query`, and more. `kv_getOrNull` returns the entry, `null` on a missing key, and throws on other errors.
73
73
  - `ctx.swarm.task_send` requires `routingReason` and `routingNote` whenever `agentId` is present. The note must explain the worker choice in at least 10 characters after trimming whitespace (maximum 200 characters). Use `human_pinned` for an explicit/configured choice, `skill` for a role or specialization match, `continuity` for the same worker/session, `reroute_fault` for a fault handoff, or `overflow` for capacity/pool escalation. Omit both `agentId` and routing fields for the pool.
74
- - `ctx.swarm.config`: `apiKey`, `agentId`, `mcpBaseUrl`, and `ctx.swarm.config.get("KEY")` for user config values. All are `Redacted` wrappers that stringify to `<redacted>`. Never unwrap one into a return value, a log line, or a request body you build by hand.
74
+ - `ctx.swarm.config`: `apiKey`, `agentId`, `mcpBaseUrl`, and `ctx.swarm.config.get("KEY")` for swarm config values, resolved for the agent running the script (agent scope over global, the same rows `get-config` returns for that agent). A key that is not set returns `undefined`, so `config.get("KEY") ?? fallback` works. All are `Redacted` wrappers that stringify to `<redacted>`. Never unwrap one into a return value, a log line, or a request body you build by hand.
75
75
  - `ctx.api.<slug>` and `ctx.mcp.<slug>`: typed clients for registered connections. They exist only for registered connections. Introspect with `Object.keys(ctx.api ?? {})` and `Object.keys(ctx.mcp ?? {})`.
76
76
  - `ctx.stdlib`: `fetch`, `fetchJson` (retries, 30 s timeout), `grep`, `glob`, `table`, `Redacted`.
77
77
  - `ctx.logger`: `log`, `warn`, `error`. Keep logs short.
@@ -102,11 +102,13 @@ export default async function main(args: { status?: string; limit?: number } | u
102
102
 
103
103
  ## Secrets
104
104
 
105
+ A config row reaches your shell env only when its `exportToEnv` flag is on. If `$KEY` is empty in your shell but `get-config` or `list-config` shows the row marked `not in agent env`, the row stays server-side on purpose: do not copy the value into a file, an env var, or a command. Use it from a script instead, through one of the paths below. Harness, git, and agent-fs credentials stay exported. Keys only the API server reads (Slack app token and signing secret, GitHub App private key, webhook and OAuth client secrets) can never be exported. If a recipe genuinely needs the variable in a shell, ask the lead to turn `exportToEnv` on for that row (`set-config` with `exportToEnv: true`); it applies to your next task.
106
+
105
107
  Order of preference:
106
108
 
107
109
  1. A registered connection: `ctx.api.<slug>.<operationId>({ path, query, header, body })` (OpenAPI), `ctx.api.<slug>.graphql(query, variables)` (GraphQL), `ctx.mcp.<slug>.<toolName>(args)` (MCP, proxied server-side, returns the raw MCP envelope: read `res.structuredContent ?? res.content?.[0]?.text`). Credentials attach at egress. The script never sees them. OAuth tokens refresh on their own.
108
110
  2. A credential binding placeholder in a hand-written request: `Authorization: Bearer [REDACTED:GITHUB_TOKEN]`. The runtime substitutes the value at egress, only for the binding's allowed hosts.
109
- 3. `ctx.swarm.config.get("KEY")` for a config value you pass to `ctx.stdlib.fetch` as a header value. Still `Redacted`; never log it.
111
+ 3. `ctx.swarm.config.get("KEY")` for a config value you pass to `ctx.stdlib.fetch` as a header value. Unwrap it with `ctx.stdlib.Redacted.value(...)` inside the header itself (a wrapped value sends the literal `<redacted>`), and never log it. Secret values are scrubbed from run output.
110
112
 
111
113
  A raw secret, or the output of `get-config` with `includeSecrets: true`, must not appear in script source, script `args`, a schedule's `taskTemplate` or `scriptArgs`, or a task description. Those are stored as plain text and replayed on every run.
112
114
 
@@ -173,6 +173,44 @@ Afterwards, a `warnings` entry on `create-workflow` or a patch tool means the ke
173
173
  - Do not set `retry` or `validation.retry` on a `system-one-decision` node. It retries connection errors, 408, 429, and 5xx itself (`config.maxRetries`, 0 to 3, default 2) inside `config.timeoutMs` (default 30000). A 401, a 422, or an answer that fails validation ends after one attempt.
174
174
  - The node reads its provider's key (`TYPESAFE_API_KEY`, `OPENROUTER_API_KEY`, `LAYA_API_KEY`, `OPENAI_DECISIONS_API_KEY`, or `CLOUDFLARE_API_TOKEN`, plus `LAYA_URL` for `laya` and `CLOUDFLARE_ACCOUNT_ID` for `cloudflare`) server-side. The key never appears in the definition, the step output, or an error. A run whose key or `LAYA_URL` is missing fails before any node executes, and a 401 or 403 fails the step as `<KEY> was rejected`. An unresolved `{{token}}` fails the step before any request.
175
175
 
176
+ #### Jev images (direct TypeSafe API)
177
+
178
+ `system-one-decision` cannot send images today: its strict config has no `assets` field, its wire sends only `state`, `model`, and `questions`, and it does not send the image opt-in header. A URL or base64 string in `state` stays text. Use a `swarm-script` calling `POST https://api.typesafe.ai/v1/systemone` with the credential kept server-side until the node supports assets.
179
+
180
+ - Send `TypeSafe-Danger-Zone-Images: true`. Both `jev-1.13.0` and `jev-1.14.0` accept images; Box questions require 1.14. Pin the model you tested.
181
+ - Upload PNG or JPEG bytes, not a URL. Prefer multipart: first part `request` is the JSON with content type `application/json`; an asset such as `assets[uuid] = { type: "image", part: "photo-file" }` names its file part. For JSON-only calls, use the base64 shape below: standard padded base64, no whitespace or `data:` prefix.
182
+ - Each image must be still, at most 16 MiB decoded, 256–1568 pixels on each side, and 78,400–2,458,624 pixels total (256×256 is too small). Request body, all processed images together, and the expanded request each have a 32 MiB limit. Limits reject the whole request; the API does not resize. Rotate pixels upright before sending because EXIF orientation is not applied.
183
+ - Generate a fresh UUID reference per image. References are replaced wherever they occur in string values in `state`, `instructions`, or `criteria`; object keys are not replaced. Every asset must be referenced. Repeating the same reference inserts and bills another image copy.
184
+
185
+ ```json
186
+ {
187
+ "model": "jev-1.13.0",
188
+ "state": { "photo": "d1369c6a-538e-4ab3-91cd-f76f2f67b651" },
189
+ "assets": {
190
+ "d1369c6a-538e-4ab3-91cd-f76f2f67b651": {
191
+ "type": "image", "format": "png", "data_base64": "<encoded PNG bytes>"
192
+ }
193
+ },
194
+ "questions": {
195
+ "ready": { "type": "noul", "instructions": "Is the product in `photo` fully assembled?" }
196
+ }
197
+ }
198
+ ```
199
+
200
+ Measured 2026-10-15 on `jev-1.13.0`, using an 850×850 RGB PNG with a red square on white. Cost is the complete request's `usage.input_tokens × $0.042 / 1,000,000`; output is free:
201
+
202
+ | Placement | Questions | Input tokens | Request cost (USD) |
203
+ |---|---:|---:|---:|
204
+ | Once in `state` | 1 | 2,273 | $0.000095466 |
205
+ | Once in `state`, questions use the `photo` path | 2 | 2,289 | $0.000096138 |
206
+ | Twice in `state` | 1 | 4,237 | $0.000177954 |
207
+ | Once in each question's `instructions` | 2 | 4,203 | $0.000176526 |
208
+ | Once in `state`, resized to 425×425 | 1 | 863 | $0.000036246 |
209
+
210
+ The roughly $0.0001 claim (about 10,000 one-image requests per dollar) holds for this example; the exact cost depends on image size and prompt. **Question count alone does not multiply a shared state image's tokens.** Put shared images in `state` once and have questions use its field path, not the asset UUID. Image duplication scales with repeated references, including one copy per question when embedded in each question's instructions. If several judgments form one classification, a single `choice` can avoid repeating question-local images. Downscale when the detail permits: halving both dimensions reduced this request's billed tokens from 2,273 to 863; recheck accuracy on your images.
211
+
212
+ Contract and current pricing: [TypeSafe images](https://docs.typesafe.ai/images), [models](https://docs.typesafe.ai/models). Re-measure before budgeting a different model, resolution, or prompt.
213
+
176
214
  ### `human-in-the-loop` (how approvals render)
177
215
 
178
216
  The same rules apply to a standalone `request-human-input` call.