@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
|
@@ -9,13 +9,28 @@
|
|
|
9
9
|
|
|
10
10
|
import { existsSync, readFileSync } from "node:fs";
|
|
11
11
|
import { dirname, join } from "node:path";
|
|
12
|
+
import {
|
|
13
|
+
baseUrlOverride,
|
|
14
|
+
ignoredBaseUrlVar,
|
|
15
|
+
type OpenAICompatibleProvider,
|
|
16
|
+
openAICompatibleKeyVars,
|
|
17
|
+
openAICompatibleProvider,
|
|
18
|
+
openAICompatibleProviders,
|
|
19
|
+
providerBaseUrl,
|
|
20
|
+
providerForKeyVar,
|
|
21
|
+
providerKeyVars,
|
|
22
|
+
} from "@desplega/model-catalog";
|
|
12
23
|
import type { OpenCode, OpenCodeEvent } from "@opencode/sdk";
|
|
13
24
|
import {
|
|
14
25
|
CONTEXT_FORMULA,
|
|
15
26
|
clampContextPercent,
|
|
16
27
|
getContextWindowSize,
|
|
17
28
|
} from "../utils/context-window";
|
|
18
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
openAICompatibleKeyLabels,
|
|
31
|
+
splitCredentialPool,
|
|
32
|
+
validateOpencodeCredentials,
|
|
33
|
+
} from "../utils/credentials";
|
|
19
34
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
20
35
|
import { fetchInstalledMcpServers } from "../utils/mcp-server-fetcher";
|
|
21
36
|
import { swarmRuntimeInstanceId } from "../utils/multi-runtime";
|
|
@@ -24,7 +39,7 @@ import {
|
|
|
24
39
|
getOpenRouterAttributionHeaders,
|
|
25
40
|
getOpenRouterBaseUrl,
|
|
26
41
|
} from "../utils/openrouter-base-url";
|
|
27
|
-
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
42
|
+
import { registerVolatileSecret, scrubSecrets } from "../utils/secret-scrubber";
|
|
28
43
|
import { resolveSlashSkillPrompt } from "./codex-skill-resolver";
|
|
29
44
|
import { CTX_MODE_NUDGE_EVERY } from "./ctx-mode-env";
|
|
30
45
|
import { OpenRouterBilling } from "./opencode-billing";
|
|
@@ -61,8 +76,12 @@ export type OpencodeConfig = {
|
|
|
61
76
|
provider?: Record<
|
|
62
77
|
string,
|
|
63
78
|
{
|
|
79
|
+
/** Env var names OpenCode reads the key from; `[]` stops it reading `process.env`. */
|
|
80
|
+
env?: string[];
|
|
81
|
+
npm?: string;
|
|
82
|
+
name?: string;
|
|
64
83
|
options?: Record<string, unknown>;
|
|
65
|
-
models?: Record<string, { options?: Record<string, unknown
|
|
84
|
+
models?: Record<string, { options?: Record<string, unknown>; [key: string]: unknown }>;
|
|
66
85
|
}
|
|
67
86
|
>;
|
|
68
87
|
[key: string]: unknown;
|
|
@@ -80,18 +99,41 @@ function opencodeModelToCredKey(modelStr: string | undefined): string | null {
|
|
|
80
99
|
if (provider === "anthropic") return "ANTHROPIC_API_KEY";
|
|
81
100
|
if (provider === "openrouter") return "OPENROUTER_API_KEY";
|
|
82
101
|
if (provider === "openai") return "OPENAI_API_KEY";
|
|
102
|
+
// OpenAI-compatible registry providers (`nan`, `helmcode`).
|
|
103
|
+
const direct = openAICompatibleProvider(provider);
|
|
104
|
+
if (direct) return direct.envVar;
|
|
83
105
|
}
|
|
84
106
|
return null;
|
|
85
107
|
}
|
|
86
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Env var names that satisfy `requiredKey`. The runner copies a registry
|
|
111
|
+
* key alias (`HELMCODE_API_NAN`) into its canonical var per task, but a
|
|
112
|
+
* check that reads `process.env` directly sees only the alias.
|
|
113
|
+
*/
|
|
114
|
+
function credKeyNames(requiredKey: string): readonly string[] {
|
|
115
|
+
const direct = providerForKeyVar(requiredKey);
|
|
116
|
+
return direct ? providerKeyVars(direct) : [requiredKey];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Keys that satisfy opencode when no model pins a provider. */
|
|
120
|
+
const OPENCODE_ANY_KEY_VARS = [
|
|
121
|
+
"OPENROUTER_API_KEY",
|
|
122
|
+
"ANTHROPIC_API_KEY",
|
|
123
|
+
"OPENAI_API_KEY",
|
|
124
|
+
...openAICompatibleKeyVars(),
|
|
125
|
+
];
|
|
126
|
+
|
|
87
127
|
/**
|
|
88
128
|
* Opencode is satisfied by ANY of:
|
|
89
129
|
* 1. `~/.local/share/opencode/auth.json` exists (the file `opencode auth login`
|
|
90
130
|
* writes; OpenCode 2 imports it into its credential store on start).
|
|
91
131
|
* 2. `MODEL_OVERRIDE` resolves to a provider-prefixed model — only that
|
|
92
|
-
* provider's key is required
|
|
132
|
+
* provider's key is required (a registry provider also accepts its key
|
|
133
|
+
* aliases: `nan/*` takes `HELMCODE_API_NAN`).
|
|
93
134
|
* 3. Otherwise any one of OPENROUTER_API_KEY / ANTHROPIC_API_KEY /
|
|
94
|
-
* OPENAI_API_KEY
|
|
135
|
+
* OPENAI_API_KEY / a registry provider key (canonical or alias)
|
|
136
|
+
* suffices.
|
|
95
137
|
*/
|
|
96
138
|
export function checkOpencodeCredentials(
|
|
97
139
|
env: Record<string, string | undefined>,
|
|
@@ -106,7 +148,7 @@ export function checkOpencodeCredentials(
|
|
|
106
148
|
|
|
107
149
|
const requiredKey = opencodeModelToCredKey(env.MODEL_OVERRIDE);
|
|
108
150
|
if (requiredKey) {
|
|
109
|
-
if (env[
|
|
151
|
+
if (credKeyNames(requiredKey).some((name) => env[name])) {
|
|
110
152
|
return { ready: true, missing: [], satisfiedBy: "env" };
|
|
111
153
|
}
|
|
112
154
|
return {
|
|
@@ -116,13 +158,26 @@ export function checkOpencodeCredentials(
|
|
|
116
158
|
};
|
|
117
159
|
}
|
|
118
160
|
|
|
119
|
-
if (
|
|
161
|
+
if (OPENCODE_ANY_KEY_VARS.some((name) => env[name])) {
|
|
120
162
|
return { ready: true, missing: [], satisfiedBy: "env" };
|
|
121
163
|
}
|
|
122
164
|
return {
|
|
123
165
|
ready: false,
|
|
124
|
-
missing: [
|
|
125
|
-
|
|
166
|
+
missing: [
|
|
167
|
+
"OPENROUTER_API_KEY",
|
|
168
|
+
"ANTHROPIC_API_KEY",
|
|
169
|
+
"OPENAI_API_KEY",
|
|
170
|
+
...openAICompatibleProviders().map((p) => p.envVar),
|
|
171
|
+
authFile,
|
|
172
|
+
],
|
|
173
|
+
hint: `Set one of ${[
|
|
174
|
+
"OPENROUTER_API_KEY",
|
|
175
|
+
"ANTHROPIC_API_KEY",
|
|
176
|
+
"OPENAI_API_KEY",
|
|
177
|
+
...openAICompatibleKeyLabels(),
|
|
178
|
+
].join(
|
|
179
|
+
" / ",
|
|
180
|
+
)} (any one suffices), or run \`opencode auth login\` to create ~/.local/share/opencode/auth.json.`,
|
|
126
181
|
};
|
|
127
182
|
}
|
|
128
183
|
|
|
@@ -217,6 +272,150 @@ export function applyOpenRouterBaseUrlOverride(
|
|
|
217
272
|
};
|
|
218
273
|
}
|
|
219
274
|
|
|
275
|
+
/**
|
|
276
|
+
* OpenCode provider block for an OpenAI-compatible registry provider that
|
|
277
|
+
* OpenCode does not ship (`catalog: "registry"`, e.g. `helmcode`). `apiKey` is
|
|
278
|
+
* a literal key (embedded host) or an `{env:NAME}` reference (ACP
|
|
279
|
+
* subprocess). `baseUrl` is the `<ID>_BASE_URL` override or the registry
|
|
280
|
+
* default. `env: []` keeps OpenCode from reading a key out of `process.env`.
|
|
281
|
+
* A `modelId` missing from the registry (accepted through `allowCustomModel`)
|
|
282
|
+
* gets a bare entry so OpenCode still resolves it instead of falling back to
|
|
283
|
+
* its default model.
|
|
284
|
+
*/
|
|
285
|
+
export function buildOpenAICompatibleProviderBlock(
|
|
286
|
+
provider: OpenAICompatibleProvider,
|
|
287
|
+
apiKey: string,
|
|
288
|
+
modelId?: string,
|
|
289
|
+
baseUrl: string = provider.baseUrl,
|
|
290
|
+
): NonNullable<OpencodeConfig["provider"]>[string] {
|
|
291
|
+
const models: Record<string, Record<string, unknown>> = {};
|
|
292
|
+
for (const m of provider.models) {
|
|
293
|
+
models[m.id] = {
|
|
294
|
+
name: m.name,
|
|
295
|
+
tool_call: true,
|
|
296
|
+
reasoning: m.reasoning,
|
|
297
|
+
limit: { context: m.contextWindow, output: m.maxOutputTokens },
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
if (modelId && !models[modelId]) models[modelId] = { name: modelId, tool_call: true };
|
|
301
|
+
return {
|
|
302
|
+
npm: provider.npm,
|
|
303
|
+
name: provider.displayName,
|
|
304
|
+
env: [],
|
|
305
|
+
options: { baseURL: baseUrl, apiKey },
|
|
306
|
+
models,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Built-in OpenCode providers whose key OpenCode reads from `process.env`:
|
|
312
|
+
* `openrouter` plus every registry provider models.dev lists
|
|
313
|
+
* (`catalog: "models.dev"`, e.g. `nan`), which OpenCode ships built in.
|
|
314
|
+
*/
|
|
315
|
+
function envBoundKeyVars(providerId: string): readonly string[] | undefined {
|
|
316
|
+
if (providerId === "openrouter") return ["OPENROUTER_API_KEY"];
|
|
317
|
+
const direct = openAICompatibleProvider(providerId);
|
|
318
|
+
return direct?.catalog === "models.dev" ? providerKeyVars(direct) : undefined;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Registry providers OpenCode does not ship (`catalog: "registry"`); they get a full custom block. */
|
|
322
|
+
function customBlockProvider(providerId: string): OpenAICompatibleProvider | undefined {
|
|
323
|
+
const direct = openAICompatibleProvider(providerId);
|
|
324
|
+
return direct?.catalog === "registry" ? direct : undefined;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* One key from the first non-empty var in `names`. The runner's per-task env
|
|
329
|
+
* already holds one picked pool member; a value that still carries a comma
|
|
330
|
+
* pool (no runner, or `process.env`) yields its first member.
|
|
331
|
+
*/
|
|
332
|
+
function pickProviderKey(
|
|
333
|
+
env: Record<string, string | undefined>,
|
|
334
|
+
names: readonly string[],
|
|
335
|
+
): { key: string; name: string } | undefined {
|
|
336
|
+
for (const name of names) {
|
|
337
|
+
const value = env[name]?.trim();
|
|
338
|
+
if (!value) continue;
|
|
339
|
+
const key = splitCredentialPool(value)[0];
|
|
340
|
+
if (key) return { key, name };
|
|
341
|
+
}
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Hand the embedded host exactly one key for the active model's provider.
|
|
347
|
+
*
|
|
348
|
+
* Embedded OpenCode reads a built-in provider's key from the shared
|
|
349
|
+
* `process.env`, and that value beats `options.apiKey`. The entrypoint exports
|
|
350
|
+
* a credential pool there as a raw comma list, and a key saved from the
|
|
351
|
+
* dashboard after boot never reaches `process.env` at all, so both 401 without
|
|
352
|
+
* this splice. For `openrouter` and the built-in registry providers (`nan`,
|
|
353
|
+
* `vercel`) it sets `env: []` plus `options.apiKey` (and `options.baseURL`
|
|
354
|
+
* when `<ID>_BASE_URL` is set; a `baseUrlLocked` provider gets none); for registry providers OpenCode does not ship
|
|
355
|
+
* (`helmcode`) it writes the full custom provider block at
|
|
356
|
+
* `<ID>_BASE_URL` or the registry default. No splice when the key is absent
|
|
357
|
+
* (credStatus reports that).
|
|
358
|
+
*
|
|
359
|
+
* The key lives only in the in-memory config string handed to the SDK.
|
|
360
|
+
* Mutates `opencodeConfig` in place and returns the env var the key came from,
|
|
361
|
+
* or `undefined` when nothing was spliced.
|
|
362
|
+
*/
|
|
363
|
+
export function applyProviderKeySplice(
|
|
364
|
+
opencodeConfig: OpencodeConfig,
|
|
365
|
+
model: string | undefined,
|
|
366
|
+
env: Record<string, string | undefined>,
|
|
367
|
+
): { key: string; name: string } | undefined {
|
|
368
|
+
const slash = model?.indexOf("/") ?? -1;
|
|
369
|
+
if (!model || slash <= 0) return undefined;
|
|
370
|
+
const providerId = model.slice(0, slash);
|
|
371
|
+
const existing = opencodeConfig.provider?.[providerId];
|
|
372
|
+
|
|
373
|
+
const custom = customBlockProvider(providerId);
|
|
374
|
+
if (custom) {
|
|
375
|
+
const picked = pickProviderKey(env, providerKeyVars(custom));
|
|
376
|
+
if (!picked) return undefined;
|
|
377
|
+
const block = buildOpenAICompatibleProviderBlock(
|
|
378
|
+
custom,
|
|
379
|
+
picked.key,
|
|
380
|
+
model.slice(slash + 1),
|
|
381
|
+
providerBaseUrl(custom, env),
|
|
382
|
+
);
|
|
383
|
+
opencodeConfig.provider = {
|
|
384
|
+
...opencodeConfig.provider,
|
|
385
|
+
[providerId]: {
|
|
386
|
+
...existing,
|
|
387
|
+
...block,
|
|
388
|
+
options: { ...existing?.options, ...block.options },
|
|
389
|
+
models: { ...existing?.models, ...block.models },
|
|
390
|
+
},
|
|
391
|
+
};
|
|
392
|
+
return picked;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const names = envBoundKeyVars(providerId);
|
|
396
|
+
if (!names) return undefined;
|
|
397
|
+
const picked = pickProviderKey(env, names);
|
|
398
|
+
if (!picked) return undefined;
|
|
399
|
+
const direct = openAICompatibleProvider(providerId);
|
|
400
|
+
const baseURL = direct ? baseUrlOverride(direct, env) : undefined;
|
|
401
|
+
const options = { ...existing?.options, ...(baseURL ? { baseURL } : {}), apiKey: picked.key };
|
|
402
|
+
if (direct?.baseUrlLocked) {
|
|
403
|
+
// OpenCode's built-in SDK (AI Gateway) knows its endpoint; any URL here is wrong.
|
|
404
|
+
const ignored = ignoredBaseUrlVar(direct, env);
|
|
405
|
+
if (ignored || options.baseURL !== undefined) {
|
|
406
|
+
console.warn(
|
|
407
|
+
`[opencode] ${ignored ?? `provider.${providerId}.options.baseURL`} is ignored: ${direct.displayName} uses its built-in endpoint`,
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
delete options.baseURL;
|
|
411
|
+
}
|
|
412
|
+
opencodeConfig.provider = {
|
|
413
|
+
...opencodeConfig.provider,
|
|
414
|
+
[providerId]: { ...existing, env: [], options },
|
|
415
|
+
};
|
|
416
|
+
return picked;
|
|
417
|
+
}
|
|
418
|
+
|
|
220
419
|
const SWARM_AGENT_NAME = "swarm";
|
|
221
420
|
const TRANSCRIPT_TAIL_CHARS = 20_000;
|
|
222
421
|
const TOOL_RESULT_PREVIEW_CHARS = 500;
|
|
@@ -547,8 +746,11 @@ export class OpencodeSession implements ProviderSession {
|
|
|
547
746
|
}
|
|
548
747
|
|
|
549
748
|
/** Settle the session as failed; also used when the event stream dies. */
|
|
550
|
-
fail(
|
|
749
|
+
fail(rawMessage: string): void {
|
|
551
750
|
if (this.aborted || this.completed) return;
|
|
751
|
+
// SDK and provider errors can echo request details; the message reaches
|
|
752
|
+
// the runner's logs and the task's failure reason.
|
|
753
|
+
const message = scrubSecrets(rawMessage);
|
|
552
754
|
this.emit({ type: "error", message });
|
|
553
755
|
void this.finish(async () => ({
|
|
554
756
|
exitCode: 1,
|
|
@@ -733,6 +935,12 @@ export class OpencodeAdapter implements ProviderAdapter {
|
|
|
733
935
|
},
|
|
734
936
|
};
|
|
735
937
|
|
|
938
|
+
// One picked key for the model's provider (D3). It stays in this
|
|
939
|
+
// in-memory config; registering it lets every scrubbed egress redact it
|
|
940
|
+
// even when it never reached `process.env` (a key saved after boot).
|
|
941
|
+
const splicedKey = applyProviderKeySplice(opencodeConfig, config.model, env);
|
|
942
|
+
if (splicedKey) registerVolatileSecret(splicedKey.key, splicedKey.name);
|
|
943
|
+
|
|
736
944
|
// Splice the provider-keyed reasoning options into
|
|
737
945
|
// `provider[providerId].models[modelId].options`. `off` (and any
|
|
738
946
|
// capability-rejected level) resolves to `noop`.
|
|
@@ -774,21 +982,30 @@ export class OpencodeAdapter implements ProviderAdapter {
|
|
|
774
982
|
const { sdk, version: opencodeVersion } = await loadOpencodeSdkImpl();
|
|
775
983
|
let listTools: OpencodeToolLister | undefined;
|
|
776
984
|
const billing = config.model.startsWith("openrouter/") ? new OpenRouterBilling() : undefined;
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
985
|
+
// The config string carries the spliced provider key and the swarm MCP
|
|
986
|
+
// bearer. It goes to the SDK only; nothing logs, writes, or uploads it,
|
|
987
|
+
// and errors raised while the SDK parses it are scrubbed before they
|
|
988
|
+
// propagate to the runner.
|
|
989
|
+
let host: OpenCode.Interface;
|
|
990
|
+
try {
|
|
991
|
+
host = await sdk.OpenCode.create({
|
|
992
|
+
config: { content: JSON.stringify(opencodeConfig) },
|
|
993
|
+
plugins: [
|
|
994
|
+
createOpencodeSwarmPlugin(swarm, {
|
|
995
|
+
onToolRegistry: (lister) => {
|
|
996
|
+
listTools = lister;
|
|
997
|
+
},
|
|
998
|
+
...(billing ? { onOpenRouterResponse: (response) => billing.observe(response) } : {}),
|
|
999
|
+
}),
|
|
1000
|
+
],
|
|
1001
|
+
log: {
|
|
1002
|
+
level: "warn",
|
|
1003
|
+
emit: (entry) => console.warn(scrubSecrets(`[opencode] ${entry.message}`)),
|
|
1004
|
+
},
|
|
1005
|
+
});
|
|
1006
|
+
} catch (err) {
|
|
1007
|
+
throw new Error(scrubSecrets(`opencode host failed to start: ${errorMessage(err, "")}`));
|
|
1008
|
+
}
|
|
792
1009
|
|
|
793
1010
|
let sessionId: string;
|
|
794
1011
|
try {
|
|
@@ -799,7 +1016,7 @@ export class OpencodeAdapter implements ProviderAdapter {
|
|
|
799
1016
|
sessionId = created.id;
|
|
800
1017
|
} catch (err) {
|
|
801
1018
|
await host.close().catch(() => {});
|
|
802
|
-
throw err;
|
|
1019
|
+
throw new Error(scrubSecrets(`opencode session create failed: ${errorMessage(err, "")}`));
|
|
803
1020
|
}
|
|
804
1021
|
|
|
805
1022
|
const session = new OpencodeSession(
|
|
@@ -32,6 +32,27 @@ export interface OpencodeSwarmPluginOptions {
|
|
|
32
32
|
onOpenRouterResponse?: (response: Response) => void;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/** Keys OpenCode sets on each shell call, on top of its base env. */
|
|
36
|
+
const OPENCODE_SHELL_ENV_KEYS = ["TERM", "OPENCODE_TERMINAL"] as const;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Rewrites one OpenCode shell call's env, in place, to the session's own env
|
|
40
|
+
* plus the keys OpenCode set for the call. Nothing else from the process env
|
|
41
|
+
* gets through.
|
|
42
|
+
*/
|
|
43
|
+
function applyOpencodeShellEnv(
|
|
44
|
+
callEnv: Record<string, string | undefined>,
|
|
45
|
+
sessionEnv: Record<string, string | undefined>,
|
|
46
|
+
): void {
|
|
47
|
+
const keep = new Set<string>(OPENCODE_SHELL_ENV_KEYS);
|
|
48
|
+
for (const key of Object.keys(callEnv)) {
|
|
49
|
+
if (!keep.has(key)) delete callEnv[key];
|
|
50
|
+
}
|
|
51
|
+
for (const [key, value] of Object.entries(sessionEnv)) {
|
|
52
|
+
if (value !== undefined && !keep.has(key)) callEnv[key] = value;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
35
56
|
export function createOpencodeSwarmPlugin(
|
|
36
57
|
config: SwarmHooksConfig,
|
|
37
58
|
options: OpencodeSwarmPluginOptions = {},
|
|
@@ -41,6 +62,16 @@ export function createOpencodeSwarmPlugin(
|
|
|
41
62
|
async setup(ctx) {
|
|
42
63
|
options.onToolRegistry?.(() => ctx.tool.list());
|
|
43
64
|
|
|
65
|
+
// OpenCode runs in-process, so its shell tool spawns with process.env,
|
|
66
|
+
// which every concurrent session shares and which never sees this
|
|
67
|
+
// task's env (rows admitted or withheld by fetchResolvedEnv after boot).
|
|
68
|
+
const sessionEnv = config.env;
|
|
69
|
+
if (sessionEnv) {
|
|
70
|
+
await ctx.shell.hook("create.before", (event) => {
|
|
71
|
+
applyOpencodeShellEnv(event.env, sessionEnv);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
44
75
|
// A throw blocks the tool; OpenCode hands the message back to the model.
|
|
45
76
|
await ctx.tool.hook("execute.before", async (event) => {
|
|
46
77
|
if (!config.isLead && config.taskId) {
|