@desplega.ai/agent-swarm 1.172.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-fpecx1g1.js → acp-adapter-sj2g0m84.js} +18 -17
- package/dist/{actions-pw87a1a8.js → actions-fegk44gr.js} +65 -35
- package/dist/{amp-adapter-8jem2bc0.js → amp-adapter-ad8ft89x.js} +8 -7
- package/dist/{anthropic-messages-8ee2f22q.js → anthropic-messages-r6czkjv1.js} +7 -7
- package/dist/{app-wmf0m843.js → app-kfvgbvzy.js} +19 -13
- package/dist/{assistant-emp1e108.js → assistant-z7zdy9ja.js} +65 -38
- package/dist/{boot-reembed-1de4f4aj.js → boot-reembed-5c2z0mbe.js} +11 -9
- package/dist/{boot-reembed-4ymn9atn.js → boot-reembed-j8xa181e.js} +11 -9
- package/dist/{boot-scrub-sweep-adhk1s8c.js → boot-scrub-sweep-hnkn3rgt.js} +12 -10
- package/dist/{boot-seeds-8q637aew.js → boot-seeds-kwjq4d2z.js} +15 -13
- package/dist/{claude-adapter-t26cv8a4.js → claude-adapter-9vmvpvgd.js} +20 -19
- 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-gsfsh662.js → claude-sdk-session-9jye6cxr.js} +12698 -11995
- package/dist/{cli-k46r9hmk.js → cli-03gedhng.js} +16 -14
- package/dist/{cli-kb4ehzx5.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-8vs9trd4.js → cli-3dj8k4vy.js} +1 -1
- package/dist/{cli-zxm9p3x4.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-6jb2rf77.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-pj6x9qce.js → cli-6jyj59nb.js} +2 -2
- package/dist/{cli-388egyf6.js → cli-6razj6t4.js} +2 -2
- package/dist/{cli-qsztpfry.js → cli-74ahz61x.js} +2 -2
- package/dist/{cli-4nz8p1p5.js → cli-7x0g4sn1.js} +15474 -16082
- 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-bf7485pm.js → cli-apx87jne.js} +2 -2
- package/dist/{cli-ztrv9y21.js → cli-bzszjf2p.js} +3689 -1081
- 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-1hgat6pa.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-j6kpj9az.js → cli-ee9gtz70.js} +1553 -68
- package/dist/{cli-e0a9sk00.js → cli-eejsgvm4.js} +4 -4
- package/dist/{cli-tgpfnm6r.js → cli-ef1hg1wv.js} +518 -59
- 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-4fnb6884.js → cli-hvqbtna4.js} +7 -1259
- package/dist/{cli-pstq9888.js → cli-j0pfptdp.js} +220 -103
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-esnpehf5.js → cli-k382tshb.js} +12 -13
- package/dist/cli-k3dp5tpf.js +263 -0
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-prrt9fa0.js → cli-ke896fcf.js} +10 -10
- package/dist/{cli-nv4zd0b9.js → cli-kt6zqg0e.js} +6 -6
- package/dist/{cli-g6t9texm.js → cli-m50t4309.js} +5 -18
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-c2pq2rjb.js → cli-n3hzg89b.js} +46 -15
- package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
- package/dist/{cli-5rv1j9ga.js → cli-ne236afy.js} +53 -7
- package/dist/cli-p0sg24zp.js +16 -0
- package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
- package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
- package/dist/{cli-g4f5pj26.js → cli-q0ke1yww.js} +111 -25
- package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-gj81e47t.js → cli-r2pnvj8g.js} +2 -2
- package/dist/{cli-r8smj8b8.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-nyhb1r6x.js → cli-s2sp957d.js} +52 -29
- package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
- package/dist/{cli-xczpdp9e.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-cf69s3ew.js → cli-tr4sxp68.js} +3 -3
- package/dist/{cli-8hzfb6xz.js → cli-tsde1hdr.js} +15 -15
- package/dist/{cli-cceskcvt.js → cli-txqb9s38.js} +8 -8
- package/dist/{cli-aspcaef3.js → cli-v1yb0rqb.js} +6 -6
- package/dist/{cli-j1pmc07z.js → cli-vatyhshy.js} +268 -40
- package/dist/{cli-04emfe2q.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-hwwvy36w.js → cli-wayw93nt.js} +3 -3
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-gp1rtyvk.js → cli-z5jjpaxw.js} +29 -6
- package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
- package/dist/cli.js +32 -48
- package/dist/{codex-adapter-m4tgdysy.js → codex-adapter-y81sssk0.js} +16 -15
- package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
- package/dist/{codex-session-runner-ymwzm6ea.js → codex-session-runner-8vx4j6a9.js} +16 -15
- package/dist/{commands-n0hshcvs.js → commands-kcpvpcrr.js} +21 -10
- package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
- package/dist/{controllers-connect-y07cqcvy.js → controllers-connect-kwpvj3rf.js} +45 -38
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
- package/dist/{db-hkqvrdcb.js → db-k8ankj20.js} +13 -11
- package/dist/{db-4w7tmt1g.js → db-ww5d7jq3.js} +29 -9
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
- package/dist/{dispatcher-5sd69y14.js → dispatcher-e8gq5m68.js} +41 -34
- package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
- package/dist/{dsh-adapter-2h8m4cab.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-h3359cwn.js +52 -0
- package/dist/{google-generative-ai-7pavrbv7.js → google-generative-ai-g8db7x0f.js} +5 -3
- package/dist/{google-vertex-3f1jk41f.js → google-vertex-r2692q0r.js} +5 -3
- package/dist/{grok-adapter-8m9yqzbq.js → grok-adapter-0d4x7gkx.js} +19 -18
- package/dist/{handlers-s20xr10r.js → handlers-an1gzv21.js} +44 -37
- package/dist/{heartbeat-3k31q4g2.js → heartbeat-6dakeb61.js} +46 -39
- package/dist/{hook-gdn6a2fn.js → hook-6v6cv6d5.js} +12 -24
- package/dist/{hook-ygwerrdh.js → hook-sa5xye4y.js} +13 -12
- package/dist/{http-jdteeg81.js → http-r7f3eky0.js} +1598 -279
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-e0snym4t.js → index-7ep4gzdk.js} +41 -34
- 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-vm3bm9t7.js → index-rmpw9a8q.js} +41 -34
- package/dist/{index-6ksewd5y.js → index-s2wxgzr0.js} +1015 -732
- package/dist/{index-tsszt7g9.js → index-v1v6n7hg.js} +46 -39
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{index-ffqzqgwb.js → index-zk96aq1k.js} +11 -9
- package/dist/{keepalive-jekc896t.js → keepalive-be9vwy5h.js} +13 -11
- package/dist/{lead-4k9s9szx.js → lead-0861cwrf.js} +64 -57
- package/dist/{maintenance-shazch4n.js → maintenance-mzzgc8bn.js} +11 -9
- package/dist/node-c9we95xf.js +1 -1
- package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
- package/dist/{oauth-refresh-sweep-5gb36kn8.js → oauth-refresh-sweep-cpdnfwdj.js} +12 -10
- package/dist/{onboard-ydrbnvww.js → onboard-fh8qs4r3.js} +11 -3
- package/dist/{opencode-adapter-5zh0he20.js → opencode-adapter-nm42wwj8.js} +19 -14
- package/dist/{otel-impl-6pf5cv86.js → otel-impl-x6c1c9g4.js} +248 -869
- package/dist/{pi-mono-adapter-ef9wwx9m.js → pi-mono-adapter-9n2ya240.js} +245 -107
- package/dist/{pricing-refresh-s52nsa5q.js → pricing-refresh-qb0rv0ap.js} +13 -11
- package/dist/{rbac-roles-aq3msh4e.js → rbac-roles-1gzdwbh1.js} +12 -10
- package/dist/{rbac-roles-q5gb5e8v.js → rbac-roles-3mraey52.js} +13 -11
- package/dist/{render-v2-pd1rg54q.js → render-v2-agpa45zz.js} +19 -13
- package/dist/{resume-gw4a2c6v.js → resume-x0ydy9s9.js} +27 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-jda1ksdh.js → setup-as9ga0d6.js} +2 -2
- package/dist/{virtual-modules-b3ga2m65.js → virtual-modules-9gkxqrap.js} +7 -6
- package/dist/{work-objects-tb7ycye8.js → work-objects-y5g1y7ev.js} +49 -37
- package/dist/{worker-njjccz5d.js → worker-860c3e38.js} +64 -57
- package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
- package/openapi.json +951 -356
- package/package.json +12 -13
- package/src/apps/catalog.generated.json +1309 -53
- package/src/apps/page-validator.ts +93 -31
- package/src/azure-devops/api.ts +94 -18
- package/src/azure-devops/auth.ts +32 -0
- package/src/azure-devops/boards-sync.ts +708 -0
- package/src/azure-devops/handlers.ts +52 -8
- package/src/azure-devops/html.ts +26 -0
- package/src/azure-devops/index.ts +15 -0
- package/src/azure-devops/templates.ts +86 -0
- package/src/azure-devops/types.ts +65 -1
- 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 +74 -13
- package/src/be/migrations/213_script_connections_sql.sql +79 -0
- 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-connections.ts +47 -8
- 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 +10 -18
- package/src/be/seed-skills/index.ts +107 -3
- package/src/be/sql-connections.ts +118 -0
- package/src/be/swarm-config-guard.ts +53 -0
- package/src/cli.tsx +0 -16
- package/src/commands/onboard/non-interactive.ts +4 -2
- package/src/commands/profile-sync.ts +5 -3
- package/src/commands/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +196 -56
- 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-oauth.ts +6 -13
- package/src/http/mcp.ts +15 -5
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +6 -5
- package/src/http/pages.ts +5 -14
- package/src/http/poll.ts +28 -68
- package/src/http/requested-by.ts +54 -0
- package/src/http/route-def.ts +7 -6
- package/src/http/script-connection-proxy.ts +51 -4
- package/src/http/script-connections.ts +5 -2
- package/src/http/scripts.ts +1 -0
- package/src/http/session-cost-recompute.ts +12 -2
- package/src/http/session-data.ts +4 -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 +183 -2
- 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/jira/adf.ts +3 -1
- package/src/kv-reserved-namespaces.ts +2 -0
- package/src/oauth/mcp-wrapper.ts +10 -6
- package/src/otel-impl.ts +2 -1
- 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 +56 -3
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +27 -2
- package/src/providers/claude-flag-settings.ts +133 -0
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-sdk-session.ts +7 -0
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +268 -37
- package/src/providers/opencode-billing.ts +86 -0
- package/src/providers/opencode-swarm-plugin.ts +51 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pricing-sources.md +37 -3
- package/src/providers/reasoning-effort.ts +27 -0
- package/src/providers/types.ts +11 -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/api-client.ts +15 -1
- package/src/scripts-runtime/api-types.ts +9 -1
- package/src/scripts-runtime/ctx.ts +1 -1
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/mcp-client.ts +30 -19
- 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/actions.ts +29 -1
- package/src/slack/app.ts +14 -2
- package/src/slack/assistant.ts +36 -2
- package/src/slack/channel-join.ts +3 -16
- package/src/slack/commands.ts +9 -1
- package/src/slack/event-dedup.ts +1 -1
- package/src/slack/external-channel-egress.ts +113 -0
- package/src/slack/external-channel.ts +309 -0
- package/src/slack/handlers.ts +61 -0
- package/src/slack/render-v2.ts +40 -47
- package/src/slack/work-objects.ts +5 -0
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +94 -2
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +4 -31
- package/src/telemetry.ts +2 -1
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/apps-catalog-feedback.test.ts +310 -0
- package/src/tests/apps-catalog-inputs.test.ts +70 -0
- package/src/tests/apps-catalog-table.test.ts +113 -0
- package/src/tests/azure-devops-boards-sync.test.ts +584 -0
- package/src/tests/azure-devops-html.test.ts +13 -0
- package/src/tests/azure-devops-webhook-malformed.test.ts +4 -0
- 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 +144 -0
- package/src/tests/claude-flag-settings.test.ts +114 -0
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +148 -1
- package/src/tests/claude-sdk-process.fixture.ts +7 -0
- 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 +51 -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/deferred-task-wake.test.ts +52 -4
- 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/azure-boards/workitem.commented.json +89 -0
- package/src/tests/fixtures/azure-boards/workitem.created.json +81 -0
- package/src/tests/fixtures/azure-boards/workitem.deleted.json +70 -0
- package/src/tests/fixtures/azure-boards/workitem.restored.json +82 -0
- package/src/tests/fixtures/azure-boards/workitem.updated.json +130 -0
- package/src/tests/fixtures/catalog-feedback-definition.json.txt +860 -0
- package/src/tests/fixtures/catalog-inputs-definition.json.txt +910 -0
- package/src/tests/fixtures/catalog-table-definition.json.txt +468 -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-identity-refresh.ts +3 -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/node-env-runtime.test.ts +98 -0
- 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 +348 -3
- package/src/tests/opencode-billing.test.ts +28 -0
- 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-identity-refresh.test.ts +3 -0
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections-sql.test.ts +675 -0
- package/src/tests/script-connections.test.ts +7 -1
- 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 +94 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/slack-channel-join.test.ts +4 -1
- package/src/tests/slack-external-channel-config.test.ts +65 -0
- package/src/tests/slack-external-channel-egress.test.ts +237 -0
- package/src/tests/slack-external-channel-guard.test.ts +280 -0
- package/src/tests/slack-external-channel-tools.test.ts +173 -0
- package/src/tests/slack-external-channel.test.ts +370 -0
- package/src/tests/slack-render-v2.test.ts +86 -10
- package/src/tests/sonnet-5-5-registry.test.ts +9 -1
- package/src/tests/spec-base-url.test.ts +16 -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/vendored-openapi.test.ts +16 -1
- 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/defer-task.ts +17 -0
- 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/slack-post.ts +6 -0
- package/src/tools/slack-read.ts +8 -0
- package/src/tools/slack-reply.ts +6 -0
- package/src/tools/slack-start-thread.ts +6 -0
- package/src/tools/slack-update.ts +6 -0
- package/src/tools/slack-upload-file.ts +6 -0
- 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/node-env.ts +24 -0
- 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 +749 -0
- package/templates/skills/apps/content.md +60 -22
- 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/qa-loom/config.json +14 -0
- package/templates/skills/qa-loom/content.md +187 -0
- package/templates/skills/qa-loom/files/build-loom.mjs +221 -0
- package/templates/skills/qa-loom/files/run-qa.sh +57 -0
- package/templates/skills/slack-interaction/content.md +4 -0
- 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-9xsmdpdt.js +0 -56377
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- 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/dist/{azure-openai-responses-ap1gwxgr.js → azure-openai-responses-ygfreq4t.js} +5 -5
- package/dist/{cli-5rqrj7q0.js → cli-pw7ebjdt.js} +0 -0
- package/dist/{openai-codex-responses-33qhkkdy.js → openai-codex-responses-3bk0grnr.js} +4 -4
- package/dist/{openai-completions-s88xm3ns.js → openai-completions-5d4jpakc.js} +9 -9
- package/dist/{openai-responses-7xd2f2e2.js → openai-responses-krb51f59.js} +5 -5
- package/dist/{pi-messages-xszk613n.js → pi-messages-x9gzynm1.js} +3 -3
- /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
- /package/src/{artifact-sdk → pages}/feedback-overlay.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Swarm Apps
|
|
2
2
|
|
|
3
|
-
Swarm Apps are persistent, agent-authored internal applications: a schema-backed row store, named queries, custom script/task actions, and a validated json-render interface served at `/apps/<id>`. Use an app when people need to view and change live records; use `create_page` for a static snapshot
|
|
3
|
+
Swarm Apps are persistent, agent-authored internal applications: a schema-backed row store, named queries, custom script/task actions, and a validated json-render interface served at `/apps/<id>`. Use an app when people need to view and change live records; use `create_page` for a static snapshot.
|
|
4
4
|
|
|
5
5
|
> **Capability gate**: app tools are available when the server's `CAPABILITIES` includes `pages` (for example `CAPABILITIES=core,task-pool,pages`). There is no separate `apps` capability. If these tools are absent from your MCP list, this is why.
|
|
6
6
|
|
|
@@ -425,50 +425,71 @@ Drawer variant: declare a route param on the containing page, set the Drawer `pr
|
|
|
425
425
|
|
|
426
426
|
Param `kind` is `string` by default, or `number` / `boolean`; `required` defaults to false. The names `mode`, `apiUrl`, `apiKey`, `email`, and `name` are reserved. `/apps/<id>` renders `defaultPage`; `/apps/<id>/p/<page>?issueId=42` is the shareable deep link for another page. Browser navigation is client-side, so app state and polled data stay warm across page changes.
|
|
427
427
|
|
|
428
|
-
Within each page, `root` names one entry in its non-empty `elements` map. Elements are a flat, single-parent tree: ids are map keys, `children` contains ids (not nested elements), all elements must be reachable from `root`, and cycles, missing children, or shared children are invalid. Element and Form/UI ids are page-local. Element keys are `type`, `props`, `children`, `on`, `visible`, `repeat`, and `watch`; only components with a `default` child slot accept `children` (Stack, Grid, Split, Tabs, Container, Card, and Drawer). `watch` maps state paths to an action step or chain.
|
|
428
|
+
Within each page, `root` names one entry in its non-empty `elements` map. Elements are a flat, single-parent tree: ids are map keys, `children` contains ids (not nested elements), all elements must be reachable from `root`, and cycles, missing children, or shared children are invalid. Element and Form/UI ids are page-local. Element keys are `type`, `props`, `children`, `on`, `visible`, `repeat`, and `watch`; only components with a `default` child slot accept `children` (Stack, Grid, Split, Tabs, Container, Card, Section, and Drawer). `watch` maps state paths to an action step or chain.
|
|
429
429
|
|
|
430
|
-
## Component catalog (all
|
|
430
|
+
## Component catalog (all 33)
|
|
431
431
|
|
|
432
432
|
Props reject unknown keys. A `{"$state":"..."}` binding may replace a literal prop value at any depth.
|
|
433
433
|
|
|
434
|
+
Icons: every `icon` prop (and the `Icon` block) takes one name from a curated lucide set: `plus`, `refresh-cw`, `search`, `filter`, `download`, `upload`, `external-link`, `copy`, `check`, `x`, `trash-2`, `pencil`, `eye`, `calendar`, `clock`, `user`, `users`, `bot`, `git-pull-request`, `git-branch`, `github`, `slack`, `mail`, `link`, `file-text`, `folder`, `database`, `zap`, `sparkles`, `flag`, `star`, `tag`, `alert-triangle`, `info`, `circle-check`, `trending-up`, `trending-down`, `dollar-sign`, `activity`, `rocket`. Any other name is rejected.
|
|
435
|
+
|
|
436
|
+
Tones: Badge, Metric and Progress `tone` take `neutral`, `success`, `active`, `error`, `info`, `pending`, `warning`, or `paused`.
|
|
437
|
+
|
|
434
438
|
| Component | Required props | Optional props / values |
|
|
435
439
|
|---|---|---|
|
|
436
|
-
| `Stack` | none | Primary layout; `direction: "column", "row"`, `gap`, `padding: "none", "xs", "sm", "md", "lg", "xl"`; `align: "start", "center", "end", "stretch"`, `justify: "start", "center", "end", "between"`, `wrap`; has the `default` child slot. |
|
|
440
|
+
| `Stack` | none | Primary layout; `direction: "column", "row"`, `gap`, `padding: "none", "xs", "sm", "md", "lg", "xl"`; `align: "start", "center", "end", "stretch"`, `justify: "start", "center", "end", "between"`, `wrap`; `motion: "rise"` (default), `"fade"`, or `"none"` (see Motion below); has the `default` child slot. |
|
|
437
441
|
| `Grid` | none | Responsive `columns`: integer 1 through 6, or `{ base, sm, md, lg }` counts 1 through 6; `gap` uses the Stack spacing values; has the `default` child slot. |
|
|
438
442
|
| `Split` | none | `ratio: "1-1", "1-2", "2-1", "1-3", "3-1"`, `gap`, `collapseBelow: "sm", "md", "lg"`, `reverse`; has the positional `default` child slot. |
|
|
439
443
|
| `Divider` | none | `label`; no children. |
|
|
440
|
-
| `Tabs` | `id`, `tabs` | `tabs` entries are `{ key, label? }
|
|
444
|
+
| `Tabs` | `id`, `tabs` | `tabs` entries are `{ key, label?, icon?, count? }` (`count` is a number shown as a small pill); `defaultTab`; `variant: "line"` (default) or `"segmented"` (a compact segmented control, same state and warm panels); has the positional `default` child slot. |
|
|
441
445
|
| `Container` | none | Legacy layout primitive; prefer Stack. `direction: "row", "column"`, `gap: "none", "sm", "md", "lg"`; has the `default` child slot. |
|
|
442
446
|
| `Card` | none | `title`, `description`; has the `default` child slot. |
|
|
443
447
|
| `Heading` | `text` | `level: "h1", "h2", or "h3"`. |
|
|
444
448
|
| `Text` | `content` | `tone: "default" or "muted"`. |
|
|
445
449
|
| `Markdown` | `content` | Rendered Markdown for help, instructions, and rich prose; no children. |
|
|
446
|
-
| `SearchInput` | `id` | `placeholder`, `label
|
|
447
|
-
| `Select` | `id`, `options` | `options` are strings or `{ value, label? }`; `placeholder`, `label`, `clearable`; writes a string or null to `/ui/<id>/value
|
|
448
|
-
| `
|
|
449
|
-
| `
|
|
450
|
-
| `
|
|
451
|
-
| `
|
|
452
|
-
| `
|
|
450
|
+
| `SearchInput` | `id` | `placeholder`, `label`, `shortcut` (one key, usually `"/"`: shows a keycap and focuses the field); writes debounced text to `/ui/<id>/value`; no children. |
|
|
451
|
+
| `Select` | `id`, `options` | `options` are strings or `{ value, label?, icon?, hint? }`; `placeholder`, `label`, `clearable`, `searchable` (type to filter; on by default past 8 options), `searchPlaceholder`, `multiple`; writes a string or null to `/ui/<id>/value`, or with `multiple` a string array (empty = nothing picked); no children. |
|
|
452
|
+
| `Chips` | `id`, `options` | Toggle chips for quick filters. `options` are strings or `{ value, label?, icon? }`; `multiple`; `label` (group name for screen readers). Writes a string or null to `/ui/<id>/value`, or a string array with `multiple`; pressing the selected chip clears it. |
|
|
453
|
+
| `Button` | `label` | `variant: "default", "secondary", "outline", "ghost", "destructive", or "destructive-outline"` (use `destructive-outline` for standalone deletes); `disabled` (constant or bound boolean); `busyWith: "<actionName>"` swaps the label for a spinner while that custom action's `/actions/<name>/status` is `"running"` (presses are ignored), then shows a check and `successLabel` for about 1.5s when it turns `"ok"`; `icon`, `iconPosition: "start" or "end"`; `size: "sm", "default", or "lg"`; `shortcut` (one key, shown as a keycap, presses the button); `hint` (tooltip); dispatch with element-level `on.press`. |
|
|
454
|
+
| `Metric` | `label`, `value` | The dashboard stat tile. `value` is string or number (empty renders an em dash); bind `loading` to `/queries/<name>/loading` for a skeleton while the query loads; `icon` with `tone` tinting its tile; `detail` (a line under the value); `trend: { direction: "up", "down", or "flat", label }`; `info` (explanation tooltip next to the label). |
|
|
455
|
+
| `Alert` | `message` | `title`, `tone: "info", "success", "warning", or "error"`, `icon` (overrides the tone icon), `actionLabel` (a button inside the callout that emits `press`; wire it with `on.press`). |
|
|
456
|
+
| `Badge` | `text` | `text` is string or number; `tone`; `icon` replaces the dot; `variant: "tag"` (default uppercase chip), `"status"` (sentence-case pill), `"count"` (numeric pill), or `"beta"` (the BETA tag); `status` (a lifecycle value renders the dashboard status chip); `hint` (tooltip; the beta tag's explanation). |
|
|
457
|
+
| `Icon` | `name` | `size: "sm", "md", or "lg"`, `tone: "default", "muted", "success", "warning", "error", or "info"`, `label` (accessible name; decorative without it). |
|
|
458
|
+
| `Progress` | `value` | `max` (default 100), `tone`, `label`, `variant: "bar"` (default) or `"ring"` (the dashboard progress ring; ignores `tone`), `showValue` (default true: percent for a bar, `value / max` for a ring). |
|
|
459
|
+
| `EmptyState` | `title` | `icon` (default inbox), `body`, `actionLabel` (a button that emits `press`; wire it with `on.press`). |
|
|
460
|
+
| `CopyButton` | `value` | `value` is string or number; `label` is the visible text, icon-only without it. Renders nothing for an empty value. |
|
|
461
|
+
| `Kbd` | `keys` | Keycaps, one per string (`["⌘", "K"]`). Display only. |
|
|
462
|
+
| `Skeleton` | `shape` | `shape: "line", "block", "rows", "metric", or "card"`; `count` (1-20: lines, rows, tiles, or cards); `height` (px, `block` only, default 128). Show it with `visible` bound to a query's `loading`. |
|
|
463
|
+
| `Spinner` | none | `variant: "ring", "ellipsis", or "bars"` (default: the dashboard spinner), `size: "sm" or "md"`, `label` (visible text and accessible name). |
|
|
464
|
+
| `AvatarStack` | `users` | `users` are display names (initials avatars); `max` (default 4) before a `+N` count. Hover lists every name. |
|
|
465
|
+
| `Section` | `title` | `description`, `collapsible`, `defaultOpen` (default true); has the `default` child slot. |
|
|
466
|
+
| `Table` | `columns` | `data`, `loading`, `error`, `emptyMessage`, `emptyState`, `rowActions`, `onRowClick`, `selectedId`, `rowId`, `mobile`, `mobileFields`, `search`, `filters`; see below. |
|
|
453
467
|
| `Form` | `id`, `fields`, `onSubmit` | `title`, `submitLabel`; see below. |
|
|
454
|
-
| `Drawer` | `param` | `title`, `description`, `side: "right" or "left"`, `size: "sm", "md", "lg", or "xl"
|
|
455
|
-
| `DetailList` | `fields` | `data`, `emptyMessage`, `columns: 1 or 2`, `loading` (bind `/queries/<name>/loading` for skeleton fields while loading); renders one record without edit controls. |
|
|
468
|
+
| `Drawer` | `param` | `title`, `description`, `side: "right" or "left"`, `size: "sm", "md" (default), "lg", or "xl"` (about 480/660/900/1010px at 1440px; grows with the viewport up to 640/960/1280/1600px; full width on phones), `actions` (sticky footer buttons; see below); has the `default` child slot. |
|
|
469
|
+
| `DetailList` | `fields` | `data`, `emptyMessage`, `columns: 1 or 2`, `loading` (bind `/queries/<name>/loading` for skeleton fields while loading); renders one record without edit controls; see below for field kinds. |
|
|
456
470
|
| `Kanban` | `columnField`, `columns`, `titleField` | `data`, `loading`, `cardFields`, `idField` (default `id`), `onMove`, `onCardClick`; see below. |
|
|
457
471
|
| `Calendar` | `startField`, `titleField` | `data`, `loading`, `endField`, `idField`, `onSelect`; read-only month grid; see below. |
|
|
458
472
|
| `ContributionGraph` | none | `data`, `loading`, `dateField` (default `date`), `countField`, `days` (7-730, default 365); read-only activity heatmap. |
|
|
459
473
|
|
|
460
474
|
Table details:
|
|
461
475
|
|
|
462
|
-
- `columns[]`: `{ key, label?, kind?, tones?: {value: badgeTone}, width?: number, pinned?: "left" or "right" }`. `kind` is `text`, `string`, `enum`, `number`, `boolean`, `date`, or `
|
|
476
|
+
- `columns[]`: `{ key, label?, kind?, tones?: {value: badgeTone}, width?: number, pinned?: "left" or "right", align?: "start" or "end", truncate?: "end" or "middle", icon?, tooltip?: "<row field>", max?: number, onChange?: chain }`. `kind` is `text`, `string`, `enum`, `number`, `boolean`, `date`, `badge`, `status`, `user`, `agent`, `relative`, `duration`, `progress`, `copy`, `switch`, or `link`; `string` and `enum` render as text. Pin id/actions columns so they survive horizontal scroll on narrow viewports.
|
|
477
|
+
- `status`: lifecycle values (`pending`, `in_progress`, `running`, `completed`, `failed`, `cancelled`, `paused`, `reviewing`, ...) render the dashboard status chip with its icon; other values use `tones` like `badge`.
|
|
478
|
+
- `user` / `agent`: avatar plus name. `relative` (and `date`): smart time, exact time on hover. `duration`: milliseconds as `1m 23s`. `progress`: a bar against `max` (default 100). `copy`: the value plus a copy button. `link`: an http(s) URL opening in a new tab (other values render as text).
|
|
479
|
+
- `switch`: a toggle. `onChange` runs with `$row` = the row with this column already set to the new value, e.g. `[{ "action": "app.mutate", "params": { "model": "m", "op": "update", "rowId": { "$row": "id" }, "values": { "enabled": { "$row": "enabled" } } } }]`. Without `onChange` the switch is read-only.
|
|
480
|
+
- Numbers, durations and progress right-align by default. `truncate: "middle"` keeps both ends of ids and paths. `icon` shows in the header; `tooltip` names a row field shown on hover.
|
|
481
|
+
- `onRowClick`: action chain with `$row` / `$rowIndex`, run when a row is clicked (or Enter on a focused cell). Pair it with `app.navigate` that sets a Drawer param, and bind `selectedId` to `{ "$state": "/route/params/<param>" }` so the open row stays highlighted. `rowId` names the id field (default `id`).
|
|
482
|
+
- Phones (below 768px): the table renders as a card list. `mobileFields: { title, subtitle?, meta?: string or string[], status? }` picks the columns; by default the first text column is the title and the first `status`/`badge` column the chip. `mobile: "scroll"` keeps the grid; it is the default when the table has `rowActions` but no `onRowClick`.
|
|
483
|
+
- `emptyState: { icon?, title, body? }` replaces the plain empty message. A search or filter that hides every row shows its own "No rows match" state.
|
|
463
484
|
- `pagination`: boolean; defaults to auto-enabling past 200 rows (set `false` to force one scroll region). `density: "compact"` tightens row height for dense readouts.
|
|
464
|
-
- `rowActions[]`: `{ label, variant?, confirm?, actions }`. Variants add `destructive-outline` to the Button variants. `destructive` and `destructive-outline` confirm by default; customize with `{ "title": ..., "description": ..., "confirmLabel": ... }`, or use a bare `confirm` string as the dialog description (use `confirm: false` only for a reversible action).
|
|
485
|
+
- `rowActions[]`: `{ label, variant?, icon?, placement?: "inline" or "menu", confirm?, actions }`. `placement: "menu"` moves the action into the row's More menu. Variants add `destructive-outline` to the Button variants. `destructive` and `destructive-outline` confirm by default; customize with `{ "title": ..., "description": ..., "confirmLabel": ... }`, or use a bare `confirm` string as the dialog description (use `confirm: false` only for a reversible action).
|
|
465
486
|
- `search`: optional string; case-insensitive substring matching across the listed string and number columns. Bind a SearchInput value for client-side search.
|
|
466
|
-
- `filters`: optional record of per-column string, number, boolean, or
|
|
487
|
+
- `filters`: optional record of per-column string, number, boolean, null, or array values. An array means "the cell is one of these" (what a `multiple` Chips or Select writes). Null, empty strings, empty arrays, or absent values disable one filter. Bind Select or Chips values for client-side filters.
|
|
467
488
|
|
|
468
489
|
Kanban details:
|
|
469
490
|
|
|
470
491
|
- One card per `data` row, grouped by the row's `columnField` value. `columns[]` are plain strings or `{ id, label? }`, in display order; rows matching no column are hidden.
|
|
471
|
-
- `cardFields[]` uses the DetailList field shape (`{ key, label?, kind?, tones? }
|
|
492
|
+
- `cardFields[]` uses the DetailList field shape (`{ key, label?, kind?, tones? }`, same kinds) for extra lines under the title.
|
|
472
493
|
- `onMove` is an action chain run when a card is dropped in another column. `$row` is the moved row with `columnField` already set to the new column: `[{ "action": "app.mutate", "params": { "model": "deal", "op": "update", "rowId": { "$row": "id" }, "values": { "stage": { "$row": "stage" } } } }]`. Without `onMove`, cards cannot be dragged.
|
|
473
494
|
- `onCardClick` is an action chain with `$row`; pair it with `app.navigate` and a `Drawer` to open a card.
|
|
474
495
|
|
|
@@ -490,10 +511,19 @@ Form details:
|
|
|
490
511
|
Drawer details:
|
|
491
512
|
|
|
492
513
|
- `param` must name a param declared on the containing page. The drawer is open exactly when `/route/params/<param>` has a non-empty value, so its open state survives refresh and is shareable. Its children mount only while open; closing it clears that param with history replacement.
|
|
514
|
+
- `actions[]`: `{ label, variant?, icon?, confirm?, actions }`, rendered as buttons in a sticky footer under the scrolling body. Confirmation follows Table `rowActions`: destructive variants confirm by default, and a chain with an `app.mutate` delete always confirms. Chains have no `$row`; address the open record with `{ "$state": "/route/params/<param>" }`, for example `{ "action": "app.mutate", "params": { "model": "order", "op": "delete", "rowId": { "$state": "/route/params/panel" } } }`. Prev/next record navigation is not available.
|
|
493
515
|
|
|
494
516
|
DetailList details:
|
|
495
517
|
|
|
496
|
-
- `fields[]`: `{ key, label?, kind?, tones? }`. Kinds reuse Table formatting (`text`, `string`, `number`, `boolean`, `date`, `badge`, `enum`) and add `code` for monospace
|
|
518
|
+
- `fields[]`: `{ key, label?, kind?, tones? }`. Kinds reuse Table formatting (`text`, `string`, `number`, `boolean`, `date`, `badge`, `enum`) and the Table cell renderers (`status`: lifecycle chip or `tones` pill; `user`: avatar plus name; `relative`: smart time, exact on hover; `copy`: value plus copy button), and add `code` for a monospace block and `json` for a collapsible JSON tree (objects, or a string holding JSON). Bind `data` to one record, commonly `/queries/<detailQuery>/data/0`.
|
|
519
|
+
|
|
520
|
+
Motion details:
|
|
521
|
+
|
|
522
|
+
- Every `Stack` fades its direct children in and lifts them 4px over 200ms on first paint, staggered 30ms (capped at the 10th child). It never replays on the 5s data poll. A Stack nested inside another one does not add its own entrance. `motion: "fade"` drops the lift; `motion: "none"` turns it off. Viewers with reduced motion get a 150ms fade.
|
|
523
|
+
|
|
524
|
+
Shortcut details:
|
|
525
|
+
|
|
526
|
+
- `Button.shortcut` and `SearchInput.shortcut` are one key. Letters and digits match without Shift; symbols such as `/` and `?` match as typed. They do nothing while focus is in a text field, while Ctrl, Cmd, or Alt is held, or while a dialog or menu is open (unless the control is inside it, such as a Button in an open Drawer).
|
|
497
527
|
|
|
498
528
|
## Layout & interactivity
|
|
499
529
|
|
|
@@ -501,7 +531,7 @@ Use `Stack` as the primary page and section layout; `Container` is the legacy tw
|
|
|
501
531
|
|
|
502
532
|
`Split` and `Tabs` children are positional. For Split, `children[0]` is the first pane, `children[1]` is the second, and extra children append inside the second pane. Below `collapseBelow`, panes stack; `reverse` changes only that narrow-layout stacking order. For Tabs, `children[i]` is the body for `tabs[i]`; keep both arrays in the same order and with the same count. Inactive tab children stay mounted but hidden, so Tables keep polling. Use `Divider` to separate sections and `Markdown` for richer explanatory content.
|
|
503
533
|
|
|
504
|
-
SearchInput and
|
|
534
|
+
SearchInput, Select, and Chips are client-side controls: each needs a literal `id` and writes state under `/ui/<id>/value`; Tabs writes its active key to `/ui/<id>/tab`. Bind those values into a Table's `search` and `filters` props. This filters already-polled rows locally; it does not alter or re-run the named query.
|
|
505
535
|
|
|
506
536
|
```json
|
|
507
537
|
{
|
|
@@ -550,7 +580,7 @@ Valid `$state` roots are:
|
|
|
550
580
|
|
|
551
581
|
- `/queries/<declaredQuery>/...`
|
|
552
582
|
- `/forms/<formId>/...`, where a `Form` element has that literal `props.id`
|
|
553
|
-
- `/ui/<id>/...`, where a SearchInput, Select, or Tabs element has that literal `props.id` (SearchInput and
|
|
583
|
+
- `/ui/<id>/...`, where a SearchInput, Select, Chips, or Tabs element has that literal `props.id` (SearchInput, Select, and Chips use `/value`; Tabs uses `/tab`)
|
|
554
584
|
- `/actions/<declaredAction>/...`
|
|
555
585
|
- `/route/page` for the active page name
|
|
556
586
|
- `/route/params/<declaredParam>` for a param declared on the current page
|
|
@@ -572,10 +602,11 @@ Each sentinel object must contain exactly the single key shown.
|
|
|
572
602
|
|
|
573
603
|
An action-chain step is `{ "action": "<type>", "params": {...} }`. Available action types:
|
|
574
604
|
|
|
575
|
-
- `app.mutate`: `{ model, op, rowId?, values?, formId? }`, where `op` is `"create"`, `"update"`, or `"delete"`. `update`/`delete` require `rowId` (usually `{ "$row": "id" }`); literal `values` keys must be model columns. Successful mutation refetches all queries on that model.
|
|
605
|
+
- `app.mutate`: `{ model, op, rowId?, values?, formId? }`, where `op` is `"create"`, `"update"`, or `"delete"`. `update`/`delete` require `rowId` (usually `{ "$row": "id" }`, or `{ "$state": "/route/params/<param>" }` in a Drawer footer); literal `values` keys must be model columns. Successful mutation refetches all queries on that model.
|
|
576
606
|
- `app.refresh`: `{ query? }`; omit `query` to refetch all, or name a declared query.
|
|
577
607
|
- `app.action`: `{ name, input? }`; `name` must be declared in definition `actions`. For a task-kind row action, pass whole-row context with `input: { issue: { "$row": "" } }`.
|
|
578
608
|
- `app.navigate`: `{ page, params? }`; `page` must be declared, supplied keys must be params of the target page, and every required target param must be supplied. `params` replace the current route params wholesale and may contain action sentinels. Navigation pushes history, so browser Back returns to the previous page/params; only `mode` is preserved automatically.
|
|
609
|
+
- `ui.toast`: `{ message, description?, tone?, undo? }`, where `tone` is `"success"`, `"error"`, `"info"` (default), or `"warning"`. `undo: { label?, actions }` adds an Undo button (default label `Undo`) that runs `actions` as a chain; its steps are validated like any chain. Put it after the step it confirms, e.g. a row delete followed by `{ "action": "ui.toast", "params": { "message": "Order deleted", "undo": { "actions": [{ "action": "app.mutate", "params": { "model": "order", "op": "create", "values": { "title": { "$row": "title" } } } }] } } }`. Undo params resolve `$state` when Undo is pressed; `$row` / `$form` resolve when the toast is shown.
|
|
579
610
|
- `swarm.sdk`: `{ sdk, args? }`; invokes a catalog-supported Swarm browser SDK method with the viewer's bearer.
|
|
580
611
|
- `swarm.call`: `{ method, endpoint: "/api/...", body? }`, where `method` is `"GET"`, `"POST"`, `"PUT"`, `"DELETE"`, or `"PATCH"`; raw authenticated API call.
|
|
581
612
|
|
|
@@ -704,3 +735,10 @@ Create this with `app-upsert`:
|
|
|
704
735
|
```
|
|
705
736
|
|
|
706
737
|
The tool returns `{ appId, url: "/apps/<id>" }`. Open that URL to verify the live UI, then continue with the read-patch-validate loop above.
|
|
738
|
+
|
|
739
|
+
## View and screenshot a live app
|
|
740
|
+
|
|
741
|
+
- An app renders at `<dashboard>/apps/<id>`. Two view modes are set by query string: `?mode=full` (full-viewport overlay with a slim header) and `?mode=chromeless` (only the rendered page, the embed surface). `app.navigate` keeps only `?mode`.
|
|
742
|
+
- Logged-in browser: a fresh dashboard has no connection and redirects to /setup. Seed the localStorage key `agent-swarm-connections` with `{connections:[{id,name,apiUrl,apiKey}],activeId}`. Build the value from an env var and pipe it to `agent-browser eval --stdin`, so the key never reaches a command line. Reload, then pick a user in the "Who are you?" dialog.
|
|
743
|
+
- Apps scroll inside an inner canvas, so a full-page screenshot captures only the viewport. Scroll the canvas or raise the viewport height. For mobile, set a 375px-wide viewport before the screenshot.
|
|
744
|
+
- App definitions: `GET /api/apps` and `GET /api/apps/<id>` with the API key as Bearer.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "skill",
|
|
3
|
+
"name": "chat-sdk",
|
|
4
|
+
"displayName": "Chat SDK",
|
|
5
|
+
"slug": "chat-sdk",
|
|
6
|
+
"title": "Chat SDK",
|
|
7
|
+
"description": "Chat threads from Telegram, Slack (Chat SDK), Discord, and Teams. Use when a task carries a task:chat-sdk contextKey or a user asked through Telegram, Slack, Discord, or Teams. Covers what the swarm posts for you, `chat-reply`, markdown and length per platform, attachments, `chat-read-thread` limits, and channel routes with `register-chat-channel`.",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"category": "skills",
|
|
10
|
+
"placeholders": [],
|
|
11
|
+
"runAllSeedersCandidate": true,
|
|
12
|
+
"systemDefault": false,
|
|
13
|
+
"tags": ["chat", "telegram", "discord", "teams", "slack", "communication"]
|
|
14
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Chat SDK
|
|
2
|
+
|
|
3
|
+
The swarm receives messages from Telegram, Slack, Discord, and Microsoft Teams through the Chat SDK channel. A person mentions the bot or sends it a direct message, and the swarm creates a task for it. This skill tells you how to work on such a task.
|
|
4
|
+
|
|
5
|
+
## How you know you are on a chat task
|
|
6
|
+
|
|
7
|
+
- The task has `source: "chat"`, or it is a lead follow-up of one.
|
|
8
|
+
- The task `contextKey` starts with `task:chat-sdk:`. The full form is `task:chat-sdk:<adapter>:<encoded thread id>`, for example `task:chat-sdk:telegram:555001`.
|
|
9
|
+
- The task text holds the user's message. Later replies in the same thread arrive as follow-up tasks with the same `contextKey`, or as steering messages on your running task.
|
|
10
|
+
- The user has four slash commands that never reach you as a task: `/help`, `/status`, `/cancel` and `/reset`. `/cancel` ends the thread's active tasks, yours included, with status `cancelled`. After `/reset` the next task has no parent task and no earlier thread context, so treat it as a new conversation.
|
|
11
|
+
|
|
12
|
+
Use `get-task-details` to read the `contextKey` when you are not sure.
|
|
13
|
+
|
|
14
|
+
## Reply with `chat-reply`
|
|
15
|
+
|
|
16
|
+
`chat-reply { text }` posts to the thread your current task came from. It finds the thread from your task, so you do not pass ids.
|
|
17
|
+
|
|
18
|
+
- Use it to ask the user a question you cannot answer yourself. Ask once, with all your questions together.
|
|
19
|
+
- Use it for one short progress note when work takes more than a few minutes, such as "Started. This takes about 10 minutes."
|
|
20
|
+
- Do not use it for receipts ("Got it", "On it"), and do not send many progress notes.
|
|
21
|
+
- It works only on a task with a `task:chat-sdk:` contextKey. A session bound to a non-chat task does not see `chat-reply` at all, because the tool is left out of its tool list.
|
|
22
|
+
|
|
23
|
+
## The final summary is posted automatically
|
|
24
|
+
|
|
25
|
+
When your task ends, the swarm posts the task output to the thread:
|
|
26
|
+
|
|
27
|
+
- Completed: your `store-progress` output.
|
|
28
|
+
- Failed: a "Task failed." line, then the failure reason.
|
|
29
|
+
- Cancelled: a "Task cancelled." line, then the reason when there is one.
|
|
30
|
+
|
|
31
|
+
Do not post your final answer with `chat-reply` as well. The user would get it twice. Put the answer in the `store-progress` output and stop.
|
|
32
|
+
|
|
33
|
+
The post is durable. If the platform is down, the swarm retries with backoff for up to 24 hours.
|
|
34
|
+
|
|
35
|
+
## Markdown per platform
|
|
36
|
+
|
|
37
|
+
Write plain, short markdown: bold, italic, inline code, code blocks, bullet lists, and links. Avoid tables, nested lists, and HTML.
|
|
38
|
+
|
|
39
|
+
| Platform | What renders | Limit per message |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Telegram | Bold, italic, code, code blocks, links, lists. No tables. | 4096 characters |
|
|
42
|
+
| Discord | Bold, italic, code, code blocks, lists, headings, links. No tables. | 2000 characters |
|
|
43
|
+
| Slack | Converted to Slack mrkdwn: bold, italic, code, lists, links. Tables do not render well. | 4000 characters |
|
|
44
|
+
| Teams | Basic markdown: bold, italic, code, lists, links. | 20000 characters |
|
|
45
|
+
|
|
46
|
+
The swarm splits longer text into several messages at line breaks. Long answers are hard to read in chat, so keep the answer short and put long material in an artifact or page, then post the link.
|
|
47
|
+
|
|
48
|
+
## Attachments arrive as task attachments
|
|
49
|
+
|
|
50
|
+
Files and images the user sends in the thread are stored as attachments of the task. The task text names them. Download them with the `download-task-attachment` skill. You cannot send files back to the thread in this version. Share a link instead.
|
|
51
|
+
|
|
52
|
+
## `chat-read-thread` limits per platform
|
|
53
|
+
|
|
54
|
+
`chat-read-thread { threadId, limit? }` returns the most recent messages of a thread, oldest first. The thread id is the adapter name plus the URI-decoded remainder of the contextKey. Telegram ids have no escaping, so `telegram:555001` stays as it is. Slack, Discord, and Teams ids contain `%3A` in the contextKey, so do not build the id by hand. `chat-reply` resolves the thread itself. For `chat-read-thread`, use the thread id returned by `chat-reply`, `chat-post`, or `chat-open-dm`. You can read the thread of your current task. Any other thread needs lead privileges.
|
|
55
|
+
|
|
56
|
+
- Telegram has no history API. The SDK keeps the Telegram thread history it saw in the swarm database, capped at 100 messages and 7 days.
|
|
57
|
+
- Teams needs the `Chat.Read.*` Graph permission on the bot. Without it, the call fails.
|
|
58
|
+
- Slack and Discord return the platform history.
|
|
59
|
+
|
|
60
|
+
The task text already holds the earlier swarm messages of the thread, so read the thread only when you need more.
|
|
61
|
+
|
|
62
|
+
## Other tools
|
|
63
|
+
|
|
64
|
+
- `chat-post { adapter, threadId | channelId, text }` posts outside your task's thread. Lead only. Use it only when the task asks you to message another thread or channel.
|
|
65
|
+
- `chat-open-dm { adapter, userId }` returns the direct-message thread id for a user. Lead only. Then post to it with `chat-post`.
|
|
66
|
+
|
|
67
|
+
## Leads: `register-chat-channel`
|
|
68
|
+
|
|
69
|
+
By default every message addressed to the swarm goes to the lead. A lead can route one channel to a fixed agent or workflow:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
register-chat-channel { adapter: "telegram", channelId: "telegram:-100123", agentId: "<agent id>" }
|
|
73
|
+
register-chat-channel { adapter: "slack", channelId: "slack:C123", workflowId: "<workflow id>" }
|
|
74
|
+
unregister-chat-channel { adapter: "telegram", channelId: "telegram:-100123" }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Give exactly one of `agentId` or `workflowId`. A `swarm#<agentId>` token in a message still wins over the route. A workflow mapping fires only for a bot mention or a DM; a plain reply in the subscribed thread does not start another run. Only the lead can call these tools.
|
|
78
|
+
|
|
79
|
+
## Etiquette
|
|
80
|
+
|
|
81
|
+
- Keep messages short. Chat is read on phones.
|
|
82
|
+
- Never post secrets, tokens, internal URLs with credentials, or private data from other users. The swarm scrubs known secrets, but do not depend on it.
|
|
83
|
+
- When you ask a question in a group, start with the user's name so they see it.
|
|
84
|
+
- One question message is better than several.
|
|
@@ -62,6 +62,13 @@ agent-swarm x composio POST /tools/execute/GMAIL_SEND_EMAIL \
|
|
|
62
62
|
- `recipient_email` is the primary; add more via `extra_recipients` / `cc` / `bcc`.
|
|
63
63
|
- **Sending is a write action** — only do it when the task explicitly asks.
|
|
64
64
|
|
|
65
|
+
## Sender (From) and footer
|
|
66
|
+
|
|
67
|
+
- A draft defaults to the connected account's primary address. Before you create drafts, list the account's verified send-as aliases and set From to the alias the requester prefers (requester profile or brief). Take the footer and signature domain from the same source.
|
|
68
|
+
- Never set From to an alias that is not verified. Gmail rewrites it to the primary address.
|
|
69
|
+
- After you create the drafts, check From as well as To and Subject on each one.
|
|
70
|
+
- To fix existing drafts, update each draft in place with the alias. Draft ids stay the same, so there is no need to delete and recreate.
|
|
71
|
+
|
|
65
72
|
## Reply in a thread
|
|
66
73
|
|
|
67
74
|
```bash
|
|
@@ -67,7 +67,7 @@ agent-swarm x composio POST /tools/execute/GOOGLEDOCS_CREATE_DOCUMENT_MARKDOWN \
|
|
|
67
67
|
2. Write the converted content to your own agent-fs namespace with a short
|
|
68
68
|
provenance header naming the source document and import method.
|
|
69
69
|
3. Resolve the destination org and drive from the environment or
|
|
70
|
-
`agent-fs stat <path> --json`; the `
|
|
70
|
+
`agent-fs stat <path> --json`; the `agent-fs` skill documents the canonical
|
|
71
71
|
storage and share-link workflow. Never copy org or drive IDs from an example.
|
|
72
72
|
4. Read the stored file back and assert several markers: the title, a middle
|
|
73
73
|
phrase, and the final sentence. A successful byte-count response alone does
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": "skill",
|
|
3
|
+
"name": "email-domain-health",
|
|
4
|
+
"displayName": "Email Domain Health",
|
|
5
|
+
"slug": "email-domain-health",
|
|
6
|
+
"title": "Email Domain Health",
|
|
7
|
+
"description": "Build a scheduled email domain health monitor: ask the user for domains, providers, test inbox, schedule and alert rules, then build a checks script (SPF, DKIM, DMARC, MX, provider records, blocklists with positive controls), a daily test send with score capture, bounce rate, run history in a Swarm App, and alerts only on a new red or a score drop. Orchestrates the swarm-scripts, apps, scheduling and composio-gmail skills.",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"category": "skills",
|
|
10
|
+
"placeholders": [],
|
|
11
|
+
"runAllSeedersCandidate": true,
|
|
12
|
+
"systemDefault": true,
|
|
13
|
+
"tags": ["email", "deliverability", "dns", "monitoring", "apps"]
|
|
14
|
+
}
|
|
@@ -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.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"category": "skills",
|
|
3
|
+
"description": "Narrated QA loom for UI work: record a UI QA pass with agent-browser and a timestamped step log, voice it with ElevenLabs, burn one-line subtitles with ffmpeg, and embed the narrated mp4 (plus an optional GIF preview) in the PR as GitHub user attachments. Use on UI-changing PRs and UI QA passes. Layers on the `qa` and `agent-browser` skills. Needs ELEVENLABS_API_KEY, ffmpeg with libass, and agent-browser.",
|
|
4
|
+
"displayName": "QA Loom",
|
|
5
|
+
"kind": "skill",
|
|
6
|
+
"name": "qa-loom",
|
|
7
|
+
"placeholders": [],
|
|
8
|
+
"runAllSeedersCandidate": true,
|
|
9
|
+
"slug": "qa-loom",
|
|
10
|
+
"systemDefault": true,
|
|
11
|
+
"tags": ["qa", "video", "screen-recording", "evidence", "elevenlabs"],
|
|
12
|
+
"title": "QA Loom",
|
|
13
|
+
"version": "1.0.0"
|
|
14
|
+
}
|