@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
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { getAgentCurrentTask, getTaskById } from "@/be/db";
|
|
4
|
+
import { errorMessage } from "@/integrations/chat-sdk/logger";
|
|
5
|
+
import { ChatAdapterUnavailableError, postChatMessage } from "@/integrations/chat-sdk/outbound";
|
|
6
|
+
import { chatThreadOfContextKey } from "@/tasks/context-key";
|
|
7
|
+
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
8
|
+
|
|
9
|
+
export const registerChatReplyTool = (server: McpServer) => {
|
|
10
|
+
createToolRegistrar(server)(
|
|
11
|
+
"chat-reply",
|
|
12
|
+
{
|
|
13
|
+
title: "Reply in the chat thread of this task",
|
|
14
|
+
description:
|
|
15
|
+
"Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user or a short progress note on long work. Markdown is supported; long text is split into several messages.",
|
|
16
|
+
annotations: { openWorldHint: true },
|
|
17
|
+
inputSchema: z.object({
|
|
18
|
+
text: z.string().min(1).max(20_000).describe("Markdown text to post to the thread."),
|
|
19
|
+
}),
|
|
20
|
+
outputSchema: swarmToolOutputSchema({
|
|
21
|
+
yourAgentId: z.string().optional(),
|
|
22
|
+
messageId: z.string().optional(),
|
|
23
|
+
adapter: z.string().optional(),
|
|
24
|
+
threadId: z.string().optional(),
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
async ({ text }, requestInfo) => {
|
|
28
|
+
if (!requestInfo.agentId) return toolErr("Agent ID not found.");
|
|
29
|
+
const data = { yourAgentId: requestInfo.agentId };
|
|
30
|
+
|
|
31
|
+
// The header names the task this session works on; without it, the
|
|
32
|
+
// agent's current in-progress task.
|
|
33
|
+
const task = requestInfo.sourceTaskId
|
|
34
|
+
? await getTaskById(requestInfo.sourceTaskId)
|
|
35
|
+
: await getAgentCurrentTask(requestInfo.agentId);
|
|
36
|
+
if (!task) return toolErr("No current task found for chat-reply.", { data });
|
|
37
|
+
// Creator is safe: a non-lead agent can only create a chat-bound task under a parent it owns or created.
|
|
38
|
+
if (task.agentId !== requestInfo.agentId && task.creatorAgentId !== requestInfo.agentId) {
|
|
39
|
+
return toolErr("You don't have context for this task.", { data });
|
|
40
|
+
}
|
|
41
|
+
const thread = chatThreadOfContextKey(task.contextKey);
|
|
42
|
+
if (!thread) {
|
|
43
|
+
return toolErr(
|
|
44
|
+
`Task ${task.id} did not come from a chat thread (no task:chat-sdk contextKey). Use the tool of the channel the task came from.`,
|
|
45
|
+
{ data },
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const sent = await postChatMessage({
|
|
51
|
+
adapter: thread.adapter,
|
|
52
|
+
threadId: thread.threadId,
|
|
53
|
+
text,
|
|
54
|
+
taskId: task.id,
|
|
55
|
+
});
|
|
56
|
+
return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}.`, {
|
|
57
|
+
data: {
|
|
58
|
+
...data,
|
|
59
|
+
messageId: sent.messageIds.at(-1),
|
|
60
|
+
adapter: sent.adapter,
|
|
61
|
+
threadId: sent.threadId,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
const message = errorMessage(error);
|
|
66
|
+
return toolErr(
|
|
67
|
+
error instanceof ChatAdapterUnavailableError
|
|
68
|
+
? `${message}. The final task output is still posted when the adapter is back.`
|
|
69
|
+
: `Could not post to the chat thread: ${message}`,
|
|
70
|
+
{ data },
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
};
|
package/src/tools/create-page.ts
CHANGED
|
@@ -21,7 +21,8 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
21
21
|
import * as z from "zod";
|
|
22
22
|
import { authorizeAssetKeyWrite } from "@/be/asset-key-auth";
|
|
23
23
|
import { resolveTaskAuditUserId } from "@/be/audit-user";
|
|
24
|
-
import { createPage, getPage, getPageBySlug,
|
|
24
|
+
import { createPage, getPage, getPageBySlug, updatePage } from "@/be/db";
|
|
25
|
+
import { getPageEditCounter } from "@/be/db/page-versions";
|
|
25
26
|
import { snapshotPage } from "@/pages/version";
|
|
26
27
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
27
28
|
import { AssetKeySchema, PageAuthModeSchema, PageContentTypeSchema } from "@/types";
|
|
@@ -45,17 +46,6 @@ function getAppBaseUrl(): string {
|
|
|
45
46
|
return getAppUrl();
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
/**
|
|
49
|
-
* Edit counter for a page — `MAX(page_versions.version) + 1`. Returned to
|
|
50
|
-
* the agent as `version` so they have a monotonic "this page has been
|
|
51
|
-
* edited N times" signal. Mirrors the value returned by
|
|
52
|
-
* `PUT /api/pages/:id` (see src/http/pages.ts:pageEditCounter).
|
|
53
|
-
*/
|
|
54
|
-
async function pageEditCounter(pageId: string): Promise<number> {
|
|
55
|
-
const versions = await getPageVersions(pageId);
|
|
56
|
-
return versions.length > 0 ? versions[0]!.version + 1 : 1;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
49
|
export const registerCreatePageTool = (server: McpServer) => {
|
|
60
50
|
createToolRegistrar(server)(
|
|
61
51
|
"create_page",
|
|
@@ -217,7 +207,7 @@ export const registerCreatePageTool = (server: McpServer) => {
|
|
|
217
207
|
|
|
218
208
|
const apiUrl = `${getApiBaseUrl()}/p/${id}`;
|
|
219
209
|
const appUrl = `${getAppBaseUrl()}/pages/${id}`;
|
|
220
|
-
const version = await
|
|
210
|
+
const version = await getPageEditCounter(id);
|
|
221
211
|
|
|
222
212
|
return toolOk(`Page "${input.title}" saved (slug=${finalSlug}, version=${version}).`, {
|
|
223
213
|
details: `API: ${apiUrl}\n App: ${appUrl}`,
|
package/src/tools/defer-task.ts
CHANGED
|
@@ -306,6 +306,23 @@ export const registerDeferTaskTool = (server: McpServer) => {
|
|
|
306
306
|
|
|
307
307
|
try {
|
|
308
308
|
const committed = await getDbClient().transaction(async () => {
|
|
309
|
+
// The transaction's write lock makes admission atomic with the INSERT.
|
|
310
|
+
if (watchedTaskIds.length) {
|
|
311
|
+
const existing = await getDbClient().get<{ scheduleId: string; parentTaskId: string }>(
|
|
312
|
+
`SELECT w.scheduleId, s.parentTaskId FROM deferred_task_waits w
|
|
313
|
+
JOIN scheduled_tasks s ON s.id = w.scheduleId
|
|
314
|
+
JOIN deferred_task_wait_members m ON m.scheduleId = w.scheduleId
|
|
315
|
+
WHERE w.status = 'pending' AND s.enabled = 1 AND s.targetAgentId = ?
|
|
316
|
+
AND m.taskId IN (${watchedTaskIds.map(() => "?").join(", ")})
|
|
317
|
+
LIMIT 1`,
|
|
318
|
+
[agent.id, ...watchedTaskIds],
|
|
319
|
+
);
|
|
320
|
+
if (existing) {
|
|
321
|
+
throw new DeferAbortedError(
|
|
322
|
+
`Pending watcher ${existing.scheduleId} (task ${existing.parentTaskId}) already watches these tasks for this agent.`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
309
326
|
const watchedAgentNames: string[] = [];
|
|
310
327
|
for (const watchedId of watchedTaskIds) {
|
|
311
328
|
if (watchedId === taskId)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { openAICompatibleProviderIds } from "@desplega/model-catalog";
|
|
1
2
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
3
|
import * as z from "zod";
|
|
3
4
|
import { getAgentById } from "@/be/db";
|
|
@@ -86,7 +87,7 @@ export const registerModelCatalogOverlayUpsertTool = (server: McpServer) => {
|
|
|
86
87
|
.string()
|
|
87
88
|
.min(1)
|
|
88
89
|
.describe(
|
|
89
|
-
|
|
90
|
+
`models.dev provider id: anthropic, openai, openrouter, amazon-bedrock, opencode, ${openAICompatibleProviderIds().join(", ")}.`,
|
|
90
91
|
),
|
|
91
92
|
modelId: z
|
|
92
93
|
.string()
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { getAgentById, getWorkflow } from "@/be/db";
|
|
4
|
+
import { CHAT_SDK_ADAPTER_NAMES } from "@/integrations/chat-sdk/config";
|
|
5
|
+
import { errorMessage } from "@/integrations/chat-sdk/logger";
|
|
6
|
+
import {
|
|
7
|
+
type ChatChannelMapping,
|
|
8
|
+
chatChannelKey,
|
|
9
|
+
deleteChatChannelMapping,
|
|
10
|
+
putChatChannelMapping,
|
|
11
|
+
} from "@/integrations/chat-sdk/router";
|
|
12
|
+
import { can } from "@/rbac";
|
|
13
|
+
import {
|
|
14
|
+
createToolRegistrar,
|
|
15
|
+
type RequestInfo,
|
|
16
|
+
swarmToolOutputSchema,
|
|
17
|
+
toolErr,
|
|
18
|
+
toolOk,
|
|
19
|
+
} from "@/tools/utils";
|
|
20
|
+
|
|
21
|
+
async function canManageChatChannels(requestInfo: RequestInfo): Promise<boolean> {
|
|
22
|
+
const caller = requestInfo.agentId ? await getAgentById(requestInfo.agentId) : null;
|
|
23
|
+
return can({
|
|
24
|
+
principal: {
|
|
25
|
+
kind: "agent",
|
|
26
|
+
agentId: requestInfo.agentId ?? "",
|
|
27
|
+
isLead: caller?.isLead ?? false,
|
|
28
|
+
},
|
|
29
|
+
verb: "integration.chat.manage",
|
|
30
|
+
resource: { kind: "none" },
|
|
31
|
+
source: "mcp",
|
|
32
|
+
}).allow;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const registerRegisterChatChannelTool = (server: McpServer) => {
|
|
36
|
+
createToolRegistrar(server)(
|
|
37
|
+
"register-chat-channel",
|
|
38
|
+
{
|
|
39
|
+
title: "Route a chat channel to an agent or workflow",
|
|
40
|
+
annotations: { idempotentHint: true },
|
|
41
|
+
description:
|
|
42
|
+
"Lead-only. Route every swarm-addressed message from one Chat SDK channel (a Telegram group, Slack channel, Discord channel or Teams chat) to a fixed agent or workflow instead of the lead. Give exactly one of agentId or workflowId. A swarm#<agentId> token in a message still wins over the mapping. Remove it with unregister-chat-channel.",
|
|
43
|
+
inputSchema: z.object({
|
|
44
|
+
adapter: z.enum(CHAT_SDK_ADAPTER_NAMES).describe("Chat SDK adapter name."),
|
|
45
|
+
channelId: z
|
|
46
|
+
.string()
|
|
47
|
+
.min(1)
|
|
48
|
+
.describe("SDK channel id, such as telegram:-100123 or slack:C123 (prefix optional)."),
|
|
49
|
+
agentId: z.string().optional().describe("Agent that receives the channel's tasks."),
|
|
50
|
+
workflowId: z
|
|
51
|
+
.string()
|
|
52
|
+
.optional()
|
|
53
|
+
.describe("Workflow whose webhook trigger receives the channel's messages."),
|
|
54
|
+
name: z.string().max(200).optional().describe("Display name for the mapping."),
|
|
55
|
+
}),
|
|
56
|
+
outputSchema: swarmToolOutputSchema({
|
|
57
|
+
yourAgentId: z.string().optional(),
|
|
58
|
+
key: z.string().optional(),
|
|
59
|
+
mapping: z
|
|
60
|
+
.looseObject({
|
|
61
|
+
agentId: z.string().optional(),
|
|
62
|
+
workflowId: z.string().optional(),
|
|
63
|
+
name: z.string().optional(),
|
|
64
|
+
createdAt: z.string().optional(),
|
|
65
|
+
})
|
|
66
|
+
.optional(),
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
async ({ adapter, channelId, agentId, workflowId, name }, requestInfo) => {
|
|
70
|
+
const data = { yourAgentId: requestInfo.agentId };
|
|
71
|
+
try {
|
|
72
|
+
if (!(await canManageChatChannels(requestInfo))) {
|
|
73
|
+
return toolErr("Permission denied. Only the lead can register a chat channel.", {
|
|
74
|
+
data,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (Boolean(agentId) === Boolean(workflowId)) {
|
|
78
|
+
return toolErr("Give exactly one of agentId or workflowId.", { data });
|
|
79
|
+
}
|
|
80
|
+
if (agentId && !(await getAgentById(agentId))) {
|
|
81
|
+
return toolErr(`Agent ${agentId} not found.`, { data });
|
|
82
|
+
}
|
|
83
|
+
if (workflowId && !(await getWorkflow(workflowId))) {
|
|
84
|
+
return toolErr(`Workflow ${workflowId} not found.`, { data });
|
|
85
|
+
}
|
|
86
|
+
const mapping: ChatChannelMapping = {
|
|
87
|
+
...(agentId ? { agentId } : {}),
|
|
88
|
+
...(workflowId ? { workflowId } : {}),
|
|
89
|
+
...(name ? { name } : {}),
|
|
90
|
+
createdAt: new Date().toISOString(),
|
|
91
|
+
};
|
|
92
|
+
const key = await putChatChannelMapping(adapter, channelId, mapping);
|
|
93
|
+
return toolOk(
|
|
94
|
+
`Registered chat channel ${key} -> ${workflowId ? `workflow ${workflowId}` : `agent ${agentId}`}.`,
|
|
95
|
+
{ data: { ...data, key, mapping } },
|
|
96
|
+
);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return toolErr(errorMessage(error), { data });
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const registerUnregisterChatChannelTool = (server: McpServer) => {
|
|
105
|
+
createToolRegistrar(server)(
|
|
106
|
+
"unregister-chat-channel",
|
|
107
|
+
{
|
|
108
|
+
title: "Remove a chat channel route",
|
|
109
|
+
annotations: { idempotentHint: true },
|
|
110
|
+
description:
|
|
111
|
+
"Lead-only. Remove the channel-to-agent or channel-to-workflow route that register-chat-channel stored. Messages from the channel go back to the default route (thread owner, then the lead).",
|
|
112
|
+
inputSchema: z.object({
|
|
113
|
+
adapter: z.enum(CHAT_SDK_ADAPTER_NAMES).describe("Chat SDK adapter name."),
|
|
114
|
+
channelId: z.string().min(1).describe("SDK channel id (prefix optional)."),
|
|
115
|
+
}),
|
|
116
|
+
outputSchema: swarmToolOutputSchema({
|
|
117
|
+
yourAgentId: z.string().optional(),
|
|
118
|
+
key: z.string().optional(),
|
|
119
|
+
}),
|
|
120
|
+
},
|
|
121
|
+
async ({ adapter, channelId }, requestInfo) => {
|
|
122
|
+
const data = { yourAgentId: requestInfo.agentId };
|
|
123
|
+
try {
|
|
124
|
+
if (!(await canManageChatChannels(requestInfo))) {
|
|
125
|
+
return toolErr("Permission denied. Only the lead can unregister a chat channel.", {
|
|
126
|
+
data,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const key = chatChannelKey(adapter, channelId);
|
|
130
|
+
const deleted = await deleteChatChannelMapping(adapter, channelId);
|
|
131
|
+
return deleted
|
|
132
|
+
? toolOk(`Unregistered chat channel ${key}.`, { data: { ...data, key } })
|
|
133
|
+
: toolErr(`No mapping found for chat channel ${key}.`, { data: { ...data, key } });
|
|
134
|
+
} catch (error) {
|
|
135
|
+
return toolErr(errorMessage(error), { data });
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
};
|
package/src/tools/send-task.ts
CHANGED
|
@@ -378,6 +378,30 @@ export async function sendTaskHandler(
|
|
|
378
378
|
const effectiveParentTask = effectiveParentTaskId
|
|
379
379
|
? await getTaskById(effectiveParentTaskId)
|
|
380
380
|
: null;
|
|
381
|
+
// The child inherits the parent's contextKey (its Slack or chat thread) and requester, and
|
|
382
|
+
// thread-scoped tools trust that binding. An agent can only build on a parent it owns or
|
|
383
|
+
// created; otherwise a worker could mint access to a foreign thread.
|
|
384
|
+
if (ctx.kind === "owner" && creatorAgentId && effectiveParentTask) {
|
|
385
|
+
const caller = await getAgentById(creatorAgentId);
|
|
386
|
+
const decision = can({
|
|
387
|
+
principal: { kind: "agent", agentId: creatorAgentId, isLead: caller?.isLead ?? false },
|
|
388
|
+
verb: "task.parent.attach",
|
|
389
|
+
resource: {
|
|
390
|
+
kind: "task",
|
|
391
|
+
taskId: effectiveParentTask.id,
|
|
392
|
+
requestedByUserId: effectiveParentTask.requestedByUserId,
|
|
393
|
+
creatorAgentId: effectiveParentTask.creatorAgentId,
|
|
394
|
+
agentId: effectiveParentTask.agentId,
|
|
395
|
+
},
|
|
396
|
+
source: "mcp",
|
|
397
|
+
});
|
|
398
|
+
if (!decision.allow) {
|
|
399
|
+
return toolErr(
|
|
400
|
+
`You don't have context for parent task ${effectiveParentTask.id}. Only its assignee, its creator, or a lead can create a child task under it.`,
|
|
401
|
+
{ data: { yourAgentId: creatorAgentId } },
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
381
405
|
if (effectiveParentTask?.routingAffinityInvalid) {
|
|
382
406
|
return toolErr("Cannot continue a task with an invalid routing affinity.", {
|
|
383
407
|
data: { yourAgentId: creatorAgentId },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
import { getSkillById, getSkillByName } from "@/be/db";
|
|
4
|
+
import { resolveSwarmSkillByName } from "@/be/db/skill-name-resolution";
|
|
4
5
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
5
6
|
|
|
6
7
|
export const registerSkillGetTool = (server: McpServer) => {
|
|
@@ -10,7 +11,7 @@ export const registerSkillGetTool = (server: McpServer) => {
|
|
|
10
11
|
title: "Get Skill",
|
|
11
12
|
annotations: { destructiveHint: false },
|
|
12
13
|
description:
|
|
13
|
-
"Get full skill content by ID or name. Name resolution checks agent scope first, then swarm, then global.",
|
|
14
|
+
"Get full skill content by ID or name. Name resolution checks agent scope first, then swarm, then global. In swarm scope the ownerless skill wins, then your own, then the only agent-owned one; when several other agents own that name, it errors with their IDs: pass skillId instead.",
|
|
14
15
|
inputSchema: z.object({
|
|
15
16
|
skillId: z.string().optional().describe("Skill ID"),
|
|
16
17
|
name: z.string().optional().describe("Skill name (resolved with precedence)"),
|
|
@@ -29,15 +30,22 @@ export const registerSkillGetTool = (server: McpServer) => {
|
|
|
29
30
|
|
|
30
31
|
if (args.skillId) {
|
|
31
32
|
skill = await getSkillById(args.skillId);
|
|
32
|
-
} else if (args.name && requestInfo.agentId) {
|
|
33
|
-
// Precedence: agent (personal) → swarm → global
|
|
34
|
-
skill =
|
|
35
|
-
(await getSkillByName(args.name, "agent", requestInfo.agentId)) ||
|
|
36
|
-
(await getSkillByName(args.name, "swarm")) ||
|
|
37
|
-
(await getSkillByName(args.name, "global"));
|
|
38
33
|
} else if (args.name) {
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
// Precedence: agent (personal) → swarm → global
|
|
35
|
+
if (requestInfo.agentId) {
|
|
36
|
+
skill = await getSkillByName(args.name, "agent", requestInfo.agentId);
|
|
37
|
+
}
|
|
38
|
+
if (!skill) {
|
|
39
|
+
const swarm = await resolveSwarmSkillByName(args.name, requestInfo.agentId);
|
|
40
|
+
if (swarm.kind === "ambiguous") {
|
|
41
|
+
return toolErr(
|
|
42
|
+
`Skill name "${args.name}" matches ${swarm.skillIds.length} swarm skills owned by other agents: ${swarm.skillIds.join(", ")}. Call skill-get with skillId instead.`,
|
|
43
|
+
{ data: { yourAgentId: requestInfo.agentId } },
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (swarm.kind === "found") skill = await getSkillById(swarm.skillId);
|
|
47
|
+
}
|
|
48
|
+
if (!skill) skill = await getSkillByName(args.name, "global");
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
if (!skill) {
|
package/src/tools/slack-post.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { can } from "@/rbac";
|
|
|
10
10
|
import { getSlackApp } from "@/slack/app";
|
|
11
11
|
import { getTaskLink } from "@/slack/blocks";
|
|
12
12
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
13
|
+
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
13
14
|
import { getAgentDisplayName, getAgentEmoji, markdownToSlack } from "@/slack/responses";
|
|
14
15
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
15
16
|
|
|
@@ -67,6 +68,11 @@ export const registerSlackPostTool = (server: McpServer) => {
|
|
|
67
68
|
return toolErr("Slack not configured.");
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
const blockReason = await getChannelBlockReason(app.client, channelId);
|
|
72
|
+
if (blockReason) {
|
|
73
|
+
return toolErr(externalChannelToolError(channelId, blockReason));
|
|
74
|
+
}
|
|
75
|
+
|
|
70
76
|
try {
|
|
71
77
|
const slackMessage = markdownToSlack(message);
|
|
72
78
|
|
package/src/tools/slack-read.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { getAgentById, getInboxMessageById, getTaskById } from "@/be/db";
|
|
|
4
4
|
import { can } from "@/rbac";
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
6
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
7
|
+
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
7
8
|
import { downloadFile, type SlackFile } from "@/slack/files";
|
|
8
9
|
import { attachableTask, attachSlackFilesForAgent } from "@/slack/inbound-files";
|
|
9
10
|
import { extractSlackMessageText } from "@/slack/message-text";
|
|
@@ -154,6 +155,13 @@ export const registerSlackReadTool = (server: McpServer) => {
|
|
|
154
155
|
return toolErr("Slack not configured.", { data: { messages: [] } });
|
|
155
156
|
}
|
|
156
157
|
|
|
158
|
+
const blockReason = await getChannelBlockReason(app.client, slackChannelId);
|
|
159
|
+
if (blockReason) {
|
|
160
|
+
return toolErr(externalChannelToolError(slackChannelId, blockReason), {
|
|
161
|
+
data: { messages: [] },
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
157
165
|
try {
|
|
158
166
|
const client = app.client;
|
|
159
167
|
|
package/src/tools/slack-reply.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { getTaskCitations } from "@/be/task-citations";
|
|
|
13
13
|
import { getSlackApp } from "@/slack/app";
|
|
14
14
|
import { buildCaptionBlock, getTaskLink, getTaskUrl } from "@/slack/blocks";
|
|
15
15
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
16
|
+
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
16
17
|
import { getAgentDisplayName, getAgentEmoji, markdownToSlack } from "@/slack/responses";
|
|
17
18
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
18
19
|
import {
|
|
@@ -110,6 +111,11 @@ export const registerSlackReplyTool = (server: McpServer) => {
|
|
|
110
111
|
return toolErr("Slack not configured.");
|
|
111
112
|
}
|
|
112
113
|
|
|
114
|
+
const blockReason = await getChannelBlockReason(app.client, slackChannelId);
|
|
115
|
+
if (blockReason) {
|
|
116
|
+
return toolErr(externalChannelToolError(slackChannelId, blockReason));
|
|
117
|
+
}
|
|
118
|
+
|
|
113
119
|
try {
|
|
114
120
|
const citations = taskId ? await getTaskCitations(taskId) : [];
|
|
115
121
|
// Sources go in a caption under the reply, never in the body or the
|
|
@@ -4,6 +4,7 @@ import { getAgentById, getTaskById, recordSlackMessage } from "@/be/db";
|
|
|
4
4
|
import { can } from "@/rbac";
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
6
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
7
|
+
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
7
8
|
import { getAgentDisplayName, getAgentEmoji, markdownToSlack } from "@/slack/responses";
|
|
8
9
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
9
10
|
|
|
@@ -56,6 +57,11 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
56
57
|
return toolErr("Slack not configured.");
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
const blockReason = await getChannelBlockReason(app.client, channelId);
|
|
61
|
+
if (blockReason) {
|
|
62
|
+
return toolErr(externalChannelToolError(channelId, blockReason));
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
try {
|
|
60
66
|
const slackMessage = markdownToSlack(message);
|
|
61
67
|
const messageBlocks = blocks ?? [
|
|
@@ -4,6 +4,7 @@ import * as z from "zod";
|
|
|
4
4
|
import { getAgentById } from "@/be/db";
|
|
5
5
|
import { can } from "@/rbac";
|
|
6
6
|
import { getSlackApp } from "@/slack/app";
|
|
7
|
+
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
7
8
|
import { parseSlackTs } from "@/slack/message-text";
|
|
8
9
|
import { markdownToSlack } from "@/slack/responses";
|
|
9
10
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
@@ -61,6 +62,11 @@ export const registerSlackUpdateTool = (server: McpServer) => {
|
|
|
61
62
|
return toolErr("Slack not configured.");
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
const blockReason = await getChannelBlockReason(app.client, channelId);
|
|
66
|
+
if (blockReason) {
|
|
67
|
+
return toolErr(externalChannelToolError(channelId, blockReason));
|
|
68
|
+
}
|
|
69
|
+
|
|
64
70
|
try {
|
|
65
71
|
const ts = parseSlackTs(messageTs);
|
|
66
72
|
const slackMessage = markdownToSlack(message);
|
|
@@ -3,6 +3,7 @@ import * as z from "zod";
|
|
|
3
3
|
import { getAgentById, getInboxMessageById, getTaskById } from "@/be/db";
|
|
4
4
|
import { can } from "@/rbac";
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
|
+
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
6
7
|
import { MAX_FILE_SIZE, uploadFile } from "@/slack/files";
|
|
7
8
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
8
9
|
|
|
@@ -223,6 +224,11 @@ export const registerSlackUploadFileTool = (server: McpServer) => {
|
|
|
223
224
|
return toolErr("Slack not configured.");
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
const blockReason = await getChannelBlockReason(app.client, slackChannelId);
|
|
228
|
+
if (blockReason) {
|
|
229
|
+
return toolErr(externalChannelToolError(slackChannelId, blockReason));
|
|
230
|
+
}
|
|
231
|
+
|
|
226
232
|
// Validate: must provide either filePath OR content (not both, not neither)
|
|
227
233
|
if (!filePath && !content) {
|
|
228
234
|
return toolErr("Must provide either filePath or content (base64).");
|
|
@@ -19,6 +19,7 @@ const configEntryShape = z.looseObject({
|
|
|
19
19
|
createdAt: z.string().optional(),
|
|
20
20
|
lastUpdatedAt: z.string().optional(),
|
|
21
21
|
encrypted: z.boolean().optional(),
|
|
22
|
+
exportToEnv: z.boolean().optional(),
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
export const registerGetConfigTool = (server: McpServer) => {
|
|
@@ -110,7 +111,7 @@ export const registerGetConfigTool = (server: McpServer) => {
|
|
|
110
111
|
: result
|
|
111
112
|
.map(
|
|
112
113
|
(c) =>
|
|
113
|
-
`- ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""})`,
|
|
114
|
+
`- ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value} (scope: ${c.scope}${c.scopeId ? `, scopeId: ${c.scopeId}` : ""}${c.exportToEnv ? "" : ", not in agent env"})`,
|
|
114
115
|
)
|
|
115
116
|
.join("\n");
|
|
116
117
|
|
|
@@ -19,6 +19,7 @@ const configEntryShape = z.looseObject({
|
|
|
19
19
|
createdAt: z.string().optional(),
|
|
20
20
|
lastUpdatedAt: z.string().optional(),
|
|
21
21
|
encrypted: z.boolean().optional(),
|
|
22
|
+
exportToEnv: z.boolean().optional(),
|
|
22
23
|
});
|
|
23
24
|
|
|
24
25
|
export const registerListConfigTool = (server: McpServer) => {
|
|
@@ -102,7 +103,7 @@ export const registerListConfigTool = (server: McpServer) => {
|
|
|
102
103
|
: result
|
|
103
104
|
.map(
|
|
104
105
|
(c) =>
|
|
105
|
-
`- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value}${c.description ? ` — ${c.description}` : ""}`,
|
|
106
|
+
`- [${c.scope}${c.scopeId ? `:${c.scopeId}` : ""}] ${c.key}=${c.isSecret && !effectiveIncludeSecrets ? "********" : c.value}${c.exportToEnv ? "" : " [not in agent env]"}${c.description ? ` — ${c.description}` : ""}`,
|
|
106
107
|
)
|
|
107
108
|
.join("\n");
|
|
108
109
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
isReservedConfigKey,
|
|
9
9
|
reservedKeyError,
|
|
10
10
|
validateConfigValue,
|
|
11
|
+
validateExportToEnv,
|
|
11
12
|
} from "@/be/swarm-config-guard";
|
|
12
13
|
import { scheduleIntegrationsReload } from "@/http/core";
|
|
13
14
|
import { can } from "@/rbac";
|
|
@@ -26,6 +27,7 @@ const configEntryShape = z.looseObject({
|
|
|
26
27
|
createdAt: z.string().optional(),
|
|
27
28
|
lastUpdatedAt: z.string().optional(),
|
|
28
29
|
encrypted: z.boolean().optional(),
|
|
30
|
+
exportToEnv: z.boolean().optional(),
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
export const registerSetConfigTool = (server: McpServer) => {
|
|
@@ -34,7 +36,7 @@ export const registerSetConfigTool = (server: McpServer) => {
|
|
|
34
36
|
{
|
|
35
37
|
title: "Set Config",
|
|
36
38
|
description:
|
|
37
|
-
"Set or update a swarm configuration value. Upserts by (scope, scopeId, key). Use scope='global' for server-wide settings, 'agent' for agent-specific, or 'repo' for repo-specific. Set isSecret=true to mask the value in API responses.",
|
|
39
|
+
"Set or update a swarm configuration value. Upserts by (scope, scopeId, key). Use scope='global' for server-wide settings, 'agent' for agent-specific, or 'repo' for repo-specific. Set isSecret=true to mask the value in API responses. Set exportToEnv=false to keep the row out of agent process env (agents then reach it through a connection or script credential binding).",
|
|
38
40
|
annotations: { idempotentHint: true },
|
|
39
41
|
|
|
40
42
|
inputSchema: z.object({
|
|
@@ -63,13 +65,22 @@ export const registerSetConfigTool = (server: McpServer) => {
|
|
|
63
65
|
.string()
|
|
64
66
|
.optional()
|
|
65
67
|
.describe("Optional human-readable description of this config entry."),
|
|
68
|
+
exportToEnv: z
|
|
69
|
+
.boolean()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe(
|
|
72
|
+
"Export this row into agent process env (default true on create, false for a few server-side secrets; omitted on update keeps the stored flag). Rejected as true for keys only the API server reads.",
|
|
73
|
+
),
|
|
66
74
|
}),
|
|
67
75
|
outputSchema: swarmToolOutputSchema({
|
|
68
76
|
yourAgentId: z.string().optional(),
|
|
69
77
|
config: configEntryShape.optional(),
|
|
70
78
|
}),
|
|
71
79
|
},
|
|
72
|
-
async (
|
|
80
|
+
async (
|
|
81
|
+
{ scope, scopeId, key, value, isSecret, envPath, description, exportToEnv },
|
|
82
|
+
requestInfo,
|
|
83
|
+
) => {
|
|
73
84
|
if (!requestInfo.agentId) {
|
|
74
85
|
return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
|
|
75
86
|
}
|
|
@@ -114,7 +125,8 @@ export const registerSetConfigTool = (server: McpServer) => {
|
|
|
114
125
|
});
|
|
115
126
|
}
|
|
116
127
|
|
|
117
|
-
const validationError =
|
|
128
|
+
const validationError =
|
|
129
|
+
validateConfigValue(key, value) ?? validateExportToEnv(key, exportToEnv);
|
|
118
130
|
if (validationError) {
|
|
119
131
|
return toolErr(validationError, { data: { yourAgentId: requestInfo.agentId } });
|
|
120
132
|
}
|
|
@@ -127,6 +139,7 @@ export const registerSetConfigTool = (server: McpServer) => {
|
|
|
127
139
|
isSecret,
|
|
128
140
|
envPath,
|
|
129
141
|
description,
|
|
142
|
+
exportToEnv,
|
|
130
143
|
});
|
|
131
144
|
|
|
132
145
|
if (scope === "global") {
|
package/src/tools/tool-config.ts
CHANGED
|
@@ -72,12 +72,6 @@ export const DEFERRED_TOOLS = new Set([
|
|
|
72
72
|
"retry-workflow-run",
|
|
73
73
|
"cancel-workflow-run",
|
|
74
74
|
|
|
75
|
-
// Services (4)
|
|
76
|
-
"register-service",
|
|
77
|
-
"unregister-service",
|
|
78
|
-
"list-services",
|
|
79
|
-
"update-service-status",
|
|
80
|
-
|
|
81
75
|
// Config (7)
|
|
82
76
|
"set-config",
|
|
83
77
|
"list-config",
|
|
@@ -127,6 +121,14 @@ export const DEFERRED_TOOLS = new Set([
|
|
|
127
121
|
"send-whatsapp-message",
|
|
128
122
|
"reply-whatsapp-message",
|
|
129
123
|
|
|
124
|
+
// Chat SDK (6)
|
|
125
|
+
"chat-reply",
|
|
126
|
+
"chat-post",
|
|
127
|
+
"chat-open-dm",
|
|
128
|
+
"chat-read-thread",
|
|
129
|
+
"register-chat-channel",
|
|
130
|
+
"unregister-chat-channel",
|
|
131
|
+
|
|
130
132
|
// Tracker (7)
|
|
131
133
|
"tracker-status",
|
|
132
134
|
"get-oauth-access-token",
|