cartethyia 2.4.5 → 2.5.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/.env.example +4 -1
- package/README.md +63 -13
- package/dist/dashboard/assets/AccountCooldown-ChpdzxRH.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-9igfctfZ.js +1 -0
- package/dist/dashboard/assets/BannedPage-9igfctfZ.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-BzGevuql.js → CliToolDetailPage-ZRr2K2sF.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-ZRr2K2sF.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BaRM_7We.js → CliToolsPage-D3xqZbN-.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-D3xqZbN-.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CVnQPBBz.js +1 -0
- package/dist/dashboard/assets/CombosPage-CVnQPBBz.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-DqUGcoH0.js → CustomizationPage-CTTpCb25.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-CTTpCb25.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-DbhTGfhb.js → LoginPage-DHoB3Agn.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DHoB3Agn.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-oQ-SDXp8.js +1 -0
- package/dist/dashboard/assets/ModelPicker-oQ-SDXp8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BrY4SgIt.js +1 -0
- package/dist/dashboard/assets/OverviewPage-BrY4SgIt.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-D9VSt7T_.js +3 -0
- package/dist/dashboard/assets/ProviderDetailPage-D9VSt7T_.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-Df77V5I5.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-Df77V5I5.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CDfxP7AC.js +7 -0
- package/dist/dashboard/assets/ProxyPage-CDfxP7AC.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CY4o2t4p.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CY4o2t4p.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-YxRml8AT.js → SettingsPage-CvjZxHE4.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-CvjZxHE4.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-D3nza7LH.js +1 -0
- package/dist/dashboard/assets/SetupPage-D3nza7LH.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-Bol1ASmI.js → SortableList-Dtt12WT1.js} +1 -1
- package/dist/dashboard/assets/SortableList-Dtt12WT1.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-CbK3hXvU.js +31 -0
- package/dist/dashboard/assets/StudioPage-CbK3hXvU.js.gz +0 -0
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BQlWbWg2.js +56 -0
- package/dist/dashboard/assets/UsagePage-BQlWbWg2.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BmDbsior.js +1 -0
- package/dist/dashboard/assets/api-keys-BmDbsior.js.gz +0 -0
- package/dist/dashboard/assets/app-BbpSarVV.css +2 -0
- package/dist/dashboard/assets/app-BbpSarVV.css.gz +0 -0
- package/dist/dashboard/assets/{app-BDJWMThu.js → app-C-Y4oZT0.js} +3 -3
- package/dist/dashboard/assets/app-C-Y4oZT0.js.gz +0 -0
- package/dist/dashboard/assets/arrow-left-CpBxkoxI.js.gz +0 -0
- package/dist/dashboard/assets/arrow-right-Dl5yKnp8.js.gz +0 -0
- package/dist/dashboard/assets/assert-BHfaei-X.js +1 -0
- package/dist/dashboard/assets/assert-BHfaei-X.js.gz +0 -0
- package/dist/dashboard/assets/backup-file-gdKIlg8U.js.gz +0 -0
- package/dist/dashboard/assets/{badge-BwmwEOgA.js → badge-DpXT4Ixt.js} +1 -1
- package/dist/dashboard/assets/badge-DpXT4Ixt.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BKBfKTqn.js → banner-CSAAWLJv.js} +1 -1
- package/dist/dashboard/assets/banner-CSAAWLJv.js.gz +0 -0
- package/dist/dashboard/assets/brain-Cwed_72z.js.gz +0 -0
- package/dist/dashboard/assets/{card-BTdbRFFg.js → card-DEhRXXw4.js} +1 -1
- package/dist/dashboard/assets/card-DEhRXXw4.js.gz +0 -0
- package/dist/dashboard/assets/check-D69FzdvC.js.gz +0 -0
- package/dist/dashboard/assets/chevron-right-BXIy5l3h.js.gz +0 -0
- package/dist/dashboard/assets/circle-alert-CntYHV5v.js.gz +0 -0
- package/dist/dashboard/assets/circle-check-BU3v_mFW.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-B0wBq-RL.js +1 -0
- package/dist/dashboard/assets/cli-tools-B0wBq-RL.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js +1 -0
- package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js.gz +0 -0
- package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
- package/dist/dashboard/assets/copy-ngmQ9zcZ.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-iocKA3jr.js → dialog-BvQeBMfP.js} +1 -1
- package/dist/dashboard/assets/dialog-BvQeBMfP.js.gz +0 -0
- package/dist/dashboard/assets/dialog-actions-B1axpEg7.js.gz +0 -0
- package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
- package/dist/dashboard/assets/download-dRFo5_Wu.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CDKOTZdY.js → drawer-CMwPXwQB.js} +1 -1
- package/dist/dashboard/assets/drawer-CMwPXwQB.js.gz +0 -0
- package/dist/dashboard/assets/entry-D4O2229X.js +1 -0
- package/dist/dashboard/assets/entry-D4O2229X.js.gz +0 -0
- package/dist/dashboard/assets/entry-DKvr5Q9K.js +1 -0
- package/dist/dashboard/assets/entry-DKvr5Q9K.js.gz +0 -0
- package/dist/dashboard/assets/entry-FQCejoDY.js +4 -0
- package/dist/dashboard/assets/entry-FQCejoDY.js.gz +0 -0
- package/dist/dashboard/assets/eye-C_hawfH4.js.gz +0 -0
- package/dist/dashboard/assets/eye-off-Bk5g2luF.js.gz +0 -0
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/gauge-BbIMy7MB.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-zliLvBwr.js +1 -0
- package/dist/dashboard/assets/github-badge-zliLvBwr.js.gz +0 -0
- package/dist/dashboard/assets/image-BPaouViG.js.gz +0 -0
- package/dist/dashboard/assets/{index-C4hXfAMs.js → index-CXm3FIyt.js} +2 -2
- package/dist/dashboard/assets/index-CXm3FIyt.js.gz +0 -0
- package/dist/dashboard/assets/{inline-DCejSLlA.js → inline-D1IlZZ8H.js} +1 -1
- package/dist/dashboard/assets/inline-D1IlZZ8H.js.gz +0 -0
- package/dist/dashboard/assets/{input-Bn4_kNav.js → input-BpVZdrbc.js} +1 -1
- package/dist/dashboard/assets/input-BpVZdrbc.js.gz +0 -0
- package/dist/dashboard/assets/jsx-runtime-CXUMngI_.js.gz +0 -0
- package/dist/dashboard/assets/key-round-UkavsGxp.js.gz +0 -0
- package/dist/dashboard/assets/layers-2-glBbjl.js.gz +0 -0
- package/dist/dashboard/assets/{layout-Bv-NxqZ5.js → layout-BioLW7gN.js} +1 -1
- package/dist/dashboard/assets/layout-BioLW7gN.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BLA0sldD.js → list-row-CwVcGAIc.js} +1 -1
- package/dist/dashboard/assets/list-row-CwVcGAIc.js.gz +0 -0
- package/dist/dashboard/assets/{live-YlifPYox.js → live-yfEJFF9T.js} +1 -1
- package/dist/dashboard/assets/live-yfEJFF9T.js.gz +0 -0
- package/dist/dashboard/assets/log-in-BmRjy60c.js.gz +0 -0
- package/dist/dashboard/assets/message-circle-CCxGwRvv.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-CT-TxSNX.js +1 -0
- package/dist/dashboard/assets/model-bans-CT-TxSNX.js.gz +0 -0
- package/dist/dashboard/assets/mutation-BkoLM5Ba.js +1 -0
- package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CFL4_Dqc.js.gz +0 -0
- package/dist/dashboard/assets/pencil-768ysRAr.js.gz +0 -0
- package/dist/dashboard/assets/plus-DIdX_g-x.js.gz +0 -0
- package/dist/dashboard/assets/power-off-Yjw9GMJh.js +1 -0
- package/dist/dashboard/assets/power-off-Yjw9GMJh.js.gz +0 -0
- package/dist/dashboard/assets/privacy-mode-GM8bej85.js +1 -0
- package/dist/dashboard/assets/privacy-mode-GM8bej85.js.gz +0 -0
- package/dist/dashboard/assets/providers/agentrouter.svg.gz +0 -0
- package/dist/dashboard/assets/providers/aihubmix.svg.gz +0 -0
- package/dist/dashboard/assets/providers/alibaba-coding-plan.svg.gz +0 -0
- package/dist/dashboard/assets/providers/alibaba.svg.gz +0 -0
- package/dist/dashboard/assets/providers/antigravity.svg.gz +0 -0
- package/dist/dashboard/assets/providers/bai.svg.gz +0 -0
- package/dist/dashboard/assets/providers/blackbox.svg.gz +0 -0
- package/dist/dashboard/assets/providers/claude-code.svg.gz +0 -0
- package/dist/dashboard/assets/providers/cursor.webp +0 -0
- package/dist/dashboard/assets/providers/exa.svg.gz +0 -0
- package/dist/dashboard/assets/providers/gmi-cloud.svg.gz +0 -0
- package/dist/dashboard/assets/providers/inferhub.svg.gz +0 -0
- package/dist/dashboard/assets/providers/muse.svg.gz +0 -0
- package/dist/dashboard/assets/providers/nous-research.svg.gz +0 -0
- package/dist/dashboard/assets/providers/openai-light.svg.gz +0 -0
- package/dist/dashboard/assets/providers/parallel.svg.gz +0 -0
- package/dist/dashboard/assets/providers/tokenharbor.svg.gz +0 -0
- package/dist/dashboard/assets/providers/trae.webp +0 -0
- package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
- package/dist/dashboard/assets/{query-keys-ROf-g1Wi.js → query-keys-D7wX2vM5.js} +1 -1
- package/dist/dashboard/assets/query-keys-D7wX2vM5.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/refresh-cw-BqJFk4sU.js.gz +0 -0
- package/dist/dashboard/assets/rotate-ccw-CufcqITi.js.gz +0 -0
- package/dist/dashboard/assets/route-CNSNj9Zm.js.gz +0 -0
- package/dist/dashboard/assets/routing-Cs6jl49L.js +1 -0
- package/dist/dashboard/assets/routing-Cs6jl49L.js.gz +0 -0
- package/dist/dashboard/assets/scaling-nWE4Cx8f.js.gz +0 -0
- package/dist/dashboard/assets/search-JOKus9rb.js.gz +0 -0
- package/dist/dashboard/assets/select-C0Rer3gF.js +41 -0
- package/dist/dashboard/assets/select-C0Rer3gF.js.gz +0 -0
- package/dist/dashboard/assets/settings-CfcTcOyU.js +1 -0
- package/dist/dashboard/assets/settings-CfcTcOyU.js.gz +0 -0
- package/dist/dashboard/assets/shield-check-DVS0Foqh.js.gz +0 -0
- package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
- package/dist/dashboard/assets/{stack-C1kTcOmP.js → stack-C9_uUjaA.js} +1 -1
- package/dist/dashboard/assets/stack-C9_uUjaA.js.gz +0 -0
- package/dist/dashboard/assets/{state-DHKdg-pm.js → state-DA0B95UQ.js} +1 -1
- package/dist/dashboard/assets/state-DA0B95UQ.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DIDeAiz9.js → switch-Cittxy-x.js} +1 -1
- package/dist/dashboard/assets/switch-Cittxy-x.js.gz +0 -0
- package/dist/dashboard/assets/terminal-Bd4ee8TA.js +1 -0
- package/dist/dashboard/assets/terminal-Bd4ee8TA.js.gz +0 -0
- package/dist/dashboard/assets/toast-CNt_jzO4.js +2 -0
- package/dist/dashboard/assets/toast-CNt_jzO4.js.gz +0 -0
- package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
- package/dist/dashboard/assets/trash-Cppn5c3R.js.gz +0 -0
- package/dist/dashboard/assets/use-clipboard-B0Sy03fE.js.gz +0 -0
- package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
- package/dist/dashboard/assets/use-reduced-motion-C4B0R6Sz.js.gz +0 -0
- package/dist/dashboard/assets/use-timeout-BwcBBRrT.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-DVmwOKU-.js → useMutation-BQKMcJ1H.js} +1 -1
- package/dist/dashboard/assets/useMutation-BQKMcJ1H.js.gz +0 -0
- package/dist/dashboard/assets/wrench-B6E1oEuY.js.gz +0 -0
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +122 -0
- package/migrations/full-postgres/0013_add_providers_tenant_id_index.sql +22 -0
- package/migrations/full-postgres/0014_add_provider_accounts_tenant_id_index.sql +21 -0
- package/migrations/full-postgres/0015_add_payload_stages.sql +18 -0
- package/migrations/full-postgres/0016_add_share_link_slug.sql +20 -0
- package/migrations/full-postgres/0017_add_models_pro_only.sql +18 -0
- package/migrations/full-postgres/0018_add_accounts_quota_plan.sql +18 -0
- package/migrations/full-postgres/0019_add_models_free_tier.sql +15 -0
- package/migrations/lite-sqlite3/0000_baseline.sql +4 -2
- package/migrations/lite-sqlite3/0013_add_providers_tenant_id_index.sql +4 -0
- package/migrations/lite-sqlite3/0014_add_provider_accounts_tenant_id_index.sql +4 -0
- package/migrations/lite-sqlite3/0015_add_payload_stages.sql +18 -0
- package/migrations/lite-sqlite3/0016_add_share_link_slug.sql +20 -0
- package/migrations/lite-sqlite3/0017_add_models_pro_only.sql +18 -0
- package/migrations/lite-sqlite3/0018_add_accounts_quota_plan.sql +18 -0
- package/migrations/lite-sqlite3/0019_add_models_free_tier.sql +15 -0
- package/package.json +26 -30
- package/scripts/cli/{carte-launcher.cjs → bin/carte.cjs} +8 -8
- package/scripts/cli/{cli-launcher.cjs → bin/cartethyia.cjs} +167 -134
- package/scripts/cli/command/admin.ts +65 -0
- package/scripts/cli/command/console-menu.ts +246 -0
- package/scripts/cli/{doctor.ts → command/doctor.ts} +257 -258
- package/scripts/cli/{setup.ts → command/setup.ts} +8 -12
- package/scripts/cli/command/start.ts +77 -0
- package/scripts/cli/command/tray.ts +165 -0
- package/scripts/cli/command/update.ts +23 -0
- package/scripts/cli/{runtime-state.ts → gateway/drain-token.ts} +78 -78
- package/scripts/cli/gateway/instance-lock.ts +105 -0
- package/scripts/cli/gateway/spawn.ts +173 -0
- package/scripts/cli/gateway/stop.ts +51 -0
- package/scripts/cli/main.ts +94 -0
- package/scripts/cli/support/bun.ts +27 -0
- package/scripts/cli/support/env.ts +99 -0
- package/scripts/cli/support/platform.ts +64 -0
- package/scripts/cli/support/services.ts +88 -0
- package/scripts/cli/support/startup-signal.ts +23 -0
- package/scripts/cli/{version.ts → support/version.ts} +1 -1
- package/scripts/cli/tray/hidden-window.vbs +28 -0
- package/scripts/cli/{tray.ts → tray/index.ts} +3 -3
- package/scripts/cli/{tray.ps1 → tray/windows.ps1} +107 -98
- package/scripts/cli/ui/background.ts +110 -0
- package/src/boot/app.ts +23 -7
- package/src/boot/dependencies.ts +55 -13
- package/src/boot/elysia-typebox-bridge.ts +37 -0
- package/src/boot/lifecycle.ts +2 -0
- package/src/config/cooldowns.ts +138 -138
- package/src/config/providers.ts +31 -5
- package/src/config/runtime.ts +19 -3
- package/src/config/spec.ts +20 -0
- package/src/console/api-keys/contracts.ts +414 -391
- package/src/console/api-keys/routes.ts +880 -870
- package/src/console/auth/account-reset-store.ts +14 -0
- package/src/console/auth/account-reset.ts +3 -2
- package/src/console/auth/setup-service.ts +6 -3
- package/src/console/backup/routes.ts +8 -0
- package/src/console/cli-tools/contracts.ts +6 -6
- package/src/console/console-router.ts +5 -3
- package/src/console/dashboard-assets.ts +81 -11
- package/src/console/domain-registration.ts +9 -2
- package/src/console/observability/contracts.ts +475 -423
- package/src/console/observability/routes.ts +31 -6
- package/src/console/observability/store.ts +1015 -912
- package/src/console/providers/catalog/contracts.ts +31 -0
- package/src/console/providers/catalog/provider-operations.ts +8 -0
- package/src/console/providers/catalog/public-model-store.ts +91 -60
- package/src/console/providers/catalog/store.ts +1532 -1521
- package/src/console/providers/oauth/callback-listener.ts +18 -3
- package/src/console/providers/oauth/routes.ts +38 -15
- package/src/console/quota/account-quota-tenant.ts +9 -6
- package/src/console/quota/refresh.ts +19 -0
- package/src/console/response-compression.ts +69 -2
- package/src/console/routing/pools/probe-verdict.ts +72 -0
- package/src/console/share/share-router.ts +7 -4
- package/src/console/share/share-stats.ts +12 -5
- package/src/console/shared/read-through-cache.ts +133 -7
- package/src/console/updates/repository-updates.ts +39 -34
- package/src/console/updates/routes.ts +162 -4
- package/src/main.ts +3 -0
- package/src/network/http2-bidi.ts +85 -0
- package/src/network/outbound-fetch.ts +87 -24
- package/src/network/pool/agent.ts +478 -460
- package/src/network/pool/resolver.ts +1104 -544
- package/src/network/pool-health-machine.ts +12 -5
- package/src/observability/event-log.ts +29 -8
- package/src/observability/metrics.ts +40 -13
- package/src/observability/payload-capture.ts +344 -324
- package/src/observability/runtime-metrics.ts +7 -0
- package/src/persistence/db-pg.ts +9 -3
- package/src/persistence/db-sqlite.ts +497 -495
- package/src/persistence/health-event-flush.ts +137 -0
- package/src/persistence/migrate.ts +181 -129
- package/src/persistence/schema.ts +1360 -1257
- package/src/persistence/settings-revision.ts +25 -0
- package/src/persistence/shared-cache.ts +217 -0
- package/src/persistence/stores/share-store.ts +556 -528
- package/src/persistence/usage-flush.ts +61 -1
- package/src/protocol/canonical-model.ts +23 -1
- package/src/protocol/response/chat.ts +143 -10
- package/src/protocol/response/codex.ts +9 -75
- package/src/protocol/response/omp-tool-call-markup.ts +221 -0
- package/src/protocol/tool-identity.ts +43 -9
- package/src/providers/authentication/jwt-validator.ts +130 -187
- package/src/providers/authentication/oauth-flow-store.ts +16 -9
- package/src/providers/default-registry.ts +177 -1
- package/src/providers/discovery/catalog/catalog-format.ts +20 -0
- package/src/providers/discovery/models-dev-catalog.ts +39 -22
- package/src/providers/discovery/openai-model-discovery.ts +39 -3
- package/src/providers/discovery/openrouter-free-roster.ts +98 -0
- package/src/providers/discovery/probe-wire.ts +29 -5
- package/src/providers/discovery/probing-service.ts +1022 -1001
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +42 -2
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +913 -914
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +88 -0
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +22 -5
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +33 -1
- package/src/providers/integrations/buddy/buddy-identity.ts +46 -0
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +37 -1
- package/src/providers/integrations/buddy/buddy-usage-store.ts +40 -5
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +4 -0
- package/src/providers/integrations/buddy/codebuddy/provider.ts +180 -175
- package/src/providers/integrations/buddy/codebuddy/shared.ts +115 -73
- package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +5 -2
- package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -204
- package/src/providers/integrations/buddy/workbuddy/quota.ts +172 -159
- package/src/providers/integrations/buddy/workbuddy/shared.ts +200 -171
- package/src/providers/integrations/claude/claude.ts +606 -582
- package/src/providers/integrations/cline/cline-quota.ts +18 -16
- package/src/providers/integrations/cline/cline.ts +539 -468
- package/src/providers/integrations/codex/codex.ts +5 -8
- package/src/providers/integrations/commandcode/commandcode.ts +675 -541
- package/src/providers/integrations/commandcode/discovery.ts +116 -0
- package/src/providers/integrations/commandcode/quota.ts +160 -0
- package/src/providers/integrations/cursor/cursor-auth.ts +418 -0
- package/src/providers/integrations/cursor/cursor-catalog.ts +368 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +300 -0
- package/src/providers/integrations/cursor/cursor-identity.ts +92 -0
- package/src/providers/integrations/cursor/cursor-request.ts +471 -0
- package/src/providers/integrations/cursor/cursor-session-manager.ts +281 -0
- package/src/providers/integrations/cursor/cursor-shared.ts +108 -0
- package/src/providers/integrations/cursor/cursor.ts +960 -0
- package/src/providers/integrations/cursor/protocol/framing.ts +129 -0
- package/src/providers/integrations/cursor/protocol/messages.ts +2355 -0
- package/src/providers/integrations/cursor/protocol/struct.ts +305 -0
- package/src/providers/integrations/factory/factory-oauth.ts +7 -11
- package/src/providers/integrations/github/github.ts +4 -4
- package/src/providers/integrations/hermes.ts +79 -8
- package/src/providers/integrations/kilo/kilo-discovery.ts +10 -1
- package/src/providers/integrations/kilo/kilo.ts +153 -146
- package/src/providers/integrations/opencode/opencode-go-quota.ts +130 -0
- package/src/providers/integrations/opencode/provider.ts +532 -499
- package/src/providers/integrations/openrouter/provider.ts +139 -281
- package/src/providers/integrations/qoder/qoder-catalog.ts +450 -0
- package/src/providers/integrations/qoder/qoder-oauth.ts +310 -263
- package/src/providers/integrations/qoder/qoder-realm.ts +106 -0
- package/src/providers/integrations/qoder/qoder-virtual.ts +77 -0
- package/src/providers/integrations/qoder/qoder.ts +865 -730
- package/src/providers/integrations/shared/install-id.ts +29 -2
- package/src/providers/integrations/trae/trae-catalog.ts +190 -0
- package/src/providers/integrations/trae/trae-headers.ts +149 -0
- package/src/providers/integrations/trae/trae-oauth.ts +773 -0
- package/src/providers/integrations/trae/trae-protocol.ts +400 -0
- package/src/providers/integrations/trae/trae-realm.ts +220 -0
- package/src/providers/integrations/trae/trae.ts +458 -0
- package/src/providers/operations/account-health-service.ts +107 -10
- package/src/providers/operations/client-versions.ts +143 -6
- package/src/providers/operations/model-catalog-cache.ts +18 -3
- package/src/providers/operations/provider-catalog-seeder.ts +95 -86
- package/src/providers/operations/provider-catalog-service.ts +76 -0
- package/src/providers/operations/provider-credential-service.ts +46 -7
- package/src/providers/provider-contracts.ts +76 -0
- package/src/providers/provider-metadata.ts +78 -6
- package/src/providers/provider-model-definition.ts +373 -349
- package/src/security/api-key-auth.ts +126 -8
- package/src/transport/contracts.ts +3 -0
- package/src/transport/dispatch/attempt-finalize.ts +39 -2
- package/src/transport/dispatch/attempt-loop.ts +530 -513
- package/src/transport/dispatch/empty-stream.ts +17 -26
- package/src/transport/dispatch/generation.ts +88 -21
- package/src/transport/dispatch/leases.ts +99 -2
- package/src/transport/dispatch/proxy-request.ts +60 -3
- package/src/transport/dispatch/streaming/finalize.ts +16 -1
- package/src/transport/dispatch/streaming/stream.ts +22 -2
- package/src/transport/dispatch/upstream.ts +19 -1
- package/src/transport/failure-policy.ts +20 -0
- package/src/transport/guards/auth-guard.ts +26 -1
- package/src/transport/guards/body-policy.ts +5 -4
- package/src/transport/request/preparer.ts +103 -0
- package/src/transport/request/state.ts +14 -0
- package/src/transport/routing/plan-gate.ts +45 -0
- package/src/transport/routing/route-catalog.ts +799 -738
- package/src/transport/routing/route-model.ts +52 -1
- package/src/transport/routing/router.ts +51 -0
- package/src/transport/surface/chat/encode.ts +18 -31
- package/src/transport/surface/messages/stream.ts +3 -2
- package/src/transport/translation/tool-repair.ts +37 -16
- package/src/workers/account-identity-sweep.ts +14 -12
- package/src/workers/daily-checkin.ts +62 -0
- package/src/workers/quota-refresh-sweep.ts +27 -2
- package/dist/dashboard/assets/BannedPage-DUrXpp-X.js +0 -1
- package/dist/dashboard/assets/CombosPage-B7ETkfVH.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-AisQzCI1.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-BNflDm_f.js +0 -1
- package/dist/dashboard/assets/ModelPicker-CAiPR5Vd.js +0 -1
- package/dist/dashboard/assets/OverviewPage-C3NIzsDx.js +0 -1
- package/dist/dashboard/assets/ProviderDetailPage-BK8i5B5X.js +0 -3
- package/dist/dashboard/assets/ProviderIcon-paOCq8I0.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-CvCVgm1e.js +0 -1
- package/dist/dashboard/assets/ProxyPage-DjabkuzP.js +0 -7
- package/dist/dashboard/assets/QuotaPage-Dxe0B0iu.js +0 -1
- package/dist/dashboard/assets/SetupPage-BaD4P_jW.js +0 -1
- package/dist/dashboard/assets/StudioPage-CLP4le3U.js +0 -31
- package/dist/dashboard/assets/UsagePage-Djes-Epy.js +0 -56
- package/dist/dashboard/assets/api-keys-CjIGQhe7.js +0 -1
- package/dist/dashboard/assets/app-Cjgo4-Lf.css +0 -2
- package/dist/dashboard/assets/assert-Bwh6DJTK.js +0 -1
- package/dist/dashboard/assets/cli-tools-DccaOfhX.js +0 -1
- package/dist/dashboard/assets/clipboard-button-DQmMikNQ.js +0 -1
- package/dist/dashboard/assets/entry-Cpi0rph1.js +0 -4
- package/dist/dashboard/assets/entry-Dm3PpDCO.js +0 -1
- package/dist/dashboard/assets/entry-keNDZ_Wz.js +0 -1
- package/dist/dashboard/assets/github-badge-BuAJr8oU.js +0 -1
- package/dist/dashboard/assets/model-bans-CVvHZ-qz.js +0 -1
- package/dist/dashboard/assets/mutation-BIizFZav.js +0 -1
- package/dist/dashboard/assets/privacy-mode-CQjbZ3xk.js +0 -1
- package/dist/dashboard/assets/routing-jntw9-Ui.js +0 -1
- package/dist/dashboard/assets/select-CGUuTQmj.js +0 -41
- package/dist/dashboard/assets/settings-BAS6QbmJ.js +0 -1
- package/dist/dashboard/assets/sliders-horizontal-ClG7dBeJ.js +0 -1
- package/dist/dashboard/assets/terminal-C9mZ4Ugm.js +0 -1
- package/dist/dashboard/assets/toast-DKAdP2mo.js +0 -2
- package/scripts/cli/cli.ts +0 -771
- package/scripts/operations/probe-egress.ts +0 -335
- package/scripts/operations/restart.ts +0 -120
- package/scripts/shared/env.ts +0 -269
- /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.ico +0 -0
- /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.png +0 -0
- /package/scripts/cli/{menu.ts → ui/prompt.ts} +0 -0
- /package/scripts/cli/{wordmark.ts → ui/wordmark.ts} +0 -0
|
@@ -29,8 +29,31 @@ const CRED_CACHE_MAX_ENTRIES = 2_000;
|
|
|
29
29
|
interface CredCacheEntry {
|
|
30
30
|
readonly at: number;
|
|
31
31
|
readonly value: ResolvedCredential;
|
|
32
|
+
/**
|
|
33
|
+
* When this entry must stop being served, or `undefined` for "the default
|
|
34
|
+
* TTL applies".
|
|
35
|
+
*
|
|
36
|
+
* Per-entry rather than global because a credential's usable lifetime is a
|
|
37
|
+
* property of the credential: an OAuth token with 30 minutes left can be
|
|
38
|
+
* served for the full window, one with 20 seconds left for almost none of
|
|
39
|
+
* it. Storing the bound on the entry lets both share one cache.
|
|
40
|
+
*/
|
|
41
|
+
readonly expiresAt?: number;
|
|
32
42
|
}
|
|
33
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Margin kept between a cached OAuth token's expiry and the moment the cache
|
|
46
|
+
* stops serving it.
|
|
47
|
+
*
|
|
48
|
+
* The old rule refused to cache OAuth at all unless the token outlived the
|
|
49
|
+
* whole 5 s window, which meant every attempt paid a SELECT + AES-GCM decrypt
|
|
50
|
+
* for every OAuth account — the largest remaining per-request DB read. Caching
|
|
51
|
+
* against the token's own expiry is the same safety with a fraction of the
|
|
52
|
+
* reads. The margin covers clock skew between this process and the issuer, and
|
|
53
|
+
* the time a request already in flight may hold the value.
|
|
54
|
+
*/
|
|
55
|
+
const CRED_CACHE_EXPIRY_MARGIN_MS = 30_000;
|
|
56
|
+
|
|
34
57
|
const credCache = new Map<string, CredCacheEntry>();
|
|
35
58
|
|
|
36
59
|
/**
|
|
@@ -159,9 +182,14 @@ export async function resolveCredentialForAccount(
|
|
|
159
182
|
// the cached value would contain a soon-to-expire secret.
|
|
160
183
|
const now = Date.now();
|
|
161
184
|
const cached = credCache.get(credCacheKey(providerId, accountId));
|
|
162
|
-
if (cached
|
|
163
|
-
|
|
164
|
-
|
|
185
|
+
if (cached) {
|
|
186
|
+
// Two independent bounds: the cache window (rotation freshness) and, for a
|
|
187
|
+
// credential whose usable life was known, the moment that life ends. The
|
|
188
|
+
// shorter one wins, so a token about to expire is never served past it and
|
|
189
|
+
// no credential is served stale for longer than the window.
|
|
190
|
+
const withinWindow = now - cached.at < CRED_CACHE_TTL_MS;
|
|
191
|
+
const withinLife = cached.expiresAt === undefined || now < cached.expiresAt;
|
|
192
|
+
if (withinWindow && withinLife) return cached.value;
|
|
165
193
|
}
|
|
166
194
|
|
|
167
195
|
const parsedProviderId = parseProviderId(providerId);
|
|
@@ -208,11 +236,22 @@ export async function resolveCredentialForAccount(
|
|
|
208
236
|
...(authState === undefined ? {} : { auth_state: authState }),
|
|
209
237
|
};
|
|
210
238
|
const value = resolver.resolve(parsedProviderId, [alternative]).credential;
|
|
211
|
-
//
|
|
239
|
+
// Every credential is cached; an OAuth token with a known expiry simply gets
|
|
240
|
+
// a shorter bound. Refusing to cache OAuth was the safe-looking choice that
|
|
241
|
+
// cost a SELECT + decrypt per attempt, and it was stricter than necessary:
|
|
242
|
+
// the risk is serving an expired token, which a TTL tied to that token
|
|
243
|
+
// expiry prevents as completely as not caching does.
|
|
212
244
|
const isOAuth = row.credentialKind === "oauth";
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
245
|
+
const lifeBound =
|
|
246
|
+
isOAuth && dueAt !== undefined ? dueAt - CRED_CACHE_EXPIRY_MARGIN_MS : undefined;
|
|
247
|
+
// A token already inside the margin must not be cached at all — its bound
|
|
248
|
+
// would be in the past, so the entry would be dead on arrival.
|
|
249
|
+
if (lifeBound === undefined || lifeBound > now) {
|
|
250
|
+
credCache.set(credCacheKey(providerId, accountId), {
|
|
251
|
+
at: now,
|
|
252
|
+
value,
|
|
253
|
+
...(lifeBound === undefined ? {} : { expiresAt: lifeBound }),
|
|
254
|
+
});
|
|
216
255
|
evictCredCacheOldest();
|
|
217
256
|
}
|
|
218
257
|
return value;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { CanonicalEvent, CanonicalRequest, WireFamily } from "../protocol/canonical-model";
|
|
6
6
|
import { GatewayError } from "../protocol/gateway-error";
|
|
7
7
|
import { BUNDLED_PROVIDER_METADATA, type BundledProviderId } from "./provider-metadata";
|
|
8
|
+
import type { ValidatedOutboundHttp2Bidi } from "../network/http2-bidi";
|
|
8
9
|
|
|
9
10
|
/** Closed union of every shipped provider ID. */
|
|
10
11
|
export const BUNDLED_PROVIDER_IDS = BUNDLED_PROVIDER_METADATA.map((definition) => definition.id) as readonly BundledProviderId[];
|
|
@@ -67,14 +68,76 @@ export type ValidatedOutboundWebSocket = (
|
|
|
67
68
|
signal: AbortSignal,
|
|
68
69
|
) => Promise<ProviderWebSocketSession>;
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Validated bidirectional HTTP/2 egress, bound to the same selected network
|
|
73
|
+
* pool as `outbound_fetch`.
|
|
74
|
+
*
|
|
75
|
+
* A Connect-RPC bidi Run is neither a `fetch` (the request body never ends)
|
|
76
|
+
* nor a WebSocket (different protocol), so it gets its own capability — and it
|
|
77
|
+
* goes through the same binding factory as every other egress, which is what
|
|
78
|
+
* keeps SSRF validation, DNS pinning, and pool byte attribution intact. A
|
|
79
|
+
* provider adapter receives this closure and never dials a socket itself.
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* The dialer contract handed to a provider adapter.
|
|
83
|
+
*
|
|
84
|
+
* Declared in `network/http2-bidi.ts` — the transport owns the contract — and
|
|
85
|
+
* re-exported here so provider code keeps one import site.
|
|
86
|
+
*/
|
|
87
|
+
export type { ValidatedOutboundHttp2Bidi };
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A provider session that outlives the HTTP request that created it.
|
|
91
|
+
*
|
|
92
|
+
* Cursor's Run stays open between the client's separate HTTP requests: the
|
|
93
|
+
* first request returns a tool call and the next submits that tool's result on
|
|
94
|
+
* the *same* upstream Run. The account and network-pool slot that Run holds
|
|
95
|
+
* must therefore stay held too, while the request-scoped accounting for the
|
|
96
|
+
* first HTTP request is already settled. Ownership is transferred here so the
|
|
97
|
+
* release is idempotent and belongs to exactly one owner.
|
|
98
|
+
*/
|
|
99
|
+
export interface AttemptLeaseOwnership {
|
|
100
|
+
/**
|
|
101
|
+
* Hands the selected account/network-pool lease to a provider session that
|
|
102
|
+
* outlives this request. Returns the release to call exactly once when the
|
|
103
|
+
* session terminates; returns `undefined` when there was nothing to transfer
|
|
104
|
+
* (a credential-less or pool-less route), which is not an error.
|
|
105
|
+
*
|
|
106
|
+
* Idempotent: a second call returns `undefined` and releases nothing.
|
|
107
|
+
*/
|
|
108
|
+
transferToProviderSession(): (() => void) | undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Identity that authorizes a later request to continue a provider session the
|
|
113
|
+
* gateway is already holding.
|
|
114
|
+
*
|
|
115
|
+
* Cursor's tool loop spans two client HTTP requests on one upstream Run, so the
|
|
116
|
+
* Run — and the account lease it holds — outlives the request that opened it. A
|
|
117
|
+
* later request may only claim the Run by presenting the same tenant, API key,
|
|
118
|
+
* provider, and account, all recorded server-side when the Run was created. A
|
|
119
|
+
* call id alone is never sufficient: it is unguessable but it is still just a
|
|
120
|
+
* string a client could carry into another key's request.
|
|
121
|
+
*/
|
|
122
|
+
export interface ProviderContinuationScope {
|
|
123
|
+
readonly tenantId: string;
|
|
124
|
+
readonly apiKeyId: string;
|
|
125
|
+
readonly providerId: string;
|
|
126
|
+
readonly providerAccountId: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
70
129
|
/** Context passed from routing to a provider adapter. */
|
|
71
130
|
export interface ProviderDispatchContext {
|
|
72
131
|
readonly credential: ResolvedCredential;
|
|
73
132
|
readonly deadline: number;
|
|
74
133
|
readonly abort_signal: AbortSignal;
|
|
75
134
|
readonly outbound_fetch?: ValidatedOutboundFetch | undefined;
|
|
135
|
+
/** Validated image/attachment egress; deliberately excluded from payload capture. */
|
|
136
|
+
readonly outbound_attachment_fetch?: ValidatedOutboundFetch | undefined;
|
|
76
137
|
/** Validated WSS egress bound to the same selected network pool as HTTP. */
|
|
77
138
|
readonly outbound_websocket?: ValidatedOutboundWebSocket | undefined;
|
|
139
|
+
/** Validated bidirectional HTTP/2 egress bound to the same selected network pool. */
|
|
140
|
+
readonly outbound_http2?: ValidatedOutboundHttp2Bidi | undefined;
|
|
78
141
|
/** Built-in API-key route-selected fallback User-Agent; custom providers leave this unset. */
|
|
79
142
|
readonly user_agent?: string | undefined;
|
|
80
143
|
/** Gateway request id, stable across provider retries for one logical request. */
|
|
@@ -85,6 +148,19 @@ export interface ProviderDispatchContext {
|
|
|
85
148
|
readonly conversation_affinity?: string | undefined;
|
|
86
149
|
/** Opaque identity shared by retries of one logical gateway request. */
|
|
87
150
|
readonly request_identity?: object | undefined;
|
|
151
|
+
/**
|
|
152
|
+
* Ownership of this attempt's account/network-pool lease. Present only when
|
|
153
|
+
* the route holds a lease; a provider session that outlives the request
|
|
154
|
+
* (Cursor's Run) takes it over so the slot is not released while the Run is
|
|
155
|
+
* live, and not released twice when it ends.
|
|
156
|
+
*/
|
|
157
|
+
readonly lease_ownership?: AttemptLeaseOwnership | undefined;
|
|
158
|
+
/**
|
|
159
|
+
* Identity of the caller, for a provider session that outlives this request.
|
|
160
|
+
* Absent when the route cannot scope a continuation, in which case a session
|
|
161
|
+
* must not be held open across requests at all.
|
|
162
|
+
*/
|
|
163
|
+
readonly continuation_scope?: ProviderContinuationScope | undefined;
|
|
88
164
|
}
|
|
89
165
|
|
|
90
166
|
const USER_AGENT_HEADER_NAME = /^user-agent$/i;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { SERVICE_KINDS, type ServiceKind, type WireFamily } from "../protocol/canonical-model";
|
|
2
|
+
import { QODER_CHAT_PATH, QODER_REALMS } from "./integrations/qoder/qoder-realm";
|
|
3
|
+
import { TRAE_CHAT_PATH, TRAE_REALMS } from "./integrations/trae/trae-realm";
|
|
2
4
|
|
|
3
5
|
/** OpenAI-compatible wire overrides persisted for bundled and BYOK providers. */
|
|
4
6
|
export interface CompatibilityProfile {
|
|
@@ -110,6 +112,17 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
|
|
|
110
112
|
credentialUrl: "https://kiro.dev",
|
|
111
113
|
credentialHint: "Sign in with Google or GitHub in the browser, or use the device-code login with an Identity Center organization, then paste a Kiro API key if you prefer. Prompt caching is not reliably working for Kiro: the upstream recomputes the prompt on every turn, so cached-token savings should not be expected.",
|
|
112
114
|
},
|
|
115
|
+
{
|
|
116
|
+
id: "cursor",
|
|
117
|
+
displayName: "Cursor",
|
|
118
|
+
baseUrl: "https://api2.cursor.sh",
|
|
119
|
+
wireFamilyDefault: "chat",
|
|
120
|
+
requiresAccount: true,
|
|
121
|
+
bespokeWire: true,
|
|
122
|
+
hasAdapterUserAgent: true,
|
|
123
|
+
credentialUrl: "https://cursor.com",
|
|
124
|
+
credentialHint: "Sign in with Cursor or import a Cursor API key.",
|
|
125
|
+
},
|
|
113
126
|
{ id: "kimi", displayName: "Kimi Code", baseUrl: "https://api.kimi.com/coding", credentialUrl: "https://platform.moonshot.ai/console/api-keys" },
|
|
114
127
|
{ id: "opencode", displayName: "OpenCode Free", baseUrl: "https://opencode.ai", requiresAccount: false, ipScopedRateLimit: true, hasAdapterUserAgent: true },
|
|
115
128
|
{ id: "opencode-zen", displayName: "OpenCode Zen", baseUrl: "https://opencode.ai", hasAdapterUserAgent: true, credentialUrl: "https://opencode.ai/auth" },
|
|
@@ -281,7 +294,23 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
|
|
|
281
294
|
baseUrl: "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
|
|
282
295
|
credentialUrl: "https://bailian.console.aliyun.com/",
|
|
283
296
|
},
|
|
284
|
-
|
|
297
|
+
// Egress pool traffic is refused here: the origin sits behind Cloudflare,
|
|
298
|
+
// which answers the pool's addresses with `403 Attention Required!` while the
|
|
299
|
+
// same request from the host answers 200. The credential is a per-account API
|
|
300
|
+
// key, so rotating the egress address buys nothing and only invites the
|
|
301
|
+
// challenge — the same reason InferHub and Cline skip the pool.
|
|
302
|
+
{
|
|
303
|
+
id: "hermes",
|
|
304
|
+
displayName: "Nous Research",
|
|
305
|
+
baseUrl: "https://inference-api.nousresearch.com/v1",
|
|
306
|
+
credentialUrl: "https://portal.nousresearch.com",
|
|
307
|
+
defaultSkipProxy: true,
|
|
308
|
+
// The adapter stamps its own identity (`hermes-agent/<version>`), which it
|
|
309
|
+
// also needs: Cloudflare in front of the origin refuses a request with no
|
|
310
|
+
// User-Agent. Letting the operator overwrite it would let them break the
|
|
311
|
+
// provider, so the console locks the control.
|
|
312
|
+
hasAdapterUserAgent: true,
|
|
313
|
+
},
|
|
285
314
|
{ id: "bai", displayName: "B.AI", baseUrl: "https://api.b.ai/v1", credentialUrl: "https://b.ai" },
|
|
286
315
|
{ id: "inferhub", displayName: "InferHub", baseUrl: "https://api.inferhub.dev/v1", defaultSkipProxy: true },
|
|
287
316
|
{ id: "aihubmix", displayName: "AiHubMix", baseUrl: "https://aihubmix.com/v1", credentialUrl: "https://aihubmix.com/token" },
|
|
@@ -308,14 +337,47 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
|
|
|
308
337
|
// (`x-command-code-version`, `x-cli-environment`, `x-session-id`) and never
|
|
309
338
|
// reads the route User-Agent, so the Routing Strategy panel must not offer
|
|
310
339
|
// a custom User-Agent for it — the field would be silently ignored.
|
|
340
|
+
//
|
|
341
|
+
// The base is the Provider API origin, not `/alpha/generate`. Command Code
|
|
342
|
+
// serves three wires from `/provider/v1` — `/chat/completions`,
|
|
343
|
+
// `/responses` and `/messages` — and `/alpha/generate` is the CLI's own
|
|
344
|
+
// NDJSON surface. Pointing the base at one endpoint made the other two
|
|
345
|
+
// unroutable, which is why every `claude-*` id (served on `/messages`
|
|
346
|
+
// only) could not be dispatched at all.
|
|
311
347
|
id: "commandcode",
|
|
312
348
|
displayName: "Command Code",
|
|
313
|
-
baseUrl: "https://api.commandcode.ai/
|
|
349
|
+
baseUrl: "https://api.commandcode.ai/provider/v1",
|
|
314
350
|
hasAdapterUserAgent: true,
|
|
315
351
|
credentialUrl: "https://commandcode.ai/studio",
|
|
316
352
|
credentialHint: "Use the API key from the Command Code CLI, or create one in the studio.",
|
|
317
353
|
},
|
|
318
354
|
{ id: "qoder", displayName: "Qoder", baseUrl: "https://api2.qoder.sh/algo/api/v2/service/pro/sse/agent_chat_generation?FetchKeys=llm_model_result&AgentId=agent_common&Encode=1", hasAdapterUserAgent: true, credentialUrl: "https://qoder.com/account/integrations", credentialHint: "Paste a Personal Access Token (pt-...) from the Qoder integrations page, or sign in with your Qoder account." },
|
|
355
|
+
// A separate provider, not a region flag on `qoder`: the China deployment has
|
|
356
|
+
// its own gateway host, OAuth client id, and model roster, and a CN account
|
|
357
|
+
// dispatched to the global host is refused rather than degraded.
|
|
358
|
+
//
|
|
359
|
+
// The base is built from the realm table rather than restated, so the host
|
|
360
|
+
// the console shows and the host the adapter dials cannot disagree.
|
|
361
|
+
{
|
|
362
|
+
id: "qodercn",
|
|
363
|
+
displayName: "Qoder CN",
|
|
364
|
+
baseUrl: `${QODER_REALMS.cn.gateway}${QODER_CHAT_PATH}`,
|
|
365
|
+
hasAdapterUserAgent: true,
|
|
366
|
+
credentialUrl: `${QODER_REALMS.cn.website}/account/integrations`,
|
|
367
|
+
credentialHint: "Paste a Personal Access Token (pt-...) from the Qoder CN integrations page, or sign in with your Qoder China account.",
|
|
368
|
+
},
|
|
369
|
+
{ id: "trae", displayName: "Trae", baseUrl: `${TRAE_REALMS.intl.core}${TRAE_CHAT_PATH}`, hasAdapterUserAgent: true, credentialUrl: "https://www.trae.ai/", credentialHint: "Paste a Trae account export (accessToken + refreshToken) or the raw access token from an international Trae account." },
|
|
370
|
+
// A separate provider, not a region flag on `trae`: the China deployment has
|
|
371
|
+
// its own core host, authorization scheme, and model roster, and a CN account
|
|
372
|
+
// dispatched to the intl host is refused rather than degraded.
|
|
373
|
+
{
|
|
374
|
+
id: "traecn",
|
|
375
|
+
displayName: "Trae CN",
|
|
376
|
+
baseUrl: `${TRAE_REALMS.cn.core}${TRAE_CHAT_PATH}`,
|
|
377
|
+
hasAdapterUserAgent: true,
|
|
378
|
+
credentialUrl: "https://www.trae.com.cn/",
|
|
379
|
+
credentialHint: "Paste a Trae CN account export (accessToken + refreshToken) or the raw access token from a Trae China account.",
|
|
380
|
+
},
|
|
319
381
|
{ id: "ollamacloud", displayName: "Ollama Cloud", baseUrl: "https://ollama.com/v1", credentialUrl: "https://ollama.com/settings/keys" },
|
|
320
382
|
{ id: "gemini", displayName: "Google Gemini", baseUrl: "https://generativelanguage.googleapis.com/v1beta", serviceKinds: ["llm", "websearch", "imageGeneration"], credentialUrl: "https://aistudio.google.com/app/apikey" },
|
|
321
383
|
{ id: "xiaomipg", displayName: "Xiaomi MiMo (PAYG)", baseUrl: "https://api.xiaomimimo.com/v1", credentialUrl: "https://platform.xiaomimimo.com" },
|
|
@@ -508,8 +570,8 @@ export function providerDisplayName(providerId: string): string {
|
|
|
508
570
|
* A bundled provider gets exactly what its manifest declares. A custom/BYOK
|
|
509
571
|
* provider has no manifest row, and this is where its capability comes from:
|
|
510
572
|
* `llm` alone is read as "every media surface this gateway knows", so a
|
|
511
|
-
* third-party provider can serve image and
|
|
512
|
-
* gateway having to be taught its id.
|
|
573
|
+
* third-party provider can serve image, video, embeddings, and audio without
|
|
574
|
+
* the gateway having to be taught its id.
|
|
513
575
|
*
|
|
514
576
|
* That widening is deliberate rather than a default of `["llm"]`, because a
|
|
515
577
|
* BYOK provider points at an operator-chosen base URL — the operator already
|
|
@@ -517,6 +579,16 @@ export function providerDisplayName(providerId: string): string {
|
|
|
517
579
|
* out of the generation routes no matter what its upstream actually answers.
|
|
518
580
|
* The upstream still decides: a request for a capability the remote does not
|
|
519
581
|
* have comes back as that remote's own error, not a gateway-side refusal.
|
|
582
|
+
*
|
|
583
|
+
* A custom provider is read as able to serve **every** kind, taken straight
|
|
584
|
+
* from `SERVICE_KINDS` rather than a second list that can drift from it. A
|
|
585
|
+
* surface added to the tuple is reachable by custom providers immediately, and
|
|
586
|
+
* one that is not there cannot be served by anyone.
|
|
587
|
+
*
|
|
588
|
+
* `systemone` and `websearch` are included even though a base URL alone rarely
|
|
589
|
+
* answers them: the upstream still decides, and an operator who points a custom
|
|
590
|
+
* provider at a host that does speak those shapes should not be blocked by the
|
|
591
|
+
* gateway guessing it will not.
|
|
520
592
|
*/
|
|
521
593
|
export function providerServiceKinds(providerId: string): readonly ServiceKind[] {
|
|
522
594
|
const declared = BUNDLED_PROVIDER_METADATA.find((candidate) => candidate.id === providerId)
|
|
@@ -524,7 +596,7 @@ export function providerServiceKinds(providerId: string): readonly ServiceKind[]
|
|
|
524
596
|
// Bundled providers are explicit: they say which surfaces they serve, and a
|
|
525
597
|
// bundled provider without the declaration serves LLM only.
|
|
526
598
|
if (declared !== undefined) return declared;
|
|
527
|
-
return
|
|
599
|
+
return SERVICE_KINDS;
|
|
528
600
|
}
|
|
529
601
|
|
|
530
602
|
|