@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
package/src/http/stats.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { z } from "zod";
|
|
|
3
3
|
import {
|
|
4
4
|
getAgentStatusCounts,
|
|
5
5
|
getAllLogs,
|
|
6
|
-
getAllServices,
|
|
7
6
|
getConcurrentContext,
|
|
8
7
|
getLogsByAgentId,
|
|
9
8
|
getScheduledTasks,
|
|
@@ -14,7 +13,7 @@ import {
|
|
|
14
13
|
import { getDbRetentionStats } from "../be/db-retention";
|
|
15
14
|
import { isSteeringEnabled } from "../be/steering";
|
|
16
15
|
import type { AgentLog } from "../types";
|
|
17
|
-
import { AgentLogSchema, ScheduledTaskSchema
|
|
16
|
+
import { AgentLogSchema, ScheduledTaskSchema } from "../types";
|
|
18
17
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
19
18
|
import { isMultiRuntimeEnabled } from "../utils/multi-runtime";
|
|
20
19
|
import { resolveHttpFavoriteOwner } from "./favorite-owner";
|
|
@@ -166,22 +165,6 @@ const getMetrics = route({
|
|
|
166
165
|
},
|
|
167
166
|
});
|
|
168
167
|
|
|
169
|
-
const listServices = route({
|
|
170
|
-
method: "get",
|
|
171
|
-
path: "/api/services",
|
|
172
|
-
pattern: ["api", "services"],
|
|
173
|
-
summary: "List all registered services",
|
|
174
|
-
tags: ["Stats"],
|
|
175
|
-
query: z.object({
|
|
176
|
-
status: z.string().optional(),
|
|
177
|
-
agentId: z.string().optional(),
|
|
178
|
-
name: z.string().optional(),
|
|
179
|
-
}),
|
|
180
|
-
responses: {
|
|
181
|
-
200: { description: "Service list", schema: z.object({ services: z.array(ServiceSchema) }) },
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
|
|
185
168
|
const listScheduledTasks = route({
|
|
186
169
|
method: "get",
|
|
187
170
|
path: "/api/scheduled-tasks",
|
|
@@ -295,18 +278,6 @@ export async function handleStats(
|
|
|
295
278
|
return true;
|
|
296
279
|
}
|
|
297
280
|
|
|
298
|
-
if (listServices.match(req.method, pathSegments)) {
|
|
299
|
-
const parsed = await listServices.parse(req, res, pathSegments, queryParams);
|
|
300
|
-
if (!parsed) return true;
|
|
301
|
-
const services = await getAllServices({
|
|
302
|
-
status: (parsed.query.status as import("../types").ServiceStatus) || undefined,
|
|
303
|
-
agentId: parsed.query.agentId || undefined,
|
|
304
|
-
name: parsed.query.name || undefined,
|
|
305
|
-
});
|
|
306
|
-
listServices.respond(res, 200, { services });
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
281
|
if (listScheduledTasks.match(req.method, pathSegments)) {
|
|
311
282
|
const parsed = await listScheduledTasks.parse(req, res, pathSegments, queryParams);
|
|
312
283
|
if (!parsed) return true;
|
package/src/http/tasks.ts
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
import { getTaskCitations, TaskCitationSchema } from "../be/task-citations";
|
|
46
46
|
import { findUserById } from "../be/users";
|
|
47
47
|
import { can, type RbacPrincipal, type RbacResource } from "../rbac";
|
|
48
|
+
import { chatThreadOfContextKey } from "../tasks/context-key";
|
|
48
49
|
import { TaskCreationBlockedError } from "../tasks/errors";
|
|
49
50
|
import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
|
|
50
51
|
import { guardTerminalTaskResultWrite } from "../tasks/terminal-result-guard";
|
|
@@ -76,6 +77,7 @@ import { ensure } from "../utils/business-use";
|
|
|
76
77
|
import { getRequestAuth } from "../utils/request-auth-context";
|
|
77
78
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
78
79
|
import { rejectGuest } from "./request-principal";
|
|
80
|
+
import { buildTaskRequestedBy, TaskRequestedBySchema } from "./requested-by";
|
|
79
81
|
import { route } from "./route-def";
|
|
80
82
|
import { jsonError, parseBody } from "./utils";
|
|
81
83
|
|
|
@@ -110,6 +112,7 @@ const AgentTaskSummarySchema = AgentTaskSchema.pick({
|
|
|
110
112
|
modelSource: true,
|
|
111
113
|
modelAlias: true,
|
|
112
114
|
effort: true,
|
|
115
|
+
resolvedEffort: true,
|
|
113
116
|
provider: true,
|
|
114
117
|
requestedByUserId: true,
|
|
115
118
|
progress: true,
|
|
@@ -308,6 +311,10 @@ const createTask = route({
|
|
|
308
311
|
description:
|
|
309
312
|
"Validation error, an unknown `model` (set `allowCustomModel` to store a custom id), or agentId/offeredTo targets an extension identity",
|
|
310
313
|
},
|
|
314
|
+
403: {
|
|
315
|
+
description:
|
|
316
|
+
"An agent caller names a parentTaskId it neither owns nor created, or a non-lead agent binds the task to a chat thread",
|
|
317
|
+
},
|
|
311
318
|
422: {
|
|
312
319
|
description: "Task creation blocked by an extension",
|
|
313
320
|
schema: z.object({
|
|
@@ -357,6 +364,8 @@ const updateSession = route({
|
|
|
357
364
|
claudeSessionId: z.string().min(1),
|
|
358
365
|
provider: ProviderNameSchema.exclude(["devin"]).optional(),
|
|
359
366
|
model: z.string().optional(),
|
|
367
|
+
// Effort the session runs at; null when the harness default applies.
|
|
368
|
+
effort: ReasoningEffortSchema.nullable().optional(),
|
|
360
369
|
providerMeta: z.object({ transport: z.enum(["cli", "sdk"]).optional() }).optional(),
|
|
361
370
|
harnessVariant: z.string().optional(),
|
|
362
371
|
harnessVariantMeta: z.record(z.string(), z.unknown()).optional(),
|
|
@@ -592,7 +601,14 @@ const listPausedTasks = route({
|
|
|
592
601
|
200: {
|
|
593
602
|
description: "Paused task list",
|
|
594
603
|
schema: z.object({
|
|
595
|
-
tasks: z.array(
|
|
604
|
+
tasks: z.array(
|
|
605
|
+
AgentTaskSchema.extend({
|
|
606
|
+
attachments: z.array(TaskAttachmentSchema),
|
|
607
|
+
// Same requester projection a fresh task_assigned trigger carries,
|
|
608
|
+
// so a resumed session gets the same requester-profile prompt.
|
|
609
|
+
requestedBy: TaskRequestedBySchema.optional(),
|
|
610
|
+
}),
|
|
611
|
+
),
|
|
596
612
|
}),
|
|
597
613
|
},
|
|
598
614
|
},
|
|
@@ -954,6 +970,41 @@ export async function handleTasks(
|
|
|
954
970
|
const parentTask = parsed.body.parentTaskId
|
|
955
971
|
? await getTaskById(parsed.body.parentTaskId)
|
|
956
972
|
: null;
|
|
973
|
+
// The child inherits the parent's thread context, so an agent caller must own or
|
|
974
|
+
// have created the parent. Operator and user callers keep their access.
|
|
975
|
+
const principal = await resolveTaskWritePrincipal(req, myAgentId);
|
|
976
|
+
if (
|
|
977
|
+
parentTask &&
|
|
978
|
+
!can({
|
|
979
|
+
principal,
|
|
980
|
+
verb: "task.parent.attach",
|
|
981
|
+
resource: {
|
|
982
|
+
kind: "task",
|
|
983
|
+
taskId: parentTask.id,
|
|
984
|
+
requestedByUserId: parentTask.requestedByUserId,
|
|
985
|
+
creatorAgentId: parentTask.creatorAgentId,
|
|
986
|
+
agentId: parentTask.agentId,
|
|
987
|
+
},
|
|
988
|
+
source: "http",
|
|
989
|
+
}).allow
|
|
990
|
+
) {
|
|
991
|
+
jsonError(res, `You don't have context for parent task ${parentTask.id}.`, 403);
|
|
992
|
+
return true;
|
|
993
|
+
}
|
|
994
|
+
// A chat-sdk contextKey binds the task to a chat thread that its assignee and creator
|
|
995
|
+
// may then read and post to. An agent may only name a thread other than the parent's
|
|
996
|
+
// with the lead's chat post permission.
|
|
997
|
+
if (
|
|
998
|
+
principal.kind === "agent" &&
|
|
999
|
+
parsed.body.contextKey &&
|
|
1000
|
+
parsed.body.contextKey !== parentTask?.contextKey &&
|
|
1001
|
+
chatThreadOfContextKey(parsed.body.contextKey) &&
|
|
1002
|
+
!can({ principal, verb: "integration.chat.post", resource: { kind: "none" }, source: "http" })
|
|
1003
|
+
.allow
|
|
1004
|
+
) {
|
|
1005
|
+
jsonError(res, "Permission denied: only a lead can bind a task to a chat thread.", 403);
|
|
1006
|
+
return true;
|
|
1007
|
+
}
|
|
957
1008
|
let assetKey: string | undefined;
|
|
958
1009
|
try {
|
|
959
1010
|
const inheritedKey = parentTask?.key;
|
|
@@ -1083,6 +1134,7 @@ export async function handleTasks(
|
|
|
1083
1134
|
parsed.body.model,
|
|
1084
1135
|
"harnessVariant" in parsed.body ? parsed.body.harnessVariant : undefined,
|
|
1085
1136
|
"harnessVariantMeta" in parsed.body ? parsed.body.harnessVariantMeta : undefined,
|
|
1137
|
+
"effort" in parsed.body ? parsed.body.effort : undefined,
|
|
1086
1138
|
);
|
|
1087
1139
|
if (!task) {
|
|
1088
1140
|
jsonError(res, "Task not found", 404);
|
|
@@ -1667,10 +1719,14 @@ export async function handleTasks(
|
|
|
1667
1719
|
}
|
|
1668
1720
|
const pausedTasks = await getPausedTasksForAgent(myAgentId);
|
|
1669
1721
|
const tasks = await Promise.all(
|
|
1670
|
-
pausedTasks.map(async (task) =>
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1722
|
+
pausedTasks.map(async (task) => {
|
|
1723
|
+
const requestedBy = await buildTaskRequestedBy(task);
|
|
1724
|
+
return {
|
|
1725
|
+
...task,
|
|
1726
|
+
attachments: await getTaskAttachments(task.id),
|
|
1727
|
+
...(requestedBy && { requestedBy }),
|
|
1728
|
+
};
|
|
1729
|
+
}),
|
|
1674
1730
|
);
|
|
1675
1731
|
listPausedTasks.respond(res, 200, { tasks });
|
|
1676
1732
|
return true;
|
package/src/http/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
2
2
|
import { getActiveTaskCount } from "../be/db";
|
|
3
3
|
import type { SwarmSpan } from "../otel";
|
|
4
4
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
5
|
+
import { getNodeEnv } from "../utils/node-env";
|
|
5
6
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
6
7
|
|
|
7
8
|
export function duplicateGuardedQueryKey(query: URLSearchParams): string | undefined {
|
|
@@ -41,6 +42,18 @@ function getAllowedOrigins(): string[] {
|
|
|
41
42
|
.filter(Boolean);
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Loopback origins on any port are trusted in local development
|
|
47
|
+
* (`NODE_ENV=development`, set by `start:http` and `dev:http`). The dashboard
|
|
48
|
+
* dev server, Playwright, or a second worktree pick arbitrary ports, and every
|
|
49
|
+
* loopback page already runs on the developer's machine. The production binary
|
|
50
|
+
* and the Docker image run without NODE_ENV, so this never applies there.
|
|
51
|
+
*/
|
|
52
|
+
function isDevLoopbackOrigin(origin: string): boolean {
|
|
53
|
+
if (getNodeEnv() !== "development") return false;
|
|
54
|
+
return /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d{1,5})?$/.test(origin);
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
/**
|
|
45
58
|
* Decide whether `origin` may receive credentialed CORS headers.
|
|
46
59
|
* Unset or blank uses the built-in hosted/dev allowlist. Exact entries retain
|
|
@@ -50,6 +63,7 @@ function getAllowedOrigins(): string[] {
|
|
|
50
63
|
* Bare `*`, `https://*`, other wildcard positions, and non-origin URLs are ignored.
|
|
51
64
|
*/
|
|
52
65
|
function originAllowedForCredentials(origin: string): boolean {
|
|
66
|
+
if (isDevLoopbackOrigin(origin)) return true;
|
|
53
67
|
return getAllowedOrigins().some((entry) => {
|
|
54
68
|
if (!entry.includes("*")) return entry === origin;
|
|
55
69
|
|
package/src/http/webhooks.ts
CHANGED
|
@@ -9,12 +9,25 @@ import {
|
|
|
9
9
|
verifyAgentMailWebhook,
|
|
10
10
|
} from "../agentmail";
|
|
11
11
|
import { archiveInboundMessage } from "../agentmail/inbound-archive";
|
|
12
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
PullRequestCommentedEvent,
|
|
14
|
+
PullRequestCreatedEvent,
|
|
15
|
+
WorkItemCommentedEvent,
|
|
16
|
+
WorkItemCreatedEvent,
|
|
17
|
+
WorkItemDeletedEvent,
|
|
18
|
+
WorkItemRestoredEvent,
|
|
19
|
+
WorkItemUpdatedEvent,
|
|
20
|
+
} from "../azure-devops";
|
|
13
21
|
import {
|
|
14
22
|
commentedPayloadOf,
|
|
15
23
|
createdPullRequestOf,
|
|
16
24
|
handlePullRequestCommented,
|
|
17
25
|
handlePullRequestCreated,
|
|
26
|
+
handleWorkItemCommented,
|
|
27
|
+
handleWorkItemCreated,
|
|
28
|
+
handleWorkItemDeleted,
|
|
29
|
+
handleWorkItemRestored,
|
|
30
|
+
handleWorkItemUpdated,
|
|
18
31
|
isAzureDevOpsEnabled,
|
|
19
32
|
verifyAzureDevOpsWebhook,
|
|
20
33
|
} from "../azure-devops";
|
|
@@ -53,6 +66,14 @@ import {
|
|
|
53
66
|
verifyGitLabWebhook,
|
|
54
67
|
} from "../gitlab";
|
|
55
68
|
import { gitlabWorkflowActionName } from "../gitlab/workflow-action-name";
|
|
69
|
+
import { trackBackground } from "../integrations/chat-sdk/background";
|
|
70
|
+
import { isChatSdkEnabled } from "../integrations/chat-sdk/config";
|
|
71
|
+
import {
|
|
72
|
+
getChatInstance,
|
|
73
|
+
isChatAdapterConfigured,
|
|
74
|
+
isChatSdkStopping,
|
|
75
|
+
} from "../integrations/chat-sdk/runtime";
|
|
76
|
+
import { isTrustedTeamsServiceUrl } from "../integrations/chat-sdk/teams-origin";
|
|
56
77
|
import {
|
|
57
78
|
type KapsoMessageActionResult,
|
|
58
79
|
markKapsoMessageRead,
|
|
@@ -63,11 +84,14 @@ import { getKapsoConfig } from "../integrations/kapso/config";
|
|
|
63
84
|
import type { KapsoWebhookPayload } from "../integrations/kapso/inbound";
|
|
64
85
|
import { resolveKapsoRequestedByUserId, routeKapsoInbound } from "../integrations/kapso/inbound";
|
|
65
86
|
import { TaskCreationBlockedError } from "../tasks/errors";
|
|
87
|
+
import { getPublicMcpBaseUrl } from "../utils/constants";
|
|
88
|
+
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
66
89
|
import { canonicalAzureDevOpsRepoUrl } from "../vcs/azure-devops";
|
|
67
90
|
import { getExecutorRegistry } from "../workflows";
|
|
68
91
|
import { workflowEventBus } from "../workflows/event-bus";
|
|
69
92
|
import { handleWebhookTrigger, verifyHmacSignature, WebhookError } from "../workflows/triggers";
|
|
70
93
|
import { route } from "./route-def";
|
|
94
|
+
import { BODY_TOO_LARGE, enforceContentLengthCap, jsonError } from "./utils";
|
|
71
95
|
|
|
72
96
|
// ─── Route Definitions (documentation only — webhooks handle their own body parsing) ─
|
|
73
97
|
|
|
@@ -190,8 +214,75 @@ const kapsoWebhook = route({
|
|
|
190
214
|
},
|
|
191
215
|
});
|
|
192
216
|
|
|
217
|
+
const chatSdkWebhook = route({
|
|
218
|
+
method: "post",
|
|
219
|
+
path: "/api/integrations/chat/{adapter}/webhook",
|
|
220
|
+
pattern: ["api", "integrations", "chat", null, "webhook"],
|
|
221
|
+
summary: "Handle Chat SDK platform webhooks (Telegram, Slack, Discord, Teams)",
|
|
222
|
+
tags: ["Webhooks"],
|
|
223
|
+
params: z.object({ adapter: z.string().describe("Chat SDK adapter name, e.g. telegram") }),
|
|
224
|
+
auth: { apiKey: false },
|
|
225
|
+
rbac: {
|
|
226
|
+
ungated:
|
|
227
|
+
"provider webhook: the Chat SDK adapter verifies the platform signature (Telegram secret token, Slack signing secret, Discord Ed25519, Teams JWT)",
|
|
228
|
+
},
|
|
229
|
+
responses: {
|
|
230
|
+
200: { description: "Adapter response", unstructured: "adapter response proxied as-is" },
|
|
231
|
+
401: { description: "Invalid platform signature or secret token" },
|
|
232
|
+
403: { description: "Teams activity whose serviceUrl is not a Bot Framework host" },
|
|
233
|
+
404: { description: "Chat SDK disabled or adapter not configured" },
|
|
234
|
+
413: { description: "Body exceeds 1 MiB" },
|
|
235
|
+
503: { description: "Adapter configured but failed to start" },
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Upper bound for a Chat SDK webhook body. Platform payloads are a few KB and
|
|
241
|
+
* files travel by URL, so anything larger is not a platform delivery.
|
|
242
|
+
*/
|
|
243
|
+
const CHAT_SDK_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
|
244
|
+
|
|
193
245
|
// ─── Handler ─────────────────────────────────────────────────────────────────
|
|
194
246
|
|
|
247
|
+
/** False when a Teams activity body carries a `serviceUrl` that is not a Bot Framework host. */
|
|
248
|
+
function hasTrustedTeamsServiceUrl(body: Buffer): boolean {
|
|
249
|
+
let serviceUrl: unknown;
|
|
250
|
+
try {
|
|
251
|
+
serviceUrl = (JSON.parse(body.toString("utf-8")) as { serviceUrl?: unknown } | null)
|
|
252
|
+
?.serviceUrl;
|
|
253
|
+
} catch {
|
|
254
|
+
// Not JSON: the adapter rejects it.
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
if (serviceUrl === undefined || serviceUrl === null || serviceUrl === "") return true;
|
|
258
|
+
return typeof serviceUrl === "string" && isTrustedTeamsServiceUrl(serviceUrl);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Rebuild a Fetch `Request` from the raw Node request. Headers come from
|
|
263
|
+
* `rawHeaders` pairs: building `Headers` from `IncomingMessage.headers`
|
|
264
|
+
* comma-joins repeated values, which breaks signature checks.
|
|
265
|
+
*/
|
|
266
|
+
function toFetchRequest(req: IncomingMessage, rawBody: Buffer, fallbackPath: string): Request {
|
|
267
|
+
const headers = new Headers();
|
|
268
|
+
if (Array.isArray(req.rawHeaders) && req.rawHeaders.length > 0) {
|
|
269
|
+
for (let i = 0; i + 1 < req.rawHeaders.length; i += 2) {
|
|
270
|
+
headers.append(req.rawHeaders[i] as string, req.rawHeaders[i + 1] as string);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
274
|
+
for (const item of Array.isArray(value) ? value : value === undefined ? [] : [value]) {
|
|
275
|
+
headers.append(name, item);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return new Request(`${getPublicMcpBaseUrl()}${req.url ?? fallbackPath}`, {
|
|
280
|
+
method: req.method ?? "POST",
|
|
281
|
+
headers,
|
|
282
|
+
body: rawBody.length > 0 ? new Uint8Array(rawBody) : undefined,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
195
286
|
function logKapsoAckResult(action: string, result: KapsoMessageActionResult): void {
|
|
196
287
|
if (result.ok) return;
|
|
197
288
|
console.warn(
|
|
@@ -303,7 +394,8 @@ export async function handleWebhooks(
|
|
|
303
394
|
return true;
|
|
304
395
|
}
|
|
305
396
|
|
|
306
|
-
|
|
397
|
+
const deliveryId = req.headers["x-github-delivery"] as string | undefined;
|
|
398
|
+
console.log(`[GitHub] Received ${eventType} event (delivery ${deliveryId ?? "unknown"})`);
|
|
307
399
|
|
|
308
400
|
let result: WebhookDispatchResult = { created: false };
|
|
309
401
|
|
|
@@ -560,6 +652,16 @@ export async function handleWebhooks(
|
|
|
560
652
|
return await handlePullRequestCreated(body as PullRequestCreatedEvent);
|
|
561
653
|
case "ms.vss-code.git-pullrequest-comment-event":
|
|
562
654
|
return await handlePullRequestCommented(body as PullRequestCommentedEvent);
|
|
655
|
+
case "workitem.created":
|
|
656
|
+
return await handleWorkItemCreated(body as WorkItemCreatedEvent);
|
|
657
|
+
case "workitem.updated":
|
|
658
|
+
return await handleWorkItemUpdated(body as WorkItemUpdatedEvent);
|
|
659
|
+
case "workitem.commented":
|
|
660
|
+
return await handleWorkItemCommented(body as WorkItemCommentedEvent);
|
|
661
|
+
case "workitem.deleted":
|
|
662
|
+
return await handleWorkItemDeleted(body as WorkItemDeletedEvent);
|
|
663
|
+
case "workitem.restored":
|
|
664
|
+
return await handleWorkItemRestored(body as WorkItemRestoredEvent);
|
|
563
665
|
default:
|
|
564
666
|
console.log(`[AzureDevOps] Ignoring unsupported event type: ${eventType}`);
|
|
565
667
|
return { created: false };
|
|
@@ -795,5 +897,84 @@ export async function handleWebhooks(
|
|
|
795
897
|
return true;
|
|
796
898
|
}
|
|
797
899
|
|
|
900
|
+
// Chat SDK webhook: the adapter verifies the platform signature over the raw
|
|
901
|
+
// body, so the request is proxied as-is and the adapter's response returned.
|
|
902
|
+
if (chatSdkWebhook.match(req.method, pathSegments)) {
|
|
903
|
+
const adapterName = pathSegments[3] ?? "";
|
|
904
|
+
if (!isChatSdkEnabled() || !isChatAdapterConfigured(adapterName)) {
|
|
905
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
906
|
+
res.end(JSON.stringify({ error: "Chat SDK adapter not configured" }));
|
|
907
|
+
return true;
|
|
908
|
+
}
|
|
909
|
+
if (isChatSdkStopping()) {
|
|
910
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
911
|
+
res.end(JSON.stringify({ error: "Chat SDK is shutting down" }));
|
|
912
|
+
return true;
|
|
913
|
+
}
|
|
914
|
+
const chat = getChatInstance(adapterName);
|
|
915
|
+
const handler = chat?.webhooks[adapterName];
|
|
916
|
+
if (!handler) {
|
|
917
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
918
|
+
res.end(JSON.stringify({ error: "Chat SDK adapter failed to start" }));
|
|
919
|
+
return true;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// The route is unauthenticated and the adapter verifies the signature over
|
|
923
|
+
// the buffered body, so the body is bounded before it is buffered. An
|
|
924
|
+
// oversized stream is answered at once and drained without buffering, the
|
|
925
|
+
// same way `parseBody` keeps the connection usable.
|
|
926
|
+
if (enforceContentLengthCap(req, res, CHAT_SDK_WEBHOOK_MAX_BODY_BYTES) === BODY_TOO_LARGE) {
|
|
927
|
+
return true;
|
|
928
|
+
}
|
|
929
|
+
const chunks: Buffer[] = [];
|
|
930
|
+
let receivedBytes = 0;
|
|
931
|
+
let tooLarge = false;
|
|
932
|
+
for await (const chunk of req) {
|
|
933
|
+
if (tooLarge) continue;
|
|
934
|
+
receivedBytes += (chunk as Buffer).byteLength;
|
|
935
|
+
if (receivedBytes > CHAT_SDK_WEBHOOK_MAX_BODY_BYTES) {
|
|
936
|
+
tooLarge = true;
|
|
937
|
+
chunks.length = 0;
|
|
938
|
+
jsonError(res, `Payload too large (max ${CHAT_SDK_WEBHOOK_MAX_BODY_BYTES} bytes)`, 413);
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
chunks.push(chunk as Buffer);
|
|
942
|
+
}
|
|
943
|
+
if (tooLarge) return true;
|
|
944
|
+
const rawBody = Buffer.concat(chunks);
|
|
945
|
+
// The Teams adapter replies, reads history and downloads files with the
|
|
946
|
+
// bot token at the activity's serviceUrl, and caches it for DMs. Refuse an
|
|
947
|
+
// untrusted one before the adapter sees the activity.
|
|
948
|
+
if (adapterName === "teams" && !hasTrustedTeamsServiceUrl(rawBody)) {
|
|
949
|
+
console.warn("[chat-sdk] teams webhook refused: serviceUrl is not a Bot Framework host");
|
|
950
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
951
|
+
res.end(JSON.stringify({ error: "Untrusted Teams serviceUrl" }));
|
|
952
|
+
return true;
|
|
953
|
+
}
|
|
954
|
+
const request = toFetchRequest(req, rawBody, `/api/integrations/chat/${adapterName}/webhook`);
|
|
955
|
+
|
|
956
|
+
try {
|
|
957
|
+
const response = await handler(request, {
|
|
958
|
+
// Handler errors are logged by `trackBackground` in `handlers.ts`.
|
|
959
|
+
waitUntil: trackBackground,
|
|
960
|
+
});
|
|
961
|
+
const responseHeaders: Record<string, string> = {};
|
|
962
|
+
response.headers.forEach((value, name) => {
|
|
963
|
+
responseHeaders[name] = value;
|
|
964
|
+
});
|
|
965
|
+
const body = Buffer.from(await response.arrayBuffer());
|
|
966
|
+
res.writeHead(response.status, responseHeaders);
|
|
967
|
+
res.end(body);
|
|
968
|
+
} catch (err) {
|
|
969
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
970
|
+
console.error(`[chat-sdk] ${adapterName} webhook failed: ${scrubSecrets(message)}`);
|
|
971
|
+
if (!res.headersSent) {
|
|
972
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
973
|
+
}
|
|
974
|
+
res.end(JSON.stringify({ error: "Chat SDK webhook failed" }));
|
|
975
|
+
}
|
|
976
|
+
return true;
|
|
977
|
+
}
|
|
978
|
+
|
|
798
979
|
return false;
|
|
799
980
|
}
|
package/src/http/x.ts
CHANGED
|
@@ -255,6 +255,7 @@ export async function handleX(
|
|
|
255
255
|
timeoutMs,
|
|
256
256
|
egressSecrets: credentials.egressSecrets,
|
|
257
257
|
failedBindings: credentials.failedBindings,
|
|
258
|
+
userConfig: credentials.userConfig,
|
|
258
259
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: endpoint.agentId }),
|
|
259
260
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: endpoint.agentId }),
|
|
260
261
|
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Adapter, Logger } from "chat";
|
|
2
|
+
import { type ChatSdkAdapterName, type ResolvedAdapterConfig, readApiUrlOverrides } from "./config";
|
|
3
|
+
import { withInfoFilter } from "./logger";
|
|
4
|
+
import { getChatSdkTestHooks } from "./test-hooks";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Platform API bases passed explicitly so the adapters never fall back to
|
|
8
|
+
* `TELEGRAM_API_BASE_URL` / `SLACK_API_URL` / `DISCORD_API_URL` /
|
|
9
|
+
* `TEAMS_API_URL` from `process.env`. Global swarm_config rows are injected
|
|
10
|
+
* into `process.env`, so an env fallback would let a config row redirect bot
|
|
11
|
+
* tokens to another host. Teams gets "" which blocks only `TEAMS_API_URL`.
|
|
12
|
+
* The other Teams SDK env fallbacks (`SERVICE_URL`, `TENANT_ID`, `CLIENT_ID`,
|
|
13
|
+
* `CLIENT_SECRET`, `MANAGED_IDENTITY_CLIENT_ID`, `CLOUD`) are closed by the
|
|
14
|
+
* injection denylist in `getInjectableGlobalConfigs` (`src/be/db.ts`).
|
|
15
|
+
* Deployment env can still set them on purpose.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_API_URLS: Record<ChatSdkAdapterName, string> = {
|
|
18
|
+
telegram: "https://api.telegram.org",
|
|
19
|
+
slack: "https://slack.com/api/",
|
|
20
|
+
discord: "https://discord.com/api/v10",
|
|
21
|
+
teams: "",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Discord adapter info lines dropped from the logs. They fire per event and
|
|
26
|
+
* carry guild message content (first 100 chars), or the public key and
|
|
27
|
+
* signature prefix of every interaction. Warn and error lines are kept.
|
|
28
|
+
*/
|
|
29
|
+
const DISCORD_NOISY_INFO_PREFIXES = [
|
|
30
|
+
"Discord Gateway message received",
|
|
31
|
+
"Discord webhook received",
|
|
32
|
+
"Discord signature verification",
|
|
33
|
+
"Discord interaction parsed",
|
|
34
|
+
"Discord PING received",
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
export function keepDiscordInfoLine(message: string): boolean {
|
|
38
|
+
return !DISCORD_NOISY_INFO_PREFIXES.some((prefix) => message.startsWith(prefix));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Platform API base for one adapter: the env-only `CHAT_SDK_API_URL_OVERRIDES`
|
|
43
|
+
* entry, else the platform default. The adapters and the Telegram
|
|
44
|
+
* register-webhook route use the same base.
|
|
45
|
+
*/
|
|
46
|
+
export function resolveAdapterApiUrl(name: ChatSdkAdapterName): string {
|
|
47
|
+
return readApiUrlOverrides()[name] ?? DEFAULT_API_URLS[name];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Construct one adapter. Each branch is a literal-path dynamic import so
|
|
52
|
+
* `bun build --compile` bundles it (a computed specifier is not bundled).
|
|
53
|
+
* `apiUrl` comes only from the env-only `CHAT_SDK_API_URL_OVERRIDES`.
|
|
54
|
+
*/
|
|
55
|
+
export async function loadAdapter(
|
|
56
|
+
name: ChatSdkAdapterName,
|
|
57
|
+
config: ResolvedAdapterConfig,
|
|
58
|
+
logger: Logger,
|
|
59
|
+
): Promise<Adapter> {
|
|
60
|
+
const apiUrl = resolveAdapterApiUrl(name);
|
|
61
|
+
const base = { ...config, apiUrl, logger };
|
|
62
|
+
switch (name) {
|
|
63
|
+
case "telegram": {
|
|
64
|
+
const { createTelegramAdapter } = await import("@chat-adapter/telegram");
|
|
65
|
+
// Explicit `false` blocks the TELEGRAM_ALLOW_UNVERIFIED_WEBHOOKS env fallback.
|
|
66
|
+
return createTelegramAdapter({ ...base, allowUnverifiedWebhooks: false } as Parameters<
|
|
67
|
+
typeof createTelegramAdapter
|
|
68
|
+
>[0]);
|
|
69
|
+
}
|
|
70
|
+
case "slack": {
|
|
71
|
+
const { createSlackAdapter } = await import("@chat-adapter/slack");
|
|
72
|
+
// "" (not undefined) blocks each `?? process.env.SLACK_*` fallback, which
|
|
73
|
+
// would pick up the built-in Slack app's secrets. Socket forwarding and
|
|
74
|
+
// the installation encryption key are multi-workspace features we do not
|
|
75
|
+
// use; "" turns both off.
|
|
76
|
+
return createSlackAdapter({
|
|
77
|
+
...base,
|
|
78
|
+
signingSecret: config.signingSecret ?? "",
|
|
79
|
+
appToken: config.appToken ?? "",
|
|
80
|
+
socketForwardingSecret: "",
|
|
81
|
+
encryptionKey: "",
|
|
82
|
+
} as Parameters<typeof createSlackAdapter>[0]);
|
|
83
|
+
}
|
|
84
|
+
case "discord": {
|
|
85
|
+
const { createDiscordAdapter } = await import("@chat-adapter/discord");
|
|
86
|
+
// `[]` (not undefined) blocks the DISCORD_RESPOND_TO_CHANNEL_IDS and
|
|
87
|
+
// DISCORD_MENTION_ROLE_IDS env fallbacks.
|
|
88
|
+
return createDiscordAdapter({
|
|
89
|
+
...base,
|
|
90
|
+
logger: withInfoFilter(logger, keepDiscordInfoLine),
|
|
91
|
+
respondToChannelIds: config.respondToChannelIds ?? [],
|
|
92
|
+
mentionRoleIds: config.mentionRoleIds ?? [],
|
|
93
|
+
} as Parameters<typeof createDiscordAdapter>[0]);
|
|
94
|
+
}
|
|
95
|
+
case "teams": {
|
|
96
|
+
const { createTeamsAdapter } = await import("@chat-adapter/teams");
|
|
97
|
+
// `webhookVerifier` replaces the Bot Framework JWT check and `token` the
|
|
98
|
+
// bot token call. Only tests set them (test-hooks.ts); the operator
|
|
99
|
+
// schema rejects `webhookVerifier`, and `token` is a function.
|
|
100
|
+
const { teamsWebhookVerifier, teamsToken } = getChatSdkTestHooks();
|
|
101
|
+
return createTeamsAdapter({
|
|
102
|
+
...base,
|
|
103
|
+
...(teamsWebhookVerifier ? { webhookVerifier: teamsWebhookVerifier } : {}),
|
|
104
|
+
...(teamsToken ? { token: teamsToken } : {}),
|
|
105
|
+
} as Parameters<typeof createTeamsAdapter>[0]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
type SocketClientLike = { on(event: string, listener: () => void): unknown };
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Slack socket mode reconnects on its own and logs through its own logger,
|
|
114
|
+
* not ours. Surface hard failures through the scrubbing logger so adapter
|
|
115
|
+
* health (`lastWarning`) shows them. A failed first connect rejects
|
|
116
|
+
* `initialize()` for auth errors. Network failures go through the WebClient
|
|
117
|
+
* retry policy and can take long before they surface here.
|
|
118
|
+
* `reconnecting` also fires on Slack's routine connection refresh, so it is
|
|
119
|
+
* logged at info only and never reaches health.
|
|
120
|
+
*/
|
|
121
|
+
export function watchSocketConnection(adapter: Adapter, logger: Logger): void {
|
|
122
|
+
const client = (adapter as { socketClient?: SocketClientLike }).socketClient;
|
|
123
|
+
if (!client) return;
|
|
124
|
+
client.on("reconnecting", () => logger.info("Slack socket mode reconnecting"));
|
|
125
|
+
client.on("unable_to_socket_mode_start", () =>
|
|
126
|
+
logger.warn("Slack socket mode unable to start, retrying"),
|
|
127
|
+
);
|
|
128
|
+
client.on("error", () => logger.warn("Slack socket mode error"));
|
|
129
|
+
}
|