cartethyia 2.4.6 → 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/README.md +45 -13
- package/dist/dashboard/assets/BannedPage-9igfctfZ.js +1 -0
- package/dist/dashboard/assets/BannedPage-9igfctfZ.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-Bcy150Jo.js → CliToolDetailPage-ZRr2K2sF.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-ZRr2K2sF.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-DyNXefph.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-CATpAEOz.js → ConsoleLogPage-u6W1UXSc.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-D6jEU7nL.js → CustomizationPage-CTTpCb25.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-CTTpCb25.js.gz +0 -0
- package/dist/dashboard/assets/{HealthEventsModal-CZkpn0a7.js → HealthEventsModal-C5XpWlvy.js} +1 -1
- package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-BJlMVN4U.js → LoginPage-DHoB3Agn.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DHoB3Agn.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-Br3CXEau.js → ModelPicker-oQ-SDXp8.js} +1 -1
- 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-BHW4Zt06.js → SettingsPage-CvjZxHE4.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-CvjZxHE4.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-VOYC_lIa.js → SetupPage-D3nza7LH.js} +1 -1
- package/dist/dashboard/assets/SetupPage-D3nza7LH.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-Dtt12WT1.js +1 -0
- package/dist/dashboard/assets/SortableList-Dtt12WT1.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-BNIDLiU6.js → StudioPage-CbK3hXvU.js} +4 -4
- package/dist/dashboard/assets/StudioPage-CbK3hXvU.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-BETfaMYZ.js → api-keys-BmDbsior.js} +1 -1
- 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/assert-BHfaei-X.js +1 -0
- package/dist/dashboard/assets/assert-BHfaei-X.js.gz +0 -0
- package/dist/dashboard/assets/{badge-BTyGk_DL.js → badge-DpXT4Ixt.js} +1 -1
- package/dist/dashboard/assets/badge-DpXT4Ixt.js.gz +0 -0
- package/dist/dashboard/assets/{banner-bujTWYM4.js → banner-CSAAWLJv.js} +1 -1
- package/dist/dashboard/assets/banner-CSAAWLJv.js.gz +0 -0
- package/dist/dashboard/assets/{card-B0Bnx5CA.js → card-DEhRXXw4.js} +1 -1
- package/dist/dashboard/assets/card-DEhRXXw4.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-DE2ug812.js → cli-tools-B0wBq-RL.js} +1 -1
- package/dist/dashboard/assets/cli-tools-B0wBq-RL.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-R_rArH8S.js → clipboard-button-DOo6EU8O.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-BWIP_EvW.js → dialog-BvQeBMfP.js} +1 -1
- package/dist/dashboard/assets/dialog-BvQeBMfP.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-BKcgVugF.js → drawer-CMwPXwQB.js} +1 -1
- package/dist/dashboard/assets/drawer-CMwPXwQB.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CcWkGR4a.js → entry-D4O2229X.js} +1 -1
- package/dist/dashboard/assets/{entry-CcWkGR4a.js.gz → entry-D4O2229X.js.gz} +0 -0
- package/dist/dashboard/assets/{entry-kTiTFrvh.js → entry-DKvr5Q9K.js} +1 -1
- 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/{github-badge-Booc5mNe.js → github-badge-zliLvBwr.js} +1 -1
- package/dist/dashboard/assets/github-badge-zliLvBwr.js.gz +0 -0
- package/dist/dashboard/assets/{index-D70pChfn.js → index-CXm3FIyt.js} +2 -2
- package/dist/dashboard/assets/index-CXm3FIyt.js.gz +0 -0
- package/dist/dashboard/assets/{inline-D1TCqM2D.js → inline-D1IlZZ8H.js} +1 -1
- package/dist/dashboard/assets/inline-D1IlZZ8H.js.gz +0 -0
- package/dist/dashboard/assets/{input-B9oyU93y.js → input-BpVZdrbc.js} +1 -1
- package/dist/dashboard/assets/input-BpVZdrbc.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BArzXirQ.js → layout-BioLW7gN.js} +1 -1
- package/dist/dashboard/assets/layout-BioLW7gN.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BVZzaoHF.js → list-row-CwVcGAIc.js} +1 -1
- package/dist/dashboard/assets/list-row-CwVcGAIc.js.gz +0 -0
- package/dist/dashboard/assets/{live-EmuIayqp.js → live-yfEJFF9T.js} +1 -1
- package/dist/dashboard/assets/live-yfEJFF9T.js.gz +0 -0
- package/dist/dashboard/assets/{model-bans-CSPQ9xB0.js → model-bans-CT-TxSNX.js} +1 -1
- package/dist/dashboard/assets/model-bans-CT-TxSNX.js.gz +0 -0
- package/dist/dashboard/assets/providers/cursor.webp +0 -0
- package/dist/dashboard/assets/providers/trae.webp +0 -0
- package/dist/dashboard/assets/{routing-BExgxxBU.js → routing-Cs6jl49L.js} +1 -1
- package/dist/dashboard/assets/routing-Cs6jl49L.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/{stack-Ca5HxI5i.js → stack-C9_uUjaA.js} +1 -1
- package/dist/dashboard/assets/stack-C9_uUjaA.js.gz +0 -0
- package/dist/dashboard/assets/{state-CzUPfLXo.js → state-DA0B95UQ.js} +1 -1
- package/dist/dashboard/assets/state-DA0B95UQ.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DOUIky_i.js → switch-Cittxy-x.js} +1 -1
- package/dist/dashboard/assets/switch-Cittxy-x.js.gz +0 -0
- package/dist/dashboard/assets/{toast-C76WrMhc.js → toast-CNt_jzO4.js} +1 -1
- package/dist/dashboard/assets/toast-CNt_jzO4.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-D87FZwH0.js → useMutation-BQKMcJ1H.js} +1 -1
- package/dist/dashboard/assets/useMutation-BQKMcJ1H.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 +51 -52
- 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/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 +3 -2
- package/scripts/cli/command/console-menu.ts +30 -11
- package/scripts/cli/command/start.ts +77 -13
- package/scripts/cli/command/update.ts +1 -1
- package/scripts/cli/gateway/instance-lock.ts +105 -0
- package/scripts/cli/gateway/spawn.ts +173 -101
- package/scripts/cli/ui/background.ts +110 -49
- package/src/boot/app.ts +20 -6
- package/src/boot/dependencies.ts +19 -0
- 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 +5 -5
- package/src/config/runtime.ts +19 -3
- package/src/config/spec.ts +9 -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/domain-registration.ts +9 -2
- package/src/console/observability/contracts.ts +475 -455
- package/src/console/observability/store.ts +1015 -952
- package/src/console/providers/catalog/contracts.ts +31 -0
- package/src/console/providers/catalog/provider-operations.ts +8 -0
- package/src/console/providers/catalog/store.ts +1532 -1525
- package/src/console/providers/oauth/callback-listener.ts +18 -3
- package/src/console/providers/oauth/routes.ts +38 -15
- package/src/console/quota/refresh.ts +19 -0
- 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 +1 -26
- 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/payload-capture.ts +344 -324
- 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 -1295
- 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/omp-tool-call-markup.ts +221 -0
- package/src/providers/default-registry.ts +173 -1
- package/src/providers/discovery/openai-model-discovery.ts +39 -3
- package/src/providers/discovery/openrouter-free-roster.ts +98 -0
- package/src/providers/discovery/probing-service.ts +1022 -1001
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +39 -0
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +913 -914
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +18 -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 +15 -6
- package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -204
- package/src/providers/integrations/buddy/workbuddy/shared.ts +3 -3
- 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/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/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/provider.ts +532 -538
- 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 -257
- 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/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 +133 -6
- package/src/providers/operations/provider-catalog-seeder.ts +95 -86
- 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 +32 -1
- package/src/transport/dispatch/attempt-loop.ts +530 -515
- 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/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 -777
- package/src/transport/routing/route-model.ts +52 -1
- package/src/transport/routing/router.ts +51 -0
- package/dist/dashboard/assets/BannedPage-QhvbJB9o.js +0 -1
- package/dist/dashboard/assets/BannedPage-QhvbJB9o.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-Bcy150Jo.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-DyNXefph.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-Cak0ljnO.js +0 -1
- package/dist/dashboard/assets/CombosPage-Cak0ljnO.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CATpAEOz.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-D6jEU7nL.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-CZkpn0a7.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-BJlMVN4U.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-Br3CXEau.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CQxXbo2g.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CQxXbo2g.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage--0RBNh99.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage--0RBNh99.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-paOCq8I0.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-paOCq8I0.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-1M-C3mbu.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-1M-C3mbu.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CXiumA53.js +0 -7
- package/dist/dashboard/assets/ProxyPage-CXiumA53.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-BGDIfIYP.js +0 -1
- package/dist/dashboard/assets/QuotaPage-BGDIfIYP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BHW4Zt06.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-VOYC_lIa.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-DpOTnGuH.js +0 -1
- package/dist/dashboard/assets/SortableList-DpOTnGuH.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-BNIDLiU6.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BAFaSDQV.js +0 -56
- package/dist/dashboard/assets/UsagePage-BAFaSDQV.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BETfaMYZ.js.gz +0 -0
- package/dist/dashboard/assets/app-BLCvGdzb.css +0 -2
- package/dist/dashboard/assets/app-BLCvGdzb.css.gz +0 -0
- package/dist/dashboard/assets/assert-7J6_LVD3.js +0 -1
- package/dist/dashboard/assets/assert-7J6_LVD3.js.gz +0 -0
- package/dist/dashboard/assets/badge-BTyGk_DL.js.gz +0 -0
- package/dist/dashboard/assets/banner-bujTWYM4.js.gz +0 -0
- package/dist/dashboard/assets/card-B0Bnx5CA.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-DE2ug812.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-R_rArH8S.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BWIP_EvW.js.gz +0 -0
- package/dist/dashboard/assets/drawer-BKcgVugF.js.gz +0 -0
- package/dist/dashboard/assets/entry-7dpgvpJ3.js +0 -4
- package/dist/dashboard/assets/entry-7dpgvpJ3.js.gz +0 -0
- package/dist/dashboard/assets/entry-kTiTFrvh.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-Booc5mNe.js.gz +0 -0
- package/dist/dashboard/assets/index-D70pChfn.js.gz +0 -0
- package/dist/dashboard/assets/inline-D1TCqM2D.js.gz +0 -0
- package/dist/dashboard/assets/input-B9oyU93y.js.gz +0 -0
- package/dist/dashboard/assets/layout-BArzXirQ.js.gz +0 -0
- package/dist/dashboard/assets/list-row-BVZzaoHF.js.gz +0 -0
- package/dist/dashboard/assets/live-EmuIayqp.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-CSPQ9xB0.js.gz +0 -0
- package/dist/dashboard/assets/routing-BExgxxBU.js.gz +0 -0
- package/dist/dashboard/assets/select-C9mMoEpJ.js +0 -41
- package/dist/dashboard/assets/select-C9mMoEpJ.js.gz +0 -0
- package/dist/dashboard/assets/settings-C4_Gn_wq.js +0 -1
- package/dist/dashboard/assets/settings-C4_Gn_wq.js.gz +0 -0
- package/dist/dashboard/assets/sliders-horizontal-ClG7dBeJ.js +0 -1
- package/dist/dashboard/assets/sliders-horizontal-ClG7dBeJ.js.gz +0 -0
- package/dist/dashboard/assets/stack-Ca5HxI5i.js.gz +0 -0
- package/dist/dashboard/assets/state-CzUPfLXo.js.gz +0 -0
- package/dist/dashboard/assets/switch-DOUIky_i.js.gz +0 -0
- package/dist/dashboard/assets/toast-C76WrMhc.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-D87FZwH0.js.gz +0 -0
- package/src/network/tls/bun-client-hello.ts +0 -112
- /package/dist/dashboard/assets/{app-Cjq7nrwu.js → app-C-Y4oZT0.js} +0 -0
- /package/dist/dashboard/assets/{app-Cjq7nrwu.js.gz → app-C-Y4oZT0.js.gz} +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
// Trae model rosters.
|
|
2
|
+
//
|
|
3
|
+
// Each realm has its own roster because upstream really does serve different
|
|
4
|
+
// models per deployment — CN is domestic (Doubao/DeepSeek/GLM/Kimi/Qwen),
|
|
5
|
+
// intl is frontier (Gemini/Claude/GPT/Grok). Merging them would offer a CN
|
|
6
|
+
// account models its realm refuses, which is a runtime failure rather than a
|
|
7
|
+
// cosmetic one.
|
|
8
|
+
//
|
|
9
|
+
// The static rosters are the fallback, not the truth: `discoverTraeModels`
|
|
10
|
+
// replaces them with the live `/api/ide/v1/model_list` answer when that
|
|
11
|
+
// endpoint works. It works on CN only — intl answers `403 no schema found`, so
|
|
12
|
+
// intl stays on its static roster and says so via `modelListSupported`.
|
|
13
|
+
|
|
14
|
+
import { defineModel, type ModelDefinition } from "../../provider-model-definition";
|
|
15
|
+
import { TRAE_AGENT_CHAT_PATH, TRAE_CHAT_PATH, type TraeRealm } from "./trae-realm";
|
|
16
|
+
|
|
17
|
+
/** One roster row, as upstream describes it. */
|
|
18
|
+
export interface TraeModelRow {
|
|
19
|
+
/** Upstream key, sent as `model_name`. */
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly displayName: string;
|
|
22
|
+
/** Context window, preferring the selectable maximum. */
|
|
23
|
+
readonly ctx: number;
|
|
24
|
+
readonly out: number;
|
|
25
|
+
readonly vision: boolean;
|
|
26
|
+
readonly reasoning: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Surface this row belongs to.
|
|
29
|
+
*
|
|
30
|
+
* Defaults to `"chat"`. The picker's models must be `"agent"`: they are
|
|
31
|
+
* absent from `model_list` and answer `4023 model is unknown` on the chat
|
|
32
|
+
* path no matter which host is tried.
|
|
33
|
+
*/
|
|
34
|
+
readonly surface?: TraeSurface;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Which upstream endpoint serves a row. */
|
|
38
|
+
export type TraeSurface = "chat" | "agent";
|
|
39
|
+
|
|
40
|
+
/** CN roster: 20 chat-face models from the donor's client-state snapshot. */
|
|
41
|
+
const TRAE_CN_ROWS: readonly TraeModelRow[] = [
|
|
42
|
+
{ id: "Doubao-Seed-Code", displayName: "Seed-Code", ctx: 256000, out: 224000, vision: true, reasoning: true },
|
|
43
|
+
{ id: "DeepSeek-V4-Flash-Official", displayName: "DeepSeek-V4-Flash", ctx: 1000000, out: 936000, vision: false, reasoning: true },
|
|
44
|
+
{ id: "DeepSeek-V4-Pro-Official", displayName: "DeepSeek-V4-Pro", ctx: 1000000, out: 936000, vision: false, reasoning: true },
|
|
45
|
+
{ id: "deepseek-v4.1-flash", displayName: "DeepSeek-V4.1-Flash", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
46
|
+
{ id: "glm-5.2", displayName: "GLM-5.2", ctx: 1000000, out: 936000, vision: false, reasoning: true },
|
|
47
|
+
{ id: "glm-5.3", displayName: "GLM-5.3", ctx: 1000000, out: 936000, vision: false, reasoning: true },
|
|
48
|
+
{ id: "glm-5.3-flash", displayName: "GLM-5.3-Flash", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
49
|
+
{ id: "glm-5.3-flashx", displayName: "GLM-5.3-FlashX", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
50
|
+
{ id: "kimi-k2.8-preview", displayName: "Kimi-K2.8-Preview", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
51
|
+
{ id: "kimi-k3", displayName: "Kimi-K3", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
52
|
+
{ id: "mimo-v2.6-flash", displayName: "MiMo-V2.6-Flash", ctx: 981504, out: 917504, vision: true, reasoning: false },
|
|
53
|
+
{ id: "mimo-v2.6-pro", displayName: "MiMo-V2.6-Pro", ctx: 981504, out: 917504, vision: true, reasoning: false },
|
|
54
|
+
{ id: "minimax-m3", displayName: "MiniMax-M3", ctx: 1000000, out: 936000, vision: true, reasoning: false },
|
|
55
|
+
{ id: "qwen-3.7-plus", displayName: "Qwen3.7-Plus", ctx: 1000000, out: 936000, vision: true, reasoning: false },
|
|
56
|
+
{ id: "qwen3.8-flash", displayName: "Qwen3.8-Flash", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
57
|
+
{ id: "qwen3.8-max", displayName: "Qwen3.8-Max", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
58
|
+
{ id: "Doubao-Seed-2.1-Pro", displayName: "Seed-2.1-Pro-0915", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
59
|
+
{ id: "Doubao-Seed-2.1-Turbo", displayName: "Seed-2.1-Turbo", ctx: 256000, out: 224000, vision: true, reasoning: true },
|
|
60
|
+
{ id: "Doubao-Seed-Evolving", displayName: "Seed-Evolving", ctx: 1000000, out: 936000, vision: true, reasoning: false },
|
|
61
|
+
{ id: "step-5-preview", displayName: "Step-5-Preview", ctx: 1000000, out: 936000, vision: true, reasoning: true },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Intl roster: the IDE picker's models, every row confirmed by a real
|
|
66
|
+
* completion on a live SG account.
|
|
67
|
+
*
|
|
68
|
+
* Agent-only, and that is a deliberate narrowing rather than an oversight.
|
|
69
|
+
* Trae serves two disjoint surfaces and the legacy chat roster (`gpt-4o`,
|
|
70
|
+
* `gemini_2.5_flash`, `deepseek-V3`, …) belongs to the other one: those ids
|
|
71
|
+
* are rejected here with `4001 param is invalid`, and the agent ids are
|
|
72
|
+
* rejected there with `4023 model is unknown`. There is no call that serves
|
|
73
|
+
* both, so a single-surface catalog is the only honest one; offering the chat
|
|
74
|
+
* ids would advertise models this provider's dispatch cannot reach. See
|
|
75
|
+
* `documentation/research/trae-agent-vs-chat-surface.md`.
|
|
76
|
+
*
|
|
77
|
+
* `ctx` is the **selectable maximum** (`context_window_tokens.max`), not the
|
|
78
|
+
* active `dev` window. Upstream advertises both and they differ by up to 5x
|
|
79
|
+
* (DeepSeek-V4 rows: 200k active, 1M selectable), so reading `dev` makes a
|
|
80
|
+
* client under-request the window it is entitled to. The maximum is per model
|
|
81
|
+
* and is **not** uniform: the GPT rows cap at 272k and Kimi-K2.5 / MiniMax-M2.7
|
|
82
|
+
* offer no selectable upgrade at all, staying at 200k.
|
|
83
|
+
*
|
|
84
|
+
* `out` is what the same model is filed at in the CodeBuddy roster where that
|
|
85
|
+
* roster carries it (DeepSeek-V4 384k, MiniMax-M3 512k, Kimi-K2.5 262k,
|
|
86
|
+
* Kimi-K3 131k, Gemini-3.1-Pro and Kimi-K2.7 65k, the GPT rows 128k), and 131k
|
|
87
|
+
* for models absent there. It is deliberately **not** Trae's
|
|
88
|
+
* `model_detail_list[0].max_tokens`: upstream states that as the cap it applies
|
|
89
|
+
* to its own output, which collapsed the whole roster onto 32k/64k and is far
|
|
90
|
+
* below what these models actually return elsewhere.
|
|
91
|
+
*
|
|
92
|
+
* `glm-5.2` is absent: it is in the harness's id map but not in any account
|
|
93
|
+
* config list, and answers `4001` identically to a bogus id.
|
|
94
|
+
*
|
|
95
|
+
* Rows report their real upstream in `timing_cost.provider_model_name`, which
|
|
96
|
+
* is usually not the id sent (DeepSeek-V4.1-Flash resolves to
|
|
97
|
+
* `ep-2026…-69njn`), so the id is always the config name, never the resolved
|
|
98
|
+
* one.
|
|
99
|
+
*/
|
|
100
|
+
const TRAE_INTL_ROWS: readonly TraeModelRow[] = [
|
|
101
|
+
{ id: "gpt-5.4", displayName: "GPT-5.4", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
102
|
+
{ id: "gpt-5.2", displayName: "GPT-5.2", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
103
|
+
{ id: "gpt-5.2-codex-paygo", displayName: "GPT-5.2-Codex", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
104
|
+
{ id: "gpt-5.1-paygo", displayName: "GPT-5.1", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
105
|
+
{ id: "gpt-5-paygo", displayName: "GPT-5", ctx: 272000, out: 128_000, vision: true, reasoning: true, surface: "agent" },
|
|
106
|
+
{ id: "Dola-Seed-2.0-Code", displayName: "Seed-2.1-Turbo", ctx: 1000000, out: 131_072, vision: true, reasoning: true, surface: "agent" },
|
|
107
|
+
{ id: "deepseek-v4.1-flash", displayName: "DeepSeek-V4.1-Flash", ctx: 1000000, out: 384_000, vision: false, reasoning: true, surface: "agent" },
|
|
108
|
+
{ id: "deepseek-v4-flash-0731", displayName: "DeepSeek-V4-Flash", ctx: 1000000, out: 384_000, vision: false, reasoning: true, surface: "agent" },
|
|
109
|
+
{ id: "deepseek-v4-pro-0813", displayName: "DeepSeek-V4-Pro", ctx: 1000000, out: 384_000, vision: false, reasoning: true, surface: "agent" },
|
|
110
|
+
{ id: "kimi-k3", displayName: "Kimi-K3", ctx: 1000000, out: 131_072, vision: true, reasoning: true, surface: "agent" },
|
|
111
|
+
{ id: "kimi-k2.7-code", displayName: "Kimi-K2.7-Code", ctx: 1000000, out: 65_536, vision: true, reasoning: true, surface: "agent" },
|
|
112
|
+
{ id: "kimi-k2.5", displayName: "Kimi-K2.5", ctx: 200000, out: 262_144, vision: false, reasoning: true, surface: "agent" },
|
|
113
|
+
{ id: "gemini-3.1-pro", displayName: "Gemini-3.1-Pro-Preview", ctx: 1000000, out: 65_536, vision: true, reasoning: true, surface: "agent" },
|
|
114
|
+
{ id: "gemini-3-flash-solo", displayName: "Gemini-3-Flash-Preview", ctx: 1000000, out: 65_536, vision: true, reasoning: true, surface: "agent" },
|
|
115
|
+
{ id: "minimax-m3", displayName: "MiniMax-M3", ctx: 1000000, out: 512_000, vision: true, reasoning: true, surface: "agent" },
|
|
116
|
+
{ id: "minimax-m2.7", displayName: "MiniMax-M2.7", ctx: 200000, out: 131_072, vision: false, reasoning: true, surface: "agent" },
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
function traeModels(rows: readonly TraeModelRow[], providerId: string): readonly ModelDefinition[] {
|
|
120
|
+
return rows.map((row) =>
|
|
121
|
+
defineModel({
|
|
122
|
+
id: row.id,
|
|
123
|
+
providerId,
|
|
124
|
+
wireFamily: "chat",
|
|
125
|
+
endpoint: row.surface === "agent" ? TRAE_AGENT_CHAT_PATH : TRAE_CHAT_PATH,
|
|
126
|
+
ctx: row.ctx,
|
|
127
|
+
out: row.out,
|
|
128
|
+
vision: row.vision,
|
|
129
|
+
reasoning: row.reasoning,
|
|
130
|
+
}),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export const TRAE_CN_MODELS: readonly ModelDefinition[] = traeModels(TRAE_CN_ROWS, "traecn");
|
|
135
|
+
export const TRAE_INTL_MODELS: readonly ModelDefinition[] = traeModels(TRAE_INTL_ROWS, "trae");
|
|
136
|
+
|
|
137
|
+
/** Roster for a realm. */
|
|
138
|
+
export function traeStaticModels(realm: TraeRealm): readonly ModelDefinition[] {
|
|
139
|
+
return realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Reads the largest context window out of one upstream model object.
|
|
144
|
+
*
|
|
145
|
+
* Upstream reports two independent numbers and they are not the same thing:
|
|
146
|
+
* `context_window_size.default` is the window that is active, while
|
|
147
|
+
* `context_window_size.max` is a *list* of selectable windows. Reading only
|
|
148
|
+
* the default is what made the fetcher always pick the smaller number — CN
|
|
149
|
+
* DeepSeek advertises 116k active but 1M selectable, so a client told 116k
|
|
150
|
+
* never asks for the window the account is entitled to.
|
|
151
|
+
*
|
|
152
|
+
* `context_window_tokens` is the older sibling spelling; `dev` pairs with
|
|
153
|
+
* `default` and `max` pairs with `max`.
|
|
154
|
+
*/
|
|
155
|
+
export function traeMaxContextWindow(raw: unknown): number | undefined {
|
|
156
|
+
if (typeof raw !== "object" || raw === null) return undefined;
|
|
157
|
+
const record = raw as Record<string, unknown>;
|
|
158
|
+
const candidates: number[] = [];
|
|
159
|
+
const collect = (value: unknown): void => {
|
|
160
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) {
|
|
161
|
+
candidates.push(value);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (Array.isArray(value)) value.forEach(collect);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const size = record["context_window_size"];
|
|
168
|
+
if (typeof size === "object" && size !== null) {
|
|
169
|
+
const sized = size as Record<string, unknown>;
|
|
170
|
+
collect(sized["max"]);
|
|
171
|
+
}
|
|
172
|
+
const tokens = record["context_window_tokens"];
|
|
173
|
+
if (typeof tokens === "object" && tokens !== null) {
|
|
174
|
+
collect((tokens as Record<string, unknown>)["max"]);
|
|
175
|
+
}
|
|
176
|
+
if (candidates.length > 0) return Math.max(...candidates);
|
|
177
|
+
|
|
178
|
+
// No selectable maximum: the active window is all we honestly know.
|
|
179
|
+
if (typeof size === "object" && size !== null) {
|
|
180
|
+
const fallback = (size as Record<string, unknown>)["default"];
|
|
181
|
+
if (typeof fallback === "number" && Number.isFinite(fallback) && fallback > 0) return fallback;
|
|
182
|
+
}
|
|
183
|
+
if (typeof tokens === "object" && tokens !== null) {
|
|
184
|
+
const fallback = (tokens as Record<string, unknown>)["dev"];
|
|
185
|
+
if (typeof fallback === "number" && Number.isFinite(fallback) && fallback > 0) return fallback;
|
|
186
|
+
}
|
|
187
|
+
const prompt = record["prompt_max_tokens"];
|
|
188
|
+
if (typeof prompt === "number" && Number.isFinite(prompt) && prompt > 0) return prompt;
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Trae request headers: auth + device fingerprint.
|
|
2
|
+
//
|
|
3
|
+
// The two realms do not authenticate the same way. CN sends
|
|
4
|
+
// `Authorization: Cloud-IDE-JWT <token>`; intl overrides it to `Bearer <token>`
|
|
5
|
+
// and additionally sends the *current* client version, because intl
|
|
6
|
+
// `llm_raw_chat` answers `4015` (risk control) when the version is stale. That
|
|
7
|
+
// is why the version here is resolved rather than pinned.
|
|
8
|
+
//
|
|
9
|
+
// Sourced from the donor hub `Public/trae2api-hub` (`auth_headers` in
|
|
10
|
+
// `trae_client.py`, `trae_device_headers` in `trae_fingerprint.py`).
|
|
11
|
+
|
|
12
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
13
|
+
import {
|
|
14
|
+
TRAE_APP_ID,
|
|
15
|
+
TRAE_PLUGIN_CHANNEL,
|
|
16
|
+
TRAE_REALMS,
|
|
17
|
+
type TraeRealm,
|
|
18
|
+
} from "./trae-realm";
|
|
19
|
+
|
|
20
|
+
/** Device fingerprint derived from an account identity. */
|
|
21
|
+
export interface TraeDeviceIdentity {
|
|
22
|
+
/** Stable per account: sha256 of a seeded string, 64 hex chars. */
|
|
23
|
+
readonly machineId: string;
|
|
24
|
+
/** Numeric, 19 digits: the upstream client reuses the account's numeric id. */
|
|
25
|
+
readonly deviceId: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Derives the device pair the upstream client sends.
|
|
30
|
+
*
|
|
31
|
+
* Both are pure one-way derivations from the account id, so one account always
|
|
32
|
+
* presents one device and two accounts never share one — the donor notes this
|
|
33
|
+
* is the risk-control correlation surface, so a per-process random id would
|
|
34
|
+
* look like many devices behind one account and a shared id would link them.
|
|
35
|
+
*/
|
|
36
|
+
export function traeDeviceIdentity(uid: string): TraeDeviceIdentity {
|
|
37
|
+
const seed = String(uid ?? "").trim() || "anonymous";
|
|
38
|
+
const machineId = createHash("sha256").update(`trae-machine:${seed}`).digest("hex");
|
|
39
|
+
const raw = String(uid ?? "").trim();
|
|
40
|
+
if (/^\d+$/.test(raw)) {
|
|
41
|
+
// The official client reuses the 19-digit userId verbatim.
|
|
42
|
+
return { machineId, deviceId: raw };
|
|
43
|
+
}
|
|
44
|
+
const digest = createHash("sha256").update(`trae-device:${raw || "anonymous"}`).digest("hex");
|
|
45
|
+
const numeric = BigInt(`0x${digest.slice(0, 16)}`);
|
|
46
|
+
return { machineId, deviceId: String(10n ** 18n + (numeric % (9n * 10n ** 18n))) };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* OS string reported as `X-Os-Version`.
|
|
51
|
+
*
|
|
52
|
+
* The donor reads this from the host registry, which leaks the operator's real
|
|
53
|
+
* Windows build to upstream. This gateway is not the operator's desktop, so a
|
|
54
|
+
* fixed value of the same shape is both more private and more stable.
|
|
55
|
+
*/
|
|
56
|
+
export const TRAE_OS_VERSION = "Windows 11 Pro";
|
|
57
|
+
|
|
58
|
+
/** Reported hardware brand, same reasoning as the OS string. */
|
|
59
|
+
export const TRAE_DEVICE_BRAND = "Default string";
|
|
60
|
+
|
|
61
|
+
/** Per-request correlation id. Random, not derived — decoupled from the device. */
|
|
62
|
+
export function traeRequestId(): string {
|
|
63
|
+
return randomUUID();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Inputs for {@link buildTraeHeaders}. */
|
|
67
|
+
export interface TraeHeaderInput {
|
|
68
|
+
readonly realm: TraeRealm;
|
|
69
|
+
/** Access token, sent as both `x-ide-token` and the Authorization bearer. */
|
|
70
|
+
readonly token: string;
|
|
71
|
+
/** Account id the device fingerprint is derived from. */
|
|
72
|
+
readonly uid: string;
|
|
73
|
+
/**
|
|
74
|
+
* Current client version, e.g. `3.6.2`. Sent by intl as `x-ide-version` and
|
|
75
|
+
* `x-app-version`; a stale value is refused with 4015.
|
|
76
|
+
*/
|
|
77
|
+
readonly clientVersion?: string;
|
|
78
|
+
/** Version code sent as `x-ide-version-code`. */
|
|
79
|
+
readonly versionCode?: string;
|
|
80
|
+
/** True for the streaming chat call, which overrides `Accept`. */
|
|
81
|
+
readonly stream?: boolean;
|
|
82
|
+
/** Extra/replacement headers, applied case-insensitively. */
|
|
83
|
+
readonly extra?: Readonly<Record<string, string | null>>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Builds the header set for one Trae request.
|
|
88
|
+
*
|
|
89
|
+
* `null` in `extra` deletes the header, matching the donor's override rule.
|
|
90
|
+
*/
|
|
91
|
+
export function buildTraeHeaders(input: TraeHeaderInput): Record<string, string> {
|
|
92
|
+
const config = TRAE_REALMS[input.realm];
|
|
93
|
+
const device = traeDeviceIdentity(input.uid);
|
|
94
|
+
const headers: Record<string, string> = {
|
|
95
|
+
"X-App-Id": TRAE_APP_ID,
|
|
96
|
+
"x-plugin-channel": TRAE_PLUGIN_CHANNEL,
|
|
97
|
+
"x-ide-version-code": input.versionCode ?? config.versionCode,
|
|
98
|
+
"x-ide-token": input.token,
|
|
99
|
+
Authorization: `Cloud-IDE-JWT ${input.token}`,
|
|
100
|
+
"Content-Type": "application/json",
|
|
101
|
+
Accept: "application/json",
|
|
102
|
+
"User-Agent": config.userAgent,
|
|
103
|
+
"X-Device-Cpu": "Intel",
|
|
104
|
+
"X-Device-Id": device.deviceId,
|
|
105
|
+
"X-Machine-Id": device.machineId,
|
|
106
|
+
"X-Device-Brand": encodeURIComponent(TRAE_DEVICE_BRAND),
|
|
107
|
+
"X-Device-Type": "windows",
|
|
108
|
+
"X-Os-Version": encodeURIComponent(TRAE_OS_VERSION),
|
|
109
|
+
"X-Request-Id": traeRequestId(),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
if (input.realm === "intl") {
|
|
113
|
+
// intl raw_chat requires Bearer (not Cloud-IDE-JWT) *and* the current
|
|
114
|
+
// client version on four headers; a stale version is answered 4015.
|
|
115
|
+
const version = input.clientVersion ?? intlVersionFallback(config.userAgent);
|
|
116
|
+
headers["Authorization"] = `Bearer ${input.token}`;
|
|
117
|
+
headers["x-ide-token"] = input.token;
|
|
118
|
+
headers["x-ide-version"] = version;
|
|
119
|
+
headers["x-app-version"] = version;
|
|
120
|
+
headers["User-Agent"] = "TraeClient/TTNet";
|
|
121
|
+
headers["store-country-code"] = "us";
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (input.stream === true) {
|
|
125
|
+
headers["Accept"] = "text/event-stream";
|
|
126
|
+
headers["Cache-Control"] = "no-cache";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (const [key, value] of Object.entries(input.extra ?? {})) {
|
|
130
|
+
const lower = key.toLowerCase();
|
|
131
|
+
for (const existing of Object.keys(headers)) {
|
|
132
|
+
if (existing.toLowerCase() === lower) delete headers[existing];
|
|
133
|
+
}
|
|
134
|
+
if (value !== null) headers[key] = value;
|
|
135
|
+
}
|
|
136
|
+
return headers;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Last-resort intl version: the one baked into the realm's own User-Agent.
|
|
141
|
+
*
|
|
142
|
+
* Only reached when the version resolver has not answered yet. It is the
|
|
143
|
+
* donor's last observed version rather than an invented number, so a cold
|
|
144
|
+
* process sends something upstream has accepted before.
|
|
145
|
+
*/
|
|
146
|
+
function intlVersionFallback(userAgent: string): string {
|
|
147
|
+
const match = userAgent.match(/(\d+\.\d+\.\d+)/);
|
|
148
|
+
return match?.[1] ?? "3.6.2";
|
|
149
|
+
}
|