@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.
- package/README.md +1 -1
- package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-sj2g0m84.js} +17 -16
- package/dist/{actions-sgeyv08k.js → actions-fegk44gr.js} +39 -34
- package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-ad8ft89x.js} +8 -7
- package/dist/{app-km9qnv2f.js → app-kfvgbvzy.js} +18 -14
- package/dist/{assistant-5r8tcvvd.js → assistant-z7zdy9ja.js} +40 -35
- package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-5c2z0mbe.js} +10 -9
- package/dist/{boot-reembed-16rv9843.js → boot-reembed-j8xa181e.js} +10 -9
- package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-hnkn3rgt.js} +11 -10
- package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-kwjq4d2z.js} +14 -13
- package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-9vmvpvgd.js} +19 -18
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-k9qae05j.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-q54zx5q2.js} +6 -4
- package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-9jye6cxr.js} +11881 -11472
- package/dist/{cli-94b48jhk.js → cli-03gedhng.js} +16 -14
- package/dist/{cli-1w0vj3gw.js → cli-1e4b6bzh.js} +7 -7
- package/dist/{cli-d603qf86.js → cli-29jc5q7w.js} +10 -8
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-x119kdba.js → cli-3dj8k4vy.js} +1 -1
- package/dist/{cli-srqq3gc5.js → cli-3fbmmawm.js} +5 -5
- package/dist/{cli-gmdajfw5.js → cli-4jxm2qtz.js} +4987 -1708
- package/dist/{cli-tadfgd0t.js → cli-5hkm7whv.js} +33 -4
- package/dist/{cli-42qhyvwx.js → cli-5t4f29ez.js} +3 -3
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-0kxf81jj.js → cli-6jyj59nb.js} +2 -2
- package/dist/{cli-w1apjecb.js → cli-6razj6t4.js} +2 -2
- package/dist/{cli-anzdk0z4.js → cli-74ahz61x.js} +2 -2
- package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-81r1wjyv.js → cli-9nfx44eh.js} +1 -1
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-na2pxe4f.js → cli-apx87jne.js} +2 -2
- package/dist/{cli-rfz2ve55.js → cli-bzszjf2p.js} +2855 -862
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/{cli-hsem16hb.js → cli-cgtksawx.js} +7 -4
- package/dist/{cli-db3m6zdt.js → cli-d2qr7aj4.js} +1 -1
- package/dist/{cli-rfs4vddv.js → cli-d5f9ed5c.js} +5 -5
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/{cli-7jykv7ef.js → cli-e6mpjhed.js} +1 -1
- package/dist/{cli-7a93cv8c.js → cli-ee9gtz70.js} +98 -23
- package/dist/{cli-3nxdmjrc.js → cli-eejsgvm4.js} +4 -4
- package/dist/{cli-fmhj1ehj.js → cli-ef1hg1wv.js} +470 -51
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-ppy4nnnh.js → cli-f7kr7svz.js} +2 -2
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-2bw3w47j.js → cli-hnhtk6cj.js} +1 -1
- package/dist/{cli-ywm1azg9.js → cli-hnmhtzvh.js} +6 -4
- package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
- package/dist/{cli-s8z6x4b4.js → cli-j0pfptdp.js} +218 -102
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-5er5gjbm.js → cli-k382tshb.js} +10 -11
- package/dist/{cli-v3zhnxsb.js → cli-k3dp5tpf.js} +2 -2
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-ne7smj1b.js → cli-ke896fcf.js} +10 -10
- package/dist/{cli-xc7p7s3g.js → cli-kt6zqg0e.js} +6 -6
- package/dist/{cli-wrh08zjd.js → cli-m50t4309.js} +5 -18
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-bv2etw2y.js → cli-n3hzg89b.js} +46 -15
- package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
- package/dist/{cli-qm1448f9.js → cli-ne236afy.js} +8 -8
- package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
- package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
- package/dist/{cli-0a7mm3zp.js → cli-q0ke1yww.js} +25 -21
- package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-phcqp1b9.js → cli-r2pnvj8g.js} +2 -2
- package/dist/{cli-jpc4r224.js → cli-r62a35ea.js} +19 -3
- package/dist/{cli-cd0hv9nh.js → cli-ra0xzggj.js} +2 -2
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-r4fqfpwf.js → cli-s2sp957d.js} +50 -27
- package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
- package/dist/{cli-6thk4jz3.js → cli-se8w6wny.js} +6 -6
- package/dist/cli-skxvvpap.js +10140 -0
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-0p3enk35.js → cli-tqaazemc.js} +9 -1
- package/dist/{cli-nwrdx840.js → cli-tr4sxp68.js} +3 -3
- package/dist/{cli-r0byd61h.js → cli-tsde1hdr.js} +15 -15
- package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
- package/dist/{cli-6r2f7edk.js → cli-v1yb0rqb.js} +6 -6
- package/dist/{cli-saqyage0.js → cli-vatyhshy.js} +179 -27
- package/dist/{cli-5wpw4rab.js → cli-vdach5a9.js} +5 -5
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/{cli-c3rk1v0x.js → cli-wayw93nt.js} +3 -3
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-9xf7fdtp.js → cli-z5jjpaxw.js} +29 -6
- package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
- package/dist/cli.js +29 -45
- package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-y81sssk0.js} +15 -14
- package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
- package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-8vx4j6a9.js} +15 -14
- package/dist/{commands-z8fq9qna.js → commands-kcpvpcrr.js} +11 -10
- package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
- package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-kwpvj3rf.js} +42 -37
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
- package/dist/{db-yyhqqrbf.js → db-k8ankj20.js} +12 -11
- package/dist/{db-qfpq4bt7.js → db-ww5d7jq3.js} +28 -9
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
- package/dist/{dispatcher-x0x7qfcq.js → dispatcher-e8gq5m68.js} +38 -33
- package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
- package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-3epjm3af.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-8ygwhg0f.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-swhnpw3n.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-6axnngdj.js} +3 -2
- package/dist/{external-channel-h1fjecwe.js → external-channel-h3359cwn.js} +11 -10
- package/dist/{google-generative-ai-szdxbpqg.js → google-generative-ai-g8db7x0f.js} +4 -2
- package/dist/{google-vertex-qzw3p36d.js → google-vertex-r2692q0r.js} +4 -2
- package/dist/{grok-adapter-e7mr287e.js → grok-adapter-0d4x7gkx.js} +18 -17
- package/dist/{handlers-znb9n7d4.js → handlers-an1gzv21.js} +41 -36
- package/dist/{heartbeat-bm4qkn8d.js → heartbeat-6dakeb61.js} +43 -38
- package/dist/{hook-254r4mza.js → hook-6v6cv6d5.js} +11 -23
- package/dist/{hook-xaa3q80s.js → hook-sa5xye4y.js} +12 -11
- package/dist/{http-3dgrgp8y.js → http-r7f3eky0.js} +1499 -251
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-fx3jqq1e.js → index-7ep4gzdk.js} +38 -33
- package/dist/index-9gw58n4k.js +193 -0
- package/dist/index-9j87mcm8.js +56305 -0
- package/dist/index-bsmcresk.js +79424 -0
- package/dist/index-mh85qhec.js +475 -0
- package/dist/{index-g2byveez.js → index-rmpw9a8q.js} +38 -33
- package/dist/{index-2ybk7khy.js → index-s2wxgzr0.js} +468 -683
- package/dist/{index-bdsqa799.js → index-v1v6n7hg.js} +43 -38
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{index-jd7sejm2.js → index-zk96aq1k.js} +10 -9
- package/dist/{keepalive-6ywhpja1.js → keepalive-be9vwy5h.js} +12 -11
- package/dist/{lead-cw45n21s.js → lead-0861cwrf.js} +61 -56
- package/dist/{maintenance-ss1a1ge9.js → maintenance-mzzgc8bn.js} +10 -9
- package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
- package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-cpdnfwdj.js} +11 -10
- package/dist/{onboard-8hzdhc1k.js → onboard-fh8qs4r3.js} +11 -3
- package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-nm42wwj8.js} +18 -13
- package/dist/{otel-impl-e6mnvc4v.js → otel-impl-x6c1c9g4.js} +242 -868
- package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-9n2ya240.js} +244 -106
- package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-qb0rv0ap.js} +12 -11
- package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-1gzdwbh1.js} +11 -10
- package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-3mraey52.js} +12 -11
- package/dist/{render-v2-907cy6sa.js → render-v2-agpa45zz.js} +18 -14
- package/dist/{resume-42stcaz0.js → resume-x0ydy9s9.js} +25 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-adbc1c10.js → setup-as9ga0d6.js} +2 -2
- package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
- package/dist/{work-objects-wpj8ck95.js → work-objects-y5g1y7ev.js} +41 -36
- package/dist/{worker-bzdra9rf.js → worker-860c3e38.js} +61 -56
- package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
- package/openapi.json +523 -344
- package/package.json +10 -11
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/page-versions.ts +15 -0
- package/src/be/db/runtime.ts +35 -8
- package/src/be/db/skill-name-resolution.ts +36 -0
- package/src/be/db/tasks/read.ts +230 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +52 -7
- package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
- package/src/be/migrations/216_task_resolved_effort.sql +5 -0
- package/src/be/migrations/217_chat_sdk_state.sql +104 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +12 -1
- package/src/be/model-validation.ts +5 -2
- package/src/be/models-catalog.ts +26 -1
- package/src/be/modelsdev-cache.json +198 -63
- package/src/be/modelsdev-cache.ts +9 -1
- package/src/be/script-credential-broker.ts +39 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +10 -8
- package/src/be/seed/runner.ts +13 -1
- package/src/be/seed/state-db.ts +5 -0
- package/src/be/seed/types.ts +6 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/seed-skills/bundled-files.generated.json +0 -18
- package/src/be/seed-skills/index.ts +104 -3
- package/src/be/swarm-config-guard.ts +52 -0
- package/src/cli.tsx +0 -16
- package/src/commands/onboard/non-interactive.ts +4 -2
- package/src/commands/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +190 -54
- package/src/e2b/env.ts +5 -0
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +45 -0
- package/src/extensions/dispatcher.ts +7 -0
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/all-routes.ts +0 -1
- package/src/http/config.ts +36 -17
- package/src/http/core.ts +4 -0
- package/src/http/index.ts +14 -2
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp.ts +15 -5
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +3 -3
- package/src/http/pages.ts +3 -13
- package/src/http/poll.ts +28 -68
- package/src/http/requested-by.ts +54 -0
- package/src/http/scripts.ts +1 -0
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +61 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +159 -1
- package/src/http/x.ts +1 -0
- package/src/integrations/chat-sdk/adapters.ts +129 -0
- package/src/integrations/chat-sdk/attachments.ts +232 -0
- package/src/integrations/chat-sdk/background.ts +36 -0
- package/src/integrations/chat-sdk/commands.ts +194 -0
- package/src/integrations/chat-sdk/config.ts +198 -0
- package/src/integrations/chat-sdk/discord-api.ts +63 -0
- package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
- package/src/integrations/chat-sdk/handlers.ts +28 -0
- package/src/integrations/chat-sdk/inbound.ts +426 -0
- package/src/integrations/chat-sdk/limits.ts +48 -0
- package/src/integrations/chat-sdk/logger.ts +81 -0
- package/src/integrations/chat-sdk/outbound.ts +123 -0
- package/src/integrations/chat-sdk/relay.ts +172 -0
- package/src/integrations/chat-sdk/router.ts +169 -0
- package/src/integrations/chat-sdk/runtime.ts +351 -0
- package/src/integrations/chat-sdk/schema.ts +245 -0
- package/src/integrations/chat-sdk/state.ts +243 -0
- package/src/integrations/chat-sdk/status.ts +244 -0
- package/src/integrations/chat-sdk/steering.ts +58 -0
- package/src/integrations/chat-sdk/teams-origin.ts +77 -0
- package/src/integrations/chat-sdk/telegram-api.ts +56 -0
- package/src/integrations/chat-sdk/templates.ts +16 -0
- package/src/integrations/chat-sdk/test-hooks.ts +37 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
- package/src/integrations/chat-sdk/typing.ts +65 -0
- package/src/pages/version.ts +4 -5
- package/src/prompts/base-prompt.ts +111 -45
- package/src/providers/acp-target-catalog.ts +6 -0
- package/src/providers/acp-targets.ts +55 -2
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +1 -1
- package/src/providers/claude-flag-settings.ts +17 -5
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +243 -26
- package/src/providers/opencode-swarm-plugin.ts +31 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pricing-sources.md +33 -2
- package/src/providers/reasoning-effort.ts +27 -0
- package/src/providers/types.ts +6 -2
- package/src/rbac/legacy-policy.ts +8 -2
- package/src/rbac/permissions.ts +21 -0
- package/src/scheduler/scheduler.ts +4 -2
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/sdk-allowlist.ts +8 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +27 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +63 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -15
- package/src/server.ts +52 -18
- package/src/slack/event-dedup.ts +1 -1
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +60 -1
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +4 -31
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/base-prompt.test.ts +58 -54
- package/src/tests/chat-sdk-commands.test.ts +191 -0
- package/src/tests/chat-sdk-config.test.ts +334 -0
- package/src/tests/chat-sdk-discord-api.test.ts +68 -0
- package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
- package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
- package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
- package/src/tests/chat-sdk-harness.ts +146 -0
- package/src/tests/chat-sdk-inbound.test.ts +363 -0
- package/src/tests/chat-sdk-relay.test.ts +470 -0
- package/src/tests/chat-sdk-reload.test.ts +128 -0
- package/src/tests/chat-sdk-shutdown.test.ts +220 -0
- package/src/tests/chat-sdk-slack.test.ts +268 -0
- package/src/tests/chat-sdk-state.test.ts +163 -0
- package/src/tests/chat-sdk-status-route.test.ts +382 -0
- package/src/tests/chat-sdk-teams.test.ts +277 -0
- package/src/tests/chat-sdk-tools.test.ts +520 -0
- package/src/tests/chat-sdk-typing.test.ts +120 -0
- package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
- package/src/tests/claude-adapter-binary.test.ts +9 -4
- package/src/tests/claude-flag-settings.test.ts +11 -3
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
- package/src/tests/claude-thinking-tokens.test.ts +57 -0
- package/src/tests/claude-worker-parity.test.ts +2 -7
- package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
- package/src/tests/config-refs.test.ts +66 -0
- package/src/tests/context-key.test.ts +19 -0
- package/src/tests/cors-allowlist.test.ts +25 -0
- package/src/tests/create-page-tool.test.ts +18 -0
- package/src/tests/credential-check.test.ts +139 -0
- package/src/tests/credentials.test.ts +21 -0
- package/src/tests/db-runtime.test.ts +61 -0
- package/src/tests/db-task-read-contract.test.ts +20 -0
- package/src/tests/db-task-write-contract.test.ts +10 -0
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/enabled-capabilities.test.ts +20 -0
- package/src/tests/entrypoint-api-readiness.test.ts +14 -8
- package/src/tests/entrypoint-config-env-export.test.ts +5 -2
- package/src/tests/entrypoint-export-to-env.test.ts +78 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-post-bridge.test.ts +51 -0
- package/src/tests/fetch-resolved-env.test.ts +128 -0
- package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
- package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
- package/src/tests/github-handlers.test.ts +35 -0
- package/src/tests/harness-provider-resolution.test.ts +12 -0
- package/src/tests/heartbeat-checklist.test.ts +3 -2
- package/src/tests/hook-runtime-close.test.ts +0 -2
- package/src/tests/http-api-integration.test.ts +0 -25
- package/src/tests/migration-046-budgets.test.ts +17 -16
- package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
- package/src/tests/model-tier-resolution.test.ts +93 -0
- package/src/tests/models-catalog.test.ts +42 -1
- package/src/tests/openai-compatible-providers.test.ts +134 -0
- package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
- package/src/tests/opencode-adapter.test.ts +216 -2
- package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
- package/src/tests/opencode-shell-env.test.ts +145 -0
- package/src/tests/openrouter-base-url.test.ts +101 -151
- package/src/tests/page-proxy.test.ts +1 -1
- package/src/tests/pages-browser-sdk.test.ts +76 -0
- package/src/tests/pages-feedback.test.ts +1 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
- package/src/tests/pi-mono-adapter.test.ts +385 -5
- package/src/tests/pi-shell-env.test.ts +170 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/rbac-engine.test.ts +11 -3
- package/src/tests/runner-exit-after-tasks.test.ts +0 -4
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections.test.ts +2 -0
- package/src/tests/scripts-http.test.ts +201 -1
- package/src/tests/scripts-only-gating.test.ts +2 -3
- package/src/tests/scripts-runtime.test.ts +58 -40
- package/src/tests/secret-scrubber.test.ts +86 -0
- package/src/tests/seed-skills-bundled-files.test.ts +45 -53
- package/src/tests/seed-skills-retire.test.ts +182 -0
- package/src/tests/send-task-requester-gate.test.ts +58 -0
- package/src/tests/session-cost-recompute-unit.test.ts +46 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/sonnet-5-5-registry.test.ts +9 -1
- package/src/tests/swarm-config-export-to-env.test.ts +267 -0
- package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
- package/src/tests/swarm-diff.test.ts +1 -1
- package/src/tests/task-model-effort-rerun.test.ts +164 -0
- package/src/tests/task-session-prompts.test.ts +132 -0
- package/src/tests/task-tool-manifest.test.ts +14 -0
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tool-annotations.test.ts +6 -6
- package/src/tests/ui-logs-parser.test.ts +43 -0
- package/src/tests/used-by-route.test.ts +6 -0
- package/src/tests/vercel-ai-gateway.test.ts +149 -0
- package/src/tests/workflow-swarm-script.test.ts +38 -0
- package/src/tests/workflow-wait-filter.test.ts +5 -3
- package/src/tools/chat-access.ts +41 -0
- package/src/tools/chat-open-dm.ts +59 -0
- package/src/tools/chat-post.ts +74 -0
- package/src/tools/chat-read-thread.ts +100 -0
- package/src/tools/chat-reply.ts +75 -0
- package/src/tools/create-page.ts +3 -13
- package/src/tools/model-catalog/index.ts +2 -1
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/send-task.ts +24 -0
- package/src/tools/skills/skill-get.ts +17 -9
- package/src/tools/swarm-config/get-config.ts +2 -1
- package/src/tools/swarm-config/list-config.ts +2 -1
- package/src/tools/swarm-config/set-config.ts +16 -3
- package/src/tools/tool-config.ts +8 -6
- package/src/types.ts +12 -2
- package/src/utils/config-env-export.ts +74 -0
- package/src/utils/credentials.test.ts +92 -0
- package/src/utils/credentials.ts +52 -4
- package/src/utils/harness-provider.ts +15 -6
- package/src/utils/runtime-model-catalog.ts +11 -1
- package/src/utils/secret-scrubber.ts +71 -2
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/templates/skills/agent-browser/SKILL.md +1 -1
- package/templates/skills/agent-browser/content.md +1 -1
- package/templates/skills/apps/SKILL.md +8 -1
- package/templates/skills/apps/content.md +8 -1
- package/templates/skills/chat-sdk/config.json +14 -0
- package/templates/skills/chat-sdk/content.md +84 -0
- package/templates/skills/composio-gmail/content.md +7 -0
- package/templates/skills/composio-google-docs/content.md +1 -1
- package/templates/skills/email-domain-health/config.json +14 -0
- package/templates/skills/email-domain-health/content.md +131 -0
- package/templates/skills/kv-storage/content.md +2 -2
- package/templates/skills/pages/content.md +8 -10
- package/templates/skills/swarm-extensions/content.md +2 -0
- package/templates/skills/swarm-scripts/SKILL.md +4 -2
- package/templates/skills/swarm-scripts/config.json +1 -1
- package/templates/skills/swarm-scripts/content.md +4 -2
- package/templates/skills/workflow-iterate/content.md +38 -0
- package/dist/artifact-eczsknc3.js +0 -3843
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- package/dist/cli-tcc4wd5d.js +0 -56471
- package/dist/index-9ch1n761.js +0 -1102
- package/src/artifact-sdk/index.ts +0 -2
- package/src/artifact-sdk/localtunnel.d.ts +0 -20
- package/src/artifact-sdk/port.ts +0 -12
- package/src/artifact-sdk/server.ts +0 -183
- package/src/artifact-sdk/tunnel.ts +0 -19
- package/src/commands/artifact.ts +0 -249
- package/src/http/ecosystem.ts +0 -77
- package/src/tests/artifact-commands.test.ts +0 -92
- package/src/tests/artifact-sdk.test.ts +0 -793
- package/src/tests/register-service-security.test.ts +0 -194
- package/src/tools/list-services.ts +0 -107
- package/src/tools/register-service.ts +0 -177
- package/src/tools/unregister-service.ts +0 -73
- package/src/tools/update-service-status.ts +0 -96
- package/templates/skills/artifacts/config.json +0 -14
- package/templates/skills/artifacts/content.md +0 -344
- package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
- package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
- package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
- package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
- /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
- /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 **`
|
|
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/
|
|
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.
|
|
5
|
-
|
|
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
|
|
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
|
-
|
|
|
25
|
-
|
|
|
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
|
|
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 **`
|
|
537
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|