@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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
-- Chat SDK (chat-sdk.dev) channel: StateAdapter tables + durable outbound relay.
|
|
2
|
+
--
|
|
3
|
+
-- The five chat_* state tables back `SqliteChatState` (src/integrations/chat-sdk/state.ts).
|
|
4
|
+
-- Keys and thread ids written by the SDK already carry the adapter prefix
|
|
5
|
+
-- (`telegram:...`, `slack:...`), so no adapter column is needed.
|
|
6
|
+
-- Expiry columns are epoch milliseconds; NULL means no expiry.
|
|
7
|
+
|
|
8
|
+
CREATE TABLE chat_state_kv (
|
|
9
|
+
key TEXT PRIMARY KEY,
|
|
10
|
+
value TEXT NOT NULL,
|
|
11
|
+
expires_at INTEGER
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
CREATE TABLE chat_subscriptions (
|
|
15
|
+
thread_id TEXT PRIMARY KEY,
|
|
16
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
CREATE TABLE chat_locks (
|
|
20
|
+
thread_id TEXT PRIMARY KEY,
|
|
21
|
+
token TEXT NOT NULL,
|
|
22
|
+
expires_at INTEGER NOT NULL
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
CREATE TABLE chat_lists (
|
|
26
|
+
key TEXT NOT NULL,
|
|
27
|
+
seq INTEGER NOT NULL,
|
|
28
|
+
value TEXT NOT NULL,
|
|
29
|
+
expires_at INTEGER,
|
|
30
|
+
PRIMARY KEY (key, seq)
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
CREATE TABLE chat_queue (
|
|
34
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
35
|
+
thread_id TEXT NOT NULL,
|
|
36
|
+
entry TEXT NOT NULL
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE INDEX idx_chat_queue_thread ON chat_queue(thread_id, id);
|
|
40
|
+
|
|
41
|
+
-- Persist the obligation to publish a terminal result for every Chat SDK-rooted
|
|
42
|
+
-- task. Mirrors 144_slack_relay_obligations.sql, plus an attempt cap: a poison
|
|
43
|
+
-- row is marked given up (with the reason) instead of retrying forever.
|
|
44
|
+
CREATE TABLE chat_relay_obligations (
|
|
45
|
+
task_id TEXT PRIMARY KEY REFERENCES agent_tasks(id) ON DELETE CASCADE,
|
|
46
|
+
delivered_at TEXT,
|
|
47
|
+
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
48
|
+
last_attempt_at TEXT,
|
|
49
|
+
given_up_at TEXT,
|
|
50
|
+
last_error TEXT,
|
|
51
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
52
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
53
|
+
created_by TEXT,
|
|
54
|
+
updated_by TEXT
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
CREATE INDEX idx_chat_relay_obligations_pending
|
|
58
|
+
ON chat_relay_obligations(last_attempt_at, created_at)
|
|
59
|
+
WHERE delivered_at IS NULL AND given_up_at IS NULL;
|
|
60
|
+
|
|
61
|
+
-- Lead follow-ups (`source='system'`, `taskType='follow-up'`) inherit the chat
|
|
62
|
+
-- contextKey and carry the lead's final answer, so they relay too. A resume
|
|
63
|
+
-- (`source='system'`, `taskType='resume'`, from `createResumeFollowUp` after a
|
|
64
|
+
-- graceful shutdown or crash recovery) inherits the contextKey too. It relays
|
|
65
|
+
-- only when a lead owns it: a worker task (resumed or not) reports back through
|
|
66
|
+
-- a lead follow-up, and the lead never gets one for its own tasks. Other system
|
|
67
|
+
-- tasks that inherit the key stay silent. GLOB, not LIKE: LIKE is
|
|
68
|
+
-- case-insensitive in SQLite.
|
|
69
|
+
CREATE TRIGGER enqueue_chat_relay_after_terminal_update
|
|
70
|
+
AFTER UPDATE OF status ON agent_tasks
|
|
71
|
+
WHEN OLD.status NOT IN ('completed', 'failed', 'cancelled', 'superseded')
|
|
72
|
+
AND NEW.status IN ('completed', 'failed', 'cancelled')
|
|
73
|
+
AND NEW.contextKey GLOB 'task:chat-sdk:*'
|
|
74
|
+
AND (
|
|
75
|
+
NEW.source = 'chat'
|
|
76
|
+
OR (NEW.source = 'system' AND NEW.taskType = 'follow-up')
|
|
77
|
+
OR (
|
|
78
|
+
NEW.source = 'system'
|
|
79
|
+
AND NEW.taskType = 'resume'
|
|
80
|
+
AND EXISTS (SELECT 1 FROM agents WHERE agents.id = NEW.agentId AND agents.isLead = 1)
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
BEGIN
|
|
84
|
+
INSERT OR IGNORE INTO chat_relay_obligations (task_id)
|
|
85
|
+
VALUES (NEW.id);
|
|
86
|
+
END;
|
|
87
|
+
|
|
88
|
+
CREATE TRIGGER enqueue_chat_relay_after_terminal_insert
|
|
89
|
+
AFTER INSERT ON agent_tasks
|
|
90
|
+
WHEN NEW.status IN ('completed', 'failed', 'cancelled')
|
|
91
|
+
AND NEW.contextKey GLOB 'task:chat-sdk:*'
|
|
92
|
+
AND (
|
|
93
|
+
NEW.source = 'chat'
|
|
94
|
+
OR (NEW.source = 'system' AND NEW.taskType = 'follow-up')
|
|
95
|
+
OR (
|
|
96
|
+
NEW.source = 'system'
|
|
97
|
+
AND NEW.taskType = 'resume'
|
|
98
|
+
AND EXISTS (SELECT 1 FROM agents WHERE agents.id = NEW.agentId AND agents.isLead = 1)
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
BEGIN
|
|
102
|
+
INSERT OR IGNORE INTO chat_relay_obligations (task_id)
|
|
103
|
+
VALUES (NEW.id);
|
|
104
|
+
END;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- The pi extension posted its per-LLM-call `context` usage snapshot as
|
|
2
|
+
-- eventType 'compaction', so every pi turn drew an AUTO COMPACTION divider and
|
|
3
|
+
-- bumped agent_tasks.compactionCount. Those rows never carry compactTrigger or
|
|
4
|
+
-- preCompactTokens (real compactions from every harness do). Relabel them as
|
|
5
|
+
-- 'progress' and recompute the counter for the pi tasks.
|
|
6
|
+
|
|
7
|
+
UPDATE task_context_snapshots
|
|
8
|
+
SET eventType = 'progress'
|
|
9
|
+
WHERE eventType = 'compaction'
|
|
10
|
+
AND compactTrigger IS NULL
|
|
11
|
+
AND preCompactTokens IS NULL
|
|
12
|
+
AND sessionId LIKE 'pi-%'
|
|
13
|
+
AND taskId IN (SELECT id FROM agent_tasks WHERE provider = 'pi');
|
|
14
|
+
|
|
15
|
+
UPDATE agent_tasks
|
|
16
|
+
SET compactionCount = (
|
|
17
|
+
SELECT COUNT(*)
|
|
18
|
+
FROM task_context_snapshots s
|
|
19
|
+
WHERE s.taskId = agent_tasks.id AND s.eventType = 'compaction'
|
|
20
|
+
)
|
|
21
|
+
WHERE provider = 'pi'
|
|
22
|
+
AND COALESCE(compactionCount, 0) > 0;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
-- Model profiles (runbooks/model-tiers.md § Model profiles): a named
|
|
2
|
+
-- (harness, model, effort) that Lead picks per task or that applies as an
|
|
3
|
+
-- agent's default. Claim stamps the profile on the task. The tier seeds
|
|
4
|
+
-- (`<harness>-<tier>`) are written at boot by src/be/seed-model-profiles.ts.
|
|
5
|
+
CREATE TABLE IF NOT EXISTS model_profiles (
|
|
6
|
+
id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
|
|
7
|
+
name TEXT NOT NULL UNIQUE,
|
|
8
|
+
harness TEXT NOT NULL,
|
|
9
|
+
model TEXT NOT NULL,
|
|
10
|
+
effort TEXT,
|
|
11
|
+
allowCustomModel INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
description TEXT,
|
|
13
|
+
-- `tier:<tier>` for a boot seed, `agent-config` for a profile this migration
|
|
14
|
+
-- made from an agent's MODEL_OVERRIDE, NULL for one an operator created.
|
|
15
|
+
seededFrom TEXT,
|
|
16
|
+
createdAt TEXT NOT NULL,
|
|
17
|
+
lastUpdatedAt TEXT NOT NULL,
|
|
18
|
+
created_by TEXT REFERENCES users(id),
|
|
19
|
+
updated_by TEXT REFERENCES users(id)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
-- `profile` is the creator's ask; `resolvedProfile` is the name claim applied
|
|
23
|
+
-- (the task's ask or the agent's default), mirroring model / resolvedModel.
|
|
24
|
+
ALTER TABLE agent_tasks ADD COLUMN profile TEXT;
|
|
25
|
+
ALTER TABLE agent_tasks ADD COLUMN resolvedProfile TEXT;
|
|
26
|
+
|
|
27
|
+
-- A profile name a task asks for, or an agent has as its default, must exist
|
|
28
|
+
-- when the row is written. Enforced here so the check and the write are one
|
|
29
|
+
-- statement: an app-level check before a separate insert races a concurrent
|
|
30
|
+
-- delete. The delete side is the matching single-statement guard in
|
|
31
|
+
-- deleteModelProfile (src/be/db/model-profiles.ts). It is not a trigger on
|
|
32
|
+
-- model_profiles because one reading agent_tasks would break every later
|
|
33
|
+
-- migration that rebuilds agent_tasks (DROP + RENAME re-parses that trigger).
|
|
34
|
+
CREATE TRIGGER IF NOT EXISTS model_profiles_task_ref_insert
|
|
35
|
+
BEFORE INSERT ON agent_tasks
|
|
36
|
+
WHEN NEW.profile IS NOT NULL
|
|
37
|
+
AND NOT EXISTS (SELECT 1 FROM model_profiles WHERE name = NEW.profile)
|
|
38
|
+
BEGIN
|
|
39
|
+
SELECT RAISE(ABORT, 'model-profile-missing: the task''s model profile does not exist');
|
|
40
|
+
END;
|
|
41
|
+
|
|
42
|
+
CREATE TRIGGER IF NOT EXISTS model_profiles_task_ref_update
|
|
43
|
+
BEFORE UPDATE OF profile ON agent_tasks
|
|
44
|
+
WHEN NEW.profile IS NOT NULL
|
|
45
|
+
AND NOT EXISTS (SELECT 1 FROM model_profiles WHERE name = NEW.profile)
|
|
46
|
+
BEGIN
|
|
47
|
+
SELECT RAISE(ABORT, 'model-profile-missing: the task''s model profile does not exist');
|
|
48
|
+
END;
|
|
49
|
+
|
|
50
|
+
CREATE TRIGGER IF NOT EXISTS model_profiles_default_ref_insert
|
|
51
|
+
BEFORE INSERT ON swarm_config
|
|
52
|
+
WHEN NEW.scope = 'agent' AND NEW.key = 'MODEL_PROFILE'
|
|
53
|
+
AND NOT EXISTS (SELECT 1 FROM model_profiles WHERE name = trim(NEW.value))
|
|
54
|
+
BEGIN
|
|
55
|
+
SELECT RAISE(ABORT, 'model-profile-missing: the agent''s default model profile does not exist');
|
|
56
|
+
END;
|
|
57
|
+
|
|
58
|
+
CREATE TRIGGER IF NOT EXISTS model_profiles_default_ref_update
|
|
59
|
+
BEFORE UPDATE OF scope, key, value ON swarm_config
|
|
60
|
+
WHEN NEW.scope = 'agent' AND NEW.key = 'MODEL_PROFILE'
|
|
61
|
+
AND NOT EXISTS (SELECT 1 FROM model_profiles WHERE name = trim(NEW.value))
|
|
62
|
+
BEGIN
|
|
63
|
+
SELECT RAISE(ABORT, 'model-profile-missing: the agent''s default model profile does not exist');
|
|
64
|
+
END;
|
|
65
|
+
|
|
66
|
+
-- Each agent's MODEL_OVERRIDE + REASONING_EFFORT_OVERRIDE pair becomes a
|
|
67
|
+
-- profile, deduped by (harness, model, effort), and that agent's default
|
|
68
|
+
-- (agent-scoped MODEL_PROFILE, never exported to the worker env). Claim then
|
|
69
|
+
-- supplies the same model and effort the worker read from its env before.
|
|
70
|
+
-- A row with exportToEnv = 0 never reached the worker, so it is not carried
|
|
71
|
+
-- over: a withheld model makes no default, a withheld effort no profile effort.
|
|
72
|
+
-- ACP keeps MODEL_OVERRIDE (no portable mapping); `latest:` aliases are not
|
|
73
|
+
-- valid agent defaults, so they are left alone too.
|
|
74
|
+
CREATE TEMP TABLE _model_profile_overrides AS
|
|
75
|
+
SELECT
|
|
76
|
+
a.id AS agentId,
|
|
77
|
+
COALESCE(a.harness_provider, a.provider) AS harness,
|
|
78
|
+
trim(m.value) AS model,
|
|
79
|
+
CASE
|
|
80
|
+
WHEN lower(trim(e.value)) IN ('off', 'low', 'medium', 'high', 'xhigh', 'max')
|
|
81
|
+
THEN lower(trim(e.value))
|
|
82
|
+
END AS effort
|
|
83
|
+
FROM agents a
|
|
84
|
+
JOIN swarm_config m
|
|
85
|
+
ON m.scope = 'agent' AND m.scopeId = a.id AND m.key = 'MODEL_OVERRIDE'
|
|
86
|
+
AND m.isSecret = 0 AND m.encrypted = 0 AND m.exportToEnv = 1
|
|
87
|
+
LEFT JOIN swarm_config e
|
|
88
|
+
ON e.scope = 'agent' AND e.scopeId = a.id AND e.key = 'REASONING_EFFORT_OVERRIDE'
|
|
89
|
+
AND e.isSecret = 0 AND e.encrypted = 0 AND e.exportToEnv = 1
|
|
90
|
+
WHERE COALESCE(a.harness_provider, a.provider) IS NOT NULL
|
|
91
|
+
AND COALESCE(a.harness_provider, a.provider) <> 'acp'
|
|
92
|
+
AND trim(m.value) <> ''
|
|
93
|
+
AND lower(trim(m.value)) NOT LIKE 'latest:%';
|
|
94
|
+
|
|
95
|
+
-- Name: `<harness>-<model>[-<effort>]`, without repeating a harness prefix the
|
|
96
|
+
-- model already carries, e.g. `codex-gpt-6.1-sol-xhigh`, `claude-opus-5-5-high`.
|
|
97
|
+
INSERT OR IGNORE INTO model_profiles
|
|
98
|
+
(name, harness, model, effort, allowCustomModel, description, seededFrom, createdAt, lastUpdatedAt)
|
|
99
|
+
SELECT
|
|
100
|
+
lower(replace(replace(
|
|
101
|
+
CASE WHEN lower(model) LIKE lower(harness) || '-%' THEN model ELSE harness || '-' || model END,
|
|
102
|
+
'/', '-'), ':', '-')) || COALESCE('-' || effort, ''),
|
|
103
|
+
harness,
|
|
104
|
+
model,
|
|
105
|
+
effort,
|
|
106
|
+
1,
|
|
107
|
+
'Created from an agent''s MODEL_OVERRIDE and REASONING_EFFORT_OVERRIDE.',
|
|
108
|
+
'agent-config',
|
|
109
|
+
strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
|
|
110
|
+
strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
111
|
+
FROM _model_profile_overrides
|
|
112
|
+
GROUP BY harness, model, effort;
|
|
113
|
+
|
|
114
|
+
INSERT OR IGNORE INTO swarm_config
|
|
115
|
+
(id, scope, scopeId, key, value, isSecret, envPath, description, createdAt, lastUpdatedAt, encrypted, exportToEnv)
|
|
116
|
+
SELECT
|
|
117
|
+
lower(hex(randomblob(4))) || '-' || lower(hex(randomblob(2))) || '-4' ||
|
|
118
|
+
substr(lower(hex(randomblob(2))), 2) || '-' ||
|
|
119
|
+
substr('89ab', 1 + (abs(random()) % 4), 1) || substr(lower(hex(randomblob(2))), 2) || '-' ||
|
|
120
|
+
lower(hex(randomblob(6))),
|
|
121
|
+
'agent',
|
|
122
|
+
o.agentId,
|
|
123
|
+
'MODEL_PROFILE',
|
|
124
|
+
p.name,
|
|
125
|
+
0,
|
|
126
|
+
NULL,
|
|
127
|
+
'Default model profile, created from this agent''s MODEL_OVERRIDE.',
|
|
128
|
+
strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
|
|
129
|
+
strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
|
|
130
|
+
0,
|
|
131
|
+
0
|
|
132
|
+
FROM _model_profile_overrides o
|
|
133
|
+
JOIN model_profiles p
|
|
134
|
+
ON p.harness = o.harness AND p.model = o.model AND p.effort IS o.effort
|
|
135
|
+
AND p.seededFrom = 'agent-config';
|
|
136
|
+
|
|
137
|
+
DROP TABLE _model_profile_overrides;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* See runbooks/model-catalog.md.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { withAgentChatRegistrySections } from "@desplega/model-catalog";
|
|
16
17
|
import { type RuntimeCatalog, setRuntimeModelCatalog } from "../utils/runtime-model-catalog";
|
|
17
18
|
import {
|
|
18
19
|
getActivePricingRow,
|
|
@@ -180,7 +181,10 @@ function pickNumber(value: unknown): number | undefined {
|
|
|
180
181
|
}
|
|
181
182
|
|
|
182
183
|
/** Project a models.dev payload into `model_catalog` rows for CATALOG_PROVIDER_IDS. */
|
|
183
|
-
export function buildCatalogEntries(
|
|
184
|
+
export function buildCatalogEntries(raw: ModelsDevCache, checkedAt: number): ModelCatalogEntry[] {
|
|
185
|
+
// A live models.dev payload still carries the embeddings and image models of
|
|
186
|
+
// the registry gateways (`vercel`); pi and opencode cannot run them.
|
|
187
|
+
const cache = withAgentChatRegistrySections(raw);
|
|
184
188
|
const entries: ModelCatalogEntry[] = [];
|
|
185
189
|
for (const providerId of CATALOG_PROVIDER_IDS) {
|
|
186
190
|
const provider = cache[providerId];
|
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Precedence (first hit wins):
|
|
9
9
|
* 1. task `model` → modelSource "model"
|
|
10
|
-
* 2.
|
|
11
|
-
* 3.
|
|
12
|
-
* 4.
|
|
10
|
+
* 2. task `profile` → "profile:task"
|
|
11
|
+
* 3. the claiming worker's MODEL_TIER_* → "worker-env" (agents.modelTierOverrides)
|
|
12
|
+
* 4. swarm_config MODEL_TIER_<PROV>_<TIER> → "tier-config"
|
|
13
|
+
* 5. DEFAULT_MODEL_TIER_MAP → "tier-default"
|
|
14
|
+
* 6. the agent's default profile → "profile:agent-default" (no model, no tier,
|
|
15
|
+
* no repo-scoped MODEL_OVERRIDE on the task's repo)
|
|
13
16
|
*
|
|
14
17
|
* Any layer may hold a `latest:` alias. An alias that resolves to nothing
|
|
15
18
|
* (empty catalog, everything filtered) falls through to the next layer.
|
|
@@ -45,8 +48,14 @@ import {
|
|
|
45
48
|
type ProviderName,
|
|
46
49
|
ProviderNameSchema,
|
|
47
50
|
parseModelTier,
|
|
51
|
+
type ReasoningEffort,
|
|
48
52
|
} from "../types";
|
|
49
53
|
import { getDbClient } from "./db";
|
|
54
|
+
import {
|
|
55
|
+
getAgentDefaultProfileName,
|
|
56
|
+
getModelProfileByName,
|
|
57
|
+
repoModelOverrideKeys,
|
|
58
|
+
} from "./db/model-profiles";
|
|
50
59
|
import {
|
|
51
60
|
CLI_PINNED_HARNESSES,
|
|
52
61
|
fallbackForUnsupportedModel,
|
|
@@ -74,7 +83,9 @@ export type ModelSource =
|
|
|
74
83
|
| "tier-config"
|
|
75
84
|
| "tier-default"
|
|
76
85
|
| "fallback:cli-unsupported"
|
|
77
|
-
| "fallback:cli-unsupported:model"
|
|
86
|
+
| "fallback:cli-unsupported:model"
|
|
87
|
+
| "profile:task"
|
|
88
|
+
| "profile:agent-default";
|
|
78
89
|
|
|
79
90
|
export interface TaskModelResolution {
|
|
80
91
|
resolvedModel: string;
|
|
@@ -490,15 +501,21 @@ async function applyCliSupport(
|
|
|
490
501
|
if (!fallback) return resolution;
|
|
491
502
|
noticeCliUnsupported(harness, cliVersion, resolution.resolvedModel, fallback);
|
|
492
503
|
// Keep the winning layer in the source: a fallback from the task's own `latest:` alias is
|
|
493
|
-
// still a task-level pin (a resume carries it), one from a tier layer is not.
|
|
494
|
-
|
|
495
|
-
|
|
504
|
+
// still a task-level pin (a resume carries it), one from a tier layer is not. A profile keeps
|
|
505
|
+
// its own source; `resolvedProfile` still names it and `resolvedModel` shows the swap.
|
|
506
|
+
const modelSource = resolution.modelSource.startsWith("profile:")
|
|
507
|
+
? resolution.modelSource
|
|
508
|
+
: resolution.modelSource === "model"
|
|
496
509
|
? "fallback:cli-unsupported:model"
|
|
497
510
|
: "fallback:cli-unsupported";
|
|
498
511
|
return { ...resolution, resolvedModel: fallback, modelSource };
|
|
499
512
|
}
|
|
500
513
|
|
|
501
514
|
export type ClaimModelFields = Partial<TaskModelResolution> & {
|
|
515
|
+
/** The profile claim applied (`agent_tasks.resolvedProfile`). */
|
|
516
|
+
resolvedProfile?: string;
|
|
517
|
+
/** The profile's effort, when it has one and the task set none; the worker spawns with it. */
|
|
518
|
+
effort?: ReasoningEffort;
|
|
502
519
|
/**
|
|
503
520
|
* Set when the task's explicit model is rejected by this worker's CLI, or belongs to another
|
|
504
521
|
* harness family (`[model-harness-mismatch]`); the worker fails the task without a spawn.
|
|
@@ -506,22 +523,150 @@ export type ClaimModelFields = Partial<TaskModelResolution> & {
|
|
|
506
523
|
modelUnsupported?: string;
|
|
507
524
|
};
|
|
508
525
|
|
|
526
|
+
/**
|
|
527
|
+
* Resolve a model profile for a claim. Null when the profile does not apply:
|
|
528
|
+
* an agent default that is missing or on another harness falls through to the
|
|
529
|
+
* tier chain. For a task's own `profile` both are a hard stop.
|
|
530
|
+
*/
|
|
531
|
+
async function resolveClaimProfile(
|
|
532
|
+
name: string,
|
|
533
|
+
source: "profile:task" | "profile:agent-default",
|
|
534
|
+
harness: ProviderName | null,
|
|
535
|
+
): Promise<
|
|
536
|
+
| { profile: { name: string; effort: ReasoningEffort | null }; resolution: TaskModelResolution }
|
|
537
|
+
| { modelUnsupported: string }
|
|
538
|
+
| null
|
|
539
|
+
> {
|
|
540
|
+
const isTask = source === "profile:task";
|
|
541
|
+
const profile = await getModelProfileByName(name);
|
|
542
|
+
if (!profile) {
|
|
543
|
+
return isTask
|
|
544
|
+
? { modelUnsupported: `[model-profile-missing] Model profile "${name}" no longer exists.` }
|
|
545
|
+
: null;
|
|
546
|
+
}
|
|
547
|
+
if (profile.harness !== harness) {
|
|
548
|
+
if (!isTask) return null;
|
|
549
|
+
return {
|
|
550
|
+
modelUnsupported: `[model-harness-mismatch] Model profile "${name}" runs on the ${profile.harness} harness, not on the ${harness ?? "unknown"} harness of this worker. Re-create the task with a ${harness ?? "matching"} profile.`,
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
let resolution: TaskModelResolution = {
|
|
554
|
+
resolvedModel: profile.model,
|
|
555
|
+
modelSource: source,
|
|
556
|
+
modelAlias: null,
|
|
557
|
+
};
|
|
558
|
+
if (isAlias(profile.model)) {
|
|
559
|
+
const resolved = await resolveLatestAlias(profile.model);
|
|
560
|
+
if (!resolved) {
|
|
561
|
+
if (!isTask) return null;
|
|
562
|
+
return {
|
|
563
|
+
modelUnsupported: `[model-profile-unresolved] Model profile "${name}" names ${profile.model}, which resolves to no usable model.`,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
resolution = {
|
|
567
|
+
resolvedModel: resolved,
|
|
568
|
+
modelSource: source,
|
|
569
|
+
modelAlias: profile.model.trim().toLowerCase(),
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
return { profile: { name: profile.name, effort: profile.effort }, resolution };
|
|
573
|
+
}
|
|
574
|
+
|
|
509
575
|
/**
|
|
510
576
|
* Resolve and record the model for a task the given agent is claiming. Runs
|
|
511
577
|
* inside the claim transaction. Returns the fields to merge into the trigger.
|
|
578
|
+
* `task.model` must be the task's own pin (`taskModelPin`), never the model a
|
|
579
|
+
* previous session reported into the column.
|
|
512
580
|
*/
|
|
513
581
|
export async function recordClaimModelResolution(
|
|
514
|
-
task: {
|
|
582
|
+
task: {
|
|
583
|
+
id: string;
|
|
584
|
+
model?: string | null;
|
|
585
|
+
modelTier?: string | null;
|
|
586
|
+
profile?: string | null;
|
|
587
|
+
effort?: string | null;
|
|
588
|
+
vcsRepo?: string | null;
|
|
589
|
+
},
|
|
515
590
|
agent: { id: string; harnessProvider?: ProviderName | null; provider?: ProviderName | null },
|
|
591
|
+
/**
|
|
592
|
+
* Whether the claiming worker's config read includes secret repo rows
|
|
593
|
+
* (`readsRepoSecrets`). A secret repo override it never receives cannot
|
|
594
|
+
* beat its default profile. Defaults to true (an operator-key worker).
|
|
595
|
+
*/
|
|
596
|
+
{ includeRepoSecrets = true }: { includeRepoSecrets?: boolean } = {},
|
|
516
597
|
): Promise<ClaimModelFields> {
|
|
517
598
|
const harnessProvider = agent.harnessProvider ?? agent.provider ?? null;
|
|
599
|
+
|
|
600
|
+
if (!task.model?.trim()) {
|
|
601
|
+
const taskProfile = task.profile?.trim();
|
|
602
|
+
const agentDefault =
|
|
603
|
+
taskProfile || parseModelTier(task.modelTier)
|
|
604
|
+
? null
|
|
605
|
+
: await getAgentDefaultProfileName(agent.id);
|
|
606
|
+
// The agent default is agent-scoped config: a repo-scoped MODEL_OVERRIDE or
|
|
607
|
+
// REASONING_EFFORT_OVERRIDE on the task's repo still beats it on that axis
|
|
608
|
+
// (repo > agent), as it beats the agent's own override in the worker env.
|
|
609
|
+
// A task's own profile is the creator's pick and beats repo config.
|
|
610
|
+
const repoKeys = agentDefault
|
|
611
|
+
? await repoModelOverrideKeys(task.vcsRepo, { includeSecrets: includeRepoSecrets })
|
|
612
|
+
: new Set<string>();
|
|
613
|
+
const defaultProfile = repoKeys.has("MODEL_OVERRIDE") ? null : agentDefault;
|
|
614
|
+
const picked = taskProfile
|
|
615
|
+
? await resolveClaimProfile(taskProfile, "profile:task", harnessProvider)
|
|
616
|
+
: defaultProfile
|
|
617
|
+
? await resolveClaimProfile(defaultProfile, "profile:agent-default", harnessProvider)
|
|
618
|
+
: null;
|
|
619
|
+
if (picked && "modelUnsupported" in picked)
|
|
620
|
+
return { modelUnsupported: picked.modelUnsupported };
|
|
621
|
+
if (picked) {
|
|
622
|
+
const checked = await applyCliSupport(
|
|
623
|
+
picked.resolution,
|
|
624
|
+
harnessProvider,
|
|
625
|
+
await getAgentHarnessCliVersion(agent.id),
|
|
626
|
+
);
|
|
627
|
+
// Profiles never fail fast on the CLI check (only a raw task pin does), so this is a resolution.
|
|
628
|
+
const resolution = "unsupported" in checked ? picked.resolution : checked;
|
|
629
|
+
await getDbClient().run(
|
|
630
|
+
"UPDATE agent_tasks SET resolvedModel = ?, modelSource = ?, modelAlias = ?, resolvedProfile = ? WHERE id = ?",
|
|
631
|
+
[
|
|
632
|
+
resolution.resolvedModel,
|
|
633
|
+
resolution.modelSource,
|
|
634
|
+
resolution.modelAlias,
|
|
635
|
+
picked.profile.name,
|
|
636
|
+
task.id,
|
|
637
|
+
],
|
|
638
|
+
);
|
|
639
|
+
return {
|
|
640
|
+
resolvedModel: resolution.resolvedModel,
|
|
641
|
+
modelSource: resolution.modelSource,
|
|
642
|
+
...(resolution.modelAlias ? { modelAlias: resolution.modelAlias } : {}),
|
|
643
|
+
resolvedProfile: picked.profile.name,
|
|
644
|
+
// A task's own effort stays the pin; the profile's fills only an unset one,
|
|
645
|
+
// and an agent default's yields to the repo's effort override.
|
|
646
|
+
...(!task.effort && picked.profile.effort && !repoKeys.has("REASONING_EFFORT_OVERRIDE")
|
|
647
|
+
? { effort: picked.profile.effort }
|
|
648
|
+
: {}),
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
518
653
|
const resolved = await resolveTaskModel({
|
|
519
654
|
model: task.model,
|
|
520
655
|
modelTier: task.modelTier,
|
|
521
656
|
harnessProvider,
|
|
522
657
|
workerOverrides: await getAgentModelTierOverrides(agent.id),
|
|
523
658
|
});
|
|
524
|
-
if (!resolved)
|
|
659
|
+
if (!resolved) {
|
|
660
|
+
// A re-claimed row keeps the claim record of its previous run; drop it so
|
|
661
|
+
// the trigger and the row do not replay that run's model.
|
|
662
|
+
await getDbClient().run(
|
|
663
|
+
`UPDATE agent_tasks SET resolvedModel = NULL, modelSource = NULL, modelAlias = NULL, resolvedProfile = NULL
|
|
664
|
+
WHERE id = ? AND (resolvedModel IS NOT NULL OR modelSource IS NOT NULL OR modelAlias IS NOT NULL
|
|
665
|
+
OR resolvedProfile IS NOT NULL)`,
|
|
666
|
+
[task.id],
|
|
667
|
+
);
|
|
668
|
+
return {};
|
|
669
|
+
}
|
|
525
670
|
if ("harnessMismatch" in resolved) return { modelUnsupported: resolved.harnessMismatch };
|
|
526
671
|
const checked = await applyCliSupport(
|
|
527
672
|
resolved,
|
|
@@ -533,7 +678,7 @@ export async function recordClaimModelResolution(
|
|
|
533
678
|
}
|
|
534
679
|
const resolution = checked;
|
|
535
680
|
await getDbClient().run(
|
|
536
|
-
"UPDATE agent_tasks SET resolvedModel = ?, modelSource = ?, modelAlias =
|
|
681
|
+
"UPDATE agent_tasks SET resolvedModel = ?, modelSource = ?, modelAlias = ?, resolvedProfile = NULL WHERE id = ?",
|
|
537
682
|
[resolution.resolvedModel, resolution.modelSource, resolution.modelAlias, task.id],
|
|
538
683
|
);
|
|
539
684
|
return resolution.modelAlias
|
|
@@ -29,8 +29,10 @@ import {
|
|
|
29
29
|
type ModelsDevCatalog,
|
|
30
30
|
parseAlias,
|
|
31
31
|
} from "@desplega/model-catalog";
|
|
32
|
+
import { type TaskModelPinFields, taskModelPin } from "../tasks/model-pin";
|
|
32
33
|
import { ampModelError, ampPinCatalogError, ampPinProviderError } from "../utils/amp-models";
|
|
33
34
|
import { getAgentById, getAllAgents } from "./db";
|
|
35
|
+
import { getModelProfileByName } from "./db/model-profiles";
|
|
34
36
|
import { loadModelsCatalog } from "./model-catalog-store";
|
|
35
37
|
import { resolveLatestAlias } from "./model-tier-resolution";
|
|
36
38
|
|
|
@@ -99,10 +101,18 @@ export async function harnessModelErrorFor(
|
|
|
99
101
|
* stays sync and catalog-free; this runs next to it.
|
|
100
102
|
*/
|
|
101
103
|
export async function poolTaskRunsOnHarness(
|
|
102
|
-
task: {
|
|
104
|
+
task: (TaskModelPinFields & { profile?: string | null }) | null | undefined,
|
|
103
105
|
harness: string | null | undefined,
|
|
104
106
|
): Promise<boolean> {
|
|
105
|
-
|
|
107
|
+
// A task's model profile runs on one harness only; other workers leave it in the pool.
|
|
108
|
+
const profileName = task?.profile?.trim();
|
|
109
|
+
if (profileName) {
|
|
110
|
+
const profile = await getModelProfileByName(profileName);
|
|
111
|
+
return !profile || !harness || profile.harness === harness;
|
|
112
|
+
}
|
|
113
|
+
// Only the task's own pin restricts harnesses; a model a previous run
|
|
114
|
+
// reported into `model` does not.
|
|
115
|
+
const model = taskModelPin(task ?? {})?.trim();
|
|
106
116
|
if (!model) return true;
|
|
107
117
|
return (await harnessModelErrorFor(model, harness)) === null;
|
|
108
118
|
}
|
package/src/be/models-catalog.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { openAICompatibleProviderIds, registryCatalogSections } from "@desplega/model-catalog";
|
|
1
2
|
import { loadModelsDevCache, type ModelsDevCache, type ModelsDevModel } from "./modelsdev-cache";
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -15,13 +16,18 @@ import { loadModelsDevCache, type ModelsDevCache, type ModelsDevModel } from "./
|
|
|
15
16
|
* same snapshot as its own fallback while the request is in flight.
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Mirrors the provider groups used by the direct harness and ACP model
|
|
21
|
+
* pickers, plus every OpenAI-compatible registry provider
|
|
22
|
+
* (`@desplega/model-catalog`).
|
|
23
|
+
*/
|
|
19
24
|
export const CATALOG_PROVIDER_IDS = [
|
|
20
25
|
"openrouter",
|
|
21
26
|
"anthropic",
|
|
22
27
|
"openai",
|
|
23
28
|
"amazon-bedrock",
|
|
24
29
|
"opencode",
|
|
30
|
+
...openAICompatibleProviderIds(),
|
|
25
31
|
] as const;
|
|
26
32
|
|
|
27
33
|
export type CatalogProviderId = (typeof CATALOG_PROVIDER_IDS)[number];
|
|
@@ -163,6 +169,24 @@ function mergePinnedEntries(catalog: ModelsCatalog): void {
|
|
|
163
169
|
}
|
|
164
170
|
}
|
|
165
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Registry-synthesized sections (`catalog: "registry"` entries such as
|
|
174
|
+
* `helmcode`) are never on models.dev, so the live catalog built from it
|
|
175
|
+
* lacks them. Fill them from the bundled snapshot, which carries them
|
|
176
|
+
* (`loadModelsDevCache`); models already present (an overlay row) win.
|
|
177
|
+
*/
|
|
178
|
+
function mergeRegistrySections(catalog: ModelsCatalog): void {
|
|
179
|
+
const snapshot = bundledSnapshotCatalog();
|
|
180
|
+
for (const providerId of Object.keys(registryCatalogSections()) as CatalogProviderId[]) {
|
|
181
|
+
const section = snapshot[providerId];
|
|
182
|
+
if (!section) continue;
|
|
183
|
+
catalog[providerId] ??= { ...section, models: {} };
|
|
184
|
+
for (const [modelId, model] of Object.entries(section.models)) {
|
|
185
|
+
catalog[providerId].models[modelId] ??= model;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
166
190
|
/**
|
|
167
191
|
* Install a freshly built live catalog (already merged with the persistent
|
|
168
192
|
* table + overlay by `src/be/model-catalog-store.ts`). Pinned snapshot entries
|
|
@@ -170,6 +194,7 @@ function mergePinnedEntries(catalog: ModelsCatalog): void {
|
|
|
170
194
|
*/
|
|
171
195
|
export function setLiveModelsCatalog(catalog: ModelsCatalog, updatedAt: number | null): void {
|
|
172
196
|
mergePinnedEntries(catalog);
|
|
197
|
+
mergeRegistrySections(catalog);
|
|
173
198
|
liveCatalog = catalog;
|
|
174
199
|
liveUpdatedAt = updatedAt;
|
|
175
200
|
}
|