@desplega.ai/agent-swarm 1.173.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-sj2g0m84.js} +17 -16
- package/dist/{actions-sgeyv08k.js → actions-fegk44gr.js} +39 -34
- package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-ad8ft89x.js} +8 -7
- package/dist/{app-km9qnv2f.js → app-kfvgbvzy.js} +18 -14
- package/dist/{assistant-5r8tcvvd.js → assistant-z7zdy9ja.js} +40 -35
- package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-5c2z0mbe.js} +10 -9
- package/dist/{boot-reembed-16rv9843.js → boot-reembed-j8xa181e.js} +10 -9
- package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-hnkn3rgt.js} +11 -10
- package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-kwjq4d2z.js} +14 -13
- package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-9vmvpvgd.js} +19 -18
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-k9qae05j.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-q54zx5q2.js} +6 -4
- package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-9jye6cxr.js} +11881 -11472
- package/dist/{cli-94b48jhk.js → cli-03gedhng.js} +16 -14
- package/dist/{cli-1w0vj3gw.js → cli-1e4b6bzh.js} +7 -7
- package/dist/{cli-d603qf86.js → cli-29jc5q7w.js} +10 -8
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-x119kdba.js → cli-3dj8k4vy.js} +1 -1
- package/dist/{cli-srqq3gc5.js → cli-3fbmmawm.js} +5 -5
- package/dist/{cli-gmdajfw5.js → cli-4jxm2qtz.js} +4987 -1708
- package/dist/{cli-tadfgd0t.js → cli-5hkm7whv.js} +33 -4
- package/dist/{cli-42qhyvwx.js → cli-5t4f29ez.js} +3 -3
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-0kxf81jj.js → cli-6jyj59nb.js} +2 -2
- package/dist/{cli-w1apjecb.js → cli-6razj6t4.js} +2 -2
- package/dist/{cli-anzdk0z4.js → cli-74ahz61x.js} +2 -2
- package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-81r1wjyv.js → cli-9nfx44eh.js} +1 -1
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-na2pxe4f.js → cli-apx87jne.js} +2 -2
- package/dist/{cli-rfz2ve55.js → cli-bzszjf2p.js} +2855 -862
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/{cli-hsem16hb.js → cli-cgtksawx.js} +7 -4
- package/dist/{cli-db3m6zdt.js → cli-d2qr7aj4.js} +1 -1
- package/dist/{cli-rfs4vddv.js → cli-d5f9ed5c.js} +5 -5
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/{cli-7jykv7ef.js → cli-e6mpjhed.js} +1 -1
- package/dist/{cli-7a93cv8c.js → cli-ee9gtz70.js} +98 -23
- package/dist/{cli-3nxdmjrc.js → cli-eejsgvm4.js} +4 -4
- package/dist/{cli-fmhj1ehj.js → cli-ef1hg1wv.js} +470 -51
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-ppy4nnnh.js → cli-f7kr7svz.js} +2 -2
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-2bw3w47j.js → cli-hnhtk6cj.js} +1 -1
- package/dist/{cli-ywm1azg9.js → cli-hnmhtzvh.js} +6 -4
- package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
- package/dist/{cli-s8z6x4b4.js → cli-j0pfptdp.js} +218 -102
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-5er5gjbm.js → cli-k382tshb.js} +10 -11
- package/dist/{cli-v3zhnxsb.js → cli-k3dp5tpf.js} +2 -2
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-ne7smj1b.js → cli-ke896fcf.js} +10 -10
- package/dist/{cli-xc7p7s3g.js → cli-kt6zqg0e.js} +6 -6
- package/dist/{cli-wrh08zjd.js → cli-m50t4309.js} +5 -18
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-bv2etw2y.js → cli-n3hzg89b.js} +46 -15
- package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
- package/dist/{cli-qm1448f9.js → cli-ne236afy.js} +8 -8
- package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
- package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
- package/dist/{cli-0a7mm3zp.js → cli-q0ke1yww.js} +25 -21
- package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-phcqp1b9.js → cli-r2pnvj8g.js} +2 -2
- package/dist/{cli-jpc4r224.js → cli-r62a35ea.js} +19 -3
- package/dist/{cli-cd0hv9nh.js → cli-ra0xzggj.js} +2 -2
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-r4fqfpwf.js → cli-s2sp957d.js} +50 -27
- package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
- package/dist/{cli-6thk4jz3.js → cli-se8w6wny.js} +6 -6
- package/dist/cli-skxvvpap.js +10140 -0
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-0p3enk35.js → cli-tqaazemc.js} +9 -1
- package/dist/{cli-nwrdx840.js → cli-tr4sxp68.js} +3 -3
- package/dist/{cli-r0byd61h.js → cli-tsde1hdr.js} +15 -15
- package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
- package/dist/{cli-6r2f7edk.js → cli-v1yb0rqb.js} +6 -6
- package/dist/{cli-saqyage0.js → cli-vatyhshy.js} +179 -27
- package/dist/{cli-5wpw4rab.js → cli-vdach5a9.js} +5 -5
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/{cli-c3rk1v0x.js → cli-wayw93nt.js} +3 -3
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-9xf7fdtp.js → cli-z5jjpaxw.js} +29 -6
- package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
- package/dist/cli.js +29 -45
- package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-y81sssk0.js} +15 -14
- package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
- package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-8vx4j6a9.js} +15 -14
- package/dist/{commands-z8fq9qna.js → commands-kcpvpcrr.js} +11 -10
- package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
- package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-kwpvj3rf.js} +42 -37
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
- package/dist/{db-yyhqqrbf.js → db-k8ankj20.js} +12 -11
- package/dist/{db-qfpq4bt7.js → db-ww5d7jq3.js} +28 -9
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
- package/dist/{dispatcher-x0x7qfcq.js → dispatcher-e8gq5m68.js} +38 -33
- package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
- package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-3epjm3af.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-8ygwhg0f.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-swhnpw3n.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-6axnngdj.js} +3 -2
- package/dist/{external-channel-h1fjecwe.js → external-channel-h3359cwn.js} +11 -10
- package/dist/{google-generative-ai-szdxbpqg.js → google-generative-ai-g8db7x0f.js} +4 -2
- package/dist/{google-vertex-qzw3p36d.js → google-vertex-r2692q0r.js} +4 -2
- package/dist/{grok-adapter-e7mr287e.js → grok-adapter-0d4x7gkx.js} +18 -17
- package/dist/{handlers-znb9n7d4.js → handlers-an1gzv21.js} +41 -36
- package/dist/{heartbeat-bm4qkn8d.js → heartbeat-6dakeb61.js} +43 -38
- package/dist/{hook-254r4mza.js → hook-6v6cv6d5.js} +11 -23
- package/dist/{hook-xaa3q80s.js → hook-sa5xye4y.js} +12 -11
- package/dist/{http-3dgrgp8y.js → http-r7f3eky0.js} +1499 -251
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-fx3jqq1e.js → index-7ep4gzdk.js} +38 -33
- package/dist/index-9gw58n4k.js +193 -0
- package/dist/index-9j87mcm8.js +56305 -0
- package/dist/index-bsmcresk.js +79424 -0
- package/dist/index-mh85qhec.js +475 -0
- package/dist/{index-g2byveez.js → index-rmpw9a8q.js} +38 -33
- package/dist/{index-2ybk7khy.js → index-s2wxgzr0.js} +468 -683
- package/dist/{index-bdsqa799.js → index-v1v6n7hg.js} +43 -38
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{index-jd7sejm2.js → index-zk96aq1k.js} +10 -9
- package/dist/{keepalive-6ywhpja1.js → keepalive-be9vwy5h.js} +12 -11
- package/dist/{lead-cw45n21s.js → lead-0861cwrf.js} +61 -56
- package/dist/{maintenance-ss1a1ge9.js → maintenance-mzzgc8bn.js} +10 -9
- package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
- package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-cpdnfwdj.js} +11 -10
- package/dist/{onboard-8hzdhc1k.js → onboard-fh8qs4r3.js} +11 -3
- package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-nm42wwj8.js} +18 -13
- package/dist/{otel-impl-e6mnvc4v.js → otel-impl-x6c1c9g4.js} +242 -868
- package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-9n2ya240.js} +244 -106
- package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-qb0rv0ap.js} +12 -11
- package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-1gzdwbh1.js} +11 -10
- package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-3mraey52.js} +12 -11
- package/dist/{render-v2-907cy6sa.js → render-v2-agpa45zz.js} +18 -14
- package/dist/{resume-42stcaz0.js → resume-x0ydy9s9.js} +25 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-adbc1c10.js → setup-as9ga0d6.js} +2 -2
- package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
- package/dist/{work-objects-wpj8ck95.js → work-objects-y5g1y7ev.js} +41 -36
- package/dist/{worker-bzdra9rf.js → worker-860c3e38.js} +61 -56
- package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
- package/openapi.json +523 -344
- package/package.json +10 -11
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/page-versions.ts +15 -0
- package/src/be/db/runtime.ts +35 -8
- package/src/be/db/skill-name-resolution.ts +36 -0
- package/src/be/db/tasks/read.ts +230 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +52 -7
- package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
- package/src/be/migrations/216_task_resolved_effort.sql +5 -0
- package/src/be/migrations/217_chat_sdk_state.sql +104 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +12 -1
- package/src/be/model-validation.ts +5 -2
- package/src/be/models-catalog.ts +26 -1
- package/src/be/modelsdev-cache.json +198 -63
- package/src/be/modelsdev-cache.ts +9 -1
- package/src/be/script-credential-broker.ts +39 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +10 -8
- package/src/be/seed/runner.ts +13 -1
- package/src/be/seed/state-db.ts +5 -0
- package/src/be/seed/types.ts +6 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/seed-skills/bundled-files.generated.json +0 -18
- package/src/be/seed-skills/index.ts +104 -3
- package/src/be/swarm-config-guard.ts +52 -0
- package/src/cli.tsx +0 -16
- package/src/commands/onboard/non-interactive.ts +4 -2
- package/src/commands/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +190 -54
- package/src/e2b/env.ts +5 -0
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +45 -0
- package/src/extensions/dispatcher.ts +7 -0
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/all-routes.ts +0 -1
- package/src/http/config.ts +36 -17
- package/src/http/core.ts +4 -0
- package/src/http/index.ts +14 -2
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp.ts +15 -5
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +3 -3
- package/src/http/pages.ts +3 -13
- package/src/http/poll.ts +28 -68
- package/src/http/requested-by.ts +54 -0
- package/src/http/scripts.ts +1 -0
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +61 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +159 -1
- package/src/http/x.ts +1 -0
- package/src/integrations/chat-sdk/adapters.ts +129 -0
- package/src/integrations/chat-sdk/attachments.ts +232 -0
- package/src/integrations/chat-sdk/background.ts +36 -0
- package/src/integrations/chat-sdk/commands.ts +194 -0
- package/src/integrations/chat-sdk/config.ts +198 -0
- package/src/integrations/chat-sdk/discord-api.ts +63 -0
- package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
- package/src/integrations/chat-sdk/handlers.ts +28 -0
- package/src/integrations/chat-sdk/inbound.ts +426 -0
- package/src/integrations/chat-sdk/limits.ts +48 -0
- package/src/integrations/chat-sdk/logger.ts +81 -0
- package/src/integrations/chat-sdk/outbound.ts +123 -0
- package/src/integrations/chat-sdk/relay.ts +172 -0
- package/src/integrations/chat-sdk/router.ts +169 -0
- package/src/integrations/chat-sdk/runtime.ts +351 -0
- package/src/integrations/chat-sdk/schema.ts +245 -0
- package/src/integrations/chat-sdk/state.ts +243 -0
- package/src/integrations/chat-sdk/status.ts +244 -0
- package/src/integrations/chat-sdk/steering.ts +58 -0
- package/src/integrations/chat-sdk/teams-origin.ts +77 -0
- package/src/integrations/chat-sdk/telegram-api.ts +56 -0
- package/src/integrations/chat-sdk/templates.ts +16 -0
- package/src/integrations/chat-sdk/test-hooks.ts +37 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
- package/src/integrations/chat-sdk/typing.ts +65 -0
- package/src/pages/version.ts +4 -5
- package/src/prompts/base-prompt.ts +111 -45
- package/src/providers/acp-target-catalog.ts +6 -0
- package/src/providers/acp-targets.ts +55 -2
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +1 -1
- package/src/providers/claude-flag-settings.ts +17 -5
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +243 -26
- package/src/providers/opencode-swarm-plugin.ts +31 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pricing-sources.md +33 -2
- package/src/providers/reasoning-effort.ts +27 -0
- package/src/providers/types.ts +6 -2
- package/src/rbac/legacy-policy.ts +8 -2
- package/src/rbac/permissions.ts +21 -0
- package/src/scheduler/scheduler.ts +4 -2
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/sdk-allowlist.ts +8 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +27 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +63 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -15
- package/src/server.ts +52 -18
- package/src/slack/event-dedup.ts +1 -1
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +60 -1
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +4 -31
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/base-prompt.test.ts +58 -54
- package/src/tests/chat-sdk-commands.test.ts +191 -0
- package/src/tests/chat-sdk-config.test.ts +334 -0
- package/src/tests/chat-sdk-discord-api.test.ts +68 -0
- package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
- package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
- package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
- package/src/tests/chat-sdk-harness.ts +146 -0
- package/src/tests/chat-sdk-inbound.test.ts +363 -0
- package/src/tests/chat-sdk-relay.test.ts +470 -0
- package/src/tests/chat-sdk-reload.test.ts +128 -0
- package/src/tests/chat-sdk-shutdown.test.ts +220 -0
- package/src/tests/chat-sdk-slack.test.ts +268 -0
- package/src/tests/chat-sdk-state.test.ts +163 -0
- package/src/tests/chat-sdk-status-route.test.ts +382 -0
- package/src/tests/chat-sdk-teams.test.ts +277 -0
- package/src/tests/chat-sdk-tools.test.ts +520 -0
- package/src/tests/chat-sdk-typing.test.ts +120 -0
- package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
- package/src/tests/claude-adapter-binary.test.ts +9 -4
- package/src/tests/claude-flag-settings.test.ts +11 -3
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
- package/src/tests/claude-thinking-tokens.test.ts +57 -0
- package/src/tests/claude-worker-parity.test.ts +2 -7
- package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
- package/src/tests/config-refs.test.ts +66 -0
- package/src/tests/context-key.test.ts +19 -0
- package/src/tests/cors-allowlist.test.ts +25 -0
- package/src/tests/create-page-tool.test.ts +18 -0
- package/src/tests/credential-check.test.ts +139 -0
- package/src/tests/credentials.test.ts +21 -0
- package/src/tests/db-runtime.test.ts +61 -0
- package/src/tests/db-task-read-contract.test.ts +20 -0
- package/src/tests/db-task-write-contract.test.ts +10 -0
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/enabled-capabilities.test.ts +20 -0
- package/src/tests/entrypoint-api-readiness.test.ts +14 -8
- package/src/tests/entrypoint-config-env-export.test.ts +5 -2
- package/src/tests/entrypoint-export-to-env.test.ts +78 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-post-bridge.test.ts +51 -0
- package/src/tests/fetch-resolved-env.test.ts +128 -0
- package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
- package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
- package/src/tests/github-handlers.test.ts +35 -0
- package/src/tests/harness-provider-resolution.test.ts +12 -0
- package/src/tests/heartbeat-checklist.test.ts +3 -2
- package/src/tests/hook-runtime-close.test.ts +0 -2
- package/src/tests/http-api-integration.test.ts +0 -25
- package/src/tests/migration-046-budgets.test.ts +17 -16
- package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
- package/src/tests/model-tier-resolution.test.ts +93 -0
- package/src/tests/models-catalog.test.ts +42 -1
- package/src/tests/openai-compatible-providers.test.ts +134 -0
- package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
- package/src/tests/opencode-adapter.test.ts +216 -2
- package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
- package/src/tests/opencode-shell-env.test.ts +145 -0
- package/src/tests/openrouter-base-url.test.ts +101 -151
- package/src/tests/page-proxy.test.ts +1 -1
- package/src/tests/pages-browser-sdk.test.ts +76 -0
- package/src/tests/pages-feedback.test.ts +1 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
- package/src/tests/pi-mono-adapter.test.ts +385 -5
- package/src/tests/pi-shell-env.test.ts +170 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/rbac-engine.test.ts +11 -3
- package/src/tests/runner-exit-after-tasks.test.ts +0 -4
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections.test.ts +2 -0
- package/src/tests/scripts-http.test.ts +201 -1
- package/src/tests/scripts-only-gating.test.ts +2 -3
- package/src/tests/scripts-runtime.test.ts +58 -40
- package/src/tests/secret-scrubber.test.ts +86 -0
- package/src/tests/seed-skills-bundled-files.test.ts +45 -53
- package/src/tests/seed-skills-retire.test.ts +182 -0
- package/src/tests/send-task-requester-gate.test.ts +58 -0
- package/src/tests/session-cost-recompute-unit.test.ts +46 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/sonnet-5-5-registry.test.ts +9 -1
- package/src/tests/swarm-config-export-to-env.test.ts +267 -0
- package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
- package/src/tests/swarm-diff.test.ts +1 -1
- package/src/tests/task-model-effort-rerun.test.ts +164 -0
- package/src/tests/task-session-prompts.test.ts +132 -0
- package/src/tests/task-tool-manifest.test.ts +14 -0
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tool-annotations.test.ts +6 -6
- package/src/tests/ui-logs-parser.test.ts +43 -0
- package/src/tests/used-by-route.test.ts +6 -0
- package/src/tests/vercel-ai-gateway.test.ts +149 -0
- package/src/tests/workflow-swarm-script.test.ts +38 -0
- package/src/tests/workflow-wait-filter.test.ts +5 -3
- package/src/tools/chat-access.ts +41 -0
- package/src/tools/chat-open-dm.ts +59 -0
- package/src/tools/chat-post.ts +74 -0
- package/src/tools/chat-read-thread.ts +100 -0
- package/src/tools/chat-reply.ts +75 -0
- package/src/tools/create-page.ts +3 -13
- package/src/tools/model-catalog/index.ts +2 -1
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/send-task.ts +24 -0
- package/src/tools/skills/skill-get.ts +17 -9
- package/src/tools/swarm-config/get-config.ts +2 -1
- package/src/tools/swarm-config/list-config.ts +2 -1
- package/src/tools/swarm-config/set-config.ts +16 -3
- package/src/tools/tool-config.ts +8 -6
- package/src/types.ts +12 -2
- package/src/utils/config-env-export.ts +74 -0
- package/src/utils/credentials.test.ts +92 -0
- package/src/utils/credentials.ts +52 -4
- package/src/utils/harness-provider.ts +15 -6
- package/src/utils/runtime-model-catalog.ts +11 -1
- package/src/utils/secret-scrubber.ts +71 -2
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/templates/skills/agent-browser/SKILL.md +1 -1
- package/templates/skills/agent-browser/content.md +1 -1
- package/templates/skills/apps/SKILL.md +8 -1
- package/templates/skills/apps/content.md +8 -1
- package/templates/skills/chat-sdk/config.json +14 -0
- package/templates/skills/chat-sdk/content.md +84 -0
- package/templates/skills/composio-gmail/content.md +7 -0
- package/templates/skills/composio-google-docs/content.md +1 -1
- package/templates/skills/email-domain-health/config.json +14 -0
- package/templates/skills/email-domain-health/content.md +131 -0
- package/templates/skills/kv-storage/content.md +2 -2
- package/templates/skills/pages/content.md +8 -10
- package/templates/skills/swarm-extensions/content.md +2 -0
- package/templates/skills/swarm-scripts/SKILL.md +4 -2
- package/templates/skills/swarm-scripts/config.json +1 -1
- package/templates/skills/swarm-scripts/content.md +4 -2
- package/templates/skills/workflow-iterate/content.md +38 -0
- package/dist/artifact-eczsknc3.js +0 -3843
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- package/dist/cli-tcc4wd5d.js +0 -56471
- package/dist/index-9ch1n761.js +0 -1102
- package/src/artifact-sdk/index.ts +0 -2
- package/src/artifact-sdk/localtunnel.d.ts +0 -20
- package/src/artifact-sdk/port.ts +0 -12
- package/src/artifact-sdk/server.ts +0 -183
- package/src/artifact-sdk/tunnel.ts +0 -19
- package/src/commands/artifact.ts +0 -249
- package/src/http/ecosystem.ts +0 -77
- package/src/tests/artifact-commands.test.ts +0 -92
- package/src/tests/artifact-sdk.test.ts +0 -793
- package/src/tests/register-service-security.test.ts +0 -194
- package/src/tools/list-services.ts +0 -107
- package/src/tools/register-service.ts +0 -177
- package/src/tools/unregister-service.ts +0 -73
- package/src/tools/update-service-status.ts +0 -96
- package/templates/skills/artifacts/config.json +0 -14
- package/templates/skills/artifacts/content.md +0 -344
- package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
- package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
- package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
- package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
- /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
- /package/src/{artifact-sdk → pages}/feedback-overlay.ts +0 -0
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BROWSER_SDK_JS,
|
|
3
|
-
SWARM_UI_JS
|
|
4
|
-
} from "./cli-t1ze64h3.js";
|
|
5
1
|
import {
|
|
6
2
|
SIMILARITY_THRESHOLD,
|
|
7
3
|
isLeadChannelMonitoringEnabled,
|
|
@@ -11,7 +7,7 @@ import {
|
|
|
11
7
|
} from "./cli-hz99wfxp.js";
|
|
12
8
|
import {
|
|
13
9
|
ACP_TARGET_IDS
|
|
14
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-6cagzc96.js";
|
|
15
11
|
import {
|
|
16
12
|
isCodexOAuthConfigKey
|
|
17
13
|
} from "./cli-bqjfjex4.js";
|
|
@@ -24,11 +20,11 @@ import {
|
|
|
24
20
|
} from "./cli-2pdaysab.js";
|
|
25
21
|
import {
|
|
26
22
|
reasoningCapability
|
|
27
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-n5vwg842.js";
|
|
28
24
|
import {
|
|
29
25
|
ensureAgentFsCredentialsForAgent,
|
|
30
26
|
inviteEmailToSharedOrg
|
|
31
|
-
} from "./cli-
|
|
27
|
+
} from "./cli-r2pnvj8g.js";
|
|
32
28
|
import"./cli-6zx22mv6.js";
|
|
33
29
|
import {
|
|
34
30
|
DEFAULT_CONNECTOR_CODE_LABEL,
|
|
@@ -39,16 +35,17 @@ import {
|
|
|
39
35
|
startPoolRouting,
|
|
40
36
|
stopHeartbeat,
|
|
41
37
|
stopPoolRouting
|
|
42
|
-
} from "./cli-
|
|
38
|
+
} from "./cli-tsde1hdr.js";
|
|
43
39
|
import {
|
|
44
40
|
Anthropic
|
|
45
|
-
} from "./cli-
|
|
41
|
+
} from "./cli-4jxm2qtz.js";
|
|
46
42
|
import {
|
|
47
43
|
runtimeSupervisorStatus,
|
|
48
44
|
startRuntimeSupervisor,
|
|
49
45
|
stopRuntimeSupervisor
|
|
50
|
-
} from "./cli-
|
|
51
|
-
import"./cli-
|
|
46
|
+
} from "./cli-ke896fcf.js";
|
|
47
|
+
import"./cli-f7kr7svz.js";
|
|
48
|
+
import"./cli-knd276ed.js";
|
|
52
49
|
import {
|
|
53
50
|
AGENT_MAX_TASKS_CONFIG_KEY,
|
|
54
51
|
ALL_CAPABILITIES,
|
|
@@ -75,6 +72,7 @@ import {
|
|
|
75
72
|
SDK_ALLOWLIST,
|
|
76
73
|
SUPPORTED_PROTOCOL_VERSIONS,
|
|
77
74
|
TaskCreationBlockedError,
|
|
75
|
+
TelegramBotApiError,
|
|
78
76
|
WebhookError,
|
|
79
77
|
activateVersion,
|
|
80
78
|
agentRanModel,
|
|
@@ -88,6 +86,7 @@ import {
|
|
|
88
86
|
authorizeAssetKeyWrite,
|
|
89
87
|
authorizeRoomNamespace,
|
|
90
88
|
calculateNextRun,
|
|
89
|
+
callTelegramBotApi,
|
|
91
90
|
canClaim,
|
|
92
91
|
canReadMemory,
|
|
93
92
|
cancelApprovalRequest,
|
|
@@ -124,6 +123,7 @@ import {
|
|
|
124
123
|
enforceContentLengthCap,
|
|
125
124
|
enqueueAdmissionRow,
|
|
126
125
|
enqueueAuditRow,
|
|
126
|
+
errorMessage,
|
|
127
127
|
estimateTokens,
|
|
128
128
|
executeRawLlm,
|
|
129
129
|
executeReadOnlyQuery,
|
|
@@ -133,6 +133,9 @@ import {
|
|
|
133
133
|
extractAndVerifyCookie,
|
|
134
134
|
flushAuditBuffer,
|
|
135
135
|
getAgentHarnessCliVersion,
|
|
136
|
+
getChatInstance,
|
|
137
|
+
getChatSdkConfig,
|
|
138
|
+
getChatSdkHealth,
|
|
136
139
|
getCombConfig,
|
|
137
140
|
getEnabledCapabilities,
|
|
138
141
|
getEventCountsFiltered,
|
|
@@ -147,6 +150,7 @@ import {
|
|
|
147
150
|
getLinksForMemory,
|
|
148
151
|
getMemoryChunks,
|
|
149
152
|
getOAuthPreset,
|
|
153
|
+
getPageEditCounter,
|
|
150
154
|
getPathSegments,
|
|
151
155
|
getPosteriorsByIds,
|
|
152
156
|
getRoom,
|
|
@@ -207,6 +211,9 @@ import {
|
|
|
207
211
|
isAgentMailEnabled,
|
|
208
212
|
isApiDraining,
|
|
209
213
|
isAzureDevOpsEnabled,
|
|
214
|
+
isChatAdapterConfigured,
|
|
215
|
+
isChatSdkEnabled,
|
|
216
|
+
isChatSdkStopping,
|
|
210
217
|
isGitHubEnabled,
|
|
211
218
|
isGitLabEnabled,
|
|
212
219
|
isInboxAllowed,
|
|
@@ -218,6 +225,7 @@ import {
|
|
|
218
225
|
isLinearEnabled,
|
|
219
226
|
isOriginAllowedForCredentials,
|
|
220
227
|
isSenderAllowed,
|
|
228
|
+
isTrustedTeamsServiceUrl,
|
|
221
229
|
issuePageSessionCookie,
|
|
222
230
|
json,
|
|
223
231
|
jsonError,
|
|
@@ -241,7 +249,6 @@ import {
|
|
|
241
249
|
parseCookieHeader,
|
|
242
250
|
parseModelTierOverridesHeader,
|
|
243
251
|
parseQueryParams,
|
|
244
|
-
parseSkillContent,
|
|
245
252
|
patchWorkflowDefinition,
|
|
246
253
|
poolTaskRunsOnHarness,
|
|
247
254
|
posteriorMean,
|
|
@@ -267,6 +274,7 @@ import {
|
|
|
267
274
|
reservedRoomKeyError,
|
|
268
275
|
resetAgentMaxTasksMirror,
|
|
269
276
|
resetRoom,
|
|
277
|
+
resolveAdapterApiUrl,
|
|
270
278
|
resolveHttpAuditUserId,
|
|
271
279
|
resolveHttpFavoriteOwner,
|
|
272
280
|
resolveHttpRequestAuth,
|
|
@@ -301,17 +309,21 @@ import {
|
|
|
301
309
|
snapshotPage,
|
|
302
310
|
startAuditGc,
|
|
303
311
|
startAuditWriter,
|
|
312
|
+
startChatSdk,
|
|
304
313
|
steerTaskHandler,
|
|
305
314
|
steerTaskOutputSchema,
|
|
306
315
|
steerTaskUserInputSchema,
|
|
307
316
|
stopAuditGc,
|
|
308
317
|
stopAuditWriter,
|
|
318
|
+
stopChatSdk,
|
|
309
319
|
stopExtensionRuntime,
|
|
310
320
|
stripSiblingBlock,
|
|
311
321
|
sweepRooms,
|
|
312
322
|
syncTelemetryEnabled,
|
|
323
|
+
taskModelPin,
|
|
313
324
|
toolErr,
|
|
314
325
|
touchRuntimeInstance,
|
|
326
|
+
trackBackground,
|
|
315
327
|
triggerSchemaErrorResponse,
|
|
316
328
|
uninstallExtension,
|
|
317
329
|
updateExtensionMeta,
|
|
@@ -332,13 +344,13 @@ import {
|
|
|
332
344
|
wireHttpSpanLifecycle,
|
|
333
345
|
workflowModelErrors,
|
|
334
346
|
writeUnhandledError
|
|
335
|
-
} from "./cli-
|
|
336
|
-
import"./cli-
|
|
347
|
+
} from "./cli-bzszjf2p.js";
|
|
348
|
+
import"./cli-zkpks3r3.js";
|
|
337
349
|
import {
|
|
338
350
|
AMP_ESTIMATE_MODELS,
|
|
339
351
|
ampBillsCacheWrites,
|
|
340
352
|
resolveAmpModel
|
|
341
|
-
} from "./cli-
|
|
353
|
+
} from "./cli-hnhtk6cj.js";
|
|
342
354
|
import {
|
|
343
355
|
RATING_MODEL_MAX_LENGTH,
|
|
344
356
|
REFERENCES_SOURCE_MAX_LENGTH,
|
|
@@ -347,16 +359,12 @@ import {
|
|
|
347
359
|
import {
|
|
348
360
|
isMultiRuntimeEnabled
|
|
349
361
|
} from "./cli-re8z5p8p.js";
|
|
350
|
-
import"./cli-42qhyvwx.js";
|
|
351
362
|
import {
|
|
352
363
|
deleteModelCatalogOverlay,
|
|
353
364
|
loadModelsCatalog,
|
|
354
365
|
requestModelCatalogRefresh,
|
|
355
366
|
upsertModelCatalogOverlay
|
|
356
|
-
} from "./cli-
|
|
357
|
-
import {
|
|
358
|
-
normalizeModelKey
|
|
359
|
-
} from "./cli-jpc4r224.js";
|
|
367
|
+
} from "./cli-z5jjpaxw.js";
|
|
360
368
|
import {
|
|
361
369
|
ConnectionAuthInputSchema,
|
|
362
370
|
MAX_SCRIPT_WALL_CLOCK_MS,
|
|
@@ -411,6 +419,7 @@ import {
|
|
|
411
419
|
mcpOAuthSsrfOptions,
|
|
412
420
|
normalizeTokenEndpointAuthMethod,
|
|
413
421
|
oauthAppToProviderConfig,
|
|
422
|
+
parseSkillContent,
|
|
414
423
|
publicEndpointSsrfOptions,
|
|
415
424
|
readStreamCapped,
|
|
416
425
|
refreshMcpToken,
|
|
@@ -434,7 +443,7 @@ import {
|
|
|
434
443
|
upsertCredentialBinding,
|
|
435
444
|
upsertMcpOAuthToken,
|
|
436
445
|
upsertScriptConnection
|
|
437
|
-
} from "./cli-
|
|
446
|
+
} from "./cli-ee9gtz70.js";
|
|
438
447
|
import"./cli-epan13p1.js";
|
|
439
448
|
import {
|
|
440
449
|
detachedProcessGroup,
|
|
@@ -449,7 +458,12 @@ import {
|
|
|
449
458
|
forceRefreshAuthorizationOrThrow,
|
|
450
459
|
forceRefreshTokenOrThrow,
|
|
451
460
|
oauthAppRowToProviderConfig
|
|
452
|
-
} from "./cli-
|
|
461
|
+
} from "./cli-6razj6t4.js";
|
|
462
|
+
import"./cli-5t4f29ez.js";
|
|
463
|
+
import {
|
|
464
|
+
normalizeModelKey
|
|
465
|
+
} from "./cli-r62a35ea.js";
|
|
466
|
+
import"./cli-6cvfxs8r.js";
|
|
453
467
|
import {
|
|
454
468
|
AgentFsProvider,
|
|
455
469
|
FilesError,
|
|
@@ -468,14 +482,14 @@ import {
|
|
|
468
482
|
startWorkflowExecution,
|
|
469
483
|
validateJsonSchema,
|
|
470
484
|
workflowSaveWarnings
|
|
471
|
-
} from "./cli-
|
|
485
|
+
} from "./cli-1e4b6bzh.js";
|
|
472
486
|
import {
|
|
473
487
|
createApprovalFollowUpTask,
|
|
474
488
|
definitionNodeIds,
|
|
475
489
|
generateEdges,
|
|
476
490
|
validateDefinition
|
|
477
|
-
} from "./cli-
|
|
478
|
-
import"./cli-
|
|
491
|
+
} from "./cli-v1yb0rqb.js";
|
|
492
|
+
import"./cli-se8w6wny.js";
|
|
479
493
|
import {
|
|
480
494
|
CLIENT_ID,
|
|
481
495
|
MAX_CODEX_OAUTH_SLOT,
|
|
@@ -486,10 +500,10 @@ import {
|
|
|
486
500
|
getAccountId,
|
|
487
501
|
getValidCodexOAuth,
|
|
488
502
|
loadAllCodexOAuthSlots
|
|
489
|
-
} from "./cli-
|
|
490
|
-
import"./cli-b07hr3bt.js";
|
|
491
|
-
import"./cli-h6vtvt5c.js";
|
|
503
|
+
} from "./cli-e6mpjhed.js";
|
|
492
504
|
import"./cli-2x0e561b.js";
|
|
505
|
+
import"./cli-txqb9s38.js";
|
|
506
|
+
import"./cli-h6vtvt5c.js";
|
|
493
507
|
import"./cli-fad8m16k.js";
|
|
494
508
|
import"./cli-bsakbbkm.js";
|
|
495
509
|
import"./cli-zxg80zs9.js";
|
|
@@ -509,18 +523,22 @@ import {
|
|
|
509
523
|
recordDbRetentionStatement,
|
|
510
524
|
recordDbRetentionSweep,
|
|
511
525
|
recordSessionCost,
|
|
512
|
-
require_content_type,
|
|
513
526
|
startSlackApp,
|
|
514
527
|
startSpan,
|
|
515
528
|
stopSlackApp,
|
|
516
529
|
withRemoteContext,
|
|
517
530
|
withSpan,
|
|
518
531
|
withSpanContext
|
|
519
|
-
} from "./cli-
|
|
520
|
-
import"./cli-
|
|
532
|
+
} from "./cli-skxvvpap.js";
|
|
533
|
+
import"./cli-n2wq4j7m.js";
|
|
534
|
+
import {
|
|
535
|
+
require_content_type
|
|
536
|
+
} from "./cli-wmgrkscj.js";
|
|
521
537
|
import"./cli-3er6gcsn.js";
|
|
522
|
-
import"./cli-
|
|
523
|
-
import"./cli-
|
|
538
|
+
import"./cli-hjwmhcg1.js";
|
|
539
|
+
import"./cli-rhs9pz33.js";
|
|
540
|
+
import"./cli-9ha6hs2d.js";
|
|
541
|
+
import"./cli-k3dp5tpf.js";
|
|
524
542
|
import {
|
|
525
543
|
InvalidRuntimeTokenError,
|
|
526
544
|
RuntimePoolError,
|
|
@@ -559,11 +577,11 @@ import {
|
|
|
559
577
|
unlinkIdentity,
|
|
560
578
|
updateRuntimeController,
|
|
561
579
|
updateRuntimePool
|
|
562
|
-
} from "./cli-
|
|
563
|
-
import"./cli-
|
|
580
|
+
} from "./cli-eejsgvm4.js";
|
|
581
|
+
import"./cli-ra0xzggj.js";
|
|
564
582
|
import {
|
|
565
583
|
bedrockProviderModule
|
|
566
|
-
} from "./cli-
|
|
584
|
+
} from "./cli-hvqbtna4.js";
|
|
567
585
|
import"./cli-phre6gz0.js";
|
|
568
586
|
import"./cli-eh1ytktb.js";
|
|
569
587
|
import"./cli-txgcknmy.js";
|
|
@@ -578,7 +596,7 @@ import"./cli-1m2e086m.js";
|
|
|
578
596
|
import"./cli-btbzvq95.js";
|
|
579
597
|
import"./cli-p7z6q2m6.js";
|
|
580
598
|
import"./cli-wnb9b2g3.js";
|
|
581
|
-
import"./cli-
|
|
599
|
+
import"./cli-f527ce74.js";
|
|
582
600
|
import {
|
|
583
601
|
import_websocket,
|
|
584
602
|
import_websocket_server
|
|
@@ -587,7 +605,7 @@ import"./cli-pzxba7gw.js";
|
|
|
587
605
|
import {
|
|
588
606
|
getUserGrant,
|
|
589
607
|
init_rbac_roles
|
|
590
|
-
} from "./cli-
|
|
608
|
+
} from "./cli-74ahz61x.js";
|
|
591
609
|
import {
|
|
592
610
|
LEGACY_RULES,
|
|
593
611
|
can,
|
|
@@ -596,10 +614,12 @@ import {
|
|
|
596
614
|
init_rbac,
|
|
597
615
|
isRbacEnabled,
|
|
598
616
|
setAuditSink
|
|
599
|
-
} from "./cli-
|
|
617
|
+
} from "./cli-przpmdgr.js";
|
|
600
618
|
import {
|
|
601
619
|
API_DRAINING_HEADER,
|
|
602
620
|
CANDIDATE_SET_MULTIPLIER,
|
|
621
|
+
CHAT_SDK_ADAPTER_NAMES,
|
|
622
|
+
CHAT_TASK_ONLY_TOOLS,
|
|
603
623
|
CODEX_AUTH_WATCH_NAMESPACE,
|
|
604
624
|
CredentialBindingSchema,
|
|
605
625
|
DB_RETENTION_TUNING_BOUNDS,
|
|
@@ -626,6 +646,7 @@ import {
|
|
|
626
646
|
cancelTask,
|
|
627
647
|
catalog_default,
|
|
628
648
|
channelTopic,
|
|
649
|
+
chatThreadOfContextKey,
|
|
629
650
|
checkoutPromptTemplate,
|
|
630
651
|
claimKv,
|
|
631
652
|
claimMentions,
|
|
@@ -715,7 +736,6 @@ import {
|
|
|
715
736
|
getAllChannelActivityCursors,
|
|
716
737
|
getAllLogs,
|
|
717
738
|
getAllPricingRows,
|
|
718
|
-
getAllServices,
|
|
719
739
|
getAllSessionCosts,
|
|
720
740
|
getAllTasks,
|
|
721
741
|
getAllUsers,
|
|
@@ -787,7 +807,6 @@ import {
|
|
|
787
807
|
getScriptRunByIdempotencyKey,
|
|
788
808
|
getScriptRunExecutionArgs,
|
|
789
809
|
getScriptRunJournalStep,
|
|
790
|
-
getServicesByAgentId,
|
|
791
810
|
getSessionCostSummary,
|
|
792
811
|
getSessionCostsByAgentId,
|
|
793
812
|
getSessionCostsByTaskId,
|
|
@@ -850,6 +869,7 @@ import {
|
|
|
850
869
|
init_reranker,
|
|
851
870
|
init_runtime,
|
|
852
871
|
init_runtime_pools_flag,
|
|
872
|
+
init_schema,
|
|
853
873
|
init_secret_registry,
|
|
854
874
|
init_steering,
|
|
855
875
|
init_swarm_config_guard,
|
|
@@ -866,6 +886,9 @@ import {
|
|
|
866
886
|
installMcpServer,
|
|
867
887
|
installSkill,
|
|
868
888
|
internalConfigKeyError,
|
|
889
|
+
isAdapterEntryEnabled,
|
|
890
|
+
isApiOnlyConfigKey,
|
|
891
|
+
isChatSdkTask,
|
|
869
892
|
isExtensionAgent,
|
|
870
893
|
isFilledOrgLogoUrl,
|
|
871
894
|
isInternalConfigKey,
|
|
@@ -998,9 +1021,10 @@ import {
|
|
|
998
1021
|
upsertSkillFiles,
|
|
999
1022
|
upsertSwarmConfig,
|
|
1000
1023
|
validateConfigValue,
|
|
1024
|
+
validateExportToEnv,
|
|
1001
1025
|
withFavoriteFlags
|
|
1002
|
-
} from "./cli-
|
|
1003
|
-
import"./cli-
|
|
1026
|
+
} from "./cli-ef1hg1wv.js";
|
|
1027
|
+
import"./cli-hnmhtzvh.js";
|
|
1004
1028
|
import {
|
|
1005
1029
|
ActiveSessionSchema,
|
|
1006
1030
|
AgentAcpStatusSchema,
|
|
@@ -1096,7 +1120,6 @@ import {
|
|
|
1096
1120
|
ScriptRunStatusSchema,
|
|
1097
1121
|
ScriptScopeSchema,
|
|
1098
1122
|
ScriptVersionRecordSchema,
|
|
1099
|
-
ServiceSchema,
|
|
1100
1123
|
SessionCostModelBreakdownSchema,
|
|
1101
1124
|
SessionCostSchema,
|
|
1102
1125
|
SessionLogSchema,
|
|
@@ -1136,22 +1159,22 @@ import {
|
|
|
1136
1159
|
isSafeBundlePath,
|
|
1137
1160
|
isTerminalTaskStatus,
|
|
1138
1161
|
splitLegacyModelAlias
|
|
1139
|
-
} from "./cli-
|
|
1162
|
+
} from "./cli-cgtksawx.js";
|
|
1140
1163
|
import {
|
|
1141
1164
|
IDENTITY_FIELD_BUDGETS,
|
|
1142
1165
|
IdentityFieldBudgetError,
|
|
1143
1166
|
init_identity_field_budget
|
|
1144
|
-
} from "./cli-
|
|
1145
|
-
import {
|
|
1146
|
-
init_steering_enabled,
|
|
1147
|
-
isSteeringEnabled
|
|
1148
|
-
} from "./cli-7mm2r1kp.js";
|
|
1167
|
+
} from "./cli-s2sp957d.js";
|
|
1149
1168
|
import {
|
|
1150
1169
|
getSlackConfiguration,
|
|
1151
1170
|
init_config
|
|
1152
1171
|
} from "./cli-dmtrxqhg.js";
|
|
1172
|
+
import {
|
|
1173
|
+
init_steering_enabled,
|
|
1174
|
+
isSteeringEnabled
|
|
1175
|
+
} from "./cli-7mm2r1kp.js";
|
|
1176
|
+
import"./cli-5hkm7whv.js";
|
|
1153
1177
|
import"./cli-mvzyxwg3.js";
|
|
1154
|
-
import"./cli-tadfgd0t.js";
|
|
1155
1178
|
import {
|
|
1156
1179
|
getAllTemplateDefinitions,
|
|
1157
1180
|
getTemplateDefinition,
|
|
@@ -1178,10 +1201,7 @@ import {
|
|
|
1178
1201
|
getOpenRouterAttributionHeaders,
|
|
1179
1202
|
init_openrouter_base_url
|
|
1180
1203
|
} from "./cli-a35hzdve.js";
|
|
1181
|
-
import
|
|
1182
|
-
init_src,
|
|
1183
|
-
isAlias
|
|
1184
|
-
} from "./cli-014vns2y.js";
|
|
1204
|
+
import"./cli-stfs0k5s.js";
|
|
1185
1205
|
import {
|
|
1186
1206
|
exports_zod,
|
|
1187
1207
|
init_zod
|
|
@@ -1202,17 +1222,17 @@ import {
|
|
|
1202
1222
|
import {
|
|
1203
1223
|
init_package,
|
|
1204
1224
|
package_default
|
|
1205
|
-
} from "./cli-
|
|
1225
|
+
} from "./cli-k382tshb.js";
|
|
1206
1226
|
import {
|
|
1207
1227
|
init_event_bus,
|
|
1208
1228
|
workflowEventBus
|
|
1209
|
-
} from "./cli-
|
|
1229
|
+
} from "./cli-9nfx44eh.js";
|
|
1210
1230
|
import {
|
|
1211
1231
|
init_bus,
|
|
1212
1232
|
realtimeBus
|
|
1213
1233
|
} from "./cli-zf8jjwex.js";
|
|
1214
1234
|
import"./cli-h8w3fg83.js";
|
|
1215
|
-
import"./cli-
|
|
1235
|
+
import"./cli-d2qr7aj4.js";
|
|
1216
1236
|
import {
|
|
1217
1237
|
MAX_PROFILE_FILE_LENGTH,
|
|
1218
1238
|
agentFsFileRoute,
|
|
@@ -1228,7 +1248,7 @@ import {
|
|
|
1228
1248
|
parseEnvFlag
|
|
1229
1249
|
} from "./cli-ej6gbxfb.js";
|
|
1230
1250
|
import"./cli-1srmzpr3.js";
|
|
1231
|
-
import"./cli-
|
|
1251
|
+
import"./cli-tqaazemc.js";
|
|
1232
1252
|
import {
|
|
1233
1253
|
getApiKey,
|
|
1234
1254
|
init_api_key
|
|
@@ -1239,7 +1259,11 @@ import {
|
|
|
1239
1259
|
registerVolatileSecret,
|
|
1240
1260
|
scrubObject,
|
|
1241
1261
|
scrubSecrets
|
|
1242
|
-
} from "./cli-
|
|
1262
|
+
} from "./cli-p1x85d2t.js";
|
|
1263
|
+
import {
|
|
1264
|
+
init_src,
|
|
1265
|
+
isAlias
|
|
1266
|
+
} from "./cli-e3g5mbkz.js";
|
|
1243
1267
|
import {
|
|
1244
1268
|
__require,
|
|
1245
1269
|
__toESM
|
|
@@ -7522,9 +7546,8 @@ init_request_auth_context();
|
|
|
7522
7546
|
init_secret_scrubber();
|
|
7523
7547
|
var MAX_ENV_PRESENCE_KEYS = 200;
|
|
7524
7548
|
var SECRETS_FORCE_MASK_NOTE = " (secret values masked: this token cannot read secrets in this scope)";
|
|
7525
|
-
var API_ONLY_CONFIG_KEYS = new Set(["API_AGENT_FS_API_KEY", "SLACK_SIGNING_SECRET"]);
|
|
7526
7549
|
function stripApiOnlyKeys(configs) {
|
|
7527
|
-
return configs.filter((config) => !
|
|
7550
|
+
return configs.filter((config) => !isApiOnlyConfigKey(config.key) && !isInternalConfigKey(config.key));
|
|
7528
7551
|
}
|
|
7529
7552
|
function singleHeader(req, name) {
|
|
7530
7553
|
const raw = req.headers[name];
|
|
@@ -7566,6 +7589,9 @@ async function resolveSecretsRead(req, includeSecrets, resolvedScope) {
|
|
|
7566
7589
|
};
|
|
7567
7590
|
}
|
|
7568
7591
|
async function ensureConfigAdmin(req, res, verb) {
|
|
7592
|
+
return ensureHttpPermission(req, res, verb, verb === "config.write.any" ? "Writing swarm config requires the lead agent" : "Deleting swarm config requires the lead agent");
|
|
7593
|
+
}
|
|
7594
|
+
async function ensureHttpPermission(req, res, verb, forbiddenMessage) {
|
|
7569
7595
|
const auth = getRequestAuth(req);
|
|
7570
7596
|
if (auth?.kind === "operator" || auth?.kind === "user")
|
|
7571
7597
|
return true;
|
|
@@ -7582,7 +7608,7 @@ async function ensureConfigAdmin(req, res, verb) {
|
|
|
7582
7608
|
source: "http"
|
|
7583
7609
|
});
|
|
7584
7610
|
if (!decision.allow) {
|
|
7585
|
-
jsonError(res,
|
|
7611
|
+
jsonError(res, forbiddenMessage, 403);
|
|
7586
7612
|
return false;
|
|
7587
7613
|
}
|
|
7588
7614
|
return true;
|
|
@@ -7700,7 +7726,8 @@ var upsertConfig = route({
|
|
|
7700
7726
|
value: exports_external.unknown(),
|
|
7701
7727
|
isSecret: exports_external.boolean().optional(),
|
|
7702
7728
|
envPath: exports_external.string().nullish(),
|
|
7703
|
-
description: exports_external.string().nullish()
|
|
7729
|
+
description: exports_external.string().nullish(),
|
|
7730
|
+
exportToEnv: exports_external.boolean().optional().describe("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.")
|
|
7704
7731
|
}),
|
|
7705
7732
|
responses: {
|
|
7706
7733
|
200: { description: "Config entry upserted", schema: SwarmConfigSchema },
|
|
@@ -7839,7 +7866,7 @@ async function handleConfig(req, res, pathSegments, queryParams) {
|
|
|
7839
7866
|
return true;
|
|
7840
7867
|
if (!await ensureConfigAdmin(req, res, "config.write.any"))
|
|
7841
7868
|
return true;
|
|
7842
|
-
const { scope, scopeId, key, value, isSecret, envPath, description } = parsed.body;
|
|
7869
|
+
const { scope, scopeId, key, value, isSecret, envPath, description, exportToEnv } = parsed.body;
|
|
7843
7870
|
if (scope === "global" && scopeId) {
|
|
7844
7871
|
jsonError(res, "Global scope must not have scopeId", 400);
|
|
7845
7872
|
return true;
|
|
@@ -7856,7 +7883,7 @@ async function handleConfig(req, res, pathSegments, queryParams) {
|
|
|
7856
7883
|
jsonError(res, internalConfigKeyError(key).message, 400);
|
|
7857
7884
|
return true;
|
|
7858
7885
|
}
|
|
7859
|
-
const validationError = validateConfigValue(key, value);
|
|
7886
|
+
const validationError = validateConfigValue(key, value) ?? validateExportToEnv(key, exportToEnv);
|
|
7860
7887
|
if (validationError) {
|
|
7861
7888
|
jsonError(res, validationError, 400);
|
|
7862
7889
|
return true;
|
|
@@ -7870,7 +7897,8 @@ async function handleConfig(req, res, pathSegments, queryParams) {
|
|
|
7870
7897
|
value: String(value),
|
|
7871
7898
|
isSecret: isSecret || false,
|
|
7872
7899
|
envPath: envPath || null,
|
|
7873
|
-
description: description || null
|
|
7900
|
+
description: description || null,
|
|
7901
|
+
exportToEnv
|
|
7874
7902
|
});
|
|
7875
7903
|
if (scope === "global" && key === "SWARM_ORG_WEBSITE") {
|
|
7876
7904
|
await fillOrgLogoFromWebsite(String(value));
|
|
@@ -8428,7 +8456,7 @@ async function sendReviewBatch(input, deps = {}) {
|
|
|
8428
8456
|
const target = targets[index];
|
|
8429
8457
|
const isRepair = index >= wonIds.length;
|
|
8430
8458
|
if (reply.status === "rejected") {
|
|
8431
|
-
console.warn(scrubSecrets(`[comb] sent reply failed comment=${target.id} task=${target.taskId}: ${
|
|
8459
|
+
console.warn(scrubSecrets(`[comb] sent reply failed comment=${target.id} task=${target.taskId}: ${errorMessage2(reply.reason)}`));
|
|
8432
8460
|
if (isRepair)
|
|
8433
8461
|
skipped.push(alreadySent(target.id, target.taskId));
|
|
8434
8462
|
} else if (isRepair) {
|
|
@@ -8459,7 +8487,7 @@ async function readComment(agentFs, drive, versionOf, id) {
|
|
|
8459
8487
|
} catch (error) {
|
|
8460
8488
|
if (error instanceof FilesError && error.code === "NotFound")
|
|
8461
8489
|
return { id, thread: null };
|
|
8462
|
-
throw new ReviewBatchError(502, scrubSecrets(`agent-fs could not read comment ${id}: ${
|
|
8490
|
+
throw new ReviewBatchError(502, scrubSecrets(`agent-fs could not read comment ${id}: ${errorMessage2(error)}`));
|
|
8463
8491
|
}
|
|
8464
8492
|
const { comment } = thread;
|
|
8465
8493
|
const version = comment.fileVersion ?? (comment.parentId ? undefined : await versionOf(comment));
|
|
@@ -8519,7 +8547,7 @@ async function settleClaims(ids, claim, next) {
|
|
|
8519
8547
|
settled.forEach((result, index) => {
|
|
8520
8548
|
if (result.status === "fulfilled" && result.value)
|
|
8521
8549
|
return;
|
|
8522
|
-
const why = result.status === "rejected" ?
|
|
8550
|
+
const why = result.status === "rejected" ? errorMessage2(result.reason) : "another send holds the claim";
|
|
8523
8551
|
console.warn(scrubSecrets(`[comb] could not ${next ? "record" : "release"} the claim on comment=${ids[index]}: ${why}`));
|
|
8524
8552
|
});
|
|
8525
8553
|
}
|
|
@@ -8621,7 +8649,7 @@ async function requesterLabel(userId) {
|
|
|
8621
8649
|
return "an operator (swarm API key)";
|
|
8622
8650
|
return user.email ? `${user.name} <${user.email}>` : user.name;
|
|
8623
8651
|
}
|
|
8624
|
-
function
|
|
8652
|
+
function errorMessage2(error) {
|
|
8625
8653
|
return error instanceof Error ? error.message : String(error);
|
|
8626
8654
|
}
|
|
8627
8655
|
|
|
@@ -8828,64 +8856,6 @@ async function handleContext(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
8828
8856
|
return false;
|
|
8829
8857
|
}
|
|
8830
8858
|
|
|
8831
|
-
// src/http/ecosystem.ts
|
|
8832
|
-
init_zod();
|
|
8833
|
-
init_db3();
|
|
8834
|
-
var EcosystemAppSchema = exports_external.object({
|
|
8835
|
-
name: exports_external.string(),
|
|
8836
|
-
script: exports_external.string(),
|
|
8837
|
-
cwd: exports_external.string().optional(),
|
|
8838
|
-
interpreter: exports_external.string().optional(),
|
|
8839
|
-
args: exports_external.array(exports_external.string()).optional(),
|
|
8840
|
-
env: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
8841
|
-
});
|
|
8842
|
-
var getEcosystem = route({
|
|
8843
|
-
method: "get",
|
|
8844
|
-
path: "/ecosystem",
|
|
8845
|
-
pattern: ["ecosystem"],
|
|
8846
|
-
summary: "Get PM2 ecosystem config for agent services",
|
|
8847
|
-
tags: ["Ecosystem"],
|
|
8848
|
-
auth: { apiKey: true, agentId: true },
|
|
8849
|
-
responses: {
|
|
8850
|
-
200: {
|
|
8851
|
-
description: "PM2 ecosystem config",
|
|
8852
|
-
schema: exports_external.object({ apps: exports_external.array(EcosystemAppSchema) })
|
|
8853
|
-
},
|
|
8854
|
-
400: { description: "Missing X-Agent-ID" }
|
|
8855
|
-
}
|
|
8856
|
-
});
|
|
8857
|
-
async function handleEcosystem(req, res, pathSegments, myAgentId) {
|
|
8858
|
-
if (getEcosystem.match(req.method, pathSegments)) {
|
|
8859
|
-
if (!myAgentId) {
|
|
8860
|
-
jsonError(res, "Missing X-Agent-ID header", 400);
|
|
8861
|
-
return true;
|
|
8862
|
-
}
|
|
8863
|
-
const services = await getServicesByAgentId(myAgentId);
|
|
8864
|
-
const ecosystem = {
|
|
8865
|
-
apps: services.filter((s) => s.script).map((s) => {
|
|
8866
|
-
const app = {
|
|
8867
|
-
name: s.name,
|
|
8868
|
-
script: s.script
|
|
8869
|
-
};
|
|
8870
|
-
if (s.cwd)
|
|
8871
|
-
app.cwd = s.cwd;
|
|
8872
|
-
if (s.interpreter)
|
|
8873
|
-
app.interpreter = s.interpreter;
|
|
8874
|
-
if (s.args && s.args.length > 0)
|
|
8875
|
-
app.args = s.args;
|
|
8876
|
-
if (s.env && Object.keys(s.env).length > 0)
|
|
8877
|
-
app.env = s.env;
|
|
8878
|
-
if (s.port)
|
|
8879
|
-
app.env = { ...app.env || {}, PORT: String(s.port) };
|
|
8880
|
-
return app;
|
|
8881
|
-
})
|
|
8882
|
-
};
|
|
8883
|
-
getEcosystem.respond(res, 200, ecosystem);
|
|
8884
|
-
return true;
|
|
8885
|
-
}
|
|
8886
|
-
return false;
|
|
8887
|
-
}
|
|
8888
|
-
|
|
8889
8859
|
// src/http/events.ts
|
|
8890
8860
|
init_zod();
|
|
8891
8861
|
init_types();
|
|
@@ -9107,6 +9077,7 @@ declare module "swarm-extension" {
|
|
|
9107
9077
|
| "linear"
|
|
9108
9078
|
| "jira"
|
|
9109
9079
|
| "comb"
|
|
9080
|
+
| "chat"
|
|
9110
9081
|
| undefined;
|
|
9111
9082
|
routingReason?:
|
|
9112
9083
|
| "skill"
|
|
@@ -9220,7 +9191,8 @@ declare module "swarm-extension" {
|
|
|
9220
9191
|
| "system"
|
|
9221
9192
|
| "linear"
|
|
9222
9193
|
| "jira"
|
|
9223
|
-
| "comb"
|
|
9194
|
+
| "comb"
|
|
9195
|
+
| "chat";
|
|
9224
9196
|
tags: string[];
|
|
9225
9197
|
priority: number;
|
|
9226
9198
|
dependsOn: string[];
|
|
@@ -9279,6 +9251,7 @@ declare module "swarm-extension" {
|
|
|
9279
9251
|
resolvedModel?: string | undefined;
|
|
9280
9252
|
modelSource?: string | undefined;
|
|
9281
9253
|
modelAlias?: string | undefined;
|
|
9254
|
+
resolvedEffort?: "off" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
9282
9255
|
scheduleId?: string | undefined;
|
|
9283
9256
|
workflowRunId?: string | null | undefined;
|
|
9284
9257
|
workflowRunStepId?: string | null | undefined;
|
|
@@ -9555,6 +9528,43 @@ declare module "swarm-extension" {
|
|
|
9555
9528
|
kind: "broadcast";
|
|
9556
9529
|
};
|
|
9557
9530
|
}
|
|
9531
|
+
/** A Chat SDK message after its thread buffer flushed, before routing. */
|
|
9532
|
+
export interface ChatRouteEvent {
|
|
9533
|
+
/** Adapter name, such as \`telegram\` or \`slack\`. */
|
|
9534
|
+
adapter: string;
|
|
9535
|
+
channelId: string;
|
|
9536
|
+
/** The Chat SDK thread id, prefixed with the adapter name. */
|
|
9537
|
+
threadId: string;
|
|
9538
|
+
/** The first buffered sender. */
|
|
9539
|
+
userId: string;
|
|
9540
|
+
userName?: string;
|
|
9541
|
+
/** The buffered messages, joined. */
|
|
9542
|
+
text: string;
|
|
9543
|
+
botMentioned: boolean;
|
|
9544
|
+
isDirectMessage: boolean;
|
|
9545
|
+
/** Set when earlier swarm tasks exist in this thread. */
|
|
9546
|
+
threadContext?: {
|
|
9547
|
+
adapter: string;
|
|
9548
|
+
threadId: string;
|
|
9549
|
+
};
|
|
9550
|
+
}
|
|
9551
|
+
export interface ChatRouteModify {
|
|
9552
|
+
target:
|
|
9553
|
+
| {
|
|
9554
|
+
kind: "agent";
|
|
9555
|
+
agentId: string;
|
|
9556
|
+
}
|
|
9557
|
+
| {
|
|
9558
|
+
kind: "lead";
|
|
9559
|
+
}
|
|
9560
|
+
| {
|
|
9561
|
+
kind: "broadcast";
|
|
9562
|
+
}
|
|
9563
|
+
| {
|
|
9564
|
+
kind: "workflow";
|
|
9565
|
+
workflowId: string;
|
|
9566
|
+
};
|
|
9567
|
+
}
|
|
9558
9568
|
export type HeartbeatClassification = "no-session" | "stale-session" | "fresh-stalled";
|
|
9559
9569
|
export type HeartbeatAction = "supersede-resume" | "fail" | "record";
|
|
9560
9570
|
export interface HeartbeatRemediateEvent {
|
|
@@ -9599,6 +9609,18 @@ declare module "swarm-extension" {
|
|
|
9599
9609
|
threadTs?: string;
|
|
9600
9610
|
taskId?: string;
|
|
9601
9611
|
}
|
|
9612
|
+
/** A Chat SDK message the swarm received or sent. */
|
|
9613
|
+
export interface ChatMessageEvent {
|
|
9614
|
+
adapter: string;
|
|
9615
|
+
channelId: string;
|
|
9616
|
+
threadId: string;
|
|
9617
|
+
/** The sender, for an inbound message. */
|
|
9618
|
+
userId?: string;
|
|
9619
|
+
text: string;
|
|
9620
|
+
direction: "inbound" | "outbound";
|
|
9621
|
+
taskId?: string;
|
|
9622
|
+
messageId?: string;
|
|
9623
|
+
}
|
|
9602
9624
|
/**
|
|
9603
9625
|
* A person answered an approval request. Fires for workflow and standalone
|
|
9604
9626
|
* requests. Timeouts and cancellations do not emit it today.
|
|
@@ -9707,6 +9729,11 @@ declare module "swarm-extension" {
|
|
|
9707
9729
|
modify: SlackRouteModify;
|
|
9708
9730
|
result: PreResult<SlackRouteModify>;
|
|
9709
9731
|
};
|
|
9732
|
+
"pre.chat.route": {
|
|
9733
|
+
event: ChatRouteEvent;
|
|
9734
|
+
modify: ChatRouteModify;
|
|
9735
|
+
result: PreResult<ChatRouteModify>;
|
|
9736
|
+
};
|
|
9710
9737
|
"pre.heartbeat.remediate": {
|
|
9711
9738
|
event: HeartbeatRemediateEvent;
|
|
9712
9739
|
modify: HeartbeatRemediateModify;
|
|
@@ -9752,6 +9779,11 @@ declare module "swarm-extension" {
|
|
|
9752
9779
|
modify: never;
|
|
9753
9780
|
result: void;
|
|
9754
9781
|
};
|
|
9782
|
+
"post.chat.message": {
|
|
9783
|
+
event: ChatMessageEvent;
|
|
9784
|
+
modify: never;
|
|
9785
|
+
result: void;
|
|
9786
|
+
};
|
|
9755
9787
|
"post.approval.resolved": {
|
|
9756
9788
|
event: ApprovalResolvedEvent;
|
|
9757
9789
|
modify: never;
|
|
@@ -12808,6 +12840,203 @@ async function handleInboxState(req, res, pathSegments, queryParams) {
|
|
|
12808
12840
|
|
|
12809
12841
|
// src/http/integrations.ts
|
|
12810
12842
|
init_zod();
|
|
12843
|
+
|
|
12844
|
+
// src/integrations/chat-sdk/status.ts
|
|
12845
|
+
init_zod();
|
|
12846
|
+
init_constants();
|
|
12847
|
+
init_env_flag();
|
|
12848
|
+
init_secret_scrubber();
|
|
12849
|
+
|
|
12850
|
+
// src/integrations/chat-sdk/discord-api.ts
|
|
12851
|
+
init_secret_scrubber();
|
|
12852
|
+
var DISCORD_TIMEOUT_MS = 5000;
|
|
12853
|
+
var GUILDS_CACHE_MS = 60000;
|
|
12854
|
+
var MAX_GUILD_NAMES = 10;
|
|
12855
|
+
var cache;
|
|
12856
|
+
async function fetchDiscordGuilds(token, now = Date.now()) {
|
|
12857
|
+
if (cache && cache.token === token && now - cache.at < GUILDS_CACHE_MS)
|
|
12858
|
+
return cache.guilds;
|
|
12859
|
+
let guilds;
|
|
12860
|
+
try {
|
|
12861
|
+
const response = await fetch(`${resolveAdapterApiUrl("discord")}/users/@me/guilds`, {
|
|
12862
|
+
headers: { authorization: `Bot ${token}` },
|
|
12863
|
+
signal: AbortSignal.timeout(DISCORD_TIMEOUT_MS)
|
|
12864
|
+
});
|
|
12865
|
+
if (!response.ok)
|
|
12866
|
+
throw new Error(`HTTP ${response.status}`);
|
|
12867
|
+
const payload = await response.json();
|
|
12868
|
+
if (!Array.isArray(payload))
|
|
12869
|
+
throw new Error("unexpected response shape");
|
|
12870
|
+
const names = payload.map((guild) => guild !== null && typeof guild === "object" && typeof guild.name === "string" ? guild.name : undefined).filter((name) => name !== undefined);
|
|
12871
|
+
guilds = { count: payload.length, names: names.slice(0, MAX_GUILD_NAMES) };
|
|
12872
|
+
} catch (error) {
|
|
12873
|
+
console.warn(scrubSecrets(`[chat-sdk] discord: could not list the bot's servers: ${errorMessage(error).replaceAll(token, "[REDACTED]")}`));
|
|
12874
|
+
}
|
|
12875
|
+
cache = { token, at: now, guilds };
|
|
12876
|
+
return guilds;
|
|
12877
|
+
}
|
|
12878
|
+
|
|
12879
|
+
// src/integrations/chat-sdk/status.ts
|
|
12880
|
+
init_schema();
|
|
12881
|
+
var ChatSdkStatusSchema = exports_external.object({
|
|
12882
|
+
enabled: exports_external.boolean(),
|
|
12883
|
+
slackClash: exports_external.boolean(),
|
|
12884
|
+
error: exports_external.string().optional(),
|
|
12885
|
+
adapters: exports_external.array(exports_external.object({
|
|
12886
|
+
name: exports_external.enum(CHAT_SDK_ADAPTER_NAMES),
|
|
12887
|
+
configured: exports_external.boolean(),
|
|
12888
|
+
enabled: exports_external.boolean(),
|
|
12889
|
+
health: exports_external.enum(["ok", "error", "disabled", "incomplete"]),
|
|
12890
|
+
error: exports_external.string().optional(),
|
|
12891
|
+
webhookUrl: exports_external.string(),
|
|
12892
|
+
mode: exports_external.string().optional(),
|
|
12893
|
+
gateway: exports_external.object({
|
|
12894
|
+
state: exports_external.enum(["running", "backoff", "stopped"]),
|
|
12895
|
+
since: exports_external.string(),
|
|
12896
|
+
restarts: exports_external.number()
|
|
12897
|
+
}).optional(),
|
|
12898
|
+
guilds: exports_external.object({ count: exports_external.number(), names: exports_external.array(exports_external.string()) }).optional()
|
|
12899
|
+
}))
|
|
12900
|
+
});
|
|
12901
|
+
var DEFAULT_MODES = {
|
|
12902
|
+
telegram: "webhook",
|
|
12903
|
+
slack: "webhook"
|
|
12904
|
+
};
|
|
12905
|
+
var NOT_RUNNING = "The adapter is starting, or the last configuration save is still applying. Refresh in a few seconds.";
|
|
12906
|
+
var SLACK_CLASH_CAUSE = "the Slack adapter conflicts with the built-in Slack integration (set SLACK_DISABLE=true)";
|
|
12907
|
+
var MAX_STATUS_ERROR_CHARS = 300;
|
|
12908
|
+
function statusError(message) {
|
|
12909
|
+
return scrubSecrets(message).slice(0, MAX_STATUS_ERROR_CHARS);
|
|
12910
|
+
}
|
|
12911
|
+
function readRawAdapters() {
|
|
12912
|
+
const raw = process.env.CHAT_SDK_ADAPTERS?.trim();
|
|
12913
|
+
if (!raw)
|
|
12914
|
+
return {};
|
|
12915
|
+
try {
|
|
12916
|
+
const parsed = JSON.parse(raw);
|
|
12917
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
12918
|
+
return {};
|
|
12919
|
+
const out = {};
|
|
12920
|
+
for (const name of CHAT_SDK_ADAPTER_NAMES) {
|
|
12921
|
+
const value = parsed[name];
|
|
12922
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
12923
|
+
out[name] = value;
|
|
12924
|
+
}
|
|
12925
|
+
}
|
|
12926
|
+
return out;
|
|
12927
|
+
} catch {
|
|
12928
|
+
return {};
|
|
12929
|
+
}
|
|
12930
|
+
}
|
|
12931
|
+
function chatSdkWebhookUrl(name) {
|
|
12932
|
+
return `${getPublicMcpBaseUrl()}/api/integrations/chat/${name}/webhook`;
|
|
12933
|
+
}
|
|
12934
|
+
async function discordGuildsFor(config, health) {
|
|
12935
|
+
if (health?.status !== "ok" || health.gateway?.state !== "running")
|
|
12936
|
+
return;
|
|
12937
|
+
const raw = config.adapters.discord?.botToken;
|
|
12938
|
+
const token = typeof raw === "function" ? await raw() : raw;
|
|
12939
|
+
if (typeof token !== "string" || token.length === 0)
|
|
12940
|
+
return;
|
|
12941
|
+
return fetchDiscordGuilds(token);
|
|
12942
|
+
}
|
|
12943
|
+
async function getChatSdkStatus() {
|
|
12944
|
+
const config = await getChatSdkConfig();
|
|
12945
|
+
const raw = readRawAdapters();
|
|
12946
|
+
const runtimeHealth = getChatSdkHealth();
|
|
12947
|
+
const slackClash = raw.slack !== undefined && !isEnvFlagEnabled("SLACK_DISABLE", false);
|
|
12948
|
+
const blockedCause = config.error ?? (config.enabled && slackClash ? SLACK_CLASH_CAUSE : undefined);
|
|
12949
|
+
const discordGuilds = await discordGuildsFor(config, runtimeHealth.discord);
|
|
12950
|
+
const adapters = CHAT_SDK_ADAPTER_NAMES.map((name) => {
|
|
12951
|
+
const configured = raw[name] !== undefined;
|
|
12952
|
+
const enabled = isAdapterEntryEnabled(raw[name]);
|
|
12953
|
+
const current = runtimeHealth[name];
|
|
12954
|
+
const incomplete = config.incomplete?.[name];
|
|
12955
|
+
const rawMode = raw[name]?.mode;
|
|
12956
|
+
const mode = typeof rawMode === "string" ? rawMode : configured ? DEFAULT_MODES[name] : undefined;
|
|
12957
|
+
let health = "disabled";
|
|
12958
|
+
let error;
|
|
12959
|
+
if (current) {
|
|
12960
|
+
health = current.status;
|
|
12961
|
+
const showWarning = current.status === "error" || current.gateway?.state === "backoff";
|
|
12962
|
+
error = current.error ?? (showWarning ? current.lastWarning : undefined);
|
|
12963
|
+
} else if (incomplete) {
|
|
12964
|
+
health = "incomplete";
|
|
12965
|
+
error = incomplete;
|
|
12966
|
+
} else if (configured && !enabled) {
|
|
12967
|
+
error = "Turned off on the card. The configuration is kept.";
|
|
12968
|
+
} else if (config.enabled && configured) {
|
|
12969
|
+
error = blockedCause ? `Not started: ${blockedCause}` : NOT_RUNNING;
|
|
12970
|
+
}
|
|
12971
|
+
return {
|
|
12972
|
+
name,
|
|
12973
|
+
configured,
|
|
12974
|
+
enabled,
|
|
12975
|
+
health,
|
|
12976
|
+
...error ? { error: statusError(error) } : {},
|
|
12977
|
+
webhookUrl: chatSdkWebhookUrl(name),
|
|
12978
|
+
...mode ? { mode } : {},
|
|
12979
|
+
...current?.gateway ? { gateway: current.gateway } : {},
|
|
12980
|
+
...name === "discord" && discordGuilds ? { guilds: discordGuilds } : {}
|
|
12981
|
+
};
|
|
12982
|
+
});
|
|
12983
|
+
return {
|
|
12984
|
+
enabled: config.enabled,
|
|
12985
|
+
slackClash,
|
|
12986
|
+
...config.error ? { error: statusError(config.error) } : {},
|
|
12987
|
+
adapters
|
|
12988
|
+
};
|
|
12989
|
+
}
|
|
12990
|
+
|
|
12991
|
+
class ChatSdkActionError extends Error {
|
|
12992
|
+
status;
|
|
12993
|
+
constructor(message, status) {
|
|
12994
|
+
super(message);
|
|
12995
|
+
this.status = status;
|
|
12996
|
+
this.name = "ChatSdkActionError";
|
|
12997
|
+
}
|
|
12998
|
+
}
|
|
12999
|
+
async function callBotApi(baseUrl, token, method, body) {
|
|
13000
|
+
try {
|
|
13001
|
+
return await callTelegramBotApi(baseUrl, token, method, body);
|
|
13002
|
+
} catch (error) {
|
|
13003
|
+
if (error instanceof TelegramBotApiError)
|
|
13004
|
+
throw new ChatSdkActionError(error.message, 502);
|
|
13005
|
+
throw error;
|
|
13006
|
+
}
|
|
13007
|
+
}
|
|
13008
|
+
async function registerTelegramWebhook() {
|
|
13009
|
+
const config = await getChatSdkConfig();
|
|
13010
|
+
if (!config.enabled) {
|
|
13011
|
+
throw new ChatSdkActionError("The Chat SDK channel is disabled (CHAT_SDK_ENABLED is not true). Enable it and restart the API first", 400);
|
|
13012
|
+
}
|
|
13013
|
+
if (config.error)
|
|
13014
|
+
throw new ChatSdkActionError(statusError(config.error), 400);
|
|
13015
|
+
const telegram = config.adapters.telegram;
|
|
13016
|
+
if (!telegram) {
|
|
13017
|
+
throw new ChatSdkActionError("Telegram is not configured in CHAT_SDK_ADAPTERS", 400);
|
|
13018
|
+
}
|
|
13019
|
+
if (telegram.mode !== "webhook") {
|
|
13020
|
+
throw new ChatSdkActionError("Telegram runs in polling mode; a registered webhook would stop polling", 400);
|
|
13021
|
+
}
|
|
13022
|
+
const secretToken = telegram.secretToken;
|
|
13023
|
+
if (typeof secretToken !== "string" || secretToken.length === 0) {
|
|
13024
|
+
throw new ChatSdkActionError("Telegram webhook mode needs a secretToken", 400);
|
|
13025
|
+
}
|
|
13026
|
+
const rawToken = telegram.botToken;
|
|
13027
|
+
const token = typeof rawToken === "function" ? await rawToken() : rawToken;
|
|
13028
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
13029
|
+
throw new ChatSdkActionError("Telegram botToken is empty", 400);
|
|
13030
|
+
}
|
|
13031
|
+
const baseUrl = resolveAdapterApiUrl("telegram");
|
|
13032
|
+
const webhookUrl = chatSdkWebhookUrl("telegram");
|
|
13033
|
+
await callBotApi(baseUrl, token, "setWebhook", { url: webhookUrl, secret_token: secretToken });
|
|
13034
|
+
const info = await callBotApi(baseUrl, token, "getWebhookInfo", {});
|
|
13035
|
+
if (info === null || typeof info !== "object" || typeof info.url !== "string") {
|
|
13036
|
+
throw new ChatSdkActionError("Telegram getWebhookInfo returned an unexpected result", 502);
|
|
13037
|
+
}
|
|
13038
|
+
return { webhookUrl, webhookInfo: info };
|
|
13039
|
+
}
|
|
12811
13040
|
// slack-manifest.json
|
|
12812
13041
|
var slack_manifest_default = {
|
|
12813
13042
|
display_information: {
|
|
@@ -12983,6 +13212,19 @@ var McpUserConfigSchema = exports_external.object({
|
|
|
12983
13212
|
mcpUserUrl: exports_external.string()
|
|
12984
13213
|
});
|
|
12985
13214
|
var SlackManifestSchema = exports_external.record(exports_external.string(), exports_external.unknown());
|
|
13215
|
+
var TelegramRegisterWebhookSchema = exports_external.object({
|
|
13216
|
+
webhookUrl: exports_external.string(),
|
|
13217
|
+
webhookInfo: exports_external.looseObject({
|
|
13218
|
+
url: exports_external.string(),
|
|
13219
|
+
has_custom_certificate: exports_external.boolean().optional(),
|
|
13220
|
+
pending_update_count: exports_external.number().optional(),
|
|
13221
|
+
last_error_date: exports_external.number().optional(),
|
|
13222
|
+
last_error_message: exports_external.string().optional(),
|
|
13223
|
+
max_connections: exports_external.number().optional(),
|
|
13224
|
+
ip_address: exports_external.string().optional(),
|
|
13225
|
+
allowed_updates: exports_external.array(exports_external.string()).optional()
|
|
13226
|
+
})
|
|
13227
|
+
});
|
|
12986
13228
|
var claudeManagedTestRoute = route({
|
|
12987
13229
|
method: "post",
|
|
12988
13230
|
path: "/api/integrations/claude-managed/test",
|
|
@@ -13021,6 +13263,34 @@ var slackManifestRoute = route({
|
|
|
13021
13263
|
200: { description: "Slack app manifest", schema: SlackManifestSchema }
|
|
13022
13264
|
}
|
|
13023
13265
|
});
|
|
13266
|
+
var chatSdkStatusRoute = route({
|
|
13267
|
+
method: "get",
|
|
13268
|
+
path: "/api/integrations/chat/status",
|
|
13269
|
+
pattern: ["api", "integrations", "chat", "status"],
|
|
13270
|
+
summary: "Chat SDK channel status: enabled flag, Slack clash, per-adapter health and webhook URL.",
|
|
13271
|
+
tags: ["Integrations"],
|
|
13272
|
+
responses: {
|
|
13273
|
+
200: {
|
|
13274
|
+
description: "Per-adapter status. `health` is `disabled` for an adapter that is not running. Never contains secret values.",
|
|
13275
|
+
schema: ChatSdkStatusSchema
|
|
13276
|
+
}
|
|
13277
|
+
}
|
|
13278
|
+
});
|
|
13279
|
+
var chatSdkTelegramRegisterWebhookRoute = route({
|
|
13280
|
+
method: "post",
|
|
13281
|
+
path: "/api/integrations/chat/telegram/register-webhook",
|
|
13282
|
+
pattern: ["api", "integrations", "chat", "telegram", "register-webhook"],
|
|
13283
|
+
summary: "Register this swarm's public Telegram webhook URL and secret token with the Bot API (setWebhook), then return getWebhookInfo.",
|
|
13284
|
+
tags: ["Integrations"],
|
|
13285
|
+
body: exports_external.object({}).optional(),
|
|
13286
|
+
responses: {
|
|
13287
|
+
200: { description: "Webhook registered", schema: TelegramRegisterWebhookSchema },
|
|
13288
|
+
400: { description: "Telegram is not configured for webhook mode" },
|
|
13289
|
+
403: { description: "Only the lead agent or a dashboard user can register the webhook" },
|
|
13290
|
+
502: { description: "The Telegram Bot API rejected the call" }
|
|
13291
|
+
},
|
|
13292
|
+
rbac: { permission: "integration.chat.manage" }
|
|
13293
|
+
});
|
|
13024
13294
|
function createIntegrationsHandler(deps = {}) {
|
|
13025
13295
|
const buildClient = deps.buildClient ?? ((apiKey) => new Anthropic({ apiKey }));
|
|
13026
13296
|
return async function handleIntegrations(req, res, pathSegments, queryParams = new URLSearchParams) {
|
|
@@ -13031,6 +13301,26 @@ function createIntegrationsHandler(deps = {}) {
|
|
|
13031
13301
|
slackManifestRoute.respond(res, 200, buildSlackManifest(parsed.query.name));
|
|
13032
13302
|
return true;
|
|
13033
13303
|
}
|
|
13304
|
+
if (chatSdkStatusRoute.match(req.method, pathSegments)) {
|
|
13305
|
+
chatSdkStatusRoute.respond(res, 200, await getChatSdkStatus());
|
|
13306
|
+
return true;
|
|
13307
|
+
}
|
|
13308
|
+
if (chatSdkTelegramRegisterWebhookRoute.match(req.method, pathSegments)) {
|
|
13309
|
+
const parsed = await chatSdkTelegramRegisterWebhookRoute.parse(req, res, pathSegments, queryParams);
|
|
13310
|
+
if (!parsed)
|
|
13311
|
+
return true;
|
|
13312
|
+
if (!await ensureHttpPermission(req, res, "integration.chat.manage", "Registering the Telegram webhook requires the lead agent")) {
|
|
13313
|
+
return true;
|
|
13314
|
+
}
|
|
13315
|
+
try {
|
|
13316
|
+
chatSdkTelegramRegisterWebhookRoute.respond(res, 200, await registerTelegramWebhook());
|
|
13317
|
+
} catch (error) {
|
|
13318
|
+
if (!(error instanceof ChatSdkActionError))
|
|
13319
|
+
throw error;
|
|
13320
|
+
jsonError(res, error.message, error.status);
|
|
13321
|
+
}
|
|
13322
|
+
return true;
|
|
13323
|
+
}
|
|
13034
13324
|
if (mcpUserConfigRoute.match(req.method, pathSegments)) {
|
|
13035
13325
|
const mcpBaseUrl = await resolveMcpBaseUrl();
|
|
13036
13326
|
mcpUserConfigRoute.respond(res, 200, { mcpBaseUrl, mcpUserUrl: `${mcpBaseUrl}/mcp-user` });
|
|
@@ -13662,7 +13952,7 @@ var toRequestError = (e) => {
|
|
|
13662
13952
|
return new RequestError(e.message, { cause: e });
|
|
13663
13953
|
};
|
|
13664
13954
|
var GlobalRequest = global.Request;
|
|
13665
|
-
var
|
|
13955
|
+
var Request2 = class extends GlobalRequest {
|
|
13666
13956
|
constructor(input, options) {
|
|
13667
13957
|
if (typeof input === "object" && getRequestCache in input) {
|
|
13668
13958
|
input = input[getRequestCache]();
|
|
@@ -13693,7 +13983,7 @@ var newRequestFromIncoming = (method, url, headers2, incoming, abortController)
|
|
|
13693
13983
|
};
|
|
13694
13984
|
if (method === "TRACE") {
|
|
13695
13985
|
init.method = "GET";
|
|
13696
|
-
const req = new
|
|
13986
|
+
const req = new Request2(url, init);
|
|
13697
13987
|
Object.defineProperty(req, "method", {
|
|
13698
13988
|
get() {
|
|
13699
13989
|
return "TRACE";
|
|
@@ -13730,7 +14020,7 @@ var newRequestFromIncoming = (method, url, headers2, incoming, abortController)
|
|
|
13730
14020
|
init.body = Readable.toWeb(incoming);
|
|
13731
14021
|
}
|
|
13732
14022
|
}
|
|
13733
|
-
return new
|
|
14023
|
+
return new Request2(url, init);
|
|
13734
14024
|
};
|
|
13735
14025
|
var getRequestCache = Symbol("getRequestCache");
|
|
13736
14026
|
var requestCache = Symbol("requestCache");
|
|
@@ -13796,7 +14086,7 @@ Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom")
|
|
|
13796
14086
|
return `Request (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
|
|
13797
14087
|
}
|
|
13798
14088
|
});
|
|
13799
|
-
Object.setPrototypeOf(requestPrototype,
|
|
14089
|
+
Object.setPrototypeOf(requestPrototype, Request2.prototype);
|
|
13800
14090
|
var newRequest = (incoming, defaultHostname) => {
|
|
13801
14091
|
const req = Object.create(requestPrototype);
|
|
13802
14092
|
req[incomingKey] = incoming;
|
|
@@ -13865,12 +14155,12 @@ var Response2 = class _Response {
|
|
|
13865
14155
|
}
|
|
13866
14156
|
}
|
|
13867
14157
|
get headers() {
|
|
13868
|
-
const
|
|
13869
|
-
if (
|
|
13870
|
-
if (!(
|
|
13871
|
-
|
|
14158
|
+
const cache2 = this[cacheKey];
|
|
14159
|
+
if (cache2) {
|
|
14160
|
+
if (!(cache2[2] instanceof Headers)) {
|
|
14161
|
+
cache2[2] = new Headers(cache2[2] || { "content-type": "text/plain; charset=UTF-8" });
|
|
13872
14162
|
}
|
|
13873
|
-
return
|
|
14163
|
+
return cache2[2];
|
|
13874
14164
|
}
|
|
13875
14165
|
return this[getResponseCache]().headers;
|
|
13876
14166
|
}
|
|
@@ -14158,9 +14448,9 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
14158
14448
|
};
|
|
14159
14449
|
var getRequestListener = (fetchCallback, options = {}) => {
|
|
14160
14450
|
const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
|
|
14161
|
-
if (options.overrideGlobalObjects !== false && global.Request !==
|
|
14451
|
+
if (options.overrideGlobalObjects !== false && global.Request !== Request2) {
|
|
14162
14452
|
Object.defineProperty(global, "Request", {
|
|
14163
|
-
value:
|
|
14453
|
+
value: Request2
|
|
14164
14454
|
});
|
|
14165
14455
|
Object.defineProperty(global, "Response", {
|
|
14166
14456
|
value: Response2
|
|
@@ -15200,13 +15490,14 @@ async function handleMcp(req, res, transports, sessionActivity = {}, sessionAgen
|
|
|
15200
15490
|
const configValue = configs.find((config) => config.key === "SCRIPTS_ONLY_MCP")?.value;
|
|
15201
15491
|
const preloadEnabled = parseEnvFlag(configs.find((config) => config.key === "TASK_TOOL_PRELOAD_ENABLED")?.value ?? process.env.TASK_TOOL_PRELOAD_ENABLED, true);
|
|
15202
15492
|
let preloadedTools = [];
|
|
15493
|
+
const sourceTaskId = headerValue(req.headers["x-source-task-id"]);
|
|
15494
|
+
const sourceTask = sourceTaskId ? await getTaskById(sourceTaskId) : undefined;
|
|
15495
|
+
const excludedTools = sourceTask && !isChatSdkTask(sourceTask) ? [...CHAT_TASK_ONLY_TOOLS] : [];
|
|
15203
15496
|
if (preloadEnabled) {
|
|
15204
|
-
|
|
15205
|
-
const task = taskId ? await getTaskById(taskId) : undefined;
|
|
15206
|
-
if (task?.agentId === agentId) {
|
|
15497
|
+
if (sourceTask?.agentId === agentId) {
|
|
15207
15498
|
const manifestValue = configs.find((config) => config.key === "TASK_TOOL_MANIFESTS")?.value ?? process.env.TASK_TOOL_MANIFESTS ?? "{}";
|
|
15208
15499
|
try {
|
|
15209
|
-
preloadedTools = selectTaskTools(parseTaskToolManifest(manifestValue),
|
|
15500
|
+
preloadedTools = selectTaskTools(parseTaskToolManifest(manifestValue), sourceTask);
|
|
15210
15501
|
} catch {
|
|
15211
15502
|
console.warn("[MCP] Invalid TASK_TOOL_MANIFESTS; using ordinary tool discovery");
|
|
15212
15503
|
}
|
|
@@ -15214,6 +15505,7 @@ async function handleMcp(req, res, transports, sessionActivity = {}, sessionAgen
|
|
|
15214
15505
|
}
|
|
15215
15506
|
const server = await createServer({
|
|
15216
15507
|
preloadedTools,
|
|
15508
|
+
excludedTools,
|
|
15217
15509
|
enabledTools: configs.find((config) => config.key === "SWARM_ENABLED_TOOLS")?.value ?? process.env.SWARM_ENABLED_TOOLS,
|
|
15218
15510
|
scriptsOnly: resolveScriptsOnlyMode({
|
|
15219
15511
|
env: process.env.SCRIPTS_ONLY_MCP,
|
|
@@ -20504,9 +20796,47 @@ init_db3();
|
|
|
20504
20796
|
init_steering();
|
|
20505
20797
|
init_users();
|
|
20506
20798
|
init_rbac();
|
|
20799
|
+
init_context_key();
|
|
20507
20800
|
init_types();
|
|
20508
20801
|
init_request_auth_context();
|
|
20509
20802
|
init_secret_scrubber();
|
|
20803
|
+
|
|
20804
|
+
// src/http/requested-by.ts
|
|
20805
|
+
init_zod();
|
|
20806
|
+
init_db3();
|
|
20807
|
+
init_types();
|
|
20808
|
+
var TaskRequestedBySchema = UserSchema.pick({
|
|
20809
|
+
id: true,
|
|
20810
|
+
name: true,
|
|
20811
|
+
email: true,
|
|
20812
|
+
role: true,
|
|
20813
|
+
notes: true
|
|
20814
|
+
}).extend({
|
|
20815
|
+
id: exports_external.string().optional(),
|
|
20816
|
+
comms: UserCommsPrefsSchema.optional()
|
|
20817
|
+
});
|
|
20818
|
+
function getRequesterNotes(notes) {
|
|
20819
|
+
return typeof notes === "string" && notes.trim().length > 0 ? notes : undefined;
|
|
20820
|
+
}
|
|
20821
|
+
async function buildTaskRequestedBy(task) {
|
|
20822
|
+
const user = task.requestedByUserId ? await getUserById(task.requestedByUserId) : undefined;
|
|
20823
|
+
if (user) {
|
|
20824
|
+
return {
|
|
20825
|
+
id: user.id,
|
|
20826
|
+
name: user.name,
|
|
20827
|
+
email: user.email,
|
|
20828
|
+
role: user.role,
|
|
20829
|
+
notes: getRequesterNotes(user.notes),
|
|
20830
|
+
comms: getUserCommsPrefs(user)
|
|
20831
|
+
};
|
|
20832
|
+
}
|
|
20833
|
+
if (task.slackUserId) {
|
|
20834
|
+
return { name: renderIdentity(await resolveIdentity("slack", task.slackUserId)) };
|
|
20835
|
+
}
|
|
20836
|
+
return;
|
|
20837
|
+
}
|
|
20838
|
+
|
|
20839
|
+
// src/http/tasks.ts
|
|
20510
20840
|
var AgentTaskSummarySchema = AgentTaskSchema.pick({
|
|
20511
20841
|
id: true,
|
|
20512
20842
|
key: true,
|
|
@@ -20530,6 +20860,7 @@ var AgentTaskSummarySchema = AgentTaskSchema.pick({
|
|
|
20530
20860
|
modelSource: true,
|
|
20531
20861
|
modelAlias: true,
|
|
20532
20862
|
effort: true,
|
|
20863
|
+
resolvedEffort: true,
|
|
20533
20864
|
provider: true,
|
|
20534
20865
|
requestedByUserId: true,
|
|
20535
20866
|
progress: true,
|
|
@@ -20673,6 +21004,9 @@ var createTask = route({
|
|
|
20673
21004
|
400: {
|
|
20674
21005
|
description: "Validation error, an unknown `model` (set `allowCustomModel` to store a custom id), or agentId/offeredTo targets an extension identity"
|
|
20675
21006
|
},
|
|
21007
|
+
403: {
|
|
21008
|
+
description: "An agent caller names a parentTaskId it neither owns nor created, or a non-lead agent binds the task to a chat thread"
|
|
21009
|
+
},
|
|
20676
21010
|
422: {
|
|
20677
21011
|
description: "Task creation blocked by an extension",
|
|
20678
21012
|
schema: exports_external.object({
|
|
@@ -20719,6 +21053,7 @@ var updateSession = route({
|
|
|
20719
21053
|
claudeSessionId: exports_external.string().min(1),
|
|
20720
21054
|
provider: ProviderNameSchema.exclude(["devin"]).optional(),
|
|
20721
21055
|
model: exports_external.string().optional(),
|
|
21056
|
+
effort: ReasoningEffortSchema.nullable().optional(),
|
|
20722
21057
|
providerMeta: exports_external.object({ transport: exports_external.enum(["cli", "sdk"]).optional() }).optional(),
|
|
20723
21058
|
harnessVariant: exports_external.string().optional(),
|
|
20724
21059
|
harnessVariantMeta: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
@@ -20933,7 +21268,10 @@ var listPausedTasks = route({
|
|
|
20933
21268
|
200: {
|
|
20934
21269
|
description: "Paused task list",
|
|
20935
21270
|
schema: exports_external.object({
|
|
20936
|
-
tasks: exports_external.array(AgentTaskSchema.extend({
|
|
21271
|
+
tasks: exports_external.array(AgentTaskSchema.extend({
|
|
21272
|
+
attachments: exports_external.array(TaskAttachmentSchema),
|
|
21273
|
+
requestedBy: TaskRequestedBySchema.optional()
|
|
21274
|
+
}))
|
|
20937
21275
|
})
|
|
20938
21276
|
}
|
|
20939
21277
|
}
|
|
@@ -21193,6 +21531,26 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
21193
21531
|
return true;
|
|
21194
21532
|
}
|
|
21195
21533
|
const parentTask = parsed.body.parentTaskId ? await getTaskById(parsed.body.parentTaskId) : null;
|
|
21534
|
+
const principal = await resolveTaskWritePrincipal(req, myAgentId);
|
|
21535
|
+
if (parentTask && !can({
|
|
21536
|
+
principal,
|
|
21537
|
+
verb: "task.parent.attach",
|
|
21538
|
+
resource: {
|
|
21539
|
+
kind: "task",
|
|
21540
|
+
taskId: parentTask.id,
|
|
21541
|
+
requestedByUserId: parentTask.requestedByUserId,
|
|
21542
|
+
creatorAgentId: parentTask.creatorAgentId,
|
|
21543
|
+
agentId: parentTask.agentId
|
|
21544
|
+
},
|
|
21545
|
+
source: "http"
|
|
21546
|
+
}).allow) {
|
|
21547
|
+
jsonError(res, `You don't have context for parent task ${parentTask.id}.`, 403);
|
|
21548
|
+
return true;
|
|
21549
|
+
}
|
|
21550
|
+
if (principal.kind === "agent" && parsed.body.contextKey && parsed.body.contextKey !== parentTask?.contextKey && chatThreadOfContextKey(parsed.body.contextKey) && !can({ principal, verb: "integration.chat.post", resource: { kind: "none" }, source: "http" }).allow) {
|
|
21551
|
+
jsonError(res, "Permission denied: only a lead can bind a task to a chat thread.", 403);
|
|
21552
|
+
return true;
|
|
21553
|
+
}
|
|
21196
21554
|
let assetKey;
|
|
21197
21555
|
try {
|
|
21198
21556
|
const inheritedKey = parentTask?.key;
|
|
@@ -21287,7 +21645,7 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
21287
21645
|
const parsed = await updateSession.parse(req, res, pathSegments, queryParams);
|
|
21288
21646
|
if (!parsed)
|
|
21289
21647
|
return true;
|
|
21290
|
-
const task = await updateTaskClaudeSessionId(parsed.params.id, parsed.body.claudeSessionId, parsed.body.provider, parsed.body.providerMeta, parsed.body.model, "harnessVariant" in parsed.body ? parsed.body.harnessVariant : undefined, "harnessVariantMeta" in parsed.body ? parsed.body.harnessVariantMeta : undefined);
|
|
21648
|
+
const task = await updateTaskClaudeSessionId(parsed.params.id, parsed.body.claudeSessionId, parsed.body.provider, parsed.body.providerMeta, parsed.body.model, "harnessVariant" in parsed.body ? parsed.body.harnessVariant : undefined, "harnessVariantMeta" in parsed.body ? parsed.body.harnessVariantMeta : undefined, "effort" in parsed.body ? parsed.body.effort : undefined);
|
|
21291
21649
|
if (!task) {
|
|
21292
21650
|
jsonError(res, "Task not found", 404);
|
|
21293
21651
|
return true;
|
|
@@ -21727,10 +22085,14 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
21727
22085
|
return true;
|
|
21728
22086
|
}
|
|
21729
22087
|
const pausedTasks = await getPausedTasksForAgent(myAgentId);
|
|
21730
|
-
const tasks = await Promise.all(pausedTasks.map(async (task) =>
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
22088
|
+
const tasks = await Promise.all(pausedTasks.map(async (task) => {
|
|
22089
|
+
const requestedBy = await buildTaskRequestedBy(task);
|
|
22090
|
+
return {
|
|
22091
|
+
...task,
|
|
22092
|
+
attachments: await getTaskAttachments(task.id),
|
|
22093
|
+
...requestedBy && { requestedBy }
|
|
22094
|
+
};
|
|
22095
|
+
}));
|
|
21734
22096
|
listPausedTasks.respond(res, 200, { tasks });
|
|
21735
22097
|
return true;
|
|
21736
22098
|
}
|
|
@@ -22236,10 +22598,6 @@ function withShareUrls(page) {
|
|
|
22236
22598
|
app_url: `${getAppBaseUrl()}/pages/${page.slug}`
|
|
22237
22599
|
};
|
|
22238
22600
|
}
|
|
22239
|
-
async function pageEditCounter(pageId) {
|
|
22240
|
-
const versions = await getPageVersions(pageId);
|
|
22241
|
-
return versions.length > 0 ? versions[0].version + 1 : 1;
|
|
22242
|
-
}
|
|
22243
22601
|
function defuseFeedbackTags(value) {
|
|
22244
22602
|
return value.replace(/<(\/?page_feedback)/gi, "‹$1");
|
|
22245
22603
|
}
|
|
@@ -22513,7 +22871,7 @@ async function handlePages(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
22513
22871
|
updatePageRoute.respond(res, 200, {
|
|
22514
22872
|
id: updated.id,
|
|
22515
22873
|
key: updated.key,
|
|
22516
|
-
version: await
|
|
22874
|
+
version: await getPageEditCounter(updated.id)
|
|
22517
22875
|
});
|
|
22518
22876
|
return true;
|
|
22519
22877
|
}
|
|
@@ -22635,8 +22993,819 @@ ${defuseFeedbackTags(note)}
|
|
|
22635
22993
|
|
|
22636
22994
|
// src/http/pages-public.ts
|
|
22637
22995
|
init_zod();
|
|
22996
|
+
init_db3();
|
|
22997
|
+
|
|
22998
|
+
// src/pages/browser-sdk.ts
|
|
22999
|
+
var BROWSER_SDK_JS = `
|
|
23000
|
+
class SwarmSDK {
|
|
23001
|
+
constructor() {
|
|
23002
|
+
let realtime;
|
|
23003
|
+
const loadRealtime = () => realtime || (realtime = import('/@swarm/realtime.js'));
|
|
23004
|
+
this.room = async (name, options) => (await loadRealtime()).room(name, options);
|
|
23005
|
+
this.channel = async (name) => (await loadRealtime()).channel(name);
|
|
23006
|
+
|
|
23007
|
+
const base = '/@swarm/api';
|
|
23008
|
+
const call = async (method, path, body) => {
|
|
23009
|
+
const init = { method };
|
|
23010
|
+
if (body !== undefined) {
|
|
23011
|
+
init.headers = { 'Content-Type': 'application/json' };
|
|
23012
|
+
init.body = JSON.stringify(body);
|
|
23013
|
+
}
|
|
23014
|
+
const res = await fetch(base + path, init);
|
|
23015
|
+
const text = await res.text();
|
|
23016
|
+
let parsed = null;
|
|
23017
|
+
if (text) {
|
|
23018
|
+
try { parsed = JSON.parse(text); } catch { parsed = text; }
|
|
23019
|
+
}
|
|
23020
|
+
if (!res.ok) {
|
|
23021
|
+
const err = new Error('SwarmSDK ' + method + ' ' + path + ': ' + res.status);
|
|
23022
|
+
err.status = res.status;
|
|
23023
|
+
err.response = parsed;
|
|
23024
|
+
throw err;
|
|
23025
|
+
}
|
|
23026
|
+
return parsed;
|
|
23027
|
+
};
|
|
23028
|
+
const qs = (obj) => {
|
|
23029
|
+
if (!obj) return '';
|
|
23030
|
+
const p = new URLSearchParams();
|
|
23031
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
23032
|
+
if (v === undefined || v === null) continue;
|
|
23033
|
+
p.set(k, String(v));
|
|
23034
|
+
}
|
|
23035
|
+
const s = p.toString();
|
|
23036
|
+
return s ? '?' + s : '';
|
|
23037
|
+
};
|
|
23038
|
+
const enc = encodeURIComponent;
|
|
23039
|
+
|
|
23040
|
+
this.tasks = {
|
|
23041
|
+
create: (body) => call('POST', '/tasks', body),
|
|
23042
|
+
list: (filters) => call('GET', '/tasks' + qs(filters)),
|
|
23043
|
+
get: (id) => call('GET', '/tasks/' + enc(id)),
|
|
23044
|
+
storeProgress: (id, data) => call('POST', '/tasks/' + enc(id) + '/progress', data),
|
|
23045
|
+
};
|
|
23046
|
+
|
|
23047
|
+
this.agents = {
|
|
23048
|
+
list: () => call('GET', '/agents'),
|
|
23049
|
+
get: (id) => call('GET', '/agents/' + enc(id)),
|
|
23050
|
+
};
|
|
23051
|
+
|
|
23052
|
+
this.events = {
|
|
23053
|
+
create: (body) => call('POST', '/events', body),
|
|
23054
|
+
list: (filters) => call('GET', '/events' + qs(filters)),
|
|
23055
|
+
batch: (body) => call('POST', '/events/batch', body),
|
|
23056
|
+
counts: (filters) => call('GET', '/events/counts' + qs(filters)),
|
|
23057
|
+
};
|
|
22638
23058
|
|
|
22639
|
-
|
|
23059
|
+
this.memory = {
|
|
23060
|
+
search: (body) => call('POST', '/memory/search', body),
|
|
23061
|
+
list: (filters) => call('GET', '/memory/list' + qs(filters)),
|
|
23062
|
+
get: (id) => call('GET', '/memory/' + enc(id)),
|
|
23063
|
+
rate: (body) => call('POST', '/memory/rate', body),
|
|
23064
|
+
};
|
|
23065
|
+
|
|
23066
|
+
this.repos = {
|
|
23067
|
+
list: () => call('GET', '/repos'),
|
|
23068
|
+
get: (id) => call('GET', '/repos/' + enc(id)),
|
|
23069
|
+
create: (body) => call('POST', '/repos', body),
|
|
23070
|
+
update: (id, body) => call('PUT', '/repos/' + enc(id), body),
|
|
23071
|
+
delete: (id) => call('DELETE', '/repos/' + enc(id)),
|
|
23072
|
+
};
|
|
23073
|
+
|
|
23074
|
+
this.schedules = {
|
|
23075
|
+
list: () => call('GET', '/schedules'),
|
|
23076
|
+
get: (id) => call('GET', '/schedules/' + enc(id)),
|
|
23077
|
+
create: (body) => call('POST', '/schedules', body),
|
|
23078
|
+
update: (id, body) => call('PUT', '/schedules/' + enc(id), body),
|
|
23079
|
+
delete: (id) => call('DELETE', '/schedules/' + enc(id)),
|
|
23080
|
+
run: (id) => call('POST', '/schedules/' + enc(id) + '/run'),
|
|
23081
|
+
};
|
|
23082
|
+
|
|
23083
|
+
this.approvalRequests = {
|
|
23084
|
+
list: (filters) => call('GET', '/approval-requests' + qs(filters)),
|
|
23085
|
+
get: (id) => call('GET', '/approval-requests/' + enc(id)),
|
|
23086
|
+
create: (body) => call('POST', '/approval-requests', body),
|
|
23087
|
+
respond: (id, body) => call('POST', '/approval-requests/' + enc(id) + '/respond', body),
|
|
23088
|
+
};
|
|
23089
|
+
|
|
23090
|
+
this.assets = {
|
|
23091
|
+
list: (filters) => call('GET', '/assets' + qs(filters)),
|
|
23092
|
+
audit: () => call('GET', '/assets/key-audit'),
|
|
23093
|
+
registerMapping: (body) => call('POST', '/assets/mappings', body),
|
|
23094
|
+
move: (entityType, id, key) => call(
|
|
23095
|
+
'PATCH',
|
|
23096
|
+
'/assets/' + enc(entityType) + '/' + enc(id) + '/key',
|
|
23097
|
+
{ key },
|
|
23098
|
+
),
|
|
23099
|
+
};
|
|
23100
|
+
|
|
23101
|
+
// KV store. The namespace is FORCED by the page-proxy to \`task:page:<id>\`
|
|
23102
|
+
// (it injects X-Page-Id which the kv handler treats as highest priority).
|
|
23103
|
+
// No namespace argument is exposed — pages cannot read/write any other
|
|
23104
|
+
// namespace via this SDK.
|
|
23105
|
+
this.kv = {
|
|
23106
|
+
get: (key) => call('GET', '/kv/' + enc(key)),
|
|
23107
|
+
set: (key, value, opts) => call('PUT', '/kv/' + enc(key), {
|
|
23108
|
+
value,
|
|
23109
|
+
valueType: opts && opts.valueType,
|
|
23110
|
+
expiresInSec: opts && opts.expiresInSec,
|
|
23111
|
+
}),
|
|
23112
|
+
del: (key) => call('DELETE', '/kv/' + enc(key)),
|
|
23113
|
+
incr: (key, by) => call('POST', '/kv/' + enc(key) + '/incr', { by: by == null ? 1 : by }),
|
|
23114
|
+
list: (opts) => call('GET', '/kv' + qs(opts)),
|
|
23115
|
+
};
|
|
23116
|
+
}
|
|
23117
|
+
}
|
|
23118
|
+
|
|
23119
|
+
// Expose BOTH the class (for \`new SwarmSDK()\`) AND a ready-to-use singleton
|
|
23120
|
+
// on \`window.swarmSdk\` so pages can call e.g. \`window.swarmSdk.agents.list()\`
|
|
23121
|
+
// directly without instantiating.
|
|
23122
|
+
window.SwarmSDK = SwarmSDK;
|
|
23123
|
+
window.swarmSdk = new SwarmSDK();
|
|
23124
|
+
`;
|
|
23125
|
+
var SWARM_UI_JS = `
|
|
23126
|
+
(function() {
|
|
23127
|
+
if (typeof window === 'undefined' || !window.customElements) return;
|
|
23128
|
+
if (window.customElements.get('swarm-diff')) return;
|
|
23129
|
+
|
|
23130
|
+
// Keep page-owned presence fields alongside the cursor. Room.presence.set
|
|
23131
|
+
// replaces its payload, so retain each room's latest page data and merge
|
|
23132
|
+
// the reserved __cursor field into it when the cursor moves.
|
|
23133
|
+
var roomPresenceTrackers = new WeakMap();
|
|
23134
|
+
|
|
23135
|
+
function clonePresenceRecord(data) {
|
|
23136
|
+
return data && typeof data === 'object' && !Array.isArray(data)
|
|
23137
|
+
? structuredClone(data)
|
|
23138
|
+
: {};
|
|
23139
|
+
}
|
|
23140
|
+
|
|
23141
|
+
function mergeCursorPresence(data, cursor) {
|
|
23142
|
+
var merged = clonePresenceRecord(data);
|
|
23143
|
+
if (cursor) merged.__cursor = { x: cursor.x, y: cursor.y };
|
|
23144
|
+
else delete merged.__cursor;
|
|
23145
|
+
return merged;
|
|
23146
|
+
}
|
|
23147
|
+
|
|
23148
|
+
function trackRoomPresence(room) {
|
|
23149
|
+
if (!room || !room.presence || typeof room.presence.set !== 'function') return null;
|
|
23150
|
+
var existing = roomPresenceTrackers.get(room);
|
|
23151
|
+
if (existing) return existing;
|
|
23152
|
+
|
|
23153
|
+
var presence = room.presence;
|
|
23154
|
+
var originalSet = presence.set;
|
|
23155
|
+
var pageData = {};
|
|
23156
|
+
var cursor = null;
|
|
23157
|
+
var tracker = {
|
|
23158
|
+
setCursor: function(nextCursor) {
|
|
23159
|
+
cursor = nextCursor;
|
|
23160
|
+
return originalSet.call(presence, mergeCursorPresence(pageData, cursor));
|
|
23161
|
+
},
|
|
23162
|
+
clearCursor: function() {
|
|
23163
|
+
if (!cursor) return;
|
|
23164
|
+
return tracker.setCursor(null);
|
|
23165
|
+
},
|
|
23166
|
+
};
|
|
23167
|
+
|
|
23168
|
+
presence.set = function(data) {
|
|
23169
|
+
pageData = clonePresenceRecord(data);
|
|
23170
|
+
return originalSet.call(presence, cursor ? mergeCursorPresence(pageData, cursor) : data);
|
|
23171
|
+
};
|
|
23172
|
+
roomPresenceTrackers.set(room, tracker);
|
|
23173
|
+
return tracker;
|
|
23174
|
+
}
|
|
23175
|
+
|
|
23176
|
+
// Wrap room creation before page scripts run so presence.set calls made by
|
|
23177
|
+
// page code are tracked even when they happen before <swarm-cursors> connects.
|
|
23178
|
+
var cursorRoomRecords = new Map();
|
|
23179
|
+
var sdkRoomMethods = new WeakMap();
|
|
23180
|
+
var observedRoomClosers = new WeakSet();
|
|
23181
|
+
var originalRoom = null;
|
|
23182
|
+
function roomRecordKey(name) {
|
|
23183
|
+
return name === undefined ? 'default' : name;
|
|
23184
|
+
}
|
|
23185
|
+
|
|
23186
|
+
function observeRoom(record, room) {
|
|
23187
|
+
record.hasResolvedRoom = true;
|
|
23188
|
+
if (!cursorRoomRecords.has(record.name)) cursorRoomRecords.set(record.name, record);
|
|
23189
|
+
trackRoomPresence(room);
|
|
23190
|
+
if (room && typeof room.close === 'function' && !observedRoomClosers.has(room)) {
|
|
23191
|
+
var originalClose = room.close;
|
|
23192
|
+
room.close = function() {
|
|
23193
|
+
if (cursorRoomRecords.get(record.name) === record) cursorRoomRecords.delete(record.name);
|
|
23194
|
+
return originalClose.apply(room, arguments);
|
|
23195
|
+
};
|
|
23196
|
+
observedRoomClosers.add(room);
|
|
23197
|
+
}
|
|
23198
|
+
return room;
|
|
23199
|
+
}
|
|
23200
|
+
|
|
23201
|
+
function observeRoomPromise(record, result) {
|
|
23202
|
+
var observed = Promise.resolve(result).then(function(room) {
|
|
23203
|
+
var resolvedRoom = observeRoom(record, room);
|
|
23204
|
+
record.pageRequests--;
|
|
23205
|
+
record.hasPageUse = true;
|
|
23206
|
+
record.pageUsed = true;
|
|
23207
|
+
record.promise = Promise.resolve(resolvedRoom);
|
|
23208
|
+
return resolvedRoom;
|
|
23209
|
+
}).catch(function(error) {
|
|
23210
|
+
record.pageRequests--;
|
|
23211
|
+
record.pageUsed = record.hasPageUse || record.pageRequests > 0;
|
|
23212
|
+
if (!record.hasResolvedRoom
|
|
23213
|
+
&& record.pageRequests === 0
|
|
23214
|
+
&& cursorRoomRecords.get(record.name) === record)
|
|
23215
|
+
cursorRoomRecords.delete(record.name);
|
|
23216
|
+
if (record.cursorRefs === 0 && record.openedByCursor && !record.pageUsed)
|
|
23217
|
+
closeCursorRoomIfUnused(record);
|
|
23218
|
+
throw error;
|
|
23219
|
+
});
|
|
23220
|
+
record.pageRequests++;
|
|
23221
|
+
record.pageUsed = true;
|
|
23222
|
+
if (!record.promise) record.promise = observed;
|
|
23223
|
+
return observed;
|
|
23224
|
+
}
|
|
23225
|
+
|
|
23226
|
+
function closeCursorRoomIfUnused(record) {
|
|
23227
|
+
if (record.closing || record.cursorRefs || !record.openedByCursor || record.pageUsed) return;
|
|
23228
|
+
record.closing = true;
|
|
23229
|
+
record.promise.then(function(room) {
|
|
23230
|
+
if (record.cursorRefs || record.pageUsed) {
|
|
23231
|
+
record.closing = false;
|
|
23232
|
+
return;
|
|
23233
|
+
}
|
|
23234
|
+
if (cursorRoomRecords.get(record.name) === record) cursorRoomRecords.delete(record.name);
|
|
23235
|
+
if (room && typeof room.close === 'function') return room.close();
|
|
23236
|
+
}).catch(function() {
|
|
23237
|
+
record.closing = false;
|
|
23238
|
+
});
|
|
23239
|
+
}
|
|
23240
|
+
|
|
23241
|
+
function instrumentSdk(sdk) {
|
|
23242
|
+
if (!sdk || typeof sdk.room !== 'function') return null;
|
|
23243
|
+
var existing = sdkRoomMethods.get(sdk);
|
|
23244
|
+
if (existing) return existing;
|
|
23245
|
+
|
|
23246
|
+
var sdkOriginalRoom = sdk.room;
|
|
23247
|
+
var wrappedRoom = function(name, options) {
|
|
23248
|
+
var key = roomRecordKey(name);
|
|
23249
|
+
var record = cursorRoomRecords.get(key);
|
|
23250
|
+
var result = sdkOriginalRoom.call(sdk, name, options);
|
|
23251
|
+
if (!record) {
|
|
23252
|
+
record = {
|
|
23253
|
+
name: key,
|
|
23254
|
+
cursorRefs: 0,
|
|
23255
|
+
openedByCursor: false,
|
|
23256
|
+
pageUsed: false,
|
|
23257
|
+
hasPageUse: false,
|
|
23258
|
+
pageRequests: 0,
|
|
23259
|
+
hasResolvedRoom: false,
|
|
23260
|
+
promise: null,
|
|
23261
|
+
};
|
|
23262
|
+
cursorRoomRecords.set(key, record);
|
|
23263
|
+
}
|
|
23264
|
+
return observeRoomPromise(record, result);
|
|
23265
|
+
};
|
|
23266
|
+
sdk.room = wrappedRoom;
|
|
23267
|
+
var methods = { original: sdkOriginalRoom, wrapped: wrappedRoom };
|
|
23268
|
+
sdkRoomMethods.set(sdk, methods);
|
|
23269
|
+
return methods;
|
|
23270
|
+
}
|
|
23271
|
+
|
|
23272
|
+
if (window.swarmSdk) {
|
|
23273
|
+
var singletonRoomMethods = instrumentSdk(window.swarmSdk);
|
|
23274
|
+
originalRoom = singletonRoomMethods && singletonRoomMethods.original;
|
|
23275
|
+
}
|
|
23276
|
+
if (typeof window.SwarmSDK === 'function') {
|
|
23277
|
+
var OriginalSwarmSDK = window.SwarmSDK;
|
|
23278
|
+
window.SwarmSDK = new Proxy(OriginalSwarmSDK, {
|
|
23279
|
+
construct: function(target, args, newTarget) {
|
|
23280
|
+
var sdk = Reflect.construct(target, args, newTarget);
|
|
23281
|
+
instrumentSdk(sdk);
|
|
23282
|
+
return sdk;
|
|
23283
|
+
},
|
|
23284
|
+
});
|
|
23285
|
+
}
|
|
23286
|
+
|
|
23287
|
+
function acquireCursorRoom(name, options) {
|
|
23288
|
+
var key = roomRecordKey(name);
|
|
23289
|
+
var record = cursorRoomRecords.get(key);
|
|
23290
|
+
if (record) {
|
|
23291
|
+
record.cursorRefs++;
|
|
23292
|
+
return { record: record, promise: record.promise };
|
|
23293
|
+
}
|
|
23294
|
+
|
|
23295
|
+
record = {
|
|
23296
|
+
name: key,
|
|
23297
|
+
cursorRefs: 1,
|
|
23298
|
+
openedByCursor: true,
|
|
23299
|
+
pageUsed: false,
|
|
23300
|
+
hasPageUse: false,
|
|
23301
|
+
pageRequests: 0,
|
|
23302
|
+
hasResolvedRoom: false,
|
|
23303
|
+
closing: false,
|
|
23304
|
+
promise: null,
|
|
23305
|
+
};
|
|
23306
|
+
cursorRoomRecords.set(key, record);
|
|
23307
|
+
record.promise = Promise.resolve().then(function() {
|
|
23308
|
+
return originalRoom(name, options);
|
|
23309
|
+
}).then(function(room) {
|
|
23310
|
+
return observeRoom(record, room);
|
|
23311
|
+
}).catch(function(error) {
|
|
23312
|
+
if (cursorRoomRecords.get(key) === record) cursorRoomRecords.delete(key);
|
|
23313
|
+
throw error;
|
|
23314
|
+
});
|
|
23315
|
+
return { record: record, promise: record.promise };
|
|
23316
|
+
}
|
|
23317
|
+
|
|
23318
|
+
function releaseCursorRoom(record, presence) {
|
|
23319
|
+
if (!record || record.cursorRefs < 1) return;
|
|
23320
|
+
if (record.cursorRefs === 1 && presence) presence.clearCursor();
|
|
23321
|
+
record.cursorRefs--;
|
|
23322
|
+
closeCursorRoomIfUnused(record);
|
|
23323
|
+
}
|
|
23324
|
+
|
|
23325
|
+
var SEV_COLOR = {
|
|
23326
|
+
error: '#ef4444',
|
|
23327
|
+
warn: '#f59e0b',
|
|
23328
|
+
info: '#3b82f6',
|
|
23329
|
+
};
|
|
23330
|
+
|
|
23331
|
+
function esc(s) {
|
|
23332
|
+
return String(s == null ? '' : s)
|
|
23333
|
+
.replace(/&/g, '&')
|
|
23334
|
+
.replace(/</g, '<')
|
|
23335
|
+
.replace(/>/g, '>')
|
|
23336
|
+
.replace(/"/g, '"')
|
|
23337
|
+
.replace(/'/g, ''');
|
|
23338
|
+
}
|
|
23339
|
+
|
|
23340
|
+
function slugifyAttr(s) {
|
|
23341
|
+
return String(s || '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
|
|
23342
|
+
}
|
|
23343
|
+
|
|
23344
|
+
function parseHunks(jsonText) {
|
|
23345
|
+
var trimmed = (jsonText || '').trim();
|
|
23346
|
+
if (!trimmed) return [];
|
|
23347
|
+
try {
|
|
23348
|
+
var parsed = JSON.parse(trimmed);
|
|
23349
|
+
if (parsed && Array.isArray(parsed.hunks)) return parsed.hunks;
|
|
23350
|
+
if (Array.isArray(parsed)) return parsed;
|
|
23351
|
+
return [];
|
|
23352
|
+
} catch (e) {
|
|
23353
|
+
console.warn('[swarm-diff] failed to parse JSON body:', e);
|
|
23354
|
+
return [];
|
|
23355
|
+
}
|
|
23356
|
+
}
|
|
23357
|
+
|
|
23358
|
+
function renderAnnotation(ann) {
|
|
23359
|
+
var color = SEV_COLOR[ann && ann.severity] || SEV_COLOR.info;
|
|
23360
|
+
return (
|
|
23361
|
+
'<span class="swarm-diff-annot no-print" '
|
|
23362
|
+
+ 'style="display:inline-block;margin-left:8px;padding:1px 6px;'
|
|
23363
|
+
+ 'border-radius:4px;font-size:11px;font-weight:600;'
|
|
23364
|
+
+ 'background:' + color + '22;color:' + color + ';border:1px solid ' + color + '55;">'
|
|
23365
|
+
+ esc((ann && ann.severity ? ann.severity.toUpperCase() : 'INFO')) + ' · ' + esc(ann && ann.text || '')
|
|
23366
|
+
+ '</span>'
|
|
23367
|
+
);
|
|
23368
|
+
}
|
|
23369
|
+
|
|
23370
|
+
function renderHunk(hunk, hunkIdx, file) {
|
|
23371
|
+
var oldLines = hunk.old_lines || 0;
|
|
23372
|
+
var newLines = hunk.new_lines || 0;
|
|
23373
|
+
var oldStart = hunk.old_start || 0;
|
|
23374
|
+
var newStart = hunk.new_start || 0;
|
|
23375
|
+
var lines = Array.isArray(hunk.lines) ? hunk.lines : [];
|
|
23376
|
+
var annotations = Array.isArray(hunk.annotations) ? hunk.annotations : [];
|
|
23377
|
+
// Index annotations by new-side line number for fast lookup per row.
|
|
23378
|
+
var annByLine = {};
|
|
23379
|
+
for (var i = 0; i < annotations.length; i++) {
|
|
23380
|
+
var a = annotations[i];
|
|
23381
|
+
if (a && typeof a.line === 'number') {
|
|
23382
|
+
if (!annByLine[a.line]) annByLine[a.line] = [];
|
|
23383
|
+
annByLine[a.line].push(a);
|
|
23384
|
+
}
|
|
23385
|
+
}
|
|
23386
|
+
|
|
23387
|
+
var rowsHtml = '';
|
|
23388
|
+
var oldN = oldStart;
|
|
23389
|
+
var newN = newStart;
|
|
23390
|
+
for (var j = 0; j < lines.length; j++) {
|
|
23391
|
+
var line = lines[j] || {};
|
|
23392
|
+
var type = line.type || 'context';
|
|
23393
|
+
var text = line.text == null ? '' : line.text;
|
|
23394
|
+
var bg, oldCell, newCell, sign;
|
|
23395
|
+
if (type === 'add') {
|
|
23396
|
+
bg = 'rgba(34,197,94,0.10)';
|
|
23397
|
+
oldCell = '';
|
|
23398
|
+
newCell = String(newN++);
|
|
23399
|
+
sign = '+';
|
|
23400
|
+
} else if (type === 'del') {
|
|
23401
|
+
bg = 'rgba(239,68,68,0.10)';
|
|
23402
|
+
oldCell = String(oldN++);
|
|
23403
|
+
newCell = '';
|
|
23404
|
+
sign = '-';
|
|
23405
|
+
} else {
|
|
23406
|
+
bg = 'transparent';
|
|
23407
|
+
oldCell = String(oldN++);
|
|
23408
|
+
newCell = String(newN++);
|
|
23409
|
+
sign = ' ';
|
|
23410
|
+
}
|
|
23411
|
+
|
|
23412
|
+
var annHtml = '';
|
|
23413
|
+
var anns = annByLine[Number(newCell)] || annByLine[Number(oldCell)] || [];
|
|
23414
|
+
for (var k = 0; k < anns.length; k++) annHtml += renderAnnotation(anns[k]);
|
|
23415
|
+
|
|
23416
|
+
rowsHtml += (
|
|
23417
|
+
'<tr style="background:' + bg + ';">'
|
|
23418
|
+
+ '<td class="swarm-diff-gutter" style="user-select:none;text-align:right;padding:0 8px;color:#7c8aa6;font-size:12px;width:48px;">' + esc(oldCell) + '</td>'
|
|
23419
|
+
+ '<td class="swarm-diff-gutter" style="user-select:none;text-align:right;padding:0 8px;color:#7c8aa6;font-size:12px;width:48px;">' + esc(newCell) + '</td>'
|
|
23420
|
+
+ '<td class="swarm-diff-sign" style="user-select:none;text-align:center;padding:0 4px;color:#7c8aa6;font-size:12px;width:18px;">' + esc(sign) + '</td>'
|
|
23421
|
+
+ '<td class="swarm-diff-code" style="padding:0 8px;white-space:pre-wrap;word-break:break-word;font-family:\\'Space Mono\\',ui-monospace,monospace;font-size:12px;">' + esc(text) + annHtml + '</td>'
|
|
23422
|
+
+ '</tr>'
|
|
23423
|
+
);
|
|
23424
|
+
}
|
|
23425
|
+
|
|
23426
|
+
var anchorSlug = slugifyAttr((file || 'hunk') + '-' + (oldStart || hunkIdx + 1));
|
|
23427
|
+
var anchorId = 'swarm-diff-' + anchorSlug;
|
|
23428
|
+
var header = (
|
|
23429
|
+
'@@ -' + oldStart + ',' + oldLines + ' +' + newStart + ',' + newLines + ' @@'
|
|
23430
|
+
);
|
|
23431
|
+
|
|
23432
|
+
return (
|
|
23433
|
+
'<a id="' + esc(anchorId) + '" class="swarm-diff-anchor" data-hunk="' + esc(anchorSlug) + '"></a>'
|
|
23434
|
+
+ '<div class="swarm-diff-hunk-header" style="padding:6px 12px;background:rgba(124,138,166,0.10);color:#7c8aa6;font-family:\\'Space Mono\\',ui-monospace,monospace;font-size:11px;border-top:1px solid var(--swarm-border,#22304a);">'
|
|
23435
|
+
+ esc(header)
|
|
23436
|
+
+ '</div>'
|
|
23437
|
+
+ '<table class="swarm-diff-table" style="width:100%;border-collapse:collapse;table-layout:fixed;">'
|
|
23438
|
+
+ '<tbody>' + rowsHtml + '</tbody>'
|
|
23439
|
+
+ '</table>'
|
|
23440
|
+
);
|
|
23441
|
+
}
|
|
23442
|
+
|
|
23443
|
+
function renderDiff(rootEl, diffData) {
|
|
23444
|
+
var hunks = (diffData && Array.isArray(diffData.hunks)) ? diffData.hunks : (Array.isArray(diffData) ? diffData : []);
|
|
23445
|
+
var file = rootEl.getAttribute('file') || '';
|
|
23446
|
+
var baseSha = rootEl.getAttribute('base-sha') || '';
|
|
23447
|
+
var headSha = rootEl.getAttribute('head-sha') || '';
|
|
23448
|
+
|
|
23449
|
+
var shaLine = '';
|
|
23450
|
+
if (baseSha || headSha) {
|
|
23451
|
+
shaLine = '<span class="swarm-diff-sha" style="font-family:\\'Space Mono\\',ui-monospace,monospace;font-size:11px;color:#7c8aa6;">'
|
|
23452
|
+
+ esc(baseSha) + ' → ' + esc(headSha)
|
|
23453
|
+
+ '</span>';
|
|
23454
|
+
}
|
|
23455
|
+
|
|
23456
|
+
var hunksHtml = '';
|
|
23457
|
+
for (var i = 0; i < hunks.length; i++) {
|
|
23458
|
+
hunksHtml += renderHunk(hunks[i] || {}, i, file);
|
|
23459
|
+
}
|
|
23460
|
+
|
|
23461
|
+
rootEl.innerHTML = (
|
|
23462
|
+
'<div class="swarm-diff-root" style="border:1px solid var(--swarm-border,#22304a);border-radius:8px;background:var(--swarm-card,#121826);overflow:hidden;margin:12px 0;break-inside:avoid;">'
|
|
23463
|
+
+ '<div class="swarm-diff-header" style="display:flex;align-items:center;justify-content:space-between;padding:10px 12px;background:rgba(59,130,246,0.10);border-bottom:1px solid var(--swarm-border,#22304a);">'
|
|
23464
|
+
+ '<span class="swarm-diff-file" style="font-family:\\'Space Mono\\',ui-monospace,monospace;font-size:13px;font-weight:700;color:var(--swarm-text,#e6eaf2);">' + esc(file || '(untitled)') + '</span>'
|
|
23465
|
+
+ shaLine
|
|
23466
|
+
+ '</div>'
|
|
23467
|
+
+ hunksHtml
|
|
23468
|
+
+ '</div>'
|
|
23469
|
+
);
|
|
23470
|
+
}
|
|
23471
|
+
|
|
23472
|
+
// Public function form lives on window.swarmUi so callers can render an
|
|
23473
|
+
// arbitrary root element programmatically. The custom element below is just
|
|
23474
|
+
// a declarative wrapper around the same render function.
|
|
23475
|
+
window.swarmUi = window.swarmUi || {};
|
|
23476
|
+
window.swarmUi.renderDiff = renderDiff;
|
|
23477
|
+
|
|
23478
|
+
// Defer the parse-and-render so the HTML parser has time to finish
|
|
23479
|
+
// appending JSON text children. \`connectedCallback\` fires on the opening
|
|
23480
|
+
// tag — \`this.textContent\` is empty until children parse. Without a
|
|
23481
|
+
// defer, every declarative <swarm-diff> renders an empty header and the
|
|
23482
|
+
// JSON text remains visible as orphan children.
|
|
23483
|
+
//
|
|
23484
|
+
// queueMicrotask alone is NOT enough — Chrome's streaming parser drains
|
|
23485
|
+
// microtasks between chunks, so the microtask can run BEFORE the JSON
|
|
23486
|
+
// child is appended. We need to wait for the parser to finish the current
|
|
23487
|
+
// document load, then read textContent.
|
|
23488
|
+
//
|
|
23489
|
+
// * \`document.readyState === 'loading'\` ⇒ parser still streaming →
|
|
23490
|
+
// wait for DOMContentLoaded (fires after all children are parsed).
|
|
23491
|
+
// * otherwise (element was created/inserted dynamically post-load) ⇒
|
|
23492
|
+
// queueMicrotask is fine — DOM is stable, just give the caller a tick.
|
|
23493
|
+
//
|
|
23494
|
+
// Re-entrancy (element moved/reconnected) re-fires connectedCallback so
|
|
23495
|
+
// we re-render against current textContent.
|
|
23496
|
+
class SwarmDiffElement extends HTMLElement {
|
|
23497
|
+
connectedCallback() {
|
|
23498
|
+
var self = this;
|
|
23499
|
+
var doRender = function() {
|
|
23500
|
+
if (!self.isConnected) return;
|
|
23501
|
+
var raw = self.textContent || '';
|
|
23502
|
+
renderDiff(self, { hunks: parseHunks(raw) });
|
|
23503
|
+
// Notify <swarm-diff-jumps> instances so they can pick up new anchors.
|
|
23504
|
+
self.dispatchEvent(new CustomEvent('swarm-diff:rendered', { bubbles: true }));
|
|
23505
|
+
};
|
|
23506
|
+
if (typeof document !== 'undefined' && document.readyState === 'loading') {
|
|
23507
|
+
document.addEventListener('DOMContentLoaded', doRender, { once: true });
|
|
23508
|
+
} else {
|
|
23509
|
+
queueMicrotask(doRender);
|
|
23510
|
+
}
|
|
23511
|
+
}
|
|
23512
|
+
}
|
|
23513
|
+
window.customElements.define('swarm-diff', SwarmDiffElement);
|
|
23514
|
+
|
|
23515
|
+
// Sibling-anchor jump list. Walks subsequent siblings, finds every
|
|
23516
|
+
// <swarm-diff data-hunk=...> anchor, and renders a small list of links.
|
|
23517
|
+
//
|
|
23518
|
+
// Same parse-order hazard as <swarm-diff>: <swarm-diff-jumps> usually
|
|
23519
|
+
// appears in the document BEFORE the <swarm-diff> elements it indexes, so
|
|
23520
|
+
// we also defer to a microtask AND re-render whenever a <swarm-diff> in the
|
|
23521
|
+
// document finishes rendering its anchors.
|
|
23522
|
+
class SwarmDiffJumpsElement extends HTMLElement {
|
|
23523
|
+
connectedCallback() {
|
|
23524
|
+
var self = this;
|
|
23525
|
+
var renderJumps = function() {
|
|
23526
|
+
var anchors = document.querySelectorAll('.swarm-diff-anchor[data-hunk]');
|
|
23527
|
+
if (!anchors.length) {
|
|
23528
|
+
self.innerHTML = '<span class="no-print" style="color:#7c8aa6;font-size:12px;">No hunks yet.</span>';
|
|
23529
|
+
return;
|
|
23530
|
+
}
|
|
23531
|
+
var items = '';
|
|
23532
|
+
for (var i = 0; i < anchors.length; i++) {
|
|
23533
|
+
var a = anchors[i];
|
|
23534
|
+
var slug = a.getAttribute('data-hunk') || ('hunk-' + i);
|
|
23535
|
+
// Hunk title = nearest preceding diff's file attribute if available.
|
|
23536
|
+
var diff = a.closest && a.closest('swarm-diff');
|
|
23537
|
+
var file = (diff && diff.getAttribute('file')) || slug;
|
|
23538
|
+
items += '<li style="margin:0;padding:2px 0;"><a href="#' + esc(a.id) + '" style="color:#3b82f6;text-decoration:none;font-family:\\'Space Mono\\',ui-monospace,monospace;font-size:12px;">' + esc(file) + '</a></li>';
|
|
23539
|
+
}
|
|
23540
|
+
self.innerHTML = (
|
|
23541
|
+
'<nav class="swarm-diff-jumps no-print" style="padding:8px 12px;border:1px dashed var(--swarm-border,#22304a);border-radius:8px;background:rgba(124,138,166,0.05);">'
|
|
23542
|
+
+ '<div style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:#7c8aa6;margin-bottom:4px;">Jump to</div>'
|
|
23543
|
+
+ '<ul style="list-style:none;padding:0;margin:0;">' + items + '</ul>'
|
|
23544
|
+
+ '</nav>'
|
|
23545
|
+
);
|
|
23546
|
+
};
|
|
23547
|
+
// Wait for the parser to finish initial load before first query —
|
|
23548
|
+
// <swarm-diff> elements also defer to DOMContentLoaded so we must
|
|
23549
|
+
// run AFTER they finish rendering their anchors. The event listener
|
|
23550
|
+
// below handles the live-update case.
|
|
23551
|
+
if (typeof document !== 'undefined' && document.readyState === 'loading') {
|
|
23552
|
+
document.addEventListener('DOMContentLoaded', function() { queueMicrotask(renderJumps); }, { once: true });
|
|
23553
|
+
} else {
|
|
23554
|
+
queueMicrotask(renderJumps);
|
|
23555
|
+
}
|
|
23556
|
+
// Re-render whenever a sibling <swarm-diff> finishes its async render.
|
|
23557
|
+
self._onDiffRendered = function() { renderJumps(); };
|
|
23558
|
+
document.addEventListener('swarm-diff:rendered', self._onDiffRendered);
|
|
23559
|
+
}
|
|
23560
|
+
disconnectedCallback() {
|
|
23561
|
+
if (this._onDiffRendered) {
|
|
23562
|
+
document.removeEventListener('swarm-diff:rendered', this._onDiffRendered);
|
|
23563
|
+
}
|
|
23564
|
+
}
|
|
23565
|
+
}
|
|
23566
|
+
window.customElements.define('swarm-diff-jumps', SwarmDiffJumpsElement);
|
|
23567
|
+
|
|
23568
|
+
var CURSOR_IDLE_MS = 3000;
|
|
23569
|
+
var CURSOR_SMOOTHING = 0.28;
|
|
23570
|
+
|
|
23571
|
+
function cursorColor(userId) {
|
|
23572
|
+
var hash = 2166136261;
|
|
23573
|
+
var value = String(userId || '');
|
|
23574
|
+
for (var i = 0; i < value.length; i++) {
|
|
23575
|
+
hash ^= value.charCodeAt(i);
|
|
23576
|
+
hash = Math.imul(hash, 16777619);
|
|
23577
|
+
}
|
|
23578
|
+
return 'hsl(' + ((hash >>> 0) % 360) + ', 72%, 42%)';
|
|
23579
|
+
}
|
|
23580
|
+
|
|
23581
|
+
function documentSize() {
|
|
23582
|
+
var root = document.documentElement || {};
|
|
23583
|
+
return {
|
|
23584
|
+
width: Math.max(1, root.scrollWidth || root.clientWidth || window.innerWidth || 1),
|
|
23585
|
+
height: Math.max(1, root.scrollHeight || root.clientHeight || window.innerHeight || 1),
|
|
23586
|
+
};
|
|
23587
|
+
}
|
|
23588
|
+
|
|
23589
|
+
function cursorMarkup(name, color) {
|
|
23590
|
+
// CursorPointer + CursorBody label structure adapted from Kibo UI (MIT):
|
|
23591
|
+
// https://github.com/shadcnblocks/kibo/blob/main/packages/cursor/index.tsx
|
|
23592
|
+
return '<svg aria-hidden="true" focusable="false" height="20" width="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" style="width:20px;height:20px;flex:none;filter:drop-shadow(0 1px 1px rgba(0,0,0,.2));">'
|
|
23593
|
+
+ '<path d="M19.438 6.716 1.115.05A.832.832 0 0 0 .05 1.116L6.712 19.45a.834.834 0 0 0 1.557.025l3.198-8 7.995-3.2a.833.833 0 0 0 0-1.559h-.024Z" fill="currentColor"></path>'
|
|
23594
|
+
+ '</svg>'
|
|
23595
|
+
+ '<span style="position:relative;margin-left:14px;display:flex;flex-direction:column;white-space:nowrap;border-radius:12px;padding:4px 12px 4px 10px;font-family:system-ui,sans-serif;font-size:12px;font-weight:500;line-height:1.4;background:' + color + ';color:#fff;box-shadow:0 2px 6px rgba(0,0,0,.18);">'
|
|
23596
|
+
+ esc(name || 'Guest')
|
|
23597
|
+
+ '</span>';
|
|
23598
|
+
}
|
|
23599
|
+
|
|
23600
|
+
class SwarmCursorsElement extends HTMLElement {
|
|
23601
|
+
connectedCallback() {
|
|
23602
|
+
if (this._startPromise) return;
|
|
23603
|
+
var roomName = this.getAttribute('room');
|
|
23604
|
+
if (!roomName || !originalRoom) return;
|
|
23605
|
+
|
|
23606
|
+
var self = this;
|
|
23607
|
+
var lifecycle = (this._lifecycle || 0) + 1;
|
|
23608
|
+
this._lifecycle = lifecycle;
|
|
23609
|
+
var begin = function() {
|
|
23610
|
+
self._onDomReady = null;
|
|
23611
|
+
if (!self.isConnected || self._lifecycle !== lifecycle) return;
|
|
23612
|
+
var schemaVersion = self.getAttribute('schema-version');
|
|
23613
|
+
var options = schemaVersion == null ? {} : { schemaVersion: Number(schemaVersion) };
|
|
23614
|
+
var acquired = acquireCursorRoom(roomName, options);
|
|
23615
|
+
self._roomRecord = acquired.record;
|
|
23616
|
+
self._startPromise = acquired.promise.then(function(room) {
|
|
23617
|
+
if (!self.isConnected || self._lifecycle !== lifecycle) return;
|
|
23618
|
+
self._startPromise = null;
|
|
23619
|
+
self._room = room;
|
|
23620
|
+
self._presence = trackRoomPresence(room);
|
|
23621
|
+
if (!self._presence) return;
|
|
23622
|
+
self._pointers = new Map();
|
|
23623
|
+
self._cursorStates = new Map();
|
|
23624
|
+
|
|
23625
|
+
self._overlay = document.createElement('div');
|
|
23626
|
+
self._overlay.setAttribute('aria-hidden', 'true');
|
|
23627
|
+
self._overlay.style.cssText = 'position:fixed;inset:0;z-index:2147483647;pointer-events:none;overflow:hidden;';
|
|
23628
|
+
var parent = document.body || document.documentElement;
|
|
23629
|
+
if (parent) parent.appendChild(self._overlay);
|
|
23630
|
+
|
|
23631
|
+
self._onPresence = function(peers) { self._renderPeers(peers || []); };
|
|
23632
|
+
self._onPointerMove = function(event) {
|
|
23633
|
+
var size = documentSize();
|
|
23634
|
+
var scrollX = window.scrollX || window.pageXOffset || 0;
|
|
23635
|
+
var scrollY = window.scrollY || window.pageYOffset || 0;
|
|
23636
|
+
var pageX = typeof event.pageX === 'number' ? event.pageX : event.clientX + scrollX;
|
|
23637
|
+
var pageY = typeof event.pageY === 'number' ? event.pageY : event.clientY + scrollY;
|
|
23638
|
+
var x = Math.max(0, Math.min(1, pageX / size.width));
|
|
23639
|
+
var y = Math.max(0, Math.min(1, pageY / size.height));
|
|
23640
|
+
self._presence.setCursor({ x: x, y: y });
|
|
23641
|
+
};
|
|
23642
|
+
self._onPointerLeave = function() {
|
|
23643
|
+
self._presence.clearCursor();
|
|
23644
|
+
};
|
|
23645
|
+
|
|
23646
|
+
self._unsubscribe = room.on('presence', self._onPresence);
|
|
23647
|
+
document.addEventListener('pointermove', self._onPointerMove, { passive: true });
|
|
23648
|
+
document.addEventListener('pointerleave', self._onPointerLeave);
|
|
23649
|
+
self._renderPeers(room.presence.peers || []);
|
|
23650
|
+
}).catch(function(error) {
|
|
23651
|
+
self._startPromise = null;
|
|
23652
|
+
console.warn('[swarm-cursors] failed to join room:', error);
|
|
23653
|
+
});
|
|
23654
|
+
};
|
|
23655
|
+
if (document.readyState === 'loading') {
|
|
23656
|
+
this._onDomReady = function() { queueMicrotask(begin); };
|
|
23657
|
+
this._startPromise = Promise.resolve();
|
|
23658
|
+
document.addEventListener('DOMContentLoaded', this._onDomReady, { once: true });
|
|
23659
|
+
} else {
|
|
23660
|
+
begin();
|
|
23661
|
+
}
|
|
23662
|
+
}
|
|
23663
|
+
|
|
23664
|
+
_renderPeers(peers) {
|
|
23665
|
+
if (!this._pointers) return;
|
|
23666
|
+
var seen = new Set();
|
|
23667
|
+
var activePeerIds = new Set();
|
|
23668
|
+
var includeAgents = this.hasAttribute('include-agents');
|
|
23669
|
+
var ownId = this._room && this._room.me && this._room.me.userId;
|
|
23670
|
+
var now = Date.now();
|
|
23671
|
+
|
|
23672
|
+
for (var i = 0; i < peers.length; i++) {
|
|
23673
|
+
var peer = peers[i];
|
|
23674
|
+
if (!peer || !peer.userId || peer.userId === ownId) continue;
|
|
23675
|
+
if (peer.kind === 'agent' && !includeAgents) continue;
|
|
23676
|
+
var data = peer.data && typeof peer.data === 'object' ? peer.data : null;
|
|
23677
|
+
var cursor = data && data.__cursor;
|
|
23678
|
+
if (!cursor || typeof cursor.x !== 'number' || typeof cursor.y !== 'number'
|
|
23679
|
+
|| !Number.isFinite(cursor.x) || !Number.isFinite(cursor.y)) continue;
|
|
23680
|
+
|
|
23681
|
+
var id = String(peer.userId);
|
|
23682
|
+
activePeerIds.add(id);
|
|
23683
|
+
var state = this._cursorStates.get(id);
|
|
23684
|
+
if (!state || state.x !== cursor.x || state.y !== cursor.y) {
|
|
23685
|
+
state = { x: cursor.x, y: cursor.y, lastSeen: now };
|
|
23686
|
+
this._cursorStates.set(id, state);
|
|
23687
|
+
}
|
|
23688
|
+
if (now - state.lastSeen > CURSOR_IDLE_MS) continue;
|
|
23689
|
+
|
|
23690
|
+
var entry = this._pointers.get(id);
|
|
23691
|
+
if (!entry) {
|
|
23692
|
+
entry = this._createPointer(peer);
|
|
23693
|
+
this._pointers.set(id, entry);
|
|
23694
|
+
}
|
|
23695
|
+
entry.cursor = { x: state.x, y: state.y };
|
|
23696
|
+
entry.lastSeen = state.lastSeen;
|
|
23697
|
+
if (entry.name !== peer.name) {
|
|
23698
|
+
entry.name = peer.name || 'Guest';
|
|
23699
|
+
entry.node.innerHTML = cursorMarkup(entry.name, entry.color);
|
|
23700
|
+
}
|
|
23701
|
+
seen.add(id);
|
|
23702
|
+
}
|
|
23703
|
+
|
|
23704
|
+
var ids = Array.from(this._pointers.keys());
|
|
23705
|
+
for (var j = 0; j < ids.length; j++) {
|
|
23706
|
+
if (!seen.has(ids[j])) this._removePointer(ids[j]);
|
|
23707
|
+
}
|
|
23708
|
+
var stateIds = Array.from(this._cursorStates.keys());
|
|
23709
|
+
for (var k = 0; k < stateIds.length; k++) {
|
|
23710
|
+
if (!activePeerIds.has(stateIds[k])) this._cursorStates.delete(stateIds[k]);
|
|
23711
|
+
}
|
|
23712
|
+
this._scheduleFrame();
|
|
23713
|
+
}
|
|
23714
|
+
|
|
23715
|
+
_createPointer(peer) {
|
|
23716
|
+
var color = cursorColor(peer.userId);
|
|
23717
|
+
var node = document.createElement('div');
|
|
23718
|
+
node.style.cssText = 'position:absolute;left:0;top:0;display:flex;align-items:flex-start;pointer-events:none;user-select:none;will-change:transform;color:' + color + ';';
|
|
23719
|
+
node.innerHTML = cursorMarkup(peer.name || 'Guest', color);
|
|
23720
|
+
this._overlay.appendChild(node);
|
|
23721
|
+
return {
|
|
23722
|
+
node: node,
|
|
23723
|
+
color: color,
|
|
23724
|
+
name: peer.name || 'Guest',
|
|
23725
|
+
cursor: null,
|
|
23726
|
+
x: null,
|
|
23727
|
+
y: null,
|
|
23728
|
+
lastSeen: Date.now(),
|
|
23729
|
+
};
|
|
23730
|
+
}
|
|
23731
|
+
|
|
23732
|
+
_removePointer(id) {
|
|
23733
|
+
var entry = this._pointers.get(id);
|
|
23734
|
+
if (entry && entry.node.parentNode) entry.node.parentNode.removeChild(entry.node);
|
|
23735
|
+
this._pointers.delete(id);
|
|
23736
|
+
}
|
|
23737
|
+
|
|
23738
|
+
_scheduleFrame() {
|
|
23739
|
+
if (this._frameId != null || !this._pointers || !this._pointers.size
|
|
23740
|
+
|| typeof window.requestAnimationFrame !== 'function') return;
|
|
23741
|
+
var self = this;
|
|
23742
|
+
this._frameId = window.requestAnimationFrame(function() { self._animate(); });
|
|
23743
|
+
}
|
|
23744
|
+
|
|
23745
|
+
_animate() {
|
|
23746
|
+
this._frameId = null;
|
|
23747
|
+
if (!this._pointers || !this._overlay) return;
|
|
23748
|
+
var now = Date.now();
|
|
23749
|
+
var size = documentSize();
|
|
23750
|
+
var scrollX = window.scrollX || window.pageXOffset || 0;
|
|
23751
|
+
var scrollY = window.scrollY || window.pageYOffset || 0;
|
|
23752
|
+
var ids = Array.from(this._pointers.keys());
|
|
23753
|
+
|
|
23754
|
+
for (var i = 0; i < ids.length; i++) {
|
|
23755
|
+
var id = ids[i];
|
|
23756
|
+
var entry = this._pointers.get(id);
|
|
23757
|
+
if (now - entry.lastSeen > CURSOR_IDLE_MS) {
|
|
23758
|
+
this._removePointer(id);
|
|
23759
|
+
continue;
|
|
23760
|
+
}
|
|
23761
|
+
var targetX = entry.cursor.x * size.width - scrollX;
|
|
23762
|
+
var targetY = entry.cursor.y * size.height - scrollY;
|
|
23763
|
+
if (entry.x == null || entry.y == null) {
|
|
23764
|
+
entry.x = targetX;
|
|
23765
|
+
entry.y = targetY;
|
|
23766
|
+
} else {
|
|
23767
|
+
// Exponential interpolation keeps 50 ms presence updates from jumping.
|
|
23768
|
+
entry.x += (targetX - entry.x) * CURSOR_SMOOTHING;
|
|
23769
|
+
entry.y += (targetY - entry.y) * CURSOR_SMOOTHING;
|
|
23770
|
+
}
|
|
23771
|
+
entry.node.style.transform = 'translate3d(' + Math.round(entry.x) + 'px,' + Math.round(entry.y) + 'px,0)';
|
|
23772
|
+
}
|
|
23773
|
+
this._scheduleFrame();
|
|
23774
|
+
}
|
|
23775
|
+
|
|
23776
|
+
disconnectedCallback() {
|
|
23777
|
+
this._lifecycle = (this._lifecycle || 0) + 1;
|
|
23778
|
+
this._startPromise = null;
|
|
23779
|
+
if (this._onDomReady) {
|
|
23780
|
+
document.removeEventListener('DOMContentLoaded', this._onDomReady);
|
|
23781
|
+
this._onDomReady = null;
|
|
23782
|
+
}
|
|
23783
|
+
if (this._unsubscribe) this._unsubscribe();
|
|
23784
|
+
if (this._onPointerMove) document.removeEventListener('pointermove', this._onPointerMove);
|
|
23785
|
+
if (this._onPointerLeave) document.removeEventListener('pointerleave', this._onPointerLeave);
|
|
23786
|
+
if (this._roomRecord) releaseCursorRoom(this._roomRecord, this._presence);
|
|
23787
|
+
if (this._frameId != null && typeof window.cancelAnimationFrame === 'function')
|
|
23788
|
+
window.cancelAnimationFrame(this._frameId);
|
|
23789
|
+
if (this._pointers) {
|
|
23790
|
+
var ids = Array.from(this._pointers.keys());
|
|
23791
|
+
for (var i = 0; i < ids.length; i++) this._removePointer(ids[i]);
|
|
23792
|
+
}
|
|
23793
|
+
if (this._overlay && this._overlay.parentNode)
|
|
23794
|
+
this._overlay.parentNode.removeChild(this._overlay);
|
|
23795
|
+
this._room = null;
|
|
23796
|
+
this._roomRecord = null;
|
|
23797
|
+
this._presence = null;
|
|
23798
|
+
this._overlay = null;
|
|
23799
|
+
this._pointers = null;
|
|
23800
|
+
this._cursorStates = null;
|
|
23801
|
+
this._frameId = null;
|
|
23802
|
+
}
|
|
23803
|
+
}
|
|
23804
|
+
window.customElements.define('swarm-cursors', SwarmCursorsElement);
|
|
23805
|
+
})();
|
|
23806
|
+
`;
|
|
23807
|
+
|
|
23808
|
+
// src/pages/feedback-overlay.ts
|
|
22640
23809
|
var PAGE_FEEDBACK_PARAM = "__swarm-feedback";
|
|
22641
23810
|
function isPageFeedbackRequested(queryParams) {
|
|
22642
23811
|
if (!queryParams.has(PAGE_FEEDBACK_PARAM))
|
|
@@ -23141,7 +24310,6 @@ function feedbackOverlayScripts(pageId) {
|
|
|
23141
24310
|
}
|
|
23142
24311
|
|
|
23143
24312
|
// src/http/pages-public.ts
|
|
23144
|
-
init_db3();
|
|
23145
24313
|
init_types();
|
|
23146
24314
|
init_constants();
|
|
23147
24315
|
init_node_env();
|
|
@@ -23709,21 +24877,11 @@ var PollTriggerAttachmentSchema = TaskAttachmentSchema.pick({
|
|
|
23709
24877
|
mimeType: true,
|
|
23710
24878
|
sizeBytes: true
|
|
23711
24879
|
});
|
|
23712
|
-
var PollRequestedBySchema = UserSchema.pick({
|
|
23713
|
-
id: true,
|
|
23714
|
-
name: true,
|
|
23715
|
-
email: true,
|
|
23716
|
-
role: true,
|
|
23717
|
-
notes: true
|
|
23718
|
-
}).extend({
|
|
23719
|
-
id: exports_external.string().optional(),
|
|
23720
|
-
comms: UserCommsPrefsSchema.optional()
|
|
23721
|
-
});
|
|
23722
24880
|
var PollTaskOfferedTriggerSchema = exports_external.object({
|
|
23723
24881
|
type: exports_external.literal("task_offered"),
|
|
23724
24882
|
taskId: exports_external.string(),
|
|
23725
24883
|
task: AgentTaskSchema,
|
|
23726
|
-
requestedBy:
|
|
24884
|
+
requestedBy: TaskRequestedBySchema.optional()
|
|
23727
24885
|
});
|
|
23728
24886
|
var PollTaskAssignedTriggerSchema = exports_external.object({
|
|
23729
24887
|
type: exports_external.literal("task_assigned"),
|
|
@@ -23732,7 +24890,7 @@ var PollTaskAssignedTriggerSchema = exports_external.object({
|
|
|
23732
24890
|
task: AgentTaskSchema.extend({
|
|
23733
24891
|
attachments: exports_external.array(PollTriggerAttachmentSchema)
|
|
23734
24892
|
}),
|
|
23735
|
-
requestedBy:
|
|
24893
|
+
requestedBy: TaskRequestedBySchema.optional()
|
|
23736
24894
|
});
|
|
23737
24895
|
var PollUnreadMentionsTriggerSchema = exports_external.object({
|
|
23738
24896
|
type: exports_external.literal("unread_mentions"),
|
|
@@ -23780,26 +24938,6 @@ var pollTriggers = route({
|
|
|
23780
24938
|
});
|
|
23781
24939
|
var CHANNEL_ACTIVITY_INTERVAL_MS = 60000;
|
|
23782
24940
|
var lastChannelActivityCheckAt = 0;
|
|
23783
|
-
function getRequesterNotes(notes) {
|
|
23784
|
-
return typeof notes === "string" && notes.trim().length > 0 ? notes : undefined;
|
|
23785
|
-
}
|
|
23786
|
-
async function buildTriggerRequestedBy(task) {
|
|
23787
|
-
const user = task.requestedByUserId ? await getUserById(task.requestedByUserId) : undefined;
|
|
23788
|
-
if (user) {
|
|
23789
|
-
return {
|
|
23790
|
-
id: user.id,
|
|
23791
|
-
name: user.name,
|
|
23792
|
-
email: user.email,
|
|
23793
|
-
role: user.role,
|
|
23794
|
-
notes: getRequesterNotes(user.notes),
|
|
23795
|
-
comms: getUserCommsPrefs(user)
|
|
23796
|
-
};
|
|
23797
|
-
}
|
|
23798
|
-
if (task.slackUserId) {
|
|
23799
|
-
return { name: renderIdentity(await resolveIdentity("slack", task.slackUserId)) };
|
|
23800
|
-
}
|
|
23801
|
-
return;
|
|
23802
|
-
}
|
|
23803
24941
|
async function attachmentsForTrigger(taskId) {
|
|
23804
24942
|
return (await getTaskAttachments(taskId)).map((a) => ({
|
|
23805
24943
|
id: a.id,
|
|
@@ -23809,11 +24947,21 @@ async function attachmentsForTrigger(taskId) {
|
|
|
23809
24947
|
}));
|
|
23810
24948
|
}
|
|
23811
24949
|
async function claimModelFields(task, agent) {
|
|
24950
|
+
const pin = taskModelPin(task);
|
|
24951
|
+
const cleared = {
|
|
24952
|
+
model: pin,
|
|
24953
|
+
resolvedModel: undefined,
|
|
24954
|
+
modelSource: undefined,
|
|
24955
|
+
modelAlias: undefined
|
|
24956
|
+
};
|
|
23812
24957
|
try {
|
|
23813
|
-
return
|
|
24958
|
+
return {
|
|
24959
|
+
...cleared,
|
|
24960
|
+
...await recordClaimModelResolution({ ...task, model: pin }, agent)
|
|
24961
|
+
};
|
|
23814
24962
|
} catch (error) {
|
|
23815
24963
|
console.warn(`[/api/poll] model resolution failed for task ${task.id}:`, error);
|
|
23816
|
-
return
|
|
24964
|
+
return cleared;
|
|
23817
24965
|
}
|
|
23818
24966
|
}
|
|
23819
24967
|
var commitCursorsRoute = route({
|
|
@@ -23898,7 +25046,7 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
23898
25046
|
const claimedTask = await claimOfferedTask(firstOfferedTask.id, myAgentId);
|
|
23899
25047
|
if (claimedTask) {
|
|
23900
25048
|
await recordRuntimeTask(claimedTask.id);
|
|
23901
|
-
const offeredRequestedBy = await
|
|
25049
|
+
const offeredRequestedBy = await buildTaskRequestedBy(claimedTask);
|
|
23902
25050
|
return {
|
|
23903
25051
|
trigger: {
|
|
23904
25052
|
type: "task_offered",
|
|
@@ -23978,7 +25126,7 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
23978
25126
|
agentId: myAgentId
|
|
23979
25127
|
});
|
|
23980
25128
|
});
|
|
23981
|
-
const assignedRequestedBy = await
|
|
25129
|
+
const assignedRequestedBy = await buildTaskRequestedBy(pendingTask);
|
|
23982
25130
|
const assignedTriggerSurface = await resolveTriggerSurface(pendingTask.id, pendingTask.source);
|
|
23983
25131
|
return {
|
|
23984
25132
|
trigger: {
|
|
@@ -24069,7 +25217,7 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
24069
25217
|
agentId: myAgentId
|
|
24070
25218
|
});
|
|
24071
25219
|
});
|
|
24072
|
-
const claimedRequestedBy = await
|
|
25220
|
+
const claimedRequestedBy = await buildTaskRequestedBy(claimed);
|
|
24073
25221
|
const claimedTriggerSurface = await resolveTriggerSurface(claimed.id, claimed.source);
|
|
24074
25222
|
return {
|
|
24075
25223
|
trigger: {
|
|
@@ -29605,6 +30753,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
|
|
|
29605
30753
|
runtimeInstanceId,
|
|
29606
30754
|
egressSecrets: credentials.egressSecrets,
|
|
29607
30755
|
failedBindings: credentials.failedBindings,
|
|
30756
|
+
userConfig: credentials.userConfig,
|
|
29608
30757
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: agent.id }),
|
|
29609
30758
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: agent.id })
|
|
29610
30759
|
});
|
|
@@ -32101,21 +33250,6 @@ var getMetrics = route({
|
|
|
32101
33250
|
200: { description: "Swarm metrics counts", schema: SwarmMetricsSchema }
|
|
32102
33251
|
}
|
|
32103
33252
|
});
|
|
32104
|
-
var listServices = route({
|
|
32105
|
-
method: "get",
|
|
32106
|
-
path: "/api/services",
|
|
32107
|
-
pattern: ["api", "services"],
|
|
32108
|
-
summary: "List all registered services",
|
|
32109
|
-
tags: ["Stats"],
|
|
32110
|
-
query: exports_external.object({
|
|
32111
|
-
status: exports_external.string().optional(),
|
|
32112
|
-
agentId: exports_external.string().optional(),
|
|
32113
|
-
name: exports_external.string().optional()
|
|
32114
|
-
}),
|
|
32115
|
-
responses: {
|
|
32116
|
-
200: { description: "Service list", schema: exports_external.object({ services: exports_external.array(ServiceSchema) }) }
|
|
32117
|
-
}
|
|
32118
|
-
});
|
|
32119
33253
|
var listScheduledTasks = route({
|
|
32120
33254
|
method: "get",
|
|
32121
33255
|
path: "/api/scheduled-tasks",
|
|
@@ -32201,18 +33335,6 @@ async function handleStats(req, res, pathSegments, queryParams, myAgentId) {
|
|
|
32201
33335
|
});
|
|
32202
33336
|
return true;
|
|
32203
33337
|
}
|
|
32204
|
-
if (listServices.match(req.method, pathSegments)) {
|
|
32205
|
-
const parsed = await listServices.parse(req, res, pathSegments, queryParams);
|
|
32206
|
-
if (!parsed)
|
|
32207
|
-
return true;
|
|
32208
|
-
const services = await getAllServices({
|
|
32209
|
-
status: parsed.query.status || undefined,
|
|
32210
|
-
agentId: parsed.query.agentId || undefined,
|
|
32211
|
-
name: parsed.query.name || undefined
|
|
32212
|
-
});
|
|
32213
|
-
listServices.respond(res, 200, { services });
|
|
32214
|
-
return true;
|
|
32215
|
-
}
|
|
32216
33338
|
if (listScheduledTasks.match(req.method, pathSegments)) {
|
|
32217
33339
|
const parsed = await listScheduledTasks.parse(req, res, pathSegments, queryParams);
|
|
32218
33340
|
if (!parsed)
|
|
@@ -34358,6 +35480,8 @@ async function routeKapsoInbound(payload) {
|
|
|
34358
35480
|
}
|
|
34359
35481
|
|
|
34360
35482
|
// src/http/webhooks.ts
|
|
35483
|
+
init_constants();
|
|
35484
|
+
init_secret_scrubber();
|
|
34361
35485
|
init_event_bus();
|
|
34362
35486
|
var WebhookDispatchResultSchema = exports_external.object({
|
|
34363
35487
|
created: exports_external.boolean(),
|
|
@@ -34453,6 +35577,57 @@ var kapsoWebhook = route({
|
|
|
34453
35577
|
503: { description: "Kapso integration not configured" }
|
|
34454
35578
|
}
|
|
34455
35579
|
});
|
|
35580
|
+
var chatSdkWebhook = route({
|
|
35581
|
+
method: "post",
|
|
35582
|
+
path: "/api/integrations/chat/{adapter}/webhook",
|
|
35583
|
+
pattern: ["api", "integrations", "chat", null, "webhook"],
|
|
35584
|
+
summary: "Handle Chat SDK platform webhooks (Telegram, Slack, Discord, Teams)",
|
|
35585
|
+
tags: ["Webhooks"],
|
|
35586
|
+
params: exports_external.object({ adapter: exports_external.string().describe("Chat SDK adapter name, e.g. telegram") }),
|
|
35587
|
+
auth: { apiKey: false },
|
|
35588
|
+
rbac: {
|
|
35589
|
+
ungated: "provider webhook: the Chat SDK adapter verifies the platform signature (Telegram secret token, Slack signing secret, Discord Ed25519, Teams JWT)"
|
|
35590
|
+
},
|
|
35591
|
+
responses: {
|
|
35592
|
+
200: { description: "Adapter response", unstructured: "adapter response proxied as-is" },
|
|
35593
|
+
401: { description: "Invalid platform signature or secret token" },
|
|
35594
|
+
403: { description: "Teams activity whose serviceUrl is not a Bot Framework host" },
|
|
35595
|
+
404: { description: "Chat SDK disabled or adapter not configured" },
|
|
35596
|
+
413: { description: "Body exceeds 1 MiB" },
|
|
35597
|
+
503: { description: "Adapter configured but failed to start" }
|
|
35598
|
+
}
|
|
35599
|
+
});
|
|
35600
|
+
var CHAT_SDK_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
|
35601
|
+
function hasTrustedTeamsServiceUrl(body) {
|
|
35602
|
+
let serviceUrl;
|
|
35603
|
+
try {
|
|
35604
|
+
serviceUrl = JSON.parse(body.toString("utf-8"))?.serviceUrl;
|
|
35605
|
+
} catch {
|
|
35606
|
+
return true;
|
|
35607
|
+
}
|
|
35608
|
+
if (serviceUrl === undefined || serviceUrl === null || serviceUrl === "")
|
|
35609
|
+
return true;
|
|
35610
|
+
return typeof serviceUrl === "string" && isTrustedTeamsServiceUrl(serviceUrl);
|
|
35611
|
+
}
|
|
35612
|
+
function toFetchRequest(req, rawBody, fallbackPath) {
|
|
35613
|
+
const headers2 = new Headers;
|
|
35614
|
+
if (Array.isArray(req.rawHeaders) && req.rawHeaders.length > 0) {
|
|
35615
|
+
for (let i = 0;i + 1 < req.rawHeaders.length; i += 2) {
|
|
35616
|
+
headers2.append(req.rawHeaders[i], req.rawHeaders[i + 1]);
|
|
35617
|
+
}
|
|
35618
|
+
} else {
|
|
35619
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
35620
|
+
for (const item of Array.isArray(value) ? value : value === undefined ? [] : [value]) {
|
|
35621
|
+
headers2.append(name, item);
|
|
35622
|
+
}
|
|
35623
|
+
}
|
|
35624
|
+
}
|
|
35625
|
+
return new Request(`${getPublicMcpBaseUrl()}${req.url ?? fallbackPath}`, {
|
|
35626
|
+
method: req.method ?? "POST",
|
|
35627
|
+
headers: headers2,
|
|
35628
|
+
body: rawBody.length > 0 ? new Uint8Array(rawBody) : undefined
|
|
35629
|
+
});
|
|
35630
|
+
}
|
|
34456
35631
|
function logKapsoAckResult(action, result) {
|
|
34457
35632
|
if (result.ok)
|
|
34458
35633
|
return;
|
|
@@ -34536,7 +35711,8 @@ async function handleWebhooks(req, res, pathSegments) {
|
|
|
34536
35711
|
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
34537
35712
|
return true;
|
|
34538
35713
|
}
|
|
34539
|
-
|
|
35714
|
+
const deliveryId = req.headers["x-github-delivery"];
|
|
35715
|
+
console.log(`[GitHub] Received ${eventType} event (delivery ${deliveryId ?? "unknown"})`);
|
|
34540
35716
|
let result = { created: false };
|
|
34541
35717
|
try {
|
|
34542
35718
|
result = await runBlockableHandler("GitHub", async () => {
|
|
@@ -34610,13 +35786,13 @@ async function handleWebhooks(req, res, pathSegments) {
|
|
|
34610
35786
|
}
|
|
34611
35787
|
githubWebhook.respond(res, 200, result);
|
|
34612
35788
|
} catch (err) {
|
|
34613
|
-
const
|
|
34614
|
-
console.error(`[GitHub] Error handling ${eventType} event: ${
|
|
35789
|
+
const errorMessage3 = err instanceof Error ? err.message : String(err);
|
|
35790
|
+
console.error(`[GitHub] Error handling ${eventType} event: ${errorMessage3}`);
|
|
34615
35791
|
if (err instanceof Error && err.stack) {
|
|
34616
35792
|
console.error(err.stack);
|
|
34617
35793
|
}
|
|
34618
35794
|
res.writeHead(500, { "Content-Type": "application/json" });
|
|
34619
|
-
res.end(JSON.stringify({ error: "Internal server error", message:
|
|
35795
|
+
res.end(JSON.stringify({ error: "Internal server error", message: errorMessage3 }));
|
|
34620
35796
|
}
|
|
34621
35797
|
return true;
|
|
34622
35798
|
}
|
|
@@ -34724,8 +35900,8 @@ async function handleWebhooks(req, res, pathSegments) {
|
|
|
34724
35900
|
}
|
|
34725
35901
|
gitlabWebhook.respond(res, 200, result);
|
|
34726
35902
|
} catch (err) {
|
|
34727
|
-
const
|
|
34728
|
-
console.error(`[GitLab] Error handling ${objectKind} event: ${
|
|
35903
|
+
const errorMessage3 = err instanceof Error ? err.message : String(err);
|
|
35904
|
+
console.error(`[GitLab] Error handling ${objectKind} event: ${errorMessage3}`);
|
|
34729
35905
|
if (err instanceof Error && err.stack) {
|
|
34730
35906
|
console.error(err.stack);
|
|
34731
35907
|
}
|
|
@@ -34815,8 +35991,8 @@ async function handleWebhooks(req, res, pathSegments) {
|
|
|
34815
35991
|
}
|
|
34816
35992
|
azureDevOpsWebhook.respond(res, 200, result);
|
|
34817
35993
|
} catch (err) {
|
|
34818
|
-
const
|
|
34819
|
-
console.error(`[AzureDevOps] Error handling ${eventType} event: ${
|
|
35994
|
+
const errorMessage3 = err instanceof Error ? err.message : String(err);
|
|
35995
|
+
console.error(`[AzureDevOps] Error handling ${eventType} event: ${errorMessage3}`);
|
|
34820
35996
|
if (err instanceof Error && err.stack) {
|
|
34821
35997
|
console.error(err.stack);
|
|
34822
35998
|
}
|
|
@@ -34884,8 +36060,8 @@ async function handleWebhooks(req, res, pathSegments) {
|
|
|
34884
36060
|
console.log(`[AgentMail] Ignoring event type: ${payload.event_type}`);
|
|
34885
36061
|
}
|
|
34886
36062
|
} catch (err) {
|
|
34887
|
-
const
|
|
34888
|
-
console.error(`[AgentMail] Error handling ${payload.event_type} event: ${
|
|
36063
|
+
const errorMessage3 = err instanceof Error ? err.message : String(err);
|
|
36064
|
+
console.error(`[AgentMail] Error handling ${payload.event_type} event: ${errorMessage3}`);
|
|
34889
36065
|
if (err instanceof Error && err.stack) {
|
|
34890
36066
|
console.error(err.stack);
|
|
34891
36067
|
}
|
|
@@ -34945,16 +36121,84 @@ async function handleWebhooks(req, res, pathSegments) {
|
|
|
34945
36121
|
}
|
|
34946
36122
|
kapsoWebhook.respond(res, 200, { received: true, routing: routing.kind });
|
|
34947
36123
|
} catch (err) {
|
|
34948
|
-
const
|
|
36124
|
+
const errorMessage3 = err instanceof Error ? err.message : String(err);
|
|
34949
36125
|
if (err instanceof WebhookError) {
|
|
34950
|
-
console.warn(`[Kapso] Workflow dispatch rejected: ${
|
|
36126
|
+
console.warn(`[Kapso] Workflow dispatch rejected: ${errorMessage3}`);
|
|
34951
36127
|
} else {
|
|
34952
|
-
console.error(`[Kapso] Error handling inbound event: ${
|
|
36128
|
+
console.error(`[Kapso] Error handling inbound event: ${errorMessage3}`);
|
|
34953
36129
|
}
|
|
34954
36130
|
kapsoWebhook.respond(res, 200, { received: true, routing: "error" });
|
|
34955
36131
|
}
|
|
34956
36132
|
return true;
|
|
34957
36133
|
}
|
|
36134
|
+
if (chatSdkWebhook.match(req.method, pathSegments)) {
|
|
36135
|
+
const adapterName = pathSegments[3] ?? "";
|
|
36136
|
+
if (!isChatSdkEnabled() || !isChatAdapterConfigured(adapterName)) {
|
|
36137
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
36138
|
+
res.end(JSON.stringify({ error: "Chat SDK adapter not configured" }));
|
|
36139
|
+
return true;
|
|
36140
|
+
}
|
|
36141
|
+
if (isChatSdkStopping()) {
|
|
36142
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
36143
|
+
res.end(JSON.stringify({ error: "Chat SDK is shutting down" }));
|
|
36144
|
+
return true;
|
|
36145
|
+
}
|
|
36146
|
+
const chat = getChatInstance(adapterName);
|
|
36147
|
+
const handler = chat?.webhooks[adapterName];
|
|
36148
|
+
if (!handler) {
|
|
36149
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
36150
|
+
res.end(JSON.stringify({ error: "Chat SDK adapter failed to start" }));
|
|
36151
|
+
return true;
|
|
36152
|
+
}
|
|
36153
|
+
if (enforceContentLengthCap(req, res, CHAT_SDK_WEBHOOK_MAX_BODY_BYTES) === BODY_TOO_LARGE) {
|
|
36154
|
+
return true;
|
|
36155
|
+
}
|
|
36156
|
+
const chunks = [];
|
|
36157
|
+
let receivedBytes = 0;
|
|
36158
|
+
let tooLarge = false;
|
|
36159
|
+
for await (const chunk of req) {
|
|
36160
|
+
if (tooLarge)
|
|
36161
|
+
continue;
|
|
36162
|
+
receivedBytes += chunk.byteLength;
|
|
36163
|
+
if (receivedBytes > CHAT_SDK_WEBHOOK_MAX_BODY_BYTES) {
|
|
36164
|
+
tooLarge = true;
|
|
36165
|
+
chunks.length = 0;
|
|
36166
|
+
jsonError(res, `Payload too large (max ${CHAT_SDK_WEBHOOK_MAX_BODY_BYTES} bytes)`, 413);
|
|
36167
|
+
continue;
|
|
36168
|
+
}
|
|
36169
|
+
chunks.push(chunk);
|
|
36170
|
+
}
|
|
36171
|
+
if (tooLarge)
|
|
36172
|
+
return true;
|
|
36173
|
+
const rawBody = Buffer.concat(chunks);
|
|
36174
|
+
if (adapterName === "teams" && !hasTrustedTeamsServiceUrl(rawBody)) {
|
|
36175
|
+
console.warn("[chat-sdk] teams webhook refused: serviceUrl is not a Bot Framework host");
|
|
36176
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
36177
|
+
res.end(JSON.stringify({ error: "Untrusted Teams serviceUrl" }));
|
|
36178
|
+
return true;
|
|
36179
|
+
}
|
|
36180
|
+
const request = toFetchRequest(req, rawBody, `/api/integrations/chat/${adapterName}/webhook`);
|
|
36181
|
+
try {
|
|
36182
|
+
const response = await handler(request, {
|
|
36183
|
+
waitUntil: trackBackground
|
|
36184
|
+
});
|
|
36185
|
+
const responseHeaders = {};
|
|
36186
|
+
response.headers.forEach((value, name) => {
|
|
36187
|
+
responseHeaders[name] = value;
|
|
36188
|
+
});
|
|
36189
|
+
const body = Buffer.from(await response.arrayBuffer());
|
|
36190
|
+
res.writeHead(response.status, responseHeaders);
|
|
36191
|
+
res.end(body);
|
|
36192
|
+
} catch (err) {
|
|
36193
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
36194
|
+
console.error(`[chat-sdk] ${adapterName} webhook failed: ${scrubSecrets(message)}`);
|
|
36195
|
+
if (!res.headersSent) {
|
|
36196
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
36197
|
+
}
|
|
36198
|
+
res.end(JSON.stringify({ error: "Chat SDK webhook failed" }));
|
|
36199
|
+
}
|
|
36200
|
+
return true;
|
|
36201
|
+
}
|
|
34958
36202
|
return false;
|
|
34959
36203
|
}
|
|
34960
36204
|
|
|
@@ -35977,6 +37221,7 @@ async function handleX(req, res, pathSegments) {
|
|
|
35977
37221
|
timeoutMs,
|
|
35978
37222
|
egressSecrets: credentials.egressSecrets,
|
|
35979
37223
|
failedBindings: credentials.failedBindings,
|
|
37224
|
+
userConfig: credentials.userConfig,
|
|
35980
37225
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: endpoint.agentId }),
|
|
35981
37226
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: endpoint.agentId })
|
|
35982
37227
|
});
|
|
@@ -36125,7 +37370,6 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
36125
37370
|
() => handleAgentRegister(req, res, pathSegments, myAgentId),
|
|
36126
37371
|
() => handlePoll(req, res, pathSegments, queryParams, myAgentId),
|
|
36127
37372
|
() => handleSessionData(req, res, pathSegments, queryParams, myAgentId),
|
|
36128
|
-
() => handleEcosystem(req, res, pathSegments, myAgentId),
|
|
36129
37373
|
() => handleTrackers(req, res, pathSegments),
|
|
36130
37374
|
() => handleWebhooks(req, res, pathSegments),
|
|
36131
37375
|
() => handleAgentsRest(req, res, pathSegments, queryParams, myAgentId),
|
|
@@ -36217,7 +37461,7 @@ var httpServer = createHttpServer(async (req, res) => {
|
|
|
36217
37461
|
});
|
|
36218
37462
|
});
|
|
36219
37463
|
var detachRealtime = attachRealtimeTransport(httpServer);
|
|
36220
|
-
var { attachControllerTransport } = await import("./controllers-connect-
|
|
37464
|
+
var { attachControllerTransport } = await import("./controllers-connect-kwpvj3rf.js");
|
|
36221
37465
|
var detachControllers = attachControllerTransport(httpServer);
|
|
36222
37466
|
var stopWorkerNudges = startWorkerNudgeListener();
|
|
36223
37467
|
var stopRoomDeletion = realtimeBus.subscribe("room:namespace-deleted", (namespace) => {
|
|
@@ -36246,7 +37490,7 @@ async function shutdown() {
|
|
|
36246
37490
|
sessionsProcessed: getServerSessionsProcessed()
|
|
36247
37491
|
});
|
|
36248
37492
|
if (hasCapability("scheduling")) {
|
|
36249
|
-
const { stopScheduler } = await import("./index-
|
|
37493
|
+
const { stopScheduler } = await import("./index-7ep4gzdk.js");
|
|
36250
37494
|
stopScheduler();
|
|
36251
37495
|
}
|
|
36252
37496
|
stopHeartbeat();
|
|
@@ -36256,8 +37500,9 @@ async function shutdown() {
|
|
|
36256
37500
|
await drainApi();
|
|
36257
37501
|
await stopScriptRunSupervisor();
|
|
36258
37502
|
await stopSlackApp();
|
|
37503
|
+
await stopChatSdk();
|
|
36259
37504
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
36260
|
-
const { stopOAuthKeepalive } = await import("./keepalive-
|
|
37505
|
+
const { stopOAuthKeepalive } = await import("./keepalive-be9vwy5h.js");
|
|
36261
37506
|
await stopOAuthKeepalive();
|
|
36262
37507
|
}
|
|
36263
37508
|
stopOAuthPendingGc();
|
|
@@ -36337,15 +37582,15 @@ try {
|
|
|
36337
37582
|
console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
|
|
36338
37583
|
}
|
|
36339
37584
|
try {
|
|
36340
|
-
const { ensurePricingSeeded } = await import("./boot-seeds-
|
|
37585
|
+
const { ensurePricingSeeded } = await import("./boot-seeds-kwjq4d2z.js");
|
|
36341
37586
|
ensurePricingSeeded();
|
|
36342
|
-
const { startPricingRefreshLoop } = await import("./pricing-refresh-
|
|
37587
|
+
const { startPricingRefreshLoop } = await import("./pricing-refresh-qb0rv0ap.js");
|
|
36343
37588
|
startPricingRefreshLoop();
|
|
36344
37589
|
} catch (err) {
|
|
36345
37590
|
console.error("[startup] Failed to seed pricing rows:", err);
|
|
36346
37591
|
}
|
|
36347
37592
|
try {
|
|
36348
|
-
const { ensureRbacSeeded } = await import("./boot-seeds-
|
|
37593
|
+
const { ensureRbacSeeded } = await import("./boot-seeds-kwjq4d2z.js");
|
|
36349
37594
|
ensureRbacSeeded();
|
|
36350
37595
|
} catch (err) {
|
|
36351
37596
|
console.error("[startup] Failed to sync RBAC seed rows:", err);
|
|
@@ -36353,7 +37598,7 @@ try {
|
|
|
36353
37598
|
throw err;
|
|
36354
37599
|
}
|
|
36355
37600
|
try {
|
|
36356
|
-
const { runAllSeeders } = await import("./index-
|
|
37601
|
+
const { runAllSeeders } = await import("./index-s2wxgzr0.js");
|
|
36357
37602
|
await runAllSeeders({ scriptEmbeddingMode: "skip" });
|
|
36358
37603
|
} catch (err) {
|
|
36359
37604
|
console.error("[startup] Failed to seed built-in entities:", err);
|
|
@@ -36401,6 +37646,9 @@ httpServer.listen(port, async () => {
|
|
|
36401
37646
|
} catch (err) {
|
|
36402
37647
|
console.error("[Slack] Failed to start, continuing boot without Slack:", err);
|
|
36403
37648
|
}
|
|
37649
|
+
startChatSdk().catch((err) => {
|
|
37650
|
+
console.error("[chat-sdk] Failed to start, continuing without Chat SDK:", scrubSecrets(err instanceof Error ? err.message : String(err)));
|
|
37651
|
+
});
|
|
36404
37652
|
startQueueStallAlarm();
|
|
36405
37653
|
initGitHub();
|
|
36406
37654
|
initGitLab();
|
|
@@ -36411,39 +37659,39 @@ httpServer.listen(port, async () => {
|
|
|
36411
37659
|
await initWorkflows();
|
|
36412
37660
|
await startScriptRunSupervisor(getMcpBaseUrl());
|
|
36413
37661
|
if (hasCapability("scheduling")) {
|
|
36414
|
-
const { startScheduler } = await import("./index-
|
|
36415
|
-
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-
|
|
37662
|
+
const { startScheduler } = await import("./index-7ep4gzdk.js");
|
|
37663
|
+
const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-rmpw9a8q.js");
|
|
36416
37664
|
const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
|
|
36417
37665
|
startScheduler(getExecutorRegistry2(), intervalMs, {
|
|
36418
37666
|
runId: globalState.__runId
|
|
36419
37667
|
});
|
|
36420
37668
|
}
|
|
36421
37669
|
if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
|
|
36422
|
-
const { startHeartbeat } = await import("./index-
|
|
37670
|
+
const { startHeartbeat } = await import("./index-v1v6n7hg.js");
|
|
36423
37671
|
const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
|
|
36424
37672
|
startHeartbeat(heartbeatMs);
|
|
36425
37673
|
}
|
|
36426
37674
|
startPoolRouting();
|
|
36427
37675
|
startRuntimeSupervisor();
|
|
36428
37676
|
if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
|
|
36429
|
-
const { startOAuthKeepalive } = await import("./keepalive-
|
|
37677
|
+
const { startOAuthKeepalive } = await import("./keepalive-be9vwy5h.js");
|
|
36430
37678
|
startOAuthKeepalive();
|
|
36431
37679
|
}
|
|
36432
37680
|
if (process.env.OAUTH_REFRESH_SWEEP_DISABLE !== "true") {
|
|
36433
|
-
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-
|
|
37681
|
+
const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-cpdnfwdj.js");
|
|
36434
37682
|
startOAuthRefreshSweep();
|
|
36435
37683
|
}
|
|
36436
37684
|
startOAuthPendingGc();
|
|
36437
37685
|
await startMemoryGc();
|
|
36438
37686
|
await startDbRetention();
|
|
36439
37687
|
startHumanFreeDrain();
|
|
36440
|
-
import("./boot-reembed-
|
|
37688
|
+
import("./boot-reembed-5c2z0mbe.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
36441
37689
|
console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
|
|
36442
37690
|
});
|
|
36443
|
-
import("./boot-reembed-
|
|
37691
|
+
import("./boot-reembed-j8xa181e.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
36444
37692
|
console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
|
|
36445
37693
|
});
|
|
36446
|
-
import("./boot-scrub-sweep-
|
|
37694
|
+
import("./boot-scrub-sweep-hnkn3rgt.js").then(({ runBootScrubSweep }) => runBootScrubSweep()).catch((err) => {
|
|
36447
37695
|
console.error("[boot-scrub-sweep] startup scrub failed (non-fatal):", err);
|
|
36448
37696
|
});
|
|
36449
37697
|
}).on("error", (err) => {
|