@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
package/src/http/pages.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
updatePage,
|
|
20
20
|
withFavoriteFlags,
|
|
21
21
|
} from "../be/db";
|
|
22
|
+
import { getPageEditCounter } from "../be/db/page-versions";
|
|
22
23
|
import { snapshotPage } from "../pages/version";
|
|
23
24
|
import { resolveTemplate } from "../prompts/resolver";
|
|
24
25
|
// Side-effect import: registers `task.page.feedback`.
|
|
@@ -227,7 +228,7 @@ const updatePageRoute = route({
|
|
|
227
228
|
/**
|
|
228
229
|
* POST /api/pages/:id/feedback — turn the element comments collected by the
|
|
229
230
|
* in-page feedback overlay (`?__swarm-feedback`, see
|
|
230
|
-
* `src/
|
|
231
|
+
* `src/pages/feedback-overlay.ts`) into one task for the lead. In the
|
|
231
232
|
* dashboard the SPA calls it with its bearer for the page it shows. A page
|
|
232
233
|
* opened directly reaches it through the `/@swarm/api/*` page proxy, which
|
|
233
234
|
* pins `X-Page-Id` to the cookie's page, so a page can only file feedback on
|
|
@@ -482,17 +483,6 @@ function withShareUrls<T extends { id: string; slug: string }>(
|
|
|
482
483
|
};
|
|
483
484
|
}
|
|
484
485
|
|
|
485
|
-
/**
|
|
486
|
-
* Compute the page's "edit counter" — `MAX(page_versions.version) + 1`. Means
|
|
487
|
-
* "this is the N-th edit since the page was created". After the first PUT the
|
|
488
|
-
* value is 2 (one snapshot row → version 1 → counter becomes 2). This is the
|
|
489
|
-
* value POST and PUT return as `version` on the wire.
|
|
490
|
-
*/
|
|
491
|
-
async function pageEditCounter(pageId: string): Promise<number> {
|
|
492
|
-
const versions = await getPageVersions(pageId);
|
|
493
|
-
return versions.length > 0 ? versions[0]!.version + 1 : 1;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
486
|
/**
|
|
497
487
|
* Viewer and page-supplied text sits inside a `<page_feedback>` block in the
|
|
498
488
|
* task prompt. Defuse any tag of that name so the text cannot close the block
|
|
@@ -843,7 +833,7 @@ export async function handlePages(
|
|
|
843
833
|
updatePageRoute.respond(res, 200, {
|
|
844
834
|
id: updated.id,
|
|
845
835
|
key: updated.key,
|
|
846
|
-
version: await
|
|
836
|
+
version: await getPageEditCounter(updated.id),
|
|
847
837
|
});
|
|
848
838
|
return true;
|
|
849
839
|
}
|
package/src/http/poll.ts
CHANGED
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
getTaskAttachments,
|
|
20
20
|
getTaskById,
|
|
21
21
|
getUnassignedTaskIdsForAgent,
|
|
22
|
-
getUserById,
|
|
23
22
|
hasCapacity,
|
|
24
23
|
isExtensionAgent,
|
|
25
24
|
recordBudgetRefusalNotification,
|
|
@@ -27,7 +26,6 @@ import {
|
|
|
27
26
|
updateAgentStatusFromCapacity,
|
|
28
27
|
upsertChannelActivityCursor,
|
|
29
28
|
} from "../be/db";
|
|
30
|
-
import { renderIdentity, resolveIdentity } from "../be/identity";
|
|
31
29
|
import {
|
|
32
30
|
parseModelTierOverridesHeader,
|
|
33
31
|
recordClaimModelResolution,
|
|
@@ -37,19 +35,14 @@ import { poolTaskRunsOnHarness } from "../be/model-validation";
|
|
|
37
35
|
import { getRuntimeInstanceById, touchRuntimeInstance } from "../be/multi-runtime";
|
|
38
36
|
import { hasCapability } from "../server";
|
|
39
37
|
import { fetchChannelActivity } from "../slack/channel-activity";
|
|
38
|
+
import { type TaskModelPinFields, taskModelPin } from "../tasks/model-pin";
|
|
40
39
|
import { emitTaskTelemetry, resolveTriggerSurface } from "../telemetry-trigger";
|
|
41
|
-
import {
|
|
42
|
-
AgentTaskSchema,
|
|
43
|
-
BudgetRefusedTriggerSchema,
|
|
44
|
-
TaskAttachmentSchema,
|
|
45
|
-
UserCommsPrefsSchema,
|
|
46
|
-
UserSchema,
|
|
47
|
-
} from "../types";
|
|
40
|
+
import { AgentTaskSchema, BudgetRefusedTriggerSchema, TaskAttachmentSchema } from "../types";
|
|
48
41
|
import { ensure } from "../utils/business-use";
|
|
49
42
|
import { isLeadChannelMonitoringEnabled } from "../utils/lead-monitor-channels";
|
|
50
43
|
import { isMultiRuntimeEnabled } from "../utils/multi-runtime";
|
|
51
|
-
import { getUserCommsPrefs } from "../utils/requester-comms";
|
|
52
44
|
import { isRuntimePoolsEnabled } from "../utils/runtime-pools-flag";
|
|
45
|
+
import { buildTaskRequestedBy, TaskRequestedBySchema } from "./requested-by";
|
|
53
46
|
import { route, runtimeInstanceHeader } from "./route-def";
|
|
54
47
|
import { jsonError } from "./utils";
|
|
55
48
|
|
|
@@ -100,27 +93,11 @@ const PollTriggerAttachmentSchema = TaskAttachmentSchema.pick({
|
|
|
100
93
|
sizeBytes: true,
|
|
101
94
|
});
|
|
102
95
|
|
|
103
|
-
// Requester projection sent on `task_assigned` triggers — either the resolved
|
|
104
|
-
// user's identity fields, or (when no `requestedByUserId` is recorded) just a
|
|
105
|
-
// rendered `name` for the UNKNOWN-identity sentinel.
|
|
106
|
-
const PollRequestedBySchema = UserSchema.pick({
|
|
107
|
-
id: true,
|
|
108
|
-
name: true,
|
|
109
|
-
email: true,
|
|
110
|
-
role: true,
|
|
111
|
-
notes: true,
|
|
112
|
-
}).extend({
|
|
113
|
-
// Absent for the UNKNOWN-identity sentinel (Slack-only requester, no users row).
|
|
114
|
-
id: z.string().optional(),
|
|
115
|
-
// Structured communication preferences from `users.metadata.comms`.
|
|
116
|
-
comms: UserCommsPrefsSchema.optional(),
|
|
117
|
-
});
|
|
118
|
-
|
|
119
96
|
const PollTaskOfferedTriggerSchema = z.object({
|
|
120
97
|
type: z.literal("task_offered"),
|
|
121
98
|
taskId: z.string(),
|
|
122
99
|
task: AgentTaskSchema,
|
|
123
|
-
requestedBy:
|
|
100
|
+
requestedBy: TaskRequestedBySchema.optional(),
|
|
124
101
|
});
|
|
125
102
|
|
|
126
103
|
const PollTaskAssignedTriggerSchema = z.object({
|
|
@@ -132,7 +109,7 @@ const PollTaskAssignedTriggerSchema = z.object({
|
|
|
132
109
|
task: AgentTaskSchema.extend({
|
|
133
110
|
attachments: z.array(PollTriggerAttachmentSchema),
|
|
134
111
|
}),
|
|
135
|
-
requestedBy:
|
|
112
|
+
requestedBy: TaskRequestedBySchema.optional(),
|
|
136
113
|
});
|
|
137
114
|
|
|
138
115
|
// `budget_refused` reuses the canonical `BudgetRefusedTriggerSchema` entity
|
|
@@ -204,38 +181,6 @@ const pollTriggers = route({
|
|
|
204
181
|
const CHANNEL_ACTIVITY_INTERVAL_MS = 60_000; // Check at most once per 60s
|
|
205
182
|
let lastChannelActivityCheckAt = 0;
|
|
206
183
|
|
|
207
|
-
function getRequesterNotes(notes: string | undefined): string | undefined {
|
|
208
|
-
return typeof notes === "string" && notes.trim().length > 0 ? notes : undefined;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Resolve the requester projection for a task trigger. If the task carries a
|
|
213
|
-
* machine-recorded external id (today: the Slack user field) but no
|
|
214
|
-
* requestedByUserId, render the explicit UNKNOWN sentinel instead of silently
|
|
215
|
-
* omitting the section: never a substituted human (Rule 33 /
|
|
216
|
-
* provenance-or-silence).
|
|
217
|
-
*/
|
|
218
|
-
async function buildTriggerRequestedBy(task: {
|
|
219
|
-
requestedByUserId?: string | null;
|
|
220
|
-
slackUserId?: string | null;
|
|
221
|
-
}): Promise<z.infer<typeof PollRequestedBySchema> | undefined> {
|
|
222
|
-
const user = task.requestedByUserId ? await getUserById(task.requestedByUserId) : undefined;
|
|
223
|
-
if (user) {
|
|
224
|
-
return {
|
|
225
|
-
id: user.id,
|
|
226
|
-
name: user.name,
|
|
227
|
-
email: user.email,
|
|
228
|
-
role: user.role,
|
|
229
|
-
notes: getRequesterNotes(user.notes),
|
|
230
|
-
comms: getUserCommsPrefs(user),
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
if (task.slackUserId) {
|
|
234
|
-
return { name: renderIdentity(await resolveIdentity("slack", task.slackUserId)) };
|
|
235
|
-
}
|
|
236
|
-
return undefined;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
184
|
/**
|
|
240
185
|
* Slim attachment projection for the `task_assigned` poll trigger — just
|
|
241
186
|
* enough (id, name, mimeType, sizeBytes) for the worker to build a one-shot
|
|
@@ -256,16 +201,31 @@ async function attachmentsForTrigger(
|
|
|
256
201
|
/**
|
|
257
202
|
* Claim-time model resolution (runbooks/model-tiers.md). Never blocks a claim:
|
|
258
203
|
* a resolution failure leaves the worker on its own local resolution.
|
|
204
|
+
*
|
|
205
|
+
* The trigger's `model` is the task's own pin, not the column: a re-claimed
|
|
206
|
+
* row carries the model its previous session reported, and the worker treats
|
|
207
|
+
* `task.model` as a pin that beats the agent's current MODEL_OVERRIDE. The
|
|
208
|
+
* previous claim record is overwritten for the same reason.
|
|
259
209
|
*/
|
|
260
210
|
async function claimModelFields(
|
|
261
|
-
task: { id: string
|
|
211
|
+
task: TaskModelPinFields & { id: string },
|
|
262
212
|
agent: Parameters<typeof recordClaimModelResolution>[1],
|
|
263
|
-
): Promise<Awaited<ReturnType<typeof recordClaimModelResolution
|
|
213
|
+
): Promise<Awaited<ReturnType<typeof recordClaimModelResolution>> & { model: string | undefined }> {
|
|
214
|
+
const pin = taskModelPin(task);
|
|
215
|
+
const cleared = {
|
|
216
|
+
model: pin,
|
|
217
|
+
resolvedModel: undefined,
|
|
218
|
+
modelSource: undefined,
|
|
219
|
+
modelAlias: undefined,
|
|
220
|
+
};
|
|
264
221
|
try {
|
|
265
|
-
return
|
|
222
|
+
return {
|
|
223
|
+
...cleared,
|
|
224
|
+
...(await recordClaimModelResolution({ ...task, model: pin }, agent)),
|
|
225
|
+
};
|
|
266
226
|
} catch (error) {
|
|
267
227
|
console.warn(`[/api/poll] model resolution failed for task ${task.id}:`, error);
|
|
268
|
-
return
|
|
228
|
+
return cleared;
|
|
269
229
|
}
|
|
270
230
|
}
|
|
271
231
|
|
|
@@ -422,7 +382,7 @@ export async function handlePoll(
|
|
|
422
382
|
const claimedTask = await claimOfferedTask(firstOfferedTask.id, myAgentId);
|
|
423
383
|
if (claimedTask) {
|
|
424
384
|
await recordRuntimeTask(claimedTask.id);
|
|
425
|
-
const offeredRequestedBy = await
|
|
385
|
+
const offeredRequestedBy = await buildTaskRequestedBy(claimedTask);
|
|
426
386
|
return {
|
|
427
387
|
trigger: {
|
|
428
388
|
type: "task_offered",
|
|
@@ -519,8 +479,8 @@ export async function handlePoll(
|
|
|
519
479
|
});
|
|
520
480
|
|
|
521
481
|
// Resolve requesting user if available (UNKNOWN sentinel handling
|
|
522
|
-
// lives in
|
|
523
|
-
const assignedRequestedBy = await
|
|
482
|
+
// lives in buildTaskRequestedBy).
|
|
483
|
+
const assignedRequestedBy = await buildTaskRequestedBy(pendingTask);
|
|
524
484
|
// The surface that started the whole chain, so the worker can tag
|
|
525
485
|
// its session events with it (workers cannot read the task tree).
|
|
526
486
|
const assignedTriggerSurface = await resolveTriggerSurface(
|
|
@@ -667,7 +627,7 @@ export async function handlePoll(
|
|
|
667
627
|
agentId: myAgentId,
|
|
668
628
|
});
|
|
669
629
|
});
|
|
670
|
-
const claimedRequestedBy = await
|
|
630
|
+
const claimedRequestedBy = await buildTaskRequestedBy(claimed);
|
|
671
631
|
const claimedTriggerSurface = await resolveTriggerSurface(
|
|
672
632
|
claimed.id,
|
|
673
633
|
claimed.source,
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getUserById } from "../be/db";
|
|
3
|
+
import { renderIdentity, resolveIdentity } from "../be/identity";
|
|
4
|
+
import { UserCommsPrefsSchema, UserSchema } from "../types";
|
|
5
|
+
import { getUserCommsPrefs } from "../utils/requester-comms";
|
|
6
|
+
|
|
7
|
+
// Requester projection sent with a task to the worker that runs it (poll
|
|
8
|
+
// triggers, paused-task resume) — either the resolved user's identity fields,
|
|
9
|
+
// or (when no `requestedByUserId` is recorded) just a rendered `name` for the
|
|
10
|
+
// UNKNOWN-identity sentinel.
|
|
11
|
+
export const TaskRequestedBySchema = UserSchema.pick({
|
|
12
|
+
id: true,
|
|
13
|
+
name: true,
|
|
14
|
+
email: true,
|
|
15
|
+
role: true,
|
|
16
|
+
notes: true,
|
|
17
|
+
}).extend({
|
|
18
|
+
// Absent for the UNKNOWN-identity sentinel (Slack-only requester, no users row).
|
|
19
|
+
id: z.string().optional(),
|
|
20
|
+
// Structured communication preferences from `users.metadata.comms`.
|
|
21
|
+
comms: UserCommsPrefsSchema.optional(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function getRequesterNotes(notes: string | undefined): string | undefined {
|
|
25
|
+
return typeof notes === "string" && notes.trim().length > 0 ? notes : undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the requester projection for a task. If the task carries a
|
|
30
|
+
* machine-recorded external id (today: the Slack user field) but no
|
|
31
|
+
* requestedByUserId, render the explicit UNKNOWN sentinel instead of silently
|
|
32
|
+
* omitting the section: never a substituted human (Rule 33 /
|
|
33
|
+
* provenance-or-silence).
|
|
34
|
+
*/
|
|
35
|
+
export async function buildTaskRequestedBy(task: {
|
|
36
|
+
requestedByUserId?: string | null;
|
|
37
|
+
slackUserId?: string | null;
|
|
38
|
+
}): Promise<z.infer<typeof TaskRequestedBySchema> | undefined> {
|
|
39
|
+
const user = task.requestedByUserId ? await getUserById(task.requestedByUserId) : undefined;
|
|
40
|
+
if (user) {
|
|
41
|
+
return {
|
|
42
|
+
id: user.id,
|
|
43
|
+
name: user.name,
|
|
44
|
+
email: user.email,
|
|
45
|
+
role: user.role,
|
|
46
|
+
notes: getRequesterNotes(user.notes),
|
|
47
|
+
comms: getUserCommsPrefs(user),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (task.slackUserId) {
|
|
51
|
+
return { name: renderIdentity(await resolveIdentity("slack", task.slackUserId)) };
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
package/src/http/scripts.ts
CHANGED
|
@@ -765,6 +765,7 @@ export async function handleScripts(
|
|
|
765
765
|
runtimeInstanceId,
|
|
766
766
|
egressSecrets: credentials.egressSecrets,
|
|
767
767
|
failedBindings: credentials.failedBindings,
|
|
768
|
+
userConfig: credentials.userConfig,
|
|
768
769
|
apiConnections: getScriptApiConnectionDescriptors({ agentId: agent.id }),
|
|
769
770
|
mcpConnections: getScriptMcpConnectionDescriptors({ agentId: agent.id }),
|
|
770
771
|
});
|
package/src/http/stats.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { z } from "zod";
|
|
|
3
3
|
import {
|
|
4
4
|
getAgentStatusCounts,
|
|
5
5
|
getAllLogs,
|
|
6
|
-
getAllServices,
|
|
7
6
|
getConcurrentContext,
|
|
8
7
|
getLogsByAgentId,
|
|
9
8
|
getScheduledTasks,
|
|
@@ -14,7 +13,7 @@ import {
|
|
|
14
13
|
import { getDbRetentionStats } from "../be/db-retention";
|
|
15
14
|
import { isSteeringEnabled } from "../be/steering";
|
|
16
15
|
import type { AgentLog } from "../types";
|
|
17
|
-
import { AgentLogSchema, ScheduledTaskSchema
|
|
16
|
+
import { AgentLogSchema, ScheduledTaskSchema } from "../types";
|
|
18
17
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
19
18
|
import { isMultiRuntimeEnabled } from "../utils/multi-runtime";
|
|
20
19
|
import { resolveHttpFavoriteOwner } from "./favorite-owner";
|
|
@@ -166,22 +165,6 @@ const getMetrics = route({
|
|
|
166
165
|
},
|
|
167
166
|
});
|
|
168
167
|
|
|
169
|
-
const listServices = route({
|
|
170
|
-
method: "get",
|
|
171
|
-
path: "/api/services",
|
|
172
|
-
pattern: ["api", "services"],
|
|
173
|
-
summary: "List all registered services",
|
|
174
|
-
tags: ["Stats"],
|
|
175
|
-
query: z.object({
|
|
176
|
-
status: z.string().optional(),
|
|
177
|
-
agentId: z.string().optional(),
|
|
178
|
-
name: z.string().optional(),
|
|
179
|
-
}),
|
|
180
|
-
responses: {
|
|
181
|
-
200: { description: "Service list", schema: z.object({ services: z.array(ServiceSchema) }) },
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
|
|
185
168
|
const listScheduledTasks = route({
|
|
186
169
|
method: "get",
|
|
187
170
|
path: "/api/scheduled-tasks",
|
|
@@ -295,18 +278,6 @@ export async function handleStats(
|
|
|
295
278
|
return true;
|
|
296
279
|
}
|
|
297
280
|
|
|
298
|
-
if (listServices.match(req.method, pathSegments)) {
|
|
299
|
-
const parsed = await listServices.parse(req, res, pathSegments, queryParams);
|
|
300
|
-
if (!parsed) return true;
|
|
301
|
-
const services = await getAllServices({
|
|
302
|
-
status: (parsed.query.status as import("../types").ServiceStatus) || undefined,
|
|
303
|
-
agentId: parsed.query.agentId || undefined,
|
|
304
|
-
name: parsed.query.name || undefined,
|
|
305
|
-
});
|
|
306
|
-
listServices.respond(res, 200, { services });
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
281
|
if (listScheduledTasks.match(req.method, pathSegments)) {
|
|
311
282
|
const parsed = await listScheduledTasks.parse(req, res, pathSegments, queryParams);
|
|
312
283
|
if (!parsed) return true;
|
package/src/http/tasks.ts
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
import { getTaskCitations, TaskCitationSchema } from "../be/task-citations";
|
|
46
46
|
import { findUserById } from "../be/users";
|
|
47
47
|
import { can, type RbacPrincipal, type RbacResource } from "../rbac";
|
|
48
|
+
import { chatThreadOfContextKey } from "../tasks/context-key";
|
|
48
49
|
import { TaskCreationBlockedError } from "../tasks/errors";
|
|
49
50
|
import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
|
|
50
51
|
import { guardTerminalTaskResultWrite } from "../tasks/terminal-result-guard";
|
|
@@ -76,6 +77,7 @@ import { ensure } from "../utils/business-use";
|
|
|
76
77
|
import { getRequestAuth } from "../utils/request-auth-context";
|
|
77
78
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
78
79
|
import { rejectGuest } from "./request-principal";
|
|
80
|
+
import { buildTaskRequestedBy, TaskRequestedBySchema } from "./requested-by";
|
|
79
81
|
import { route } from "./route-def";
|
|
80
82
|
import { jsonError, parseBody } from "./utils";
|
|
81
83
|
|
|
@@ -110,6 +112,7 @@ const AgentTaskSummarySchema = AgentTaskSchema.pick({
|
|
|
110
112
|
modelSource: true,
|
|
111
113
|
modelAlias: true,
|
|
112
114
|
effort: true,
|
|
115
|
+
resolvedEffort: true,
|
|
113
116
|
provider: true,
|
|
114
117
|
requestedByUserId: true,
|
|
115
118
|
progress: true,
|
|
@@ -308,6 +311,10 @@ const createTask = route({
|
|
|
308
311
|
description:
|
|
309
312
|
"Validation error, an unknown `model` (set `allowCustomModel` to store a custom id), or agentId/offeredTo targets an extension identity",
|
|
310
313
|
},
|
|
314
|
+
403: {
|
|
315
|
+
description:
|
|
316
|
+
"An agent caller names a parentTaskId it neither owns nor created, or a non-lead agent binds the task to a chat thread",
|
|
317
|
+
},
|
|
311
318
|
422: {
|
|
312
319
|
description: "Task creation blocked by an extension",
|
|
313
320
|
schema: z.object({
|
|
@@ -357,6 +364,8 @@ const updateSession = route({
|
|
|
357
364
|
claudeSessionId: z.string().min(1),
|
|
358
365
|
provider: ProviderNameSchema.exclude(["devin"]).optional(),
|
|
359
366
|
model: z.string().optional(),
|
|
367
|
+
// Effort the session runs at; null when the harness default applies.
|
|
368
|
+
effort: ReasoningEffortSchema.nullable().optional(),
|
|
360
369
|
providerMeta: z.object({ transport: z.enum(["cli", "sdk"]).optional() }).optional(),
|
|
361
370
|
harnessVariant: z.string().optional(),
|
|
362
371
|
harnessVariantMeta: z.record(z.string(), z.unknown()).optional(),
|
|
@@ -592,7 +601,14 @@ const listPausedTasks = route({
|
|
|
592
601
|
200: {
|
|
593
602
|
description: "Paused task list",
|
|
594
603
|
schema: z.object({
|
|
595
|
-
tasks: z.array(
|
|
604
|
+
tasks: z.array(
|
|
605
|
+
AgentTaskSchema.extend({
|
|
606
|
+
attachments: z.array(TaskAttachmentSchema),
|
|
607
|
+
// Same requester projection a fresh task_assigned trigger carries,
|
|
608
|
+
// so a resumed session gets the same requester-profile prompt.
|
|
609
|
+
requestedBy: TaskRequestedBySchema.optional(),
|
|
610
|
+
}),
|
|
611
|
+
),
|
|
596
612
|
}),
|
|
597
613
|
},
|
|
598
614
|
},
|
|
@@ -954,6 +970,41 @@ export async function handleTasks(
|
|
|
954
970
|
const parentTask = parsed.body.parentTaskId
|
|
955
971
|
? await getTaskById(parsed.body.parentTaskId)
|
|
956
972
|
: null;
|
|
973
|
+
// The child inherits the parent's thread context, so an agent caller must own or
|
|
974
|
+
// have created the parent. Operator and user callers keep their access.
|
|
975
|
+
const principal = await resolveTaskWritePrincipal(req, myAgentId);
|
|
976
|
+
if (
|
|
977
|
+
parentTask &&
|
|
978
|
+
!can({
|
|
979
|
+
principal,
|
|
980
|
+
verb: "task.parent.attach",
|
|
981
|
+
resource: {
|
|
982
|
+
kind: "task",
|
|
983
|
+
taskId: parentTask.id,
|
|
984
|
+
requestedByUserId: parentTask.requestedByUserId,
|
|
985
|
+
creatorAgentId: parentTask.creatorAgentId,
|
|
986
|
+
agentId: parentTask.agentId,
|
|
987
|
+
},
|
|
988
|
+
source: "http",
|
|
989
|
+
}).allow
|
|
990
|
+
) {
|
|
991
|
+
jsonError(res, `You don't have context for parent task ${parentTask.id}.`, 403);
|
|
992
|
+
return true;
|
|
993
|
+
}
|
|
994
|
+
// A chat-sdk contextKey binds the task to a chat thread that its assignee and creator
|
|
995
|
+
// may then read and post to. An agent may only name a thread other than the parent's
|
|
996
|
+
// with the lead's chat post permission.
|
|
997
|
+
if (
|
|
998
|
+
principal.kind === "agent" &&
|
|
999
|
+
parsed.body.contextKey &&
|
|
1000
|
+
parsed.body.contextKey !== parentTask?.contextKey &&
|
|
1001
|
+
chatThreadOfContextKey(parsed.body.contextKey) &&
|
|
1002
|
+
!can({ principal, verb: "integration.chat.post", resource: { kind: "none" }, source: "http" })
|
|
1003
|
+
.allow
|
|
1004
|
+
) {
|
|
1005
|
+
jsonError(res, "Permission denied: only a lead can bind a task to a chat thread.", 403);
|
|
1006
|
+
return true;
|
|
1007
|
+
}
|
|
957
1008
|
let assetKey: string | undefined;
|
|
958
1009
|
try {
|
|
959
1010
|
const inheritedKey = parentTask?.key;
|
|
@@ -1083,6 +1134,7 @@ export async function handleTasks(
|
|
|
1083
1134
|
parsed.body.model,
|
|
1084
1135
|
"harnessVariant" in parsed.body ? parsed.body.harnessVariant : undefined,
|
|
1085
1136
|
"harnessVariantMeta" in parsed.body ? parsed.body.harnessVariantMeta : undefined,
|
|
1137
|
+
"effort" in parsed.body ? parsed.body.effort : undefined,
|
|
1086
1138
|
);
|
|
1087
1139
|
if (!task) {
|
|
1088
1140
|
jsonError(res, "Task not found", 404);
|
|
@@ -1667,10 +1719,14 @@ export async function handleTasks(
|
|
|
1667
1719
|
}
|
|
1668
1720
|
const pausedTasks = await getPausedTasksForAgent(myAgentId);
|
|
1669
1721
|
const tasks = await Promise.all(
|
|
1670
|
-
pausedTasks.map(async (task) =>
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1722
|
+
pausedTasks.map(async (task) => {
|
|
1723
|
+
const requestedBy = await buildTaskRequestedBy(task);
|
|
1724
|
+
return {
|
|
1725
|
+
...task,
|
|
1726
|
+
attachments: await getTaskAttachments(task.id),
|
|
1727
|
+
...(requestedBy && { requestedBy }),
|
|
1728
|
+
};
|
|
1729
|
+
}),
|
|
1674
1730
|
);
|
|
1675
1731
|
listPausedTasks.respond(res, 200, { tasks });
|
|
1676
1732
|
return true;
|
package/src/http/utils.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
2
2
|
import { getActiveTaskCount } from "../be/db";
|
|
3
3
|
import type { SwarmSpan } from "../otel";
|
|
4
4
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
5
|
+
import { getNodeEnv } from "../utils/node-env";
|
|
5
6
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
6
7
|
|
|
7
8
|
export function duplicateGuardedQueryKey(query: URLSearchParams): string | undefined {
|
|
@@ -41,6 +42,18 @@ function getAllowedOrigins(): string[] {
|
|
|
41
42
|
.filter(Boolean);
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Loopback origins on any port are trusted in local development
|
|
47
|
+
* (`NODE_ENV=development`, set by `start:http` and `dev:http`). The dashboard
|
|
48
|
+
* dev server, Playwright, or a second worktree pick arbitrary ports, and every
|
|
49
|
+
* loopback page already runs on the developer's machine. The production binary
|
|
50
|
+
* and the Docker image run without NODE_ENV, so this never applies there.
|
|
51
|
+
*/
|
|
52
|
+
function isDevLoopbackOrigin(origin: string): boolean {
|
|
53
|
+
if (getNodeEnv() !== "development") return false;
|
|
54
|
+
return /^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d{1,5})?$/.test(origin);
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
/**
|
|
45
58
|
* Decide whether `origin` may receive credentialed CORS headers.
|
|
46
59
|
* Unset or blank uses the built-in hosted/dev allowlist. Exact entries retain
|
|
@@ -50,6 +63,7 @@ function getAllowedOrigins(): string[] {
|
|
|
50
63
|
* Bare `*`, `https://*`, other wildcard positions, and non-origin URLs are ignored.
|
|
51
64
|
*/
|
|
52
65
|
function originAllowedForCredentials(origin: string): boolean {
|
|
66
|
+
if (isDevLoopbackOrigin(origin)) return true;
|
|
53
67
|
return getAllowedOrigins().some((entry) => {
|
|
54
68
|
if (!entry.includes("*")) return entry === origin;
|
|
55
69
|
|