@desplega.ai/agent-swarm 1.172.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{acp-adapter-fpecx1g1.js → acp-adapter-sj2g0m84.js} +18 -17
- package/dist/{actions-pw87a1a8.js → actions-fegk44gr.js} +65 -35
- package/dist/{amp-adapter-8jem2bc0.js → amp-adapter-ad8ft89x.js} +8 -7
- package/dist/{anthropic-messages-8ee2f22q.js → anthropic-messages-r6czkjv1.js} +7 -7
- package/dist/{app-wmf0m843.js → app-kfvgbvzy.js} +19 -13
- package/dist/{assistant-emp1e108.js → assistant-z7zdy9ja.js} +65 -38
- package/dist/{boot-reembed-1de4f4aj.js → boot-reembed-5c2z0mbe.js} +11 -9
- package/dist/{boot-reembed-4ymn9atn.js → boot-reembed-j8xa181e.js} +11 -9
- package/dist/{boot-scrub-sweep-adhk1s8c.js → boot-scrub-sweep-hnkn3rgt.js} +12 -10
- package/dist/{boot-seeds-8q637aew.js → boot-seeds-kwjq4d2z.js} +15 -13
- package/dist/{claude-adapter-t26cv8a4.js → claude-adapter-9vmvpvgd.js} +20 -19
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-k9qae05j.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-q54zx5q2.js} +6 -4
- package/dist/{claude-sdk-session-gsfsh662.js → claude-sdk-session-9jye6cxr.js} +12698 -11995
- package/dist/{cli-k46r9hmk.js → cli-03gedhng.js} +16 -14
- package/dist/{cli-kb4ehzx5.js → cli-1e4b6bzh.js} +7 -7
- package/dist/{cli-d603qf86.js → cli-29jc5q7w.js} +10 -8
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-8vs9trd4.js → cli-3dj8k4vy.js} +1 -1
- package/dist/{cli-zxm9p3x4.js → cli-3fbmmawm.js} +5 -5
- package/dist/{cli-gmdajfw5.js → cli-4jxm2qtz.js} +4987 -1708
- package/dist/{cli-tadfgd0t.js → cli-5hkm7whv.js} +33 -4
- package/dist/{cli-6jb2rf77.js → cli-5t4f29ez.js} +3 -3
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-pj6x9qce.js → cli-6jyj59nb.js} +2 -2
- package/dist/{cli-388egyf6.js → cli-6razj6t4.js} +2 -2
- package/dist/{cli-qsztpfry.js → cli-74ahz61x.js} +2 -2
- package/dist/{cli-4nz8p1p5.js → cli-7x0g4sn1.js} +15474 -16082
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-81r1wjyv.js → cli-9nfx44eh.js} +1 -1
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-bf7485pm.js → cli-apx87jne.js} +2 -2
- package/dist/{cli-ztrv9y21.js → cli-bzszjf2p.js} +3689 -1081
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/{cli-hsem16hb.js → cli-cgtksawx.js} +7 -4
- package/dist/{cli-db3m6zdt.js → cli-d2qr7aj4.js} +1 -1
- package/dist/{cli-1hgat6pa.js → cli-d5f9ed5c.js} +5 -5
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/{cli-7jykv7ef.js → cli-e6mpjhed.js} +1 -1
- package/dist/{cli-j6kpj9az.js → cli-ee9gtz70.js} +1553 -68
- package/dist/{cli-e0a9sk00.js → cli-eejsgvm4.js} +4 -4
- package/dist/{cli-tgpfnm6r.js → cli-ef1hg1wv.js} +518 -59
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-ppy4nnnh.js → cli-f7kr7svz.js} +2 -2
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-2bw3w47j.js → cli-hnhtk6cj.js} +1 -1
- package/dist/{cli-ywm1azg9.js → cli-hnmhtzvh.js} +6 -4
- package/dist/{cli-4fnb6884.js → cli-hvqbtna4.js} +7 -1259
- package/dist/{cli-pstq9888.js → cli-j0pfptdp.js} +220 -103
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-esnpehf5.js → cli-k382tshb.js} +12 -13
- package/dist/cli-k3dp5tpf.js +263 -0
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-prrt9fa0.js → cli-ke896fcf.js} +10 -10
- package/dist/{cli-nv4zd0b9.js → cli-kt6zqg0e.js} +6 -6
- package/dist/{cli-g6t9texm.js → cli-m50t4309.js} +5 -18
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-c2pq2rjb.js → cli-n3hzg89b.js} +46 -15
- package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
- package/dist/{cli-5rv1j9ga.js → cli-ne236afy.js} +53 -7
- package/dist/cli-p0sg24zp.js +16 -0
- package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
- package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
- package/dist/{cli-g4f5pj26.js → cli-q0ke1yww.js} +111 -25
- package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-gj81e47t.js → cli-r2pnvj8g.js} +2 -2
- package/dist/{cli-r8smj8b8.js → cli-r62a35ea.js} +19 -3
- package/dist/{cli-cd0hv9nh.js → cli-ra0xzggj.js} +2 -2
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-nyhb1r6x.js → cli-s2sp957d.js} +52 -29
- package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
- package/dist/{cli-xczpdp9e.js → cli-se8w6wny.js} +6 -6
- package/dist/cli-skxvvpap.js +10140 -0
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-0p3enk35.js → cli-tqaazemc.js} +9 -1
- package/dist/{cli-cf69s3ew.js → cli-tr4sxp68.js} +3 -3
- package/dist/{cli-8hzfb6xz.js → cli-tsde1hdr.js} +15 -15
- package/dist/{cli-cceskcvt.js → cli-txqb9s38.js} +8 -8
- package/dist/{cli-aspcaef3.js → cli-v1yb0rqb.js} +6 -6
- package/dist/{cli-j1pmc07z.js → cli-vatyhshy.js} +268 -40
- package/dist/{cli-04emfe2q.js → cli-vdach5a9.js} +5 -5
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/{cli-hwwvy36w.js → cli-wayw93nt.js} +3 -3
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-gp1rtyvk.js → cli-z5jjpaxw.js} +29 -6
- package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
- package/dist/cli.js +32 -48
- package/dist/{codex-adapter-m4tgdysy.js → codex-adapter-y81sssk0.js} +16 -15
- package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
- package/dist/{codex-session-runner-ymwzm6ea.js → codex-session-runner-8vx4j6a9.js} +16 -15
- package/dist/{commands-n0hshcvs.js → commands-kcpvpcrr.js} +21 -10
- package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
- package/dist/{controllers-connect-y07cqcvy.js → controllers-connect-kwpvj3rf.js} +45 -38
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
- package/dist/{db-hkqvrdcb.js → db-k8ankj20.js} +13 -11
- package/dist/{db-4w7tmt1g.js → db-ww5d7jq3.js} +29 -9
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
- package/dist/{dispatcher-5sd69y14.js → dispatcher-e8gq5m68.js} +41 -34
- package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
- package/dist/{dsh-adapter-2h8m4cab.js → dsh-adapter-3epjm3af.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-8ygwhg0f.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-swhnpw3n.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-6axnngdj.js} +3 -2
- package/dist/external-channel-h3359cwn.js +52 -0
- package/dist/{google-generative-ai-7pavrbv7.js → google-generative-ai-g8db7x0f.js} +5 -3
- package/dist/{google-vertex-3f1jk41f.js → google-vertex-r2692q0r.js} +5 -3
- package/dist/{grok-adapter-8m9yqzbq.js → grok-adapter-0d4x7gkx.js} +19 -18
- package/dist/{handlers-s20xr10r.js → handlers-an1gzv21.js} +44 -37
- package/dist/{heartbeat-3k31q4g2.js → heartbeat-6dakeb61.js} +46 -39
- package/dist/{hook-gdn6a2fn.js → hook-6v6cv6d5.js} +12 -24
- package/dist/{hook-ygwerrdh.js → hook-sa5xye4y.js} +13 -12
- package/dist/{http-jdteeg81.js → http-r7f3eky0.js} +1598 -279
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-e0snym4t.js → index-7ep4gzdk.js} +41 -34
- package/dist/index-9gw58n4k.js +193 -0
- package/dist/index-9j87mcm8.js +56305 -0
- package/dist/index-bsmcresk.js +79424 -0
- package/dist/index-mh85qhec.js +475 -0
- package/dist/{index-vm3bm9t7.js → index-rmpw9a8q.js} +41 -34
- package/dist/{index-6ksewd5y.js → index-s2wxgzr0.js} +1015 -732
- package/dist/{index-tsszt7g9.js → index-v1v6n7hg.js} +46 -39
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{index-ffqzqgwb.js → index-zk96aq1k.js} +11 -9
- package/dist/{keepalive-jekc896t.js → keepalive-be9vwy5h.js} +13 -11
- package/dist/{lead-4k9s9szx.js → lead-0861cwrf.js} +64 -57
- package/dist/{maintenance-shazch4n.js → maintenance-mzzgc8bn.js} +11 -9
- package/dist/node-c9we95xf.js +1 -1
- package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
- package/dist/{oauth-refresh-sweep-5gb36kn8.js → oauth-refresh-sweep-cpdnfwdj.js} +12 -10
- package/dist/{onboard-ydrbnvww.js → onboard-fh8qs4r3.js} +11 -3
- package/dist/{opencode-adapter-5zh0he20.js → opencode-adapter-nm42wwj8.js} +19 -14
- package/dist/{otel-impl-6pf5cv86.js → otel-impl-x6c1c9g4.js} +248 -869
- package/dist/{pi-mono-adapter-ef9wwx9m.js → pi-mono-adapter-9n2ya240.js} +245 -107
- package/dist/{pricing-refresh-s52nsa5q.js → pricing-refresh-qb0rv0ap.js} +13 -11
- package/dist/{rbac-roles-aq3msh4e.js → rbac-roles-1gzdwbh1.js} +12 -10
- package/dist/{rbac-roles-q5gb5e8v.js → rbac-roles-3mraey52.js} +13 -11
- package/dist/{render-v2-pd1rg54q.js → render-v2-agpa45zz.js} +19 -13
- package/dist/{resume-gw4a2c6v.js → resume-x0ydy9s9.js} +27 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-jda1ksdh.js → setup-as9ga0d6.js} +2 -2
- package/dist/{virtual-modules-b3ga2m65.js → virtual-modules-9gkxqrap.js} +7 -6
- package/dist/{work-objects-tb7ycye8.js → work-objects-y5g1y7ev.js} +49 -37
- package/dist/{worker-njjccz5d.js → worker-860c3e38.js} +64 -57
- package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
- package/openapi.json +951 -356
- package/package.json +12 -13
- package/src/apps/catalog.generated.json +1309 -53
- package/src/apps/page-validator.ts +93 -31
- package/src/azure-devops/api.ts +94 -18
- package/src/azure-devops/auth.ts +32 -0
- package/src/azure-devops/boards-sync.ts +708 -0
- package/src/azure-devops/handlers.ts +52 -8
- package/src/azure-devops/html.ts +26 -0
- package/src/azure-devops/index.ts +15 -0
- package/src/azure-devops/templates.ts +86 -0
- package/src/azure-devops/types.ts +65 -1
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/page-versions.ts +15 -0
- package/src/be/db/runtime.ts +35 -8
- package/src/be/db/skill-name-resolution.ts +36 -0
- package/src/be/db/tasks/read.ts +230 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +74 -13
- package/src/be/migrations/213_script_connections_sql.sql +79 -0
- package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
- package/src/be/migrations/216_task_resolved_effort.sql +5 -0
- package/src/be/migrations/217_chat_sdk_state.sql +104 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +12 -1
- package/src/be/model-validation.ts +5 -2
- package/src/be/models-catalog.ts +26 -1
- package/src/be/modelsdev-cache.json +198 -63
- package/src/be/modelsdev-cache.ts +9 -1
- package/src/be/script-connections.ts +47 -8
- package/src/be/script-credential-broker.ts +39 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +10 -8
- package/src/be/seed/runner.ts +13 -1
- package/src/be/seed/state-db.ts +5 -0
- package/src/be/seed/types.ts +6 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/seed-skills/bundled-files.generated.json +10 -18
- package/src/be/seed-skills/index.ts +107 -3
- package/src/be/sql-connections.ts +118 -0
- package/src/be/swarm-config-guard.ts +53 -0
- package/src/cli.tsx +0 -16
- package/src/commands/onboard/non-interactive.ts +4 -2
- package/src/commands/profile-sync.ts +5 -3
- package/src/commands/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +196 -56
- package/src/e2b/env.ts +5 -0
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +45 -0
- package/src/extensions/dispatcher.ts +7 -0
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/all-routes.ts +0 -1
- package/src/http/config.ts +36 -17
- package/src/http/core.ts +4 -0
- package/src/http/index.ts +14 -2
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp-oauth.ts +6 -13
- package/src/http/mcp.ts +15 -5
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +6 -5
- package/src/http/pages.ts +5 -14
- package/src/http/poll.ts +28 -68
- package/src/http/requested-by.ts +54 -0
- package/src/http/route-def.ts +7 -6
- package/src/http/script-connection-proxy.ts +51 -4
- package/src/http/script-connections.ts +5 -2
- package/src/http/scripts.ts +1 -0
- package/src/http/session-cost-recompute.ts +12 -2
- package/src/http/session-data.ts +4 -0
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +61 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +183 -2
- package/src/http/x.ts +1 -0
- package/src/integrations/chat-sdk/adapters.ts +129 -0
- package/src/integrations/chat-sdk/attachments.ts +232 -0
- package/src/integrations/chat-sdk/background.ts +36 -0
- package/src/integrations/chat-sdk/commands.ts +194 -0
- package/src/integrations/chat-sdk/config.ts +198 -0
- package/src/integrations/chat-sdk/discord-api.ts +63 -0
- package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
- package/src/integrations/chat-sdk/handlers.ts +28 -0
- package/src/integrations/chat-sdk/inbound.ts +426 -0
- package/src/integrations/chat-sdk/limits.ts +48 -0
- package/src/integrations/chat-sdk/logger.ts +81 -0
- package/src/integrations/chat-sdk/outbound.ts +123 -0
- package/src/integrations/chat-sdk/relay.ts +172 -0
- package/src/integrations/chat-sdk/router.ts +169 -0
- package/src/integrations/chat-sdk/runtime.ts +351 -0
- package/src/integrations/chat-sdk/schema.ts +245 -0
- package/src/integrations/chat-sdk/state.ts +243 -0
- package/src/integrations/chat-sdk/status.ts +244 -0
- package/src/integrations/chat-sdk/steering.ts +58 -0
- package/src/integrations/chat-sdk/teams-origin.ts +77 -0
- package/src/integrations/chat-sdk/telegram-api.ts +56 -0
- package/src/integrations/chat-sdk/templates.ts +16 -0
- package/src/integrations/chat-sdk/test-hooks.ts +37 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
- package/src/integrations/chat-sdk/typing.ts +65 -0
- package/src/jira/adf.ts +3 -1
- package/src/kv-reserved-namespaces.ts +2 -0
- package/src/oauth/mcp-wrapper.ts +10 -6
- package/src/otel-impl.ts +2 -1
- package/src/pages/version.ts +4 -5
- package/src/prompts/base-prompt.ts +111 -45
- package/src/providers/acp-target-catalog.ts +6 -0
- package/src/providers/acp-targets.ts +56 -3
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +27 -2
- package/src/providers/claude-flag-settings.ts +133 -0
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-sdk-session.ts +7 -0
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +268 -37
- package/src/providers/opencode-billing.ts +86 -0
- package/src/providers/opencode-swarm-plugin.ts +51 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pricing-sources.md +37 -3
- package/src/providers/reasoning-effort.ts +27 -0
- package/src/providers/types.ts +11 -2
- package/src/rbac/legacy-policy.ts +8 -2
- package/src/rbac/permissions.ts +21 -0
- package/src/scheduler/scheduler.ts +4 -2
- package/src/scripts-runtime/api-client.ts +15 -1
- package/src/scripts-runtime/api-types.ts +9 -1
- package/src/scripts-runtime/ctx.ts +1 -1
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/mcp-client.ts +30 -19
- package/src/scripts-runtime/sdk-allowlist.ts +8 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +27 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +63 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -15
- package/src/server.ts +52 -18
- package/src/slack/actions.ts +29 -1
- package/src/slack/app.ts +14 -2
- package/src/slack/assistant.ts +36 -2
- package/src/slack/channel-join.ts +3 -16
- package/src/slack/commands.ts +9 -1
- package/src/slack/event-dedup.ts +1 -1
- package/src/slack/external-channel-egress.ts +113 -0
- package/src/slack/external-channel.ts +309 -0
- package/src/slack/handlers.ts +61 -0
- package/src/slack/render-v2.ts +40 -47
- package/src/slack/work-objects.ts +5 -0
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +94 -2
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +4 -31
- package/src/telemetry.ts +2 -1
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/apps-catalog-feedback.test.ts +310 -0
- package/src/tests/apps-catalog-inputs.test.ts +70 -0
- package/src/tests/apps-catalog-table.test.ts +113 -0
- package/src/tests/azure-devops-boards-sync.test.ts +584 -0
- package/src/tests/azure-devops-html.test.ts +13 -0
- package/src/tests/azure-devops-webhook-malformed.test.ts +4 -0
- package/src/tests/base-prompt.test.ts +58 -54
- package/src/tests/chat-sdk-commands.test.ts +191 -0
- package/src/tests/chat-sdk-config.test.ts +334 -0
- package/src/tests/chat-sdk-discord-api.test.ts +68 -0
- package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
- package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
- package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
- package/src/tests/chat-sdk-harness.ts +146 -0
- package/src/tests/chat-sdk-inbound.test.ts +363 -0
- package/src/tests/chat-sdk-relay.test.ts +470 -0
- package/src/tests/chat-sdk-reload.test.ts +128 -0
- package/src/tests/chat-sdk-shutdown.test.ts +220 -0
- package/src/tests/chat-sdk-slack.test.ts +268 -0
- package/src/tests/chat-sdk-state.test.ts +163 -0
- package/src/tests/chat-sdk-status-route.test.ts +382 -0
- package/src/tests/chat-sdk-teams.test.ts +277 -0
- package/src/tests/chat-sdk-tools.test.ts +520 -0
- package/src/tests/chat-sdk-typing.test.ts +120 -0
- package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
- package/src/tests/claude-adapter-binary.test.ts +144 -0
- package/src/tests/claude-flag-settings.test.ts +114 -0
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +148 -1
- package/src/tests/claude-sdk-process.fixture.ts +7 -0
- package/src/tests/claude-thinking-tokens.test.ts +57 -0
- package/src/tests/claude-worker-parity.test.ts +2 -7
- package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
- package/src/tests/config-refs.test.ts +66 -0
- package/src/tests/context-key.test.ts +51 -0
- package/src/tests/cors-allowlist.test.ts +25 -0
- package/src/tests/create-page-tool.test.ts +18 -0
- package/src/tests/credential-check.test.ts +139 -0
- package/src/tests/credentials.test.ts +21 -0
- package/src/tests/db-runtime.test.ts +61 -0
- package/src/tests/db-task-read-contract.test.ts +20 -0
- package/src/tests/db-task-write-contract.test.ts +10 -0
- package/src/tests/deferred-task-wake.test.ts +52 -4
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/enabled-capabilities.test.ts +20 -0
- package/src/tests/entrypoint-api-readiness.test.ts +14 -8
- package/src/tests/entrypoint-config-env-export.test.ts +5 -2
- package/src/tests/entrypoint-export-to-env.test.ts +78 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-post-bridge.test.ts +51 -0
- package/src/tests/fetch-resolved-env.test.ts +128 -0
- package/src/tests/fixtures/azure-boards/workitem.commented.json +89 -0
- package/src/tests/fixtures/azure-boards/workitem.created.json +81 -0
- package/src/tests/fixtures/azure-boards/workitem.deleted.json +70 -0
- package/src/tests/fixtures/azure-boards/workitem.restored.json +82 -0
- package/src/tests/fixtures/azure-boards/workitem.updated.json +130 -0
- package/src/tests/fixtures/catalog-feedback-definition.json.txt +860 -0
- package/src/tests/fixtures/catalog-inputs-definition.json.txt +910 -0
- package/src/tests/fixtures/catalog-table-definition.json.txt +468 -0
- package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
- package/src/tests/fixtures/runner-identity-refresh.ts +3 -0
- package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
- package/src/tests/github-handlers.test.ts +35 -0
- package/src/tests/harness-provider-resolution.test.ts +12 -0
- package/src/tests/heartbeat-checklist.test.ts +3 -2
- package/src/tests/hook-runtime-close.test.ts +0 -2
- package/src/tests/http-api-integration.test.ts +0 -25
- package/src/tests/migration-046-budgets.test.ts +17 -16
- package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
- package/src/tests/model-tier-resolution.test.ts +93 -0
- package/src/tests/models-catalog.test.ts +42 -1
- package/src/tests/node-env-runtime.test.ts +98 -0
- package/src/tests/openai-compatible-providers.test.ts +134 -0
- package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
- package/src/tests/opencode-adapter.test.ts +348 -3
- package/src/tests/opencode-billing.test.ts +28 -0
- package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
- package/src/tests/opencode-shell-env.test.ts +145 -0
- package/src/tests/openrouter-base-url.test.ts +101 -151
- package/src/tests/page-proxy.test.ts +1 -1
- package/src/tests/pages-browser-sdk.test.ts +76 -0
- package/src/tests/pages-feedback.test.ts +1 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
- package/src/tests/pi-mono-adapter.test.ts +385 -5
- package/src/tests/pi-shell-env.test.ts +170 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/rbac-engine.test.ts +11 -3
- package/src/tests/runner-exit-after-tasks.test.ts +0 -4
- package/src/tests/runner-identity-refresh.test.ts +3 -0
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections-sql.test.ts +675 -0
- package/src/tests/script-connections.test.ts +7 -1
- package/src/tests/scripts-http.test.ts +201 -1
- package/src/tests/scripts-only-gating.test.ts +2 -3
- package/src/tests/scripts-runtime.test.ts +58 -40
- package/src/tests/secret-scrubber.test.ts +86 -0
- package/src/tests/seed-skills-bundled-files.test.ts +45 -53
- package/src/tests/seed-skills-retire.test.ts +182 -0
- package/src/tests/send-task-requester-gate.test.ts +58 -0
- package/src/tests/session-cost-recompute-unit.test.ts +94 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/slack-channel-join.test.ts +4 -1
- package/src/tests/slack-external-channel-config.test.ts +65 -0
- package/src/tests/slack-external-channel-egress.test.ts +237 -0
- package/src/tests/slack-external-channel-guard.test.ts +280 -0
- package/src/tests/slack-external-channel-tools.test.ts +173 -0
- package/src/tests/slack-external-channel.test.ts +370 -0
- package/src/tests/slack-render-v2.test.ts +86 -10
- package/src/tests/sonnet-5-5-registry.test.ts +9 -1
- package/src/tests/spec-base-url.test.ts +16 -1
- package/src/tests/swarm-config-export-to-env.test.ts +267 -0
- package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
- package/src/tests/swarm-diff.test.ts +1 -1
- package/src/tests/task-model-effort-rerun.test.ts +164 -0
- package/src/tests/task-session-prompts.test.ts +132 -0
- package/src/tests/task-tool-manifest.test.ts +14 -0
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tool-annotations.test.ts +6 -6
- package/src/tests/ui-logs-parser.test.ts +43 -0
- package/src/tests/used-by-route.test.ts +6 -0
- package/src/tests/vendored-openapi.test.ts +16 -1
- package/src/tests/vercel-ai-gateway.test.ts +149 -0
- package/src/tests/workflow-swarm-script.test.ts +38 -0
- package/src/tests/workflow-wait-filter.test.ts +5 -3
- package/src/tools/chat-access.ts +41 -0
- package/src/tools/chat-open-dm.ts +59 -0
- package/src/tools/chat-post.ts +74 -0
- package/src/tools/chat-read-thread.ts +100 -0
- package/src/tools/chat-reply.ts +75 -0
- package/src/tools/create-page.ts +3 -13
- package/src/tools/defer-task.ts +17 -0
- package/src/tools/model-catalog/index.ts +2 -1
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/send-task.ts +24 -0
- package/src/tools/skills/skill-get.ts +17 -9
- package/src/tools/slack-post.ts +6 -0
- package/src/tools/slack-read.ts +8 -0
- package/src/tools/slack-reply.ts +6 -0
- package/src/tools/slack-start-thread.ts +6 -0
- package/src/tools/slack-update.ts +6 -0
- package/src/tools/slack-upload-file.ts +6 -0
- package/src/tools/swarm-config/get-config.ts +2 -1
- package/src/tools/swarm-config/list-config.ts +2 -1
- package/src/tools/swarm-config/set-config.ts +16 -3
- package/src/tools/tool-config.ts +8 -6
- package/src/types.ts +12 -2
- package/src/utils/config-env-export.ts +74 -0
- package/src/utils/credentials.test.ts +92 -0
- package/src/utils/credentials.ts +52 -4
- package/src/utils/harness-provider.ts +15 -6
- package/src/utils/node-env.ts +24 -0
- package/src/utils/runtime-model-catalog.ts +11 -1
- package/src/utils/secret-scrubber.ts +71 -2
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/templates/skills/agent-browser/SKILL.md +1 -1
- package/templates/skills/agent-browser/content.md +1 -1
- package/templates/skills/apps/SKILL.md +749 -0
- package/templates/skills/apps/content.md +60 -22
- package/templates/skills/chat-sdk/config.json +14 -0
- package/templates/skills/chat-sdk/content.md +84 -0
- package/templates/skills/composio-gmail/content.md +7 -0
- package/templates/skills/composio-google-docs/content.md +1 -1
- package/templates/skills/email-domain-health/config.json +14 -0
- package/templates/skills/email-domain-health/content.md +131 -0
- package/templates/skills/kv-storage/content.md +2 -2
- package/templates/skills/pages/content.md +8 -10
- package/templates/skills/qa-loom/config.json +14 -0
- package/templates/skills/qa-loom/content.md +187 -0
- package/templates/skills/qa-loom/files/build-loom.mjs +221 -0
- package/templates/skills/qa-loom/files/run-qa.sh +57 -0
- package/templates/skills/slack-interaction/content.md +4 -0
- package/templates/skills/swarm-extensions/content.md +2 -0
- package/templates/skills/swarm-scripts/SKILL.md +4 -2
- package/templates/skills/swarm-scripts/config.json +1 -1
- package/templates/skills/swarm-scripts/content.md +4 -2
- package/templates/skills/workflow-iterate/content.md +38 -0
- package/dist/artifact-eczsknc3.js +0 -3843
- package/dist/cli-9xsmdpdt.js +0 -56377
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- package/dist/index-9ch1n761.js +0 -1102
- package/src/artifact-sdk/index.ts +0 -2
- package/src/artifact-sdk/localtunnel.d.ts +0 -20
- package/src/artifact-sdk/port.ts +0 -12
- package/src/artifact-sdk/server.ts +0 -183
- package/src/artifact-sdk/tunnel.ts +0 -19
- package/src/commands/artifact.ts +0 -249
- package/src/http/ecosystem.ts +0 -77
- package/src/tests/artifact-commands.test.ts +0 -92
- package/src/tests/artifact-sdk.test.ts +0 -793
- package/src/tests/register-service-security.test.ts +0 -194
- package/src/tools/list-services.ts +0 -107
- package/src/tools/register-service.ts +0 -177
- package/src/tools/unregister-service.ts +0 -73
- package/src/tools/update-service-status.ts +0 -96
- package/templates/skills/artifacts/config.json +0 -14
- package/templates/skills/artifacts/content.md +0 -344
- package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
- package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
- package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
- package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
- package/dist/{azure-openai-responses-ap1gwxgr.js → azure-openai-responses-ygfreq4t.js} +5 -5
- package/dist/{cli-5rqrj7q0.js → cli-pw7ebjdt.js} +0 -0
- package/dist/{openai-codex-responses-33qhkkdy.js → openai-codex-responses-3bk0grnr.js} +4 -4
- package/dist/{openai-completions-s88xm3ns.js → openai-completions-5d4jpakc.js} +9 -9
- package/dist/{openai-responses-7xd2f2e2.js → openai-responses-krb51f59.js} +5 -5
- package/dist/{pi-messages-xszk613n.js → pi-messages-x9gzynm1.js} +3 -3
- /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
- /package/src/{artifact-sdk → pages}/feedback-overlay.ts +0 -0
|
@@ -16,8 +16,6 @@ import agentBrowserContent from "../../../templates/skills/agent-browser/content
|
|
|
16
16
|
};
|
|
17
17
|
import appsConfig from "../../../templates/skills/apps/config.json" with { type: "text" };
|
|
18
18
|
import appsContent from "../../../templates/skills/apps/content.md" with { type: "text" };
|
|
19
|
-
import artifactsConfig from "../../../templates/skills/artifacts/config.json" with { type: "text" };
|
|
20
|
-
import artifactsContent from "../../../templates/skills/artifacts/content.md" with { type: "text" };
|
|
21
19
|
import askUserConfig from "../../../templates/skills/ask-user/config.json" with { type: "text" };
|
|
22
20
|
import askUserContent from "../../../templates/skills/ask-user/content.md" with { type: "text" };
|
|
23
21
|
import assetNamespacesConfig from "../../../templates/skills/asset-namespaces/config.json" with {
|
|
@@ -38,6 +36,8 @@ import brainstormingConfig from "../../../templates/skills/brainstorming/config.
|
|
|
38
36
|
import brainstormingContent from "../../../templates/skills/brainstorming/content.md" with {
|
|
39
37
|
type: "text",
|
|
40
38
|
};
|
|
39
|
+
import chatSdkConfig from "../../../templates/skills/chat-sdk/config.json" with { type: "text" };
|
|
40
|
+
import chatSdkContent from "../../../templates/skills/chat-sdk/content.md" with { type: "text" };
|
|
41
41
|
import codeQualityConfig from "../../../templates/skills/code-quality/config.json" with {
|
|
42
42
|
type: "text",
|
|
43
43
|
};
|
|
@@ -96,6 +96,12 @@ import downloadTaskAttachmentConfig from "../../../templates/skills/download-tas
|
|
|
96
96
|
import downloadTaskAttachmentContent from "../../../templates/skills/download-task-attachment/content.md" with {
|
|
97
97
|
type: "text",
|
|
98
98
|
};
|
|
99
|
+
import emailDomainHealthConfig from "../../../templates/skills/email-domain-health/config.json" with {
|
|
100
|
+
type: "text",
|
|
101
|
+
};
|
|
102
|
+
import emailDomainHealthContent from "../../../templates/skills/email-domain-health/content.md" with {
|
|
103
|
+
type: "text",
|
|
104
|
+
};
|
|
99
105
|
import engineeringStandardsConfig from "../../../templates/skills/engineering-standards/config.json" with {
|
|
100
106
|
type: "text",
|
|
101
107
|
};
|
|
@@ -144,6 +150,8 @@ import planningConfig from "../../../templates/skills/planning/config.json" with
|
|
|
144
150
|
import planningContent from "../../../templates/skills/planning/content.md" with { type: "text" };
|
|
145
151
|
import qaConfig from "../../../templates/skills/qa/config.json" with { type: "text" };
|
|
146
152
|
import qaContent from "../../../templates/skills/qa/content.md" with { type: "text" };
|
|
153
|
+
import qaLoomConfig from "../../../templates/skills/qa-loom/config.json" with { type: "text" };
|
|
154
|
+
import qaLoomContent from "../../../templates/skills/qa-loom/content.md" with { type: "text" };
|
|
147
155
|
import questioningConfig from "../../../templates/skills/questioning/config.json" with {
|
|
148
156
|
type: "text",
|
|
149
157
|
};
|
|
@@ -268,9 +276,11 @@ import wtsExpertConfig from "../../../templates/skills/wts-expert/config.json" w
|
|
|
268
276
|
import wtsExpertContent from "../../../templates/skills/wts-expert/content.md" with {
|
|
269
277
|
type: "text",
|
|
270
278
|
};
|
|
279
|
+
import type { Skill } from "../../types";
|
|
271
280
|
import {
|
|
272
281
|
computeContentHash,
|
|
273
282
|
createSkill,
|
|
283
|
+
deleteSkill,
|
|
274
284
|
deleteSkillFile,
|
|
275
285
|
getDbClient,
|
|
276
286
|
getSkillByName,
|
|
@@ -278,7 +288,9 @@ import {
|
|
|
278
288
|
updateSkill,
|
|
279
289
|
upsertSkillFiles,
|
|
280
290
|
} from "../db";
|
|
291
|
+
import { deleteSeedState, getSeedState } from "../seed/state-db";
|
|
281
292
|
import type { Seeder, SeedItem } from "../seed/types";
|
|
293
|
+
import { parseSkillContent } from "../skill-parser";
|
|
282
294
|
import bundledFilesManifest from "./bundled-files.generated.json";
|
|
283
295
|
import { buildSkillContent, type SkillTemplateConfig } from "./render";
|
|
284
296
|
|
|
@@ -319,11 +331,11 @@ const BUILT_IN_SKILL_FILES = bundledFilesManifest as Record<string, SeedSkillFil
|
|
|
319
331
|
const BUILT_IN_SKILL_SOURCES = [
|
|
320
332
|
{ config: agentBrowserConfig, body: agentBrowserContent },
|
|
321
333
|
{ config: appsConfig, body: appsContent },
|
|
322
|
-
{ config: artifactsConfig, body: artifactsContent },
|
|
323
334
|
{ config: askUserConfig, body: askUserContent },
|
|
324
335
|
{ config: assetNamespacesConfig, body: assetNamespacesContent },
|
|
325
336
|
{ config: attioInteractionConfig, body: attioInteractionContent },
|
|
326
337
|
{ config: brainstormingConfig, body: brainstormingContent },
|
|
338
|
+
{ config: chatSdkConfig, body: chatSdkContent },
|
|
327
339
|
{ config: codeQualityConfig, body: codeQualityContent },
|
|
328
340
|
{ config: codeReviewingConfig, body: codeReviewingContent },
|
|
329
341
|
{ config: commsConfig, body: commsContent },
|
|
@@ -335,6 +347,7 @@ const BUILT_IN_SKILL_SOURCES = [
|
|
|
335
347
|
{ config: delegateWorkConfig, body: delegateWorkContent },
|
|
336
348
|
{ config: designDocsConfig, body: designDocsContent },
|
|
337
349
|
{ config: downloadTaskAttachmentConfig, body: downloadTaskAttachmentContent },
|
|
350
|
+
{ config: emailDomainHealthConfig, body: emailDomainHealthContent },
|
|
338
351
|
{ config: engineeringStandardsConfig, body: engineeringStandardsContent },
|
|
339
352
|
{ config: heartbeatRunbookConfig, body: heartbeatRunbookContent },
|
|
340
353
|
{ config: implementingConfig, body: implementingContent },
|
|
@@ -347,6 +360,7 @@ const BUILT_IN_SKILL_SOURCES = [
|
|
|
347
360
|
{ config: phaseRunningConfig, body: phaseRunningContent },
|
|
348
361
|
{ config: planningConfig, body: planningContent },
|
|
349
362
|
{ config: qaConfig, body: qaContent },
|
|
363
|
+
{ config: qaLoomConfig, body: qaLoomContent },
|
|
350
364
|
{ config: questioningConfig, body: questioningContent },
|
|
351
365
|
{ config: researchingConfig, body: researchingContent },
|
|
352
366
|
{ config: reviewOfferedTaskConfig, body: reviewOfferedTaskContent },
|
|
@@ -524,6 +538,94 @@ async function syncSeededSkillFiles(skillId: string, files: SeedSkillFile[]): Pr
|
|
|
524
538
|
if (files.length > 0) await upsertSkillFiles(skillId, files);
|
|
525
539
|
}
|
|
526
540
|
|
|
541
|
+
/**
|
|
542
|
+
* Skills this catalog used to seed and no longer ships. Dropping a template
|
|
543
|
+
* alone leaves its last seeded row live on every existing install, so agents
|
|
544
|
+
* keep reading instructions for a removed feature. `artifacts` documented the
|
|
545
|
+
* PM2 + localtunnel serving path, removed together with PM2.
|
|
546
|
+
*/
|
|
547
|
+
export const RETIRED_SEED_SKILLS: readonly string[] = ["artifacts"];
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* True when every user-editable column outside the seed hash still holds what
|
|
551
|
+
* `skillsSeeder.apply` writes. The seed hash covers only content,
|
|
552
|
+
* systemDefault, userInvocable and bundled files, so an edit to any other
|
|
553
|
+
* column (description, model, allowedTools, source fields, ...) is invisible
|
|
554
|
+
* to it. The seeder writes the description from the same config as the
|
|
555
|
+
* content's frontmatter, so a pristine row's description equals the
|
|
556
|
+
* frontmatter one; every other column keeps its insert default.
|
|
557
|
+
*/
|
|
558
|
+
function metadataAsSeeded(skill: Skill, fileCount: number): boolean {
|
|
559
|
+
let seededDescription: string;
|
|
560
|
+
try {
|
|
561
|
+
seededDescription = parseSkillContent(skill.content).description;
|
|
562
|
+
} catch {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return (
|
|
567
|
+
skill.description === seededDescription &&
|
|
568
|
+
skill.type === "personal" &&
|
|
569
|
+
skill.isComplex === fileCount > 0 &&
|
|
570
|
+
skill.isEnabled &&
|
|
571
|
+
!skill.disableModelInvocation &&
|
|
572
|
+
skill.allowedTools === null &&
|
|
573
|
+
skill.model === null &&
|
|
574
|
+
skill.effort === null &&
|
|
575
|
+
skill.context === null &&
|
|
576
|
+
skill.agent === null &&
|
|
577
|
+
skill.sourceUrl === null &&
|
|
578
|
+
skill.sourceRepo === null &&
|
|
579
|
+
skill.sourcePath === null &&
|
|
580
|
+
skill.sourceBranch === "main" &&
|
|
581
|
+
skill.sourceHash === null &&
|
|
582
|
+
skill.lastFetchedAt === null
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Delete each retired skill the seeder still owns: a `seed_state` row exists,
|
|
588
|
+
* the live copy hashes to what was last seeded, and its metadata is as seeded.
|
|
589
|
+
* A skill the seeder never recorded, or one a user edited since (content,
|
|
590
|
+
* files or metadata), is left in place.
|
|
591
|
+
*/
|
|
592
|
+
export async function retireSeedSkills(
|
|
593
|
+
names: readonly string[] = RETIRED_SEED_SKILLS,
|
|
594
|
+
): Promise<string[]> {
|
|
595
|
+
const retired: string[] = [];
|
|
596
|
+
|
|
597
|
+
for (const name of names) {
|
|
598
|
+
const existing = await getSkillByName(name, "swarm");
|
|
599
|
+
if (!existing) continue;
|
|
600
|
+
|
|
601
|
+
const state = await getSeedState("skill", name);
|
|
602
|
+
if (!state) continue;
|
|
603
|
+
|
|
604
|
+
const liveFiles = (await getSkillFiles(existing.id)).map((file) => ({
|
|
605
|
+
path: file.path,
|
|
606
|
+
content: file.content,
|
|
607
|
+
}));
|
|
608
|
+
const liveHash = skillSeedHash(
|
|
609
|
+
existing.content,
|
|
610
|
+
existing.systemDefault,
|
|
611
|
+
liveFiles,
|
|
612
|
+
existing.userInvocable,
|
|
613
|
+
);
|
|
614
|
+
if (liveHash !== state.seededHash || !metadataAsSeeded(existing, liveFiles.length)) {
|
|
615
|
+
console.warn(`[seed:skill] kept retired skill "${name}": edited since it was seeded`);
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
await getDbClient().transaction(async () => {
|
|
620
|
+
await deleteSkill(existing.id);
|
|
621
|
+
await deleteSeedState("skill", name);
|
|
622
|
+
});
|
|
623
|
+
retired.push(name);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return retired;
|
|
627
|
+
}
|
|
628
|
+
|
|
527
629
|
type SkillSeedItem = SeedItem & { skill: SeedSkill };
|
|
528
630
|
|
|
529
631
|
export const skillsSeeder: Seeder<SkillSeedItem> = {
|
|
@@ -611,4 +713,6 @@ export const skillsSeeder: Seeder<SkillSeedItem> = {
|
|
|
611
713
|
await syncSeededSkillFiles(created.id, skill.files);
|
|
612
714
|
});
|
|
613
715
|
},
|
|
716
|
+
|
|
717
|
+
retire: () => retireSeedSkills(),
|
|
614
718
|
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { getResolvedConfig } from "@/be/db";
|
|
2
|
+
import { registerVolatileSecret, scrubSecrets } from "@/utils/secret-scrubber";
|
|
3
|
+
import type { ScriptConnectionRecord } from "./script-connections";
|
|
4
|
+
|
|
5
|
+
export const SQL_MAX_ROWS = 1000;
|
|
6
|
+
/** Serialized JSON budget for one response; rows past it are dropped and `truncated` is set. */
|
|
7
|
+
export const SQL_MAX_BYTES = 5 * 1024 * 1024;
|
|
8
|
+
const SQL_FETCH_BATCH = 100;
|
|
9
|
+
|
|
10
|
+
export type SqlQueryResult = {
|
|
11
|
+
rows: Record<string, unknown>[];
|
|
12
|
+
rowCount: number;
|
|
13
|
+
truncated: boolean;
|
|
14
|
+
};
|
|
15
|
+
type SqlRow = Record<string, unknown>;
|
|
16
|
+
/** Feeds fetched batches to `take` until it returns false or the cursor is drained. */
|
|
17
|
+
type SqlExecutor = (
|
|
18
|
+
dsn: string,
|
|
19
|
+
query: string,
|
|
20
|
+
params: unknown[],
|
|
21
|
+
take: (batch: SqlRow[]) => boolean,
|
|
22
|
+
) => Promise<void>;
|
|
23
|
+
|
|
24
|
+
/** Only Postgres: Bun `SQL` would open a `sqlite://` URL as a file on the API host. Never echo the DSN. */
|
|
25
|
+
export function assertPostgresDsn(dsn: string): void {
|
|
26
|
+
if (!URL.canParse(dsn) || !["postgres:", "postgresql:"].includes(new URL(dsn).protocol)) {
|
|
27
|
+
throw new Error("SQL connection DSN must be a postgres:// or postgresql:// URL.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Resolve the encrypted DSN server-side. No process.env fallback: a lead must not point it at API env vars. */
|
|
32
|
+
export async function resolveSqlDsn(
|
|
33
|
+
connection: ScriptConnectionRecord,
|
|
34
|
+
agentId: string,
|
|
35
|
+
): Promise<string> {
|
|
36
|
+
const key = connection.authConfigKey;
|
|
37
|
+
if (!key) throw new Error("SQL connection has no DSN config key.");
|
|
38
|
+
const repoId = connection.scope === "repo" ? (connection.scopeId ?? undefined) : undefined;
|
|
39
|
+
const dsn = (await getResolvedConfig(agentId, repoId)).find((c) => c.key === key)?.value;
|
|
40
|
+
if (!dsn) throw new Error(`SQL connection DSN '${key}' is not set.`);
|
|
41
|
+
registerVolatileSecret(dsn, key);
|
|
42
|
+
if (URL.canParse(dsn)) registerVolatileSecret(decodeURIComponent(new URL(dsn).password), key);
|
|
43
|
+
assertPostgresDsn(dsn);
|
|
44
|
+
return dsn;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Read-only enforcement point. Every layer is enforced by Postgres, never by inspecting the SQL:
|
|
48
|
+
// 1. default_transaction_read_only=on for the whole session, 2. an explicit READ ONLY transaction,
|
|
49
|
+
// 3. one statement per call over the extended protocol, 4. a fresh connection closed after each call.
|
|
50
|
+
// Bun runs a parameterless `unsafe()` over the simple protocol, which accepts `commit; ...; insert`,
|
|
51
|
+
// so the parameterless case goes through the tagged-template path instead. Never use `.simple()`.
|
|
52
|
+
// The statement runs as a server-side cursor fetched in batches, so the API never holds more than
|
|
53
|
+
// one batch past the caps. DECLARE only accepts SELECT, VALUES, TABLE and WITH ... SELECT.
|
|
54
|
+
const asTemplate = (text: string): TemplateStringsArray => Object.assign([text], { raw: [text] });
|
|
55
|
+
|
|
56
|
+
const defaultExecutor: SqlExecutor = async (dsn, query, params, take) => {
|
|
57
|
+
// Bun.SQL global, not `import { SQL } from "bun"`: the node-target CLI bundle cannot import "bun".
|
|
58
|
+
const sql = new Bun.SQL({
|
|
59
|
+
adapter: "postgres",
|
|
60
|
+
url: dsn,
|
|
61
|
+
max: 1,
|
|
62
|
+
connectionTimeout: 10,
|
|
63
|
+
connection: { default_transaction_read_only: "on", statement_timeout: 30_000 },
|
|
64
|
+
});
|
|
65
|
+
try {
|
|
66
|
+
await sql.begin("read only", async (tx) => {
|
|
67
|
+
const declare = `declare swarm_sql_cursor no scroll cursor for ${query}`;
|
|
68
|
+
await (params.length > 0 ? tx.unsafe(declare, params) : tx(asTemplate(declare)));
|
|
69
|
+
const fetchNext = asTemplate(`fetch ${SQL_FETCH_BATCH} from swarm_sql_cursor`);
|
|
70
|
+
for (;;) {
|
|
71
|
+
const batch = [...((await tx(fetchNext)) as SqlRow[])];
|
|
72
|
+
if (!take(batch) || batch.length < SQL_FETCH_BATCH) return;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
} finally {
|
|
76
|
+
await sql.close();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
let sqlExecutorForTesting: SqlExecutor | null = null;
|
|
81
|
+
|
|
82
|
+
export function setSqlExecutorForTesting(executor: SqlExecutor | null): void {
|
|
83
|
+
sqlExecutorForTesting = executor;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function runReadOnlyQuery(
|
|
87
|
+
dsn: string,
|
|
88
|
+
query: string,
|
|
89
|
+
params: unknown[] = [],
|
|
90
|
+
): Promise<SqlQueryResult> {
|
|
91
|
+
const rows: SqlRow[] = [];
|
|
92
|
+
let bytes = 0;
|
|
93
|
+
let truncated = false;
|
|
94
|
+
const take = (batch: SqlRow[]): boolean => {
|
|
95
|
+
for (const row of batch) {
|
|
96
|
+
const size = Buffer.byteLength(
|
|
97
|
+
JSON.stringify(row, (_, v) => (typeof v === "bigint" ? v.toString() : v)),
|
|
98
|
+
);
|
|
99
|
+
if (rows.length >= SQL_MAX_ROWS || bytes + size > SQL_MAX_BYTES) {
|
|
100
|
+
truncated = true;
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
bytes += size;
|
|
104
|
+
rows.push(row);
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
await (sqlExecutorForTesting ?? defaultExecutor)(dsn, query, params, take);
|
|
110
|
+
return { rows, rowCount: rows.length, truncated };
|
|
111
|
+
} catch (err) {
|
|
112
|
+
const code = (err as { errno?: unknown }).errno;
|
|
113
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
114
|
+
throw new Error(
|
|
115
|
+
scrubSecrets(typeof code === "string" ? `${message} (SQLSTATE ${code})` : message),
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { validateChatSdkAdaptersValue } from "../integrations/chat-sdk/schema";
|
|
1
2
|
import { validateQuickJSPoolSize } from "../scripts-runtime/executors/quickjs-pool-config";
|
|
2
3
|
import { normalizeSlackReactionShortcode } from "../slack/reaction-shortcode";
|
|
3
4
|
import { ProviderNameSchema } from "../types";
|
|
4
5
|
import { API_DRAIN_MAX_MS_LIMIT } from "../utils/api-drain";
|
|
6
|
+
import { envExportRestrictedError, isEnvExportRestrictedKey } from "../utils/config-env-export";
|
|
5
7
|
import { parseEnabledTools } from "../utils/enabled-tools";
|
|
6
8
|
import { normalizeOrgWebsite } from "../utils/org-website";
|
|
7
9
|
import { parseTaskToolManifest } from "../utils/task-tool-manifest";
|
|
@@ -24,13 +26,47 @@ import { isTierConfigKey, validateTierConfigValue } from "./model-tier-keys";
|
|
|
24
26
|
* rejected at every write path (DB helpers, HTTP routes, MCP tools).
|
|
25
27
|
*/
|
|
26
28
|
// Lead activation is also deployment-only: leads can write ordinary global config.
|
|
29
|
+
// CHAT_SDK_API_URL_OVERRIDES points Chat SDK adapters (and the secrets they carry)
|
|
30
|
+
// at another host, so it must never come from a config row.
|
|
31
|
+
/**
|
|
32
|
+
* Teams SDK env fallbacks; a config row must not redirect the bot token.
|
|
33
|
+
* `@microsoft/teams.apps` reads these from `process.env`. Operators may still
|
|
34
|
+
* store them (they are not reserved), they just never reach env through
|
|
35
|
+
* `getInjectableGlobalConfigs`.
|
|
36
|
+
*/
|
|
37
|
+
export const TEAMS_SDK_ENV_KEYS = [
|
|
38
|
+
"SERVICE_URL",
|
|
39
|
+
"TENANT_ID",
|
|
40
|
+
"CLIENT_ID",
|
|
41
|
+
"CLIENT_SECRET",
|
|
42
|
+
"MANAGED_IDENTITY_CLIENT_ID",
|
|
43
|
+
"CLOUD",
|
|
44
|
+
] as const;
|
|
45
|
+
|
|
46
|
+
/** SQL literal list for the `NOT IN (...)` injection denylist in db.ts. */
|
|
47
|
+
export function teamsSdkEnvKeysSql(): string {
|
|
48
|
+
return TEAMS_SDK_ENV_KEYS.map((key) => `'${key}'`).join(", ");
|
|
49
|
+
}
|
|
50
|
+
|
|
27
51
|
const RESERVED_KEYS = new Set([
|
|
28
52
|
"API_KEY",
|
|
29
53
|
"SECRETS_ENCRYPTION_KEY",
|
|
30
54
|
"CORS_ALLOW_ANY_ORIGIN",
|
|
31
55
|
"EXTENSION_ALLOW_LEAD_ACTIVATION",
|
|
56
|
+
"CHAT_SDK_API_URL_OVERRIDES",
|
|
32
57
|
]);
|
|
33
58
|
|
|
59
|
+
// Config keys the API server owns for its own use and must NEVER hand out over
|
|
60
|
+
// HTTP or to a script — workers/entrypoints read config to build their env, and
|
|
61
|
+
// the agent-fs bootstrap admin key would let a compromised worker administer the
|
|
62
|
+
// shared org. The API materializes these into its own process.env at boot via
|
|
63
|
+
// getInjectableGlobalConfigs, so no HTTP consumer legitimately needs them.
|
|
64
|
+
const API_ONLY_CONFIG_KEYS = new Set(["API_AGENT_FS_API_KEY", "SLACK_SIGNING_SECRET"]);
|
|
65
|
+
|
|
66
|
+
export function isApiOnlyConfigKey(key: string): boolean {
|
|
67
|
+
return API_ONLY_CONFIG_KEYS.has(key);
|
|
68
|
+
}
|
|
69
|
+
|
|
34
70
|
/** Config rows owned by dedicated API surfaces, not the generic config API. */
|
|
35
71
|
export const INTERNAL_CONFIG_KEYS = new Set(["onboarding_state", "runtime_owner_id"]);
|
|
36
72
|
|
|
@@ -254,6 +290,7 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
|
|
|
254
290
|
["RUNTIME_WAKE_GRACE_SEC", "RUNTIME_WAKE_REROUTE_SEC", "RUNTIME_ROUTING_INTERVAL_MS"],
|
|
255
291
|
0,
|
|
256
292
|
),
|
|
293
|
+
CHAT_SDK_ADAPTERS: validateChatSdkAdaptersValue,
|
|
257
294
|
TASK_TOOL_MANIFESTS: (value) => {
|
|
258
295
|
try {
|
|
259
296
|
if (typeof value !== "string") throw new Error("Expected JSON string");
|
|
@@ -380,8 +417,10 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
|
|
|
380
417
|
"OPENROUTER_APP_ATTRIBUTION",
|
|
381
418
|
"CURSOR_NATIVE_SYSTEM_PROMPT",
|
|
382
419
|
"SLACK_DISABLE",
|
|
420
|
+
"CHAT_SDK_ENABLED",
|
|
383
421
|
"SLACK_RENDER_V2",
|
|
384
422
|
"SLACK_RENDER_V2_DELEGATION",
|
|
423
|
+
"SLACK_BLOCK_EXTERNAL_CHANNELS",
|
|
385
424
|
"GITHUB_DISABLE",
|
|
386
425
|
"GITLAB_DISABLE",
|
|
387
426
|
"AZURE_DEVOPS_DISABLE",
|
|
@@ -473,6 +512,10 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
|
|
|
473
512
|
...integerValidators(["APPROVAL_REQUEST_AUTO_CANCELLATION_DAYS"], 0),
|
|
474
513
|
// 0 turns the shutdown drain off; the shutdown path clamps to the same limit.
|
|
475
514
|
...boundedIntegerValidators(["API_DRAIN_MAX_MS"], 0, API_DRAIN_MAX_MS_LIMIT),
|
|
515
|
+
// Chat SDK thread buffer window. 0 or an invalid value falls back to the 10 s
|
|
516
|
+
// default in thread-buffer.ts; above 10 minutes a
|
|
517
|
+
// reply waits longer than any operator expects.
|
|
518
|
+
...boundedIntegerValidators(["CHAT_SDK_BUFFER_MS"], 1, 600_000),
|
|
476
519
|
// Below ~100 tokens the preamble can't fit a useful summary; above 20000
|
|
477
520
|
// (~80k chars) it risks the SIGTERM-143 context-saturation failure mode
|
|
478
521
|
// the cap exists to prevent (see context-preamble.ts).
|
|
@@ -494,3 +537,13 @@ export function validateConfigValue(key: string, value: unknown): string | null
|
|
|
494
537
|
const validator = VALIDATED_KEYS[key.toUpperCase()];
|
|
495
538
|
return validator ? validator(value) : null;
|
|
496
539
|
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Rejects `exportToEnv: true` for keys only the API server reads. Omitting the
|
|
543
|
+
* flag is fine: the write path stores false for those keys.
|
|
544
|
+
*/
|
|
545
|
+
export function validateExportToEnv(key: string, exportToEnv: boolean | undefined): string | null {
|
|
546
|
+
return exportToEnv === true && isEnvExportRestrictedKey(key)
|
|
547
|
+
? envExportRestrictedError(key)
|
|
548
|
+
: null;
|
|
549
|
+
}
|
package/src/cli.tsx
CHANGED
|
@@ -303,12 +303,6 @@ const COMMAND_HELP: Record<
|
|
|
303
303
|
options: " Internal command; no user-facing options",
|
|
304
304
|
examples: ` ${binName} session-summary-stdin`,
|
|
305
305
|
},
|
|
306
|
-
artifact: {
|
|
307
|
-
usage: `${binName} artifact <subcommand> [options]`,
|
|
308
|
-
description: "Manage agent artifacts (serve, list, etc.).",
|
|
309
|
-
options: " -h, --help Show this help",
|
|
310
|
-
examples: [` ${binName} artifact serve`, ` ${binName} artifact help`].join("\n"),
|
|
311
|
-
},
|
|
312
306
|
x: {
|
|
313
307
|
usage: `${binName} x <target> [args]`,
|
|
314
308
|
description:
|
|
@@ -445,7 +439,6 @@ function printHelp(command?: string) {
|
|
|
445
439
|
["hook", "Handle Claude Code hook events (stdin)"],
|
|
446
440
|
["codex-hook", "Handle Codex CLI hook events (stdin, steering delivery)"],
|
|
447
441
|
["session-summary-stdin", "Generate a Claude session summary (internal, stdin)"],
|
|
448
|
-
["artifact", "Manage agent artifacts"],
|
|
449
442
|
["x", "Execute external command routes"],
|
|
450
443
|
["scripts", "Reusable scripts maintenance"],
|
|
451
444
|
["rbac", "RBAC role management (bootstrap)"],
|
|
@@ -774,15 +767,6 @@ if (args.showHelp || args.command === "help" || args.command === undefined) {
|
|
|
774
767
|
const { runSessionSummaryFromStdin } = await import("./hooks/hook.ts");
|
|
775
768
|
await runSessionSummaryFromStdin();
|
|
776
769
|
process.exit(process.exitCode ?? 0);
|
|
777
|
-
} else if (args.command === "artifact") {
|
|
778
|
-
// Pass all args after "artifact" directly
|
|
779
|
-
const artifactArgs = process.argv.slice(process.argv.indexOf("artifact") + 1);
|
|
780
|
-
const { runArtifact } = await import("./commands/artifact");
|
|
781
|
-
await runArtifact(artifactArgs[0] || "help", {
|
|
782
|
-
additionalArgs: artifactArgs.slice(1),
|
|
783
|
-
port: args.port,
|
|
784
|
-
key: args.key,
|
|
785
|
-
});
|
|
786
770
|
} else if (args.command === "x") {
|
|
787
771
|
const xArgs = process.argv.slice(process.argv.indexOf("x") + 1);
|
|
788
772
|
const { runXCommand } = await import("./commands/x");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { openAICompatibleProviders, providerKeyVars } from "@desplega/model-catalog";
|
|
1
2
|
import {
|
|
2
3
|
type HarnessProvider,
|
|
3
4
|
type InstallProvider,
|
|
@@ -42,8 +43,9 @@ type ProviderStateKey =
|
|
|
42
43
|
| "awsSessionToken"
|
|
43
44
|
| "awsProfile";
|
|
44
45
|
|
|
45
|
-
const ACCEPTED_CREDENTIALS =
|
|
46
|
-
|
|
46
|
+
const ACCEPTED_CREDENTIALS = `Set one of: CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY (Claude Code); OPENAI_API_KEY (OpenAI); OPENROUTER_API_KEY (OpenRouter); or AWS_REGION plus AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY or AWS_PROFILE and a Bedrock MODEL_OVERRIDE. ${openAICompatibleProviders()
|
|
47
|
+
.map((p) => `${p.displayName} (${providerKeyVars(p).join(" or ")})`)
|
|
48
|
+
.join(" and ")} keys for pi/opencode are added from the dashboard.`;
|
|
47
49
|
|
|
48
50
|
const DEFERRED_CREDENTIAL_LABEL = "no credential yet";
|
|
49
51
|
|
|
@@ -146,9 +146,9 @@ const PROFILE_FIELD_DETAILS: Record<
|
|
|
146
146
|
},
|
|
147
147
|
claudeMd: {
|
|
148
148
|
label:
|
|
149
|
-
"claudeMd (/
|
|
149
|
+
"claudeMd (~/.claude/CLAUDE.md for Claude; /workspace/CLAUDE.md for non-Claude harnesses, which Claude excludes from its memory load)",
|
|
150
150
|
recoveryGuidance:
|
|
151
|
-
"Inspect and shrink the live CLAUDE.md source first, moving durable tail content into memory. After a worker restart, non-Claude harnesses can use /workspace/CLAUDE.md.pre-boot-<timestamp>.bak as the fallback copy; Claude's native ~/.claude/CLAUDE.md source is not archived by that boot step.",
|
|
151
|
+
"Inspect and shrink the live CLAUDE.md source first, moving durable tail content into memory. Claude edits ~/.claude/CLAUDE.md; editing /workspace/CLAUDE.md does not reach a Claude session. After a worker restart, non-Claude harnesses can use /workspace/CLAUDE.md.pre-boot-<timestamp>.bak as the fallback copy; Claude's native ~/.claude/CLAUDE.md source is not archived by that boot step.",
|
|
152
152
|
},
|
|
153
153
|
toolsMd: {
|
|
154
154
|
label: `toolsMd (${TOOLS_MD_PATH})`,
|
|
@@ -510,7 +510,9 @@ export function planClaudeMdSync(state: {
|
|
|
510
510
|
* materializes from the `claudeMd` DB field at boot (`runner.ts`) and that the
|
|
511
511
|
* base-prompt truncation notice tells NON-Claude harnesses (codex/pi/opencode)
|
|
512
512
|
* to edit. Distinct from CLAUDE_MD_PATH; this is the FS→DB source for the
|
|
513
|
-
* non-Claude providers that previously had no sync path at all.
|
|
513
|
+
* non-Claude providers that previously had no sync path at all. Written for
|
|
514
|
+
* every harness (a container can live-swap providers), but Claude sessions
|
|
515
|
+
* skip it via `claudeMdExcludes` (`src/providers/claude-flag-settings.ts`).
|
|
514
516
|
*/
|
|
515
517
|
export const WORKSPACE_CLAUDE_MD_PATH = "/workspace/CLAUDE.md";
|
|
516
518
|
|
|
@@ -18,6 +18,13 @@
|
|
|
18
18
|
* runs the predicate itself — it just reads the agent row.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import {
|
|
22
|
+
type OpenAICompatibleProvider,
|
|
23
|
+
openAICompatibleKeyVars,
|
|
24
|
+
openAICompatibleProviders,
|
|
25
|
+
providerBaseUrl,
|
|
26
|
+
providerKeyFromEnv,
|
|
27
|
+
} from "@desplega/model-catalog";
|
|
21
28
|
import { deriveDefaultRoute, validateRoute } from "@desplega/model-routing";
|
|
22
29
|
import { ACP_TARGET_IDS, isAcpTarget } from "../providers/acp-target-catalog";
|
|
23
30
|
import { checkAmpCredentials, liveTestAmpCredentials } from "../providers/amp-adapter";
|
|
@@ -116,8 +123,13 @@ export const REQUIRED_CRED_VARS_BY_PROVIDER: Record<SupportedProvider, readonly
|
|
|
116
123
|
],
|
|
117
124
|
codex: ["OPENAI_API_KEY", "CODEX_OAUTH"],
|
|
118
125
|
devin: ["DEVIN_API_KEY", "DEVIN_ORG_ID"],
|
|
119
|
-
opencode: [
|
|
120
|
-
|
|
126
|
+
opencode: [
|
|
127
|
+
"OPENROUTER_API_KEY",
|
|
128
|
+
"ANTHROPIC_API_KEY",
|
|
129
|
+
"OPENAI_API_KEY",
|
|
130
|
+
...openAICompatibleKeyVars(),
|
|
131
|
+
],
|
|
132
|
+
pi: ["ANTHROPIC_API_KEY", "OPENROUTER_API_KEY", "OPENAI_API_KEY", ...openAICompatibleKeyVars()],
|
|
121
133
|
// The ACP target owns its auth; custom targets still need a command.
|
|
122
134
|
acp: [],
|
|
123
135
|
dsh: ["DEEPSEEK_API_KEY", "OPENROUTER_API_KEY"],
|
|
@@ -323,6 +335,29 @@ async function checkOpenRouter(apiKey: string): Promise<LiveValidationResult> {
|
|
|
323
335
|
};
|
|
324
336
|
}
|
|
325
337
|
|
|
338
|
+
/**
|
|
339
|
+
* `GET <baseUrl>/models` with a Bearer key against an OpenAI-compatible
|
|
340
|
+
* registry provider (NaN, Helmcode). Lists models, runs no inference.
|
|
341
|
+
* `baseUrl` defaults to the registry entry; the probe passes the
|
|
342
|
+
* `<ID>_BASE_URL` override, and tests inject a fake server.
|
|
343
|
+
*/
|
|
344
|
+
export async function checkOpenAICompatibleProvider(
|
|
345
|
+
provider: OpenAICompatibleProvider,
|
|
346
|
+
apiKey: string,
|
|
347
|
+
baseUrl: string = provider.baseUrl,
|
|
348
|
+
): Promise<LiveValidationResult> {
|
|
349
|
+
const r = await timedFetch(`${baseUrl.replace(/\/+$/, "")}/models`, {
|
|
350
|
+
method: "GET",
|
|
351
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
352
|
+
});
|
|
353
|
+
if (r.ok) return { ok: true, latency_ms: r.latency_ms };
|
|
354
|
+
return {
|
|
355
|
+
ok: false,
|
|
356
|
+
error: scrubSecrets(`HTTP ${r.status}: ${r.bodyText.slice(0, 200)}`),
|
|
357
|
+
latency_ms: r.latency_ms,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
326
361
|
/**
|
|
327
362
|
* Mirror of the disk check in `checkCodexCredentials` — true when the worker
|
|
328
363
|
* has a materialised `~/.codex/auth.json`, which is the canonical "logged in"
|
|
@@ -365,7 +400,7 @@ function parseCodexOAuthAccess(blob: string | undefined): string | null {
|
|
|
365
400
|
* | `claude` | default route: Foundry / Bedrock / Vertex → gateway (`ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY`) → `CLAUDE_CODE_OAUTH_TOKEN` → `ANTHROPIC_API_KEY` | the route's own `/v1/models`; OAuth presence-only; cloud routes skipped |
|
|
366
401
|
* | `claude-managed` | `ANTHROPIC_API_KEY` (managed agents always use API key + managed envs) | Anthropic `/v1/models` |
|
|
367
402
|
* | `codex` | `~/.codex/auth.json` (file) → `CODEX_OAUTH` (env OAuth) → `OPENAI_API_KEY` | OpenAI `/v1/models` (api-key path only) |
|
|
368
|
-
* | `opencode` | auth.json (file) → `OPENROUTER_API_KEY` → `ANTHROPIC_API_KEY` → `OPENAI_API_KEY` | file presence-only, otherwise provider's `/v1/models` |
|
|
403
|
+
* | `opencode` | auth.json (file) → `OPENROUTER_API_KEY` → `ANTHROPIC_API_KEY` → `OPENAI_API_KEY` → each registry provider key (`NAN_API_KEY` or `HELMCODE_API_NAN`, `HELMCODE_API_KEY`) | file presence-only, otherwise provider's `/v1/models` |
|
|
369
404
|
* | `pi` | auth.json (file) → provider API keys, including model-specific keys | file/model-specific key presence-only, otherwise provider's `/v1/models` |
|
|
370
405
|
* | `acp` | target-specific (the ACP target process owns its own auth) | presence-only (validated by the target process) |
|
|
371
406
|
* | `pi` (bedrock) | `MODEL_OVERRIDE=amazon-bedrock/*` → AWS SDK default credential chain | presence-only (real check is the worker-side Bedrock enumeration) |
|
|
@@ -459,17 +494,28 @@ export async function validateProviderCredentials(
|
|
|
459
494
|
// decision, including any injected filesystem probe used by reports.
|
|
460
495
|
if (status.ready && status.satisfiedBy === "file") return presenceCheckOk();
|
|
461
496
|
// Preserve the live-probe order for supported env keys:
|
|
462
|
-
// OPENROUTER → ANTHROPIC → OPENAI
|
|
497
|
+
// OPENROUTER → ANTHROPIC → OPENAI, then the OpenAI-compatible
|
|
498
|
+
// registry providers in declaration order (NaN, canonical key or
|
|
499
|
+
// alias → Helmcode) at their `<ID>_BASE_URL`, so existing env
|
|
500
|
+
// combinations keep their probe.
|
|
463
501
|
if (env.OPENROUTER_API_KEY) return checkOpenRouter(env.OPENROUTER_API_KEY);
|
|
464
502
|
if (env.ANTHROPIC_API_KEY) return checkAnthropicApiKey(env.ANTHROPIC_API_KEY);
|
|
465
503
|
if (env.OPENAI_API_KEY) return checkOpenAiApiKey(env.OPENAI_API_KEY);
|
|
504
|
+
for (const direct of openAICompatibleProviders()) {
|
|
505
|
+
const key = providerKeyFromEnv(direct, env);
|
|
506
|
+
if (key) {
|
|
507
|
+
return checkOpenAICompatibleProvider(direct, key, providerBaseUrl(direct, env));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
466
510
|
// Model-specific keys (e.g. GEMINI_API_KEY) can satisfy readiness
|
|
467
511
|
// without a probeable endpoint. The harness validates them at inference.
|
|
468
512
|
if (status.ready) return presenceCheckOk();
|
|
469
513
|
return {
|
|
470
514
|
ok: false,
|
|
471
|
-
error:
|
|
472
|
-
|
|
515
|
+
error: `No usable credential found (OPENROUTER_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, ${openAICompatibleProviders()
|
|
516
|
+
.map((p) => p.envVar)
|
|
517
|
+
.join(", ")
|
|
518
|
+
.replace(/, (?=[^,]*$)/, ", or ")}).`,
|
|
473
519
|
latency_ms: Date.now() - startedAt,
|
|
474
520
|
};
|
|
475
521
|
}
|