@desplega.ai/agent-swarm 1.173.0 → 2.1.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-kr4abrsk.js} +17 -16
- package/dist/{actions-sgeyv08k.js → actions-eh4g6w2r.js} +39 -34
- package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-7h7wdt8q.js} +8 -7
- package/dist/{app-km9qnv2f.js → app-7k8s9w5p.js} +18 -14
- package/dist/{assistant-5r8tcvvd.js → assistant-wswt2y7p.js} +40 -35
- package/dist/{boot-reembed-16rv9843.js → boot-reembed-9apm9qw6.js} +10 -9
- package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-whzbdthj.js} +10 -9
- package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-ndzmvmgt.js} +11 -10
- package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-e9sta0yt.js} +16 -13
- package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-4mqd3r6r.js} +19 -18
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-9wswb52m.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-tpe1effx.js} +6 -4
- package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-q49ghmh9.js} +12402 -11850
- package/dist/{cli-ne7smj1b.js → cli-01xvj1rq.js} +10 -10
- package/dist/{cli-nwrdx840.js → cli-035vekcw.js} +3 -3
- package/dist/{cli-9xf7fdtp.js → cli-0pd8hzhc.js} +29 -6
- package/dist/{cli-tmhsxhb8.js → cli-0veb92a3.js} +28 -6
- package/dist/{cli-c3rk1v0x.js → cli-10jesr25.js} +3 -3
- package/dist/{cli-6thk4jz3.js → cli-1y7yywmj.js} +6 -6
- package/dist/{cli-6r2f7edk.js → cli-20krdhz5.js} +47 -19
- package/dist/{cli-rfs4vddv.js → cli-29rja109.js} +39 -20
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-na2pxe4f.js → cli-2pwa0q4d.js} +15 -4
- package/dist/{cli-7a93cv8c.js → cli-4mengw46.js} +441 -43
- package/dist/{cli-94b48jhk.js → cli-5twdke5x.js} +16 -14
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-w1apjecb.js → cli-711vwbxn.js} +2 -2
- package/dist/{cli-r4fqfpwf.js → cli-78vv7446.js} +50 -27
- package/dist/{cli-srqq3gc5.js → cli-7n6s5man.js} +5 -5
- package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
- package/dist/{cli-2bw3w47j.js → cli-8wwxw8a3.js} +1 -1
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-ywm1azg9.js → cli-9jzdj90z.js} +8 -4
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/cli-cvv9k0hh.js +10143 -0
- package/dist/{cli-anzdk0z4.js → cli-d9286m9h.js} +2 -2
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-gmdajfw5.js → cli-gxzkg1de.js} +5020 -1729
- package/dist/{cli-451ks6aw.js → cli-h1arqn31.js} +1 -1
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-jpc4r224.js → cli-hqr88ew6.js} +19 -3
- package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
- package/dist/{cli-cd0hv9nh.js → cli-j67mh2vg.js} +2 -2
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-d603qf86.js → cli-ksphgh48.js} +10 -8
- package/dist/{cli-3nxdmjrc.js → cli-mgz4nbgg.js} +4 -4
- package/dist/{cli-saqyage0.js → cli-mz5as5ha.js} +179 -27
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-ppy4nnnh.js → cli-n8ndw8j7.js} +2 -2
- package/dist/{cli-1w0vj3gw.js → cli-naqzr17j.js} +7 -7
- package/dist/{cli-0a7mm3zp.js → cli-nm1p8jfr.js} +25 -21
- package/dist/{cli-wrh08zjd.js → cli-p3zbc1rw.js} +5 -18
- package/dist/{cli-hsem16hb.js → cli-pe05f8yk.js} +29 -6
- package/dist/{cli-5wpw4rab.js → cli-qmzsbkvy.js} +5 -5
- package/dist/{cli-bv2etw2y.js → cli-qnm4e9e4.js} +99 -590
- package/dist/{cli-1x7da0de.js → cli-qqy4q48b.js} +8 -8
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-5er5gjbm.js → cli-r35rw5de.js} +15 -15
- package/dist/{cli-v3zhnxsb.js → cli-r610p9bs.js} +2 -2
- package/dist/{cli-7jykv7ef.js → cli-rc6pf5kv.js} +1 -1
- package/dist/{cli-x119kdba.js → cli-rdxm77k3.js} +1 -1
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-0p3enk35.js → cli-s69nfyeh.js} +9 -1
- package/dist/{cli-0kxf81jj.js → cli-sawv63e8.js} +2 -2
- package/dist/{cli-e3pmyt39.js → cli-sg19gbf0.js} +1 -1
- package/dist/{cli-d161g69q.js → cli-shk7r5cs.js} +57 -6
- package/dist/{cli-7pz3b7x5.js → cli-sksetb2q.js} +36 -1
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-db3m6zdt.js → cli-t02z59f2.js} +1 -1
- package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
- package/dist/{cli-s8z6x4b4.js → cli-v7g551te.js} +225 -113
- package/dist/{cli-rfz2ve55.js → cli-vgqzp4em.js} +3341 -955
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/cli-wfnemr1t.js +86 -0
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-qm1448f9.js → cli-wms6x9db.js} +8 -8
- package/dist/{cli-tadfgd0t.js → cli-x1r545x8.js} +33 -4
- package/dist/{cli-xc7p7s3g.js → cli-xczsgshn.js} +6 -6
- package/dist/{cli-fmhj1ehj.js → cli-y3167wt1.js} +882 -271
- package/dist/{cli-r0byd61h.js → cli-yjmqpxt3.js} +17 -16
- package/dist/{cli-81r1wjyv.js → cli-z780ec7c.js} +1 -1
- package/dist/{cli-phcqp1b9.js → cli-zm9t2vde.js} +2 -2
- package/dist/cli.js +34 -49
- package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-4z16v9n0.js} +15 -14
- package/dist/{codex-login-841kv5fk.js → codex-login-pkepy2j1.js} +3 -2
- package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-rvms9y2x.js} +15 -14
- package/dist/{commands-z8fq9qna.js → commands-2a9rtyat.js} +11 -10
- package/dist/{controller-hq5ggpcp.js → controller-3k3madbn.js} +5 -4
- package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-v9yn8zb9.js} +42 -37
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-98gbhyzn.js} +7 -6
- package/dist/{db-qfpq4bt7.js → db-eywwsnjw.js} +30 -9
- package/dist/{db-yyhqqrbf.js → db-ncypk9np.js} +12 -11
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-zeq8b9gz.js} +3 -2
- package/dist/{dispatcher-x0x7qfcq.js → dispatcher-w94kc575.js} +38 -33
- package/dist/{docker-f503k9p0.js → docker-b1e4cqab.js} +3 -2
- package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-47ztej36.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-bbt8ey45.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-dp804sen.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-j2jdg3qb.js} +3 -2
- package/dist/{external-channel-h1fjecwe.js → external-channel-zrkg8ar9.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-s9ncp9vy.js} +18 -17
- package/dist/{handlers-znb9n7d4.js → handlers-kqftvjgw.js} +41 -36
- package/dist/{heartbeat-bm4qkn8d.js → heartbeat-9q96p8v9.js} +43 -38
- package/dist/{hook-254r4mza.js → hook-56qe10dp.js} +11 -23
- package/dist/{hook-xaa3q80s.js → hook-yy6rw42k.js} +12 -11
- package/dist/{http-3dgrgp8y.js → http-r2dnb8f8.js} +2411 -275
- package/dist/{index-fx3jqq1e.js → index-3gtmkhc6.js} +38 -33
- package/dist/{index-bdsqa799.js → index-3k5hkz7r.js} +43 -38
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-g2byveez.js → index-5e101240.js} +38 -33
- package/dist/{index-2ybk7khy.js → index-5wyfjc2c.js} +845 -683
- 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-jd7sejm2.js → index-vxvhxxbn.js} +10 -9
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{keepalive-6ywhpja1.js → keepalive-psj6j54c.js} +12 -11
- package/dist/{lead-cw45n21s.js → lead-hajz4688.js} +61 -56
- package/dist/{maintenance-ss1a1ge9.js → maintenance-ps02sb5m.js} +10 -9
- package/dist/{node-fkajaq96.js → node-mwb5r697.js} +2 -1
- package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-0284h93b.js} +11 -10
- package/dist/{onboard-8hzdhc1k.js → onboard-rbf6bg01.js} +11 -3
- package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-13dcatgq.js} +18 -13
- package/dist/{otel-impl-e6mnvc4v.js → otel-impl-zvqcbhp7.js} +242 -868
- package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-xxy47q4v.js} +244 -106
- package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-kefx9v3t.js} +12 -11
- package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-3m36rxm2.js} +11 -10
- package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-z76xv0hq.js} +12 -11
- package/dist/{render-v2-907cy6sa.js → render-v2-wz73bs25.js} +18 -14
- package/dist/{resume-42stcaz0.js → resume-k4wzge8w.js} +25 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-adbc1c10.js → setup-2fp2pypp.js} +2 -2
- package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
- package/dist/{work-objects-wpj8ck95.js → work-objects-6k0ywz3m.js} +41 -36
- package/dist/{worker-bzdra9rf.js → worker-5v3rxsdh.js} +61 -56
- package/dist/{x-qfmygqqv.js → x-4mtdeym1.js} +3 -2
- package/openapi.json +1279 -329
- package/package.json +15 -15
- package/src/agentmail/handlers.ts +21 -11
- package/src/apps/definition.ts +16 -0
- package/src/azure-devops/api.ts +52 -2
- package/src/azure-devops/boards-sync.ts +50 -20
- package/src/azure-devops/index.ts +1 -0
- package/src/azure-devops/outbound.ts +95 -0
- package/src/be/boot-seeds.ts +11 -0
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/model-profiles.ts +315 -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 +237 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +87 -36
- 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/migrations/219_relabel_pi_context_compactions.sql +22 -0
- package/src/be/migrations/220_model_profiles.sql +137 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +155 -10
- package/src/be/model-validation.ts +12 -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 +22 -8
- package/src/be/secret-registry.ts +6 -2
- 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-model-profiles.ts +41 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +368 -0
- 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-scripts/index.ts +9 -0
- 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 +53 -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 +193 -71
- package/src/e2b/env.ts +5 -0
- package/src/extensions/catalog.generated.json +17 -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/loader.ts +10 -5
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/heartbeat.ts +2 -1
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/agents.ts +49 -2
- package/src/http/all-routes.ts +1 -1
- package/src/http/apps.ts +30 -3
- package/src/http/config.ts +62 -19
- package/src/http/core.ts +8 -0
- package/src/http/index.ts +25 -3
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp.ts +15 -5
- package/src/http/model-profiles.ts +303 -0
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +13 -7
- package/src/http/pages.ts +3 -13
- package/src/http/poll.ts +42 -71
- package/src/http/requested-by.ts +54 -0
- package/src/http/script-runs.ts +1 -1
- package/src/http/scripts.ts +26 -2
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +79 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +160 -3
- 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/{artifact-sdk → pages}/feedback-overlay.ts +65 -6
- package/src/pages/version.ts +4 -5
- package/src/prompts/base-prompt.ts +111 -45
- package/src/providers/acp-target-catalog.ts +6 -0
- package/src/providers/acp-targets.ts +56 -3
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +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/pi-mono-extension.ts +17 -3
- package/src/providers/pricing-sources.md +33 -2
- package/src/providers/reasoning-effort.ts +37 -0
- package/src/providers/types.ts +6 -2
- package/src/rbac/legacy-policy.ts +16 -2
- package/src/rbac/permissions.ts +26 -0
- package/src/scheduler/deferred-task-waits.ts +18 -5
- package/src/scheduler/scheduler.ts +11 -3
- package/src/scripts-runtime/executors/quickjs-prelude.ts +75 -6
- package/src/scripts-runtime/executors/quickjs-runner.ts +85 -8
- package/src/scripts-runtime/executors/quickjs-web-shims.ts +1041 -0
- package/src/scripts-runtime/extract-args-schema.ts +9 -8
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/quickjs-compat.ts +464 -0
- package/src/scripts-runtime/sdk-allowlist.ts +12 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +39 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +66 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +39 -15
- package/src/server.ts +62 -19
- package/src/slack/blocks.ts +4 -2
- package/src/slack/event-dedup.ts +1 -1
- package/src/slack/reaction-shortcode.ts +14 -0
- package/src/slack/render-v2.ts +12 -7
- package/src/slack/responses.ts +5 -4
- package/src/slack/thread-buffer.ts +41 -22
- 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 +15 -33
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/agentmail-filters.test.ts +47 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/apps-spike2.test.ts +35 -0
- package/src/tests/azure-devops-outbound.test.ts +420 -0
- package/src/tests/base-prompt.test.ts +58 -54
- package/src/tests/chat-sdk-commands.test.ts +191 -0
- package/src/tests/chat-sdk-config.test.ts +334 -0
- package/src/tests/chat-sdk-discord-api.test.ts +68 -0
- package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
- package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
- package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
- package/src/tests/chat-sdk-harness.ts +146 -0
- package/src/tests/chat-sdk-inbound.test.ts +363 -0
- package/src/tests/chat-sdk-relay.test.ts +470 -0
- package/src/tests/chat-sdk-reload.test.ts +128 -0
- package/src/tests/chat-sdk-shutdown.test.ts +220 -0
- package/src/tests/chat-sdk-slack.test.ts +268 -0
- package/src/tests/chat-sdk-state.test.ts +163 -0
- package/src/tests/chat-sdk-status-route.test.ts +382 -0
- package/src/tests/chat-sdk-teams.test.ts +277 -0
- package/src/tests/chat-sdk-tools.test.ts +520 -0
- package/src/tests/chat-sdk-typing.test.ts +120 -0
- package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
- package/src/tests/claude-adapter-binary.test.ts +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 +22 -0
- package/src/tests/db-task-write-contract.test.ts +11 -0
- package/src/tests/deferred-task-wake.test.ts +78 -1
- 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/env-flag.test.ts +1 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-catalog.test.ts +1 -0
- package/src/tests/extensions-example-comms-adherence-gate.test.ts +413 -0
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-loader.test.ts +15 -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/heartbeat-jev-gate-credentials.test.ts +168 -0
- package/src/tests/heartbeat-jev-gate.test.ts +385 -0
- 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-profile-backcompat.test.ts +327 -0
- package/src/tests/model-profile-providers.test.ts +302 -0
- package/src/tests/model-profile-runtime-secrets.test.ts +223 -0
- package/src/tests/model-profiles-api.test.ts +614 -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-keys.test.ts +121 -0
- package/src/tests/pages-feedback.test.ts +4 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-context-compaction.test.ts +193 -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/profile-claim.test.ts +269 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/quickjs-compat.test.ts +213 -0
- package/src/tests/rbac-engine.test.ts +32 -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 +6 -0
- package/src/tests/script-executor-conformance.test.ts +252 -1
- package/src/tests/script-executor-quickjs.test.ts +96 -0
- package/src/tests/script-runs-http.test.ts +89 -0
- package/src/tests/scripts-http.test.ts +217 -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 +96 -0
- package/src/tests/seed-model-profiles.test.ts +174 -0
- package/src/tests/seed-scripts.test.ts +2 -2
- 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/skill-invocations.test.ts +4 -2
- package/src/tests/slack-blocks.test.ts +36 -0
- package/src/tests/slack-inline-output.test.ts +14 -0
- package/src/tests/slack-reaction-config.test.ts +20 -0
- package/src/tests/slack-render-v2.test.ts +37 -0
- package/src/tests/slack-thread-buffer.test.ts +98 -1
- 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-llm.test.ts +61 -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/model-profiles/list-model-profiles.ts +54 -0
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/request-human-input.ts +11 -3
- package/src/tools/script-apis.ts +5 -1
- package/src/tools/script-upsert.ts +4 -1
- package/src/tools/send-task.ts +48 -1
- 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/system-one-decide.ts +104 -0
- package/src/tools/task-action.ts +22 -1
- package/src/tools/tool-config.ts +14 -6
- package/src/types.ts +48 -3
- 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 +86 -10
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/utils/vcs-repo-match.ts +29 -0
- package/src/workflows/executors/raw-llm.ts +8 -3
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/src/workflows/executors/system-one-decision.ts +21 -11
- package/src/workflows/executors/workflow-llm.ts +22 -0
- package/src/workflows/index.ts +21 -12
- package/templates/extensions/README.md +1 -0
- package/templates/extensions/comms-adherence-gate/README.md +88 -0
- package/templates/extensions/comms-adherence-gate/hooks.ts +489 -0
- package/templates/extensions/comms-adherence-gate/manifest.json +8 -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-42qhyvwx.js +0 -33
- 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/http/scripts.ts
CHANGED
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
import { can } from "../rbac";
|
|
42
42
|
import { extractScriptSignature, type ScriptSignature } from "../scripts-runtime/extract-signature";
|
|
43
43
|
import { runScript } from "../scripts-runtime/loader";
|
|
44
|
+
import { checkQuickJSCompat, quickJSCompatWarnings } from "../scripts-runtime/quickjs-compat";
|
|
44
45
|
import {
|
|
45
46
|
ScriptApiAuthModeSchema,
|
|
46
47
|
ScriptApiRecordSchema,
|
|
@@ -236,6 +237,10 @@ const upsertRoute = route({
|
|
|
236
237
|
name: z.string(),
|
|
237
238
|
version: z.number(),
|
|
238
239
|
contentDeduped: z.boolean(),
|
|
240
|
+
warnings: z
|
|
241
|
+
.array(z.string())
|
|
242
|
+
.optional()
|
|
243
|
+
.describe("Advisory quickjs-executor compatibility findings. Never blocks the save."),
|
|
239
244
|
}),
|
|
240
245
|
},
|
|
241
246
|
400: { description: "Validation or typecheck failure" },
|
|
@@ -424,7 +429,15 @@ const createScriptApiRoute = route({
|
|
|
424
429
|
params: idParamsSchema,
|
|
425
430
|
body: createScriptApiBodySchema,
|
|
426
431
|
responses: {
|
|
427
|
-
201: {
|
|
432
|
+
201: {
|
|
433
|
+
description: "Endpoint created",
|
|
434
|
+
schema: scriptApiWithSecretSchema.extend({
|
|
435
|
+
warnings: z
|
|
436
|
+
.array(z.string())
|
|
437
|
+
.optional()
|
|
438
|
+
.describe("Advisory quickjs-executor compatibility findings for the script."),
|
|
439
|
+
}),
|
|
440
|
+
},
|
|
428
441
|
400: { description: "Validation error or script has no owning agent" },
|
|
429
442
|
404: { description: "Script not found" },
|
|
430
443
|
},
|
|
@@ -702,10 +715,14 @@ export async function handleScripts(
|
|
|
702
715
|
});
|
|
703
716
|
}
|
|
704
717
|
|
|
718
|
+
const warnings = quickJSCompatWarnings(
|
|
719
|
+
checkQuickJSCompat(parsed.body.source, { fsMode: parsed.body.fsMode }),
|
|
720
|
+
);
|
|
705
721
|
upsertRoute.respond(res, 200, {
|
|
706
722
|
name: result.script.name,
|
|
707
723
|
version: result.script.version,
|
|
708
724
|
contentDeduped: result.contentDeduped,
|
|
725
|
+
...(warnings.length > 0 ? { warnings } : {}),
|
|
709
726
|
});
|
|
710
727
|
return true;
|
|
711
728
|
}
|
|
@@ -765,6 +782,7 @@ export async function handleScripts(
|
|
|
765
782
|
runtimeInstanceId,
|
|
766
783
|
egressSecrets: credentials.egressSecrets,
|
|
767
784
|
failedBindings: credentials.failedBindings,
|
|
785
|
+
userConfig: credentials.userConfig,
|
|
768
786
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: agent.id }),
|
|
769
787
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: agent.id }),
|
|
770
788
|
});
|
|
@@ -1091,7 +1109,13 @@ export async function handleScripts(
|
|
|
1091
1109
|
label: parsed.body.label ?? null,
|
|
1092
1110
|
createdBy: await resolveHttpAuditUserId(req, agentId),
|
|
1093
1111
|
});
|
|
1094
|
-
|
|
1112
|
+
const warnings = quickJSCompatWarnings(
|
|
1113
|
+
checkQuickJSCompat(script.source, { fsMode: script.fsMode }),
|
|
1114
|
+
);
|
|
1115
|
+
createScriptApiRoute.respond(res, 201, {
|
|
1116
|
+
...endpoint,
|
|
1117
|
+
...(warnings.length > 0 ? { warnings } : {}),
|
|
1118
|
+
});
|
|
1095
1119
|
return true;
|
|
1096
1120
|
}
|
|
1097
1121
|
|
package/src/http/stats.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { z } from "zod";
|
|
|
3
3
|
import {
|
|
4
4
|
getAgentStatusCounts,
|
|
5
5
|
getAllLogs,
|
|
6
|
-
getAllServices,
|
|
7
6
|
getConcurrentContext,
|
|
8
7
|
getLogsByAgentId,
|
|
9
8
|
getScheduledTasks,
|
|
@@ -14,7 +13,7 @@ import {
|
|
|
14
13
|
import { getDbRetentionStats } from "../be/db-retention";
|
|
15
14
|
import { isSteeringEnabled } from "../be/steering";
|
|
16
15
|
import type { AgentLog } from "../types";
|
|
17
|
-
import { AgentLogSchema, ScheduledTaskSchema
|
|
16
|
+
import { AgentLogSchema, ScheduledTaskSchema } from "../types";
|
|
18
17
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
19
18
|
import { isMultiRuntimeEnabled } from "../utils/multi-runtime";
|
|
20
19
|
import { resolveHttpFavoriteOwner } from "./favorite-owner";
|
|
@@ -166,22 +165,6 @@ const getMetrics = route({
|
|
|
166
165
|
},
|
|
167
166
|
});
|
|
168
167
|
|
|
169
|
-
const listServices = route({
|
|
170
|
-
method: "get",
|
|
171
|
-
path: "/api/services",
|
|
172
|
-
pattern: ["api", "services"],
|
|
173
|
-
summary: "List all registered services",
|
|
174
|
-
tags: ["Stats"],
|
|
175
|
-
query: z.object({
|
|
176
|
-
status: z.string().optional(),
|
|
177
|
-
agentId: z.string().optional(),
|
|
178
|
-
name: z.string().optional(),
|
|
179
|
-
}),
|
|
180
|
-
responses: {
|
|
181
|
-
200: { description: "Service list", schema: z.object({ services: z.array(ServiceSchema) }) },
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
|
|
185
168
|
const listScheduledTasks = route({
|
|
186
169
|
method: "get",
|
|
187
170
|
path: "/api/scheduled-tasks",
|
|
@@ -295,18 +278,6 @@ export async function handleStats(
|
|
|
295
278
|
return true;
|
|
296
279
|
}
|
|
297
280
|
|
|
298
|
-
if (listServices.match(req.method, pathSegments)) {
|
|
299
|
-
const parsed = await listServices.parse(req, res, pathSegments, queryParams);
|
|
300
|
-
if (!parsed) return true;
|
|
301
|
-
const services = await getAllServices({
|
|
302
|
-
status: (parsed.query.status as import("../types").ServiceStatus) || undefined,
|
|
303
|
-
agentId: parsed.query.agentId || undefined,
|
|
304
|
-
name: parsed.query.name || undefined,
|
|
305
|
-
});
|
|
306
|
-
listServices.respond(res, 200, { services });
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
281
|
if (listScheduledTasks.match(req.method, pathSegments)) {
|
|
311
282
|
const parsed = await listScheduledTasks.parse(req, res, pathSegments, queryParams);
|
|
312
283
|
if (!parsed) return true;
|
package/src/http/tasks.ts
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
updateTaskTitle,
|
|
36
36
|
updateTaskVcs,
|
|
37
37
|
} from "../be/db";
|
|
38
|
+
import { modelProfileRefError, taskProfileError } from "../be/db/model-profiles";
|
|
38
39
|
import { explicitModelErrorForAgent } from "../be/model-validation";
|
|
39
40
|
import {
|
|
40
41
|
getTaskSteeringFields,
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
import { getTaskCitations, TaskCitationSchema } from "../be/task-citations";
|
|
46
47
|
import { findUserById } from "../be/users";
|
|
47
48
|
import { can, type RbacPrincipal, type RbacResource } from "../rbac";
|
|
49
|
+
import { chatThreadOfContextKey } from "../tasks/context-key";
|
|
48
50
|
import { TaskCreationBlockedError } from "../tasks/errors";
|
|
49
51
|
import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
|
|
50
52
|
import { guardTerminalTaskResultWrite } from "../tasks/terminal-result-guard";
|
|
@@ -76,6 +78,7 @@ import { ensure } from "../utils/business-use";
|
|
|
76
78
|
import { getRequestAuth } from "../utils/request-auth-context";
|
|
77
79
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
78
80
|
import { rejectGuest } from "./request-principal";
|
|
81
|
+
import { buildTaskRequestedBy, TaskRequestedBySchema } from "./requested-by";
|
|
79
82
|
import { route } from "./route-def";
|
|
80
83
|
import { jsonError, parseBody } from "./utils";
|
|
81
84
|
|
|
@@ -110,6 +113,7 @@ const AgentTaskSummarySchema = AgentTaskSchema.pick({
|
|
|
110
113
|
modelSource: true,
|
|
111
114
|
modelAlias: true,
|
|
112
115
|
effort: true,
|
|
116
|
+
resolvedEffort: true,
|
|
113
117
|
provider: true,
|
|
114
118
|
requestedByUserId: true,
|
|
115
119
|
progress: true,
|
|
@@ -284,6 +288,8 @@ const createTask = route({
|
|
|
284
288
|
*/
|
|
285
289
|
allowCustomModel: z.boolean().optional(),
|
|
286
290
|
effort: ReasoningEffortSchema.optional(),
|
|
291
|
+
/** Model profile name, applied at claim. Exclusive with `model` and `modelTier`. */
|
|
292
|
+
profile: z.string().trim().min(1).optional(),
|
|
287
293
|
/**
|
|
288
294
|
* Create in `draft` status instead of the normal pending/unassigned/offered
|
|
289
295
|
* status (#1240) — the task exists and is visible to its owner, but is not
|
|
@@ -308,6 +314,10 @@ const createTask = route({
|
|
|
308
314
|
description:
|
|
309
315
|
"Validation error, an unknown `model` (set `allowCustomModel` to store a custom id), or agentId/offeredTo targets an extension identity",
|
|
310
316
|
},
|
|
317
|
+
403: {
|
|
318
|
+
description:
|
|
319
|
+
"An agent caller names a parentTaskId it neither owns nor created, or a non-lead agent binds the task to a chat thread",
|
|
320
|
+
},
|
|
311
321
|
422: {
|
|
312
322
|
description: "Task creation blocked by an extension",
|
|
313
323
|
schema: z.object({
|
|
@@ -357,6 +367,8 @@ const updateSession = route({
|
|
|
357
367
|
claudeSessionId: z.string().min(1),
|
|
358
368
|
provider: ProviderNameSchema.exclude(["devin"]).optional(),
|
|
359
369
|
model: z.string().optional(),
|
|
370
|
+
// Effort the session runs at; null when the harness default applies.
|
|
371
|
+
effort: ReasoningEffortSchema.nullable().optional(),
|
|
360
372
|
providerMeta: z.object({ transport: z.enum(["cli", "sdk"]).optional() }).optional(),
|
|
361
373
|
harnessVariant: z.string().optional(),
|
|
362
374
|
harnessVariantMeta: z.record(z.string(), z.unknown()).optional(),
|
|
@@ -592,7 +604,14 @@ const listPausedTasks = route({
|
|
|
592
604
|
200: {
|
|
593
605
|
description: "Paused task list",
|
|
594
606
|
schema: z.object({
|
|
595
|
-
tasks: z.array(
|
|
607
|
+
tasks: z.array(
|
|
608
|
+
AgentTaskSchema.extend({
|
|
609
|
+
attachments: z.array(TaskAttachmentSchema),
|
|
610
|
+
// Same requester projection a fresh task_assigned trigger carries,
|
|
611
|
+
// so a resumed session gets the same requester-profile prompt.
|
|
612
|
+
requestedBy: TaskRequestedBySchema.optional(),
|
|
613
|
+
}),
|
|
614
|
+
),
|
|
596
615
|
}),
|
|
597
616
|
},
|
|
598
617
|
},
|
|
@@ -950,10 +969,54 @@ export async function handleTasks(
|
|
|
950
969
|
jsonError(res, modelError, 400);
|
|
951
970
|
return true;
|
|
952
971
|
}
|
|
972
|
+
const profileError = await taskProfileError({
|
|
973
|
+
profile: parsed.body.profile,
|
|
974
|
+
...splitLegacyModelAlias({ model: parsed.body.model, modelTier: parsed.body.modelTier }),
|
|
975
|
+
agentId: defaultAgentId,
|
|
976
|
+
});
|
|
977
|
+
if (profileError) {
|
|
978
|
+
jsonError(res, profileError, 400);
|
|
979
|
+
return true;
|
|
980
|
+
}
|
|
953
981
|
|
|
954
982
|
const parentTask = parsed.body.parentTaskId
|
|
955
983
|
? await getTaskById(parsed.body.parentTaskId)
|
|
956
984
|
: null;
|
|
985
|
+
// The child inherits the parent's thread context, so an agent caller must own or
|
|
986
|
+
// have created the parent. Operator and user callers keep their access.
|
|
987
|
+
const principal = await resolveTaskWritePrincipal(req, myAgentId);
|
|
988
|
+
if (
|
|
989
|
+
parentTask &&
|
|
990
|
+
!can({
|
|
991
|
+
principal,
|
|
992
|
+
verb: "task.parent.attach",
|
|
993
|
+
resource: {
|
|
994
|
+
kind: "task",
|
|
995
|
+
taskId: parentTask.id,
|
|
996
|
+
requestedByUserId: parentTask.requestedByUserId,
|
|
997
|
+
creatorAgentId: parentTask.creatorAgentId,
|
|
998
|
+
agentId: parentTask.agentId,
|
|
999
|
+
},
|
|
1000
|
+
source: "http",
|
|
1001
|
+
}).allow
|
|
1002
|
+
) {
|
|
1003
|
+
jsonError(res, `You don't have context for parent task ${parentTask.id}.`, 403);
|
|
1004
|
+
return true;
|
|
1005
|
+
}
|
|
1006
|
+
// A chat-sdk contextKey binds the task to a chat thread that its assignee and creator
|
|
1007
|
+
// may then read and post to. An agent may only name a thread other than the parent's
|
|
1008
|
+
// with the lead's chat post permission.
|
|
1009
|
+
if (
|
|
1010
|
+
principal.kind === "agent" &&
|
|
1011
|
+
parsed.body.contextKey &&
|
|
1012
|
+
parsed.body.contextKey !== parentTask?.contextKey &&
|
|
1013
|
+
chatThreadOfContextKey(parsed.body.contextKey) &&
|
|
1014
|
+
!can({ principal, verb: "integration.chat.post", resource: { kind: "none" }, source: "http" })
|
|
1015
|
+
.allow
|
|
1016
|
+
) {
|
|
1017
|
+
jsonError(res, "Permission denied: only a lead can bind a task to a chat thread.", 403);
|
|
1018
|
+
return true;
|
|
1019
|
+
}
|
|
957
1020
|
let assetKey: string | undefined;
|
|
958
1021
|
try {
|
|
959
1022
|
const inheritedKey = parentTask?.key;
|
|
@@ -1006,6 +1069,7 @@ export async function handleTasks(
|
|
|
1006
1069
|
modelTier: parsed.body.modelTier,
|
|
1007
1070
|
}),
|
|
1008
1071
|
effort: parsed.body.effort,
|
|
1072
|
+
profile: parsed.body.profile,
|
|
1009
1073
|
},
|
|
1010
1074
|
{ origin: "rest", allowCustomModel: parsed.body.allowCustomModel },
|
|
1011
1075
|
);
|
|
@@ -1036,6 +1100,11 @@ export async function handleTasks(
|
|
|
1036
1100
|
jsonError(res, error.message, 400);
|
|
1037
1101
|
return true;
|
|
1038
1102
|
}
|
|
1103
|
+
// The profile was deleted between taskProfileError and the insert.
|
|
1104
|
+
if (modelProfileRefError(error) === "missing") {
|
|
1105
|
+
jsonError(res, `Unknown model profile "${parsed.body.profile}"`, 400);
|
|
1106
|
+
return true;
|
|
1107
|
+
}
|
|
1039
1108
|
console.error("[HTTP] Failed to create task:", error);
|
|
1040
1109
|
jsonError(res, "Failed to create task", 500);
|
|
1041
1110
|
}
|
|
@@ -1083,6 +1152,7 @@ export async function handleTasks(
|
|
|
1083
1152
|
parsed.body.model,
|
|
1084
1153
|
"harnessVariant" in parsed.body ? parsed.body.harnessVariant : undefined,
|
|
1085
1154
|
"harnessVariantMeta" in parsed.body ? parsed.body.harnessVariantMeta : undefined,
|
|
1155
|
+
"effort" in parsed.body ? parsed.body.effort : undefined,
|
|
1086
1156
|
);
|
|
1087
1157
|
if (!task) {
|
|
1088
1158
|
jsonError(res, "Task not found", 404);
|
|
@@ -1667,10 +1737,14 @@ export async function handleTasks(
|
|
|
1667
1737
|
}
|
|
1668
1738
|
const pausedTasks = await getPausedTasksForAgent(myAgentId);
|
|
1669
1739
|
const tasks = await Promise.all(
|
|
1670
|
-
pausedTasks.map(async (task) =>
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1740
|
+
pausedTasks.map(async (task) => {
|
|
1741
|
+
const requestedBy = await buildTaskRequestedBy(task);
|
|
1742
|
+
return {
|
|
1743
|
+
...task,
|
|
1744
|
+
attachments: await getTaskAttachments(task.id),
|
|
1745
|
+
...(requestedBy && { requestedBy }),
|
|
1746
|
+
};
|
|
1747
|
+
}),
|
|
1674
1748
|
);
|
|
1675
1749
|
listPausedTasks.respond(res, 200, { tasks });
|
|
1676
1750
|
return true;
|
package/src/http/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
2
2
|
import { getActiveTaskCount } from "../be/db";
|
|
3
3
|
import type { SwarmSpan } from "../otel";
|
|
4
4
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
5
|
+
import { getNodeEnv } from "../utils/node-env";
|
|
5
6
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
6
7
|
|
|
7
8
|
export function duplicateGuardedQueryKey(query: URLSearchParams): string | undefined {
|
|
@@ -41,6 +42,18 @@ function getAllowedOrigins(): string[] {
|
|
|
41
42
|
.filter(Boolean);
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Loopback origins on any port are trusted in local development
|
|
47
|
+
* (`NODE_ENV=development`, set by `start:http` and `dev:http`). The dashboard
|
|
48
|
+
* dev server, Playwright, or a second worktree pick arbitrary ports, and every
|
|
49
|
+
* loopback page already runs on the developer's machine. The production binary
|
|
50
|
+
* and the Docker image run without NODE_ENV, so this never applies there.
|
|
51
|
+
*/
|
|
52
|
+
function isDevLoopbackOrigin(origin: string): boolean {
|
|
53
|
+
if (getNodeEnv() !== "development") return false;
|
|
54
|
+
return /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d{1,5})?$/.test(origin);
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
/**
|
|
45
58
|
* Decide whether `origin` may receive credentialed CORS headers.
|
|
46
59
|
* Unset or blank uses the built-in hosted/dev allowlist. Exact entries retain
|
|
@@ -50,6 +63,7 @@ function getAllowedOrigins(): string[] {
|
|
|
50
63
|
* Bare `*`, `https://*`, other wildcard positions, and non-origin URLs are ignored.
|
|
51
64
|
*/
|
|
52
65
|
function originAllowedForCredentials(origin: string): boolean {
|
|
66
|
+
if (isDevLoopbackOrigin(origin)) return true;
|
|
53
67
|
return getAllowedOrigins().some((entry) => {
|
|
54
68
|
if (!entry.includes("*")) return entry === origin;
|
|
55
69
|
|
package/src/http/webhooks.ts
CHANGED
|
@@ -66,6 +66,14 @@ import {
|
|
|
66
66
|
verifyGitLabWebhook,
|
|
67
67
|
} from "../gitlab";
|
|
68
68
|
import { gitlabWorkflowActionName } from "../gitlab/workflow-action-name";
|
|
69
|
+
import { trackBackground } from "../integrations/chat-sdk/background";
|
|
70
|
+
import { isChatSdkEnabled } from "../integrations/chat-sdk/config";
|
|
71
|
+
import {
|
|
72
|
+
getChatInstance,
|
|
73
|
+
isChatAdapterConfigured,
|
|
74
|
+
isChatSdkStopping,
|
|
75
|
+
} from "../integrations/chat-sdk/runtime";
|
|
76
|
+
import { isTrustedTeamsServiceUrl } from "../integrations/chat-sdk/teams-origin";
|
|
69
77
|
import {
|
|
70
78
|
type KapsoMessageActionResult,
|
|
71
79
|
markKapsoMessageRead,
|
|
@@ -76,11 +84,14 @@ import { getKapsoConfig } from "../integrations/kapso/config";
|
|
|
76
84
|
import type { KapsoWebhookPayload } from "../integrations/kapso/inbound";
|
|
77
85
|
import { resolveKapsoRequestedByUserId, routeKapsoInbound } from "../integrations/kapso/inbound";
|
|
78
86
|
import { TaskCreationBlockedError } from "../tasks/errors";
|
|
87
|
+
import { getPublicMcpBaseUrl } from "../utils/constants";
|
|
88
|
+
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
79
89
|
import { canonicalAzureDevOpsRepoUrl } from "../vcs/azure-devops";
|
|
80
90
|
import { getExecutorRegistry } from "../workflows";
|
|
81
91
|
import { workflowEventBus } from "../workflows/event-bus";
|
|
82
92
|
import { handleWebhookTrigger, verifyHmacSignature, WebhookError } from "../workflows/triggers";
|
|
83
93
|
import { route } from "./route-def";
|
|
94
|
+
import { BODY_TOO_LARGE, enforceContentLengthCap, jsonError } from "./utils";
|
|
84
95
|
|
|
85
96
|
// ─── Route Definitions (documentation only — webhooks handle their own body parsing) ─
|
|
86
97
|
|
|
@@ -203,8 +214,75 @@ const kapsoWebhook = route({
|
|
|
203
214
|
},
|
|
204
215
|
});
|
|
205
216
|
|
|
217
|
+
const chatSdkWebhook = route({
|
|
218
|
+
method: "post",
|
|
219
|
+
path: "/api/integrations/chat/{adapter}/webhook",
|
|
220
|
+
pattern: ["api", "integrations", "chat", null, "webhook"],
|
|
221
|
+
summary: "Handle Chat SDK platform webhooks (Telegram, Slack, Discord, Teams)",
|
|
222
|
+
tags: ["Webhooks"],
|
|
223
|
+
params: z.object({ adapter: z.string().describe("Chat SDK adapter name, e.g. telegram") }),
|
|
224
|
+
auth: { apiKey: false },
|
|
225
|
+
rbac: {
|
|
226
|
+
ungated:
|
|
227
|
+
"provider webhook: the Chat SDK adapter verifies the platform signature (Telegram secret token, Slack signing secret, Discord Ed25519, Teams JWT)",
|
|
228
|
+
},
|
|
229
|
+
responses: {
|
|
230
|
+
200: { description: "Adapter response", unstructured: "adapter response proxied as-is" },
|
|
231
|
+
401: { description: "Invalid platform signature or secret token" },
|
|
232
|
+
403: { description: "Teams activity whose serviceUrl is not a Bot Framework host" },
|
|
233
|
+
404: { description: "Chat SDK disabled or adapter not configured" },
|
|
234
|
+
413: { description: "Body exceeds 1 MiB" },
|
|
235
|
+
503: { description: "Adapter configured but failed to start" },
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Upper bound for a Chat SDK webhook body. Platform payloads are a few KB and
|
|
241
|
+
* files travel by URL, so anything larger is not a platform delivery.
|
|
242
|
+
*/
|
|
243
|
+
const CHAT_SDK_WEBHOOK_MAX_BODY_BYTES = 1024 * 1024;
|
|
244
|
+
|
|
206
245
|
// ─── Handler ─────────────────────────────────────────────────────────────────
|
|
207
246
|
|
|
247
|
+
/** False when a Teams activity body carries a `serviceUrl` that is not a Bot Framework host. */
|
|
248
|
+
function hasTrustedTeamsServiceUrl(body: Buffer): boolean {
|
|
249
|
+
let serviceUrl: unknown;
|
|
250
|
+
try {
|
|
251
|
+
serviceUrl = (JSON.parse(body.toString("utf-8")) as { serviceUrl?: unknown } | null)
|
|
252
|
+
?.serviceUrl;
|
|
253
|
+
} catch {
|
|
254
|
+
// Not JSON: the adapter rejects it.
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
if (serviceUrl === undefined || serviceUrl === null || serviceUrl === "") return true;
|
|
258
|
+
return typeof serviceUrl === "string" && isTrustedTeamsServiceUrl(serviceUrl);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Rebuild a Fetch `Request` from the raw Node request. Headers come from
|
|
263
|
+
* `rawHeaders` pairs: building `Headers` from `IncomingMessage.headers`
|
|
264
|
+
* comma-joins repeated values, which breaks signature checks.
|
|
265
|
+
*/
|
|
266
|
+
function toFetchRequest(req: IncomingMessage, rawBody: Buffer, fallbackPath: string): Request {
|
|
267
|
+
const headers = new Headers();
|
|
268
|
+
if (Array.isArray(req.rawHeaders) && req.rawHeaders.length > 0) {
|
|
269
|
+
for (let i = 0; i + 1 < req.rawHeaders.length; i += 2) {
|
|
270
|
+
headers.append(req.rawHeaders[i] as string, req.rawHeaders[i + 1] as string);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
274
|
+
for (const item of Array.isArray(value) ? value : value === undefined ? [] : [value]) {
|
|
275
|
+
headers.append(name, item);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return new Request(`${getPublicMcpBaseUrl()}${req.url ?? fallbackPath}`, {
|
|
280
|
+
method: req.method ?? "POST",
|
|
281
|
+
headers,
|
|
282
|
+
body: rawBody.length > 0 ? new Uint8Array(rawBody) : undefined,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
208
286
|
function logKapsoAckResult(action: string, result: KapsoMessageActionResult): void {
|
|
209
287
|
if (result.ok) return;
|
|
210
288
|
console.warn(
|
|
@@ -316,7 +394,8 @@ export async function handleWebhooks(
|
|
|
316
394
|
return true;
|
|
317
395
|
}
|
|
318
396
|
|
|
319
|
-
|
|
397
|
+
const deliveryId = req.headers["x-github-delivery"] as string | undefined;
|
|
398
|
+
console.log(`[GitHub] Received ${eventType} event (delivery ${deliveryId ?? "unknown"})`);
|
|
320
399
|
|
|
321
400
|
let result: WebhookDispatchResult = { created: false };
|
|
322
401
|
|
|
@@ -678,9 +757,8 @@ export async function handleWebhooks(
|
|
|
678
757
|
payload.message &&
|
|
679
758
|
!isInboxAllowed(payload.message.inbox_id, process.env.AGENTMAIL_INBOX_DOMAIN_FILTER)
|
|
680
759
|
) {
|
|
681
|
-
const domain = payload.message.inbox_id.split("@")[1] ?? "unknown";
|
|
682
760
|
console.log(
|
|
683
|
-
`[AgentMail] Ignoring event for inbox
|
|
761
|
+
`[AgentMail] Ignoring event for inbox "${payload.message.inbox_id}" (not in AGENTMAIL_INBOX_DOMAIN_FILTER)`,
|
|
684
762
|
);
|
|
685
763
|
return true;
|
|
686
764
|
}
|
|
@@ -818,5 +896,84 @@ export async function handleWebhooks(
|
|
|
818
896
|
return true;
|
|
819
897
|
}
|
|
820
898
|
|
|
899
|
+
// Chat SDK webhook: the adapter verifies the platform signature over the raw
|
|
900
|
+
// body, so the request is proxied as-is and the adapter's response returned.
|
|
901
|
+
if (chatSdkWebhook.match(req.method, pathSegments)) {
|
|
902
|
+
const adapterName = pathSegments[3] ?? "";
|
|
903
|
+
if (!isChatSdkEnabled() || !isChatAdapterConfigured(adapterName)) {
|
|
904
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
905
|
+
res.end(JSON.stringify({ error: "Chat SDK adapter not configured" }));
|
|
906
|
+
return true;
|
|
907
|
+
}
|
|
908
|
+
if (isChatSdkStopping()) {
|
|
909
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
910
|
+
res.end(JSON.stringify({ error: "Chat SDK is shutting down" }));
|
|
911
|
+
return true;
|
|
912
|
+
}
|
|
913
|
+
const chat = getChatInstance(adapterName);
|
|
914
|
+
const handler = chat?.webhooks[adapterName];
|
|
915
|
+
if (!handler) {
|
|
916
|
+
res.writeHead(503, { "Content-Type": "application/json" });
|
|
917
|
+
res.end(JSON.stringify({ error: "Chat SDK adapter failed to start" }));
|
|
918
|
+
return true;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// The route is unauthenticated and the adapter verifies the signature over
|
|
922
|
+
// the buffered body, so the body is bounded before it is buffered. An
|
|
923
|
+
// oversized stream is answered at once and drained without buffering, the
|
|
924
|
+
// same way `parseBody` keeps the connection usable.
|
|
925
|
+
if (enforceContentLengthCap(req, res, CHAT_SDK_WEBHOOK_MAX_BODY_BYTES) === BODY_TOO_LARGE) {
|
|
926
|
+
return true;
|
|
927
|
+
}
|
|
928
|
+
const chunks: Buffer[] = [];
|
|
929
|
+
let receivedBytes = 0;
|
|
930
|
+
let tooLarge = false;
|
|
931
|
+
for await (const chunk of req) {
|
|
932
|
+
if (tooLarge) continue;
|
|
933
|
+
receivedBytes += (chunk as Buffer).byteLength;
|
|
934
|
+
if (receivedBytes > CHAT_SDK_WEBHOOK_MAX_BODY_BYTES) {
|
|
935
|
+
tooLarge = true;
|
|
936
|
+
chunks.length = 0;
|
|
937
|
+
jsonError(res, `Payload too large (max ${CHAT_SDK_WEBHOOK_MAX_BODY_BYTES} bytes)`, 413);
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
chunks.push(chunk as Buffer);
|
|
941
|
+
}
|
|
942
|
+
if (tooLarge) return true;
|
|
943
|
+
const rawBody = Buffer.concat(chunks);
|
|
944
|
+
// The Teams adapter replies, reads history and downloads files with the
|
|
945
|
+
// bot token at the activity's serviceUrl, and caches it for DMs. Refuse an
|
|
946
|
+
// untrusted one before the adapter sees the activity.
|
|
947
|
+
if (adapterName === "teams" && !hasTrustedTeamsServiceUrl(rawBody)) {
|
|
948
|
+
console.warn("[chat-sdk] teams webhook refused: serviceUrl is not a Bot Framework host");
|
|
949
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
950
|
+
res.end(JSON.stringify({ error: "Untrusted Teams serviceUrl" }));
|
|
951
|
+
return true;
|
|
952
|
+
}
|
|
953
|
+
const request = toFetchRequest(req, rawBody, `/api/integrations/chat/${adapterName}/webhook`);
|
|
954
|
+
|
|
955
|
+
try {
|
|
956
|
+
const response = await handler(request, {
|
|
957
|
+
// Handler errors are logged by `trackBackground` in `handlers.ts`.
|
|
958
|
+
waitUntil: trackBackground,
|
|
959
|
+
});
|
|
960
|
+
const responseHeaders: Record<string, string> = {};
|
|
961
|
+
response.headers.forEach((value, name) => {
|
|
962
|
+
responseHeaders[name] = value;
|
|
963
|
+
});
|
|
964
|
+
const body = Buffer.from(await response.arrayBuffer());
|
|
965
|
+
res.writeHead(response.status, responseHeaders);
|
|
966
|
+
res.end(body);
|
|
967
|
+
} catch (err) {
|
|
968
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
969
|
+
console.error(`[chat-sdk] ${adapterName} webhook failed: ${scrubSecrets(message)}`);
|
|
970
|
+
if (!res.headersSent) {
|
|
971
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
972
|
+
}
|
|
973
|
+
res.end(JSON.stringify({ error: "Chat SDK webhook failed" }));
|
|
974
|
+
}
|
|
975
|
+
return true;
|
|
976
|
+
}
|
|
977
|
+
|
|
821
978
|
return false;
|
|
822
979
|
}
|
package/src/http/x.ts
CHANGED
|
@@ -255,6 +255,7 @@ export async function handleX(
|
|
|
255
255
|
timeoutMs,
|
|
256
256
|
egressSecrets: credentials.egressSecrets,
|
|
257
257
|
failedBindings: credentials.failedBindings,
|
|
258
|
+
userConfig: credentials.userConfig,
|
|
258
259
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: endpoint.agentId }),
|
|
259
260
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: endpoint.agentId }),
|
|
260
261
|
});
|