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
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The header family only the CLI identity sends.
|
|
3
|
+
*
|
|
4
|
+
* Everything here comes from the two reference gateways, which agree: the
|
|
5
|
+
* desktop product sends conversation/tracing headers and browser transport,
|
|
6
|
+
* while the CLI sends the agent envelope plus the OpenAI Node SDK fingerprint
|
|
7
|
+
* and no browser headers at all. A request carrying both halves is a hybrid no
|
|
8
|
+
* real client produces, which is what risk control keys on.
|
|
9
|
+
*
|
|
10
|
+
* Two references, two fingerprints: the hub derives OS/arch and a Node version
|
|
11
|
+
* from its own host, and codebuddy2api pins a fixed Linux/x64/v24.21.0 set.
|
|
12
|
+
* Neither can be right for every deployment, so the values here follow the
|
|
13
|
+
* host this gateway actually runs on — they are a fingerprint of the process,
|
|
14
|
+
* not a claim about a remote machine.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** OpenAI Node SDK 6.25.0 `x-stainless-*` fingerprint; both references agree. */
|
|
18
|
+
const STAINLESS_PACKAGE_VERSION = "6.25.0";
|
|
19
|
+
|
|
20
|
+
function hostOs(): string {
|
|
21
|
+
return process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "MacOS" : "Linux";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function hostArch(): string {
|
|
25
|
+
return process.arch === "arm64" || process.arch === "ia32" ? process.arch : "x64";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The SDK fingerprint headers.
|
|
30
|
+
*
|
|
31
|
+
* `x-stainless-timeout` is in the hub only and `x-stainless-retry-count` is in
|
|
32
|
+
* both; the SDK sends both, so both go out.
|
|
33
|
+
*/
|
|
34
|
+
export function buddyStainlessHeaders(): Record<string, string> {
|
|
35
|
+
return {
|
|
36
|
+
"x-stainless-lang": "js",
|
|
37
|
+
"x-stainless-package-version": STAINLESS_PACKAGE_VERSION,
|
|
38
|
+
"x-stainless-os": hostOs(),
|
|
39
|
+
"x-stainless-arch": hostArch(),
|
|
40
|
+
"x-stainless-runtime": "node",
|
|
41
|
+
"x-stainless-runtime-version": process.version,
|
|
42
|
+
"x-stainless-retry-count": "0",
|
|
43
|
+
"x-stainless-timeout": "1200",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The trace family the CLI carries as a child span.
|
|
49
|
+
*
|
|
50
|
+
* The desktop product omits the parent (`with_parent=False` in the reference);
|
|
51
|
+
* the CLI conversation request is a child span, so it also sends `b3`'s fourth
|
|
52
|
+
* field and `X-B3-ParentSpanId`. `buddyConversationHeaders` already produces
|
|
53
|
+
* `traceparent`, `b3`, and the `X-B3-*` set, so only the parent is added here.
|
|
54
|
+
*/
|
|
55
|
+
export function buddyCliTraceHeaders(
|
|
56
|
+
conversation: Readonly<Record<string, string>>,
|
|
57
|
+
): Record<string, string> {
|
|
58
|
+
const traceId = conversation["x-trace-id"] ?? conversation["x-b3-traceid"];
|
|
59
|
+
const spanId = conversation["x-b3-spanid"];
|
|
60
|
+
if (traceId === undefined) return {};
|
|
61
|
+
const b3 = `${traceId}-${spanId ?? traceId.slice(0, 16)}-1-${traceId.slice(0, 16)}`;
|
|
62
|
+
return { ...(spanId === undefined ? {} : { "X-B3-ParentSpanId": spanId }), b3 };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The full CLI identity envelope, minus what each caller already supplies.
|
|
67
|
+
*
|
|
68
|
+
* The caller keeps ownership of `User-Agent`, `X-IDE-*`, `X-Domain`, and the
|
|
69
|
+
* conversation family, because those vary by provider and realm: only the
|
|
70
|
+
* headers that are the same for every CLI dispatch are built here.
|
|
71
|
+
*/
|
|
72
|
+
export function buddyCliHeaders(args: { readonly userId: string }): Record<string, string> {
|
|
73
|
+
return {
|
|
74
|
+
"X-Agent-Intent": "craft",
|
|
75
|
+
"X-Agent-Type": "main",
|
|
76
|
+
// The reference enum is local-agent / cloud-agent / agent-agent, and its
|
|
77
|
+
// parser returns "other" for anything unknown or absent. A gateway is none
|
|
78
|
+
// of the three, so "other" is the honest value rather than a guess.
|
|
79
|
+
"X-Agent-Runtime": "other",
|
|
80
|
+
"X-User-Id": args.userId,
|
|
81
|
+
// Personal accounts are not an enterprise and the reference sends the flag
|
|
82
|
+
// either way (`true` only for an enterprise id), so the non-enterprise
|
|
83
|
+
// default goes out here. Step 3 replaces this with the account's real
|
|
84
|
+
// enterprise id once discovery carries one.
|
|
85
|
+
"X-Private-Data": "false",
|
|
86
|
+
...buddyStainlessHeaders(),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -81,14 +81,31 @@ export function buddyConversationHeaders(
|
|
|
81
81
|
"x-request-id": messageId,
|
|
82
82
|
"x-root-request-id": conversationRequestId,
|
|
83
83
|
"x-trace-id": traceId,
|
|
84
|
+
// W3C trace context alongside the B3 set below: the upstream reads both,
|
|
85
|
+
// and every reference request carries `traceparent`, so sending only the
|
|
86
|
+
// B3 half leaves a header the channel check expects absent.
|
|
87
|
+
traceparent: `00-${b3TraceId}-${messageId.slice(0, 16)}-01`,
|
|
84
88
|
"x-b3-traceid": b3TraceId,
|
|
85
89
|
"x-b3-spanid": messageId.slice(0, 16),
|
|
86
90
|
"x-b3-sampled": "1",
|
|
87
91
|
};
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
// Always sent, invented when the caller gave none.
|
|
93
|
+
//
|
|
94
|
+
// This used to be omitted unless the client supplied one. That was wrong:
|
|
95
|
+
// `x-conversation-id` is mandatory, and a chat request without it is refused
|
|
96
|
+
// with `400 · 11-128 "request illegal"` — an error that names neither the
|
|
97
|
+
// header nor the channel, and which reads like a block rather than a missing
|
|
98
|
+
// field. Isolated against the live API by removing one header at a time:
|
|
99
|
+
// only `x-conversation-id`, `x-conversation-request-id` and
|
|
100
|
+
// `x-conversation-message-id` are required; the B3/W3C trace set, the
|
|
101
|
+
// stainless set, the agent block and the IDE block are all optional.
|
|
102
|
+
//
|
|
103
|
+
// Inventing one when the caller has none is still the right default: the id
|
|
104
|
+
// is per-dispatch here, so a caller with no session is not claiming a session
|
|
105
|
+
// it never had — and withholding the header only guarantees a refusal.
|
|
106
|
+
headers["x-conversation-id"] =
|
|
107
|
+
ids.conversationId !== undefined && ids.conversationId.trim().length > 0
|
|
108
|
+
? ids.conversationId.trim()
|
|
109
|
+
: newMessageId();
|
|
93
110
|
return headers;
|
|
94
111
|
}
|
|
@@ -37,6 +37,18 @@ export const BUDDY_CN_MODELS_PATH = "/console/enterprises/personal/models" as co
|
|
|
37
37
|
*/
|
|
38
38
|
export const BUDDY_INTL_MODELS_PATH = "/v2/enterprises/personal/models" as const;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Remote config path, answered on every realm's chat host.
|
|
42
|
+
*
|
|
43
|
+
* Both reference gateways treat this as the primary model catalog and the
|
|
44
|
+
* personal-models paths above as the narrower fallback: `/v3/config` carries
|
|
45
|
+
* the same `{ code, msg, data: { models, agents } }` envelope plus the
|
|
46
|
+
* per-product rosters the personal path does not always publish. It is tried
|
|
47
|
+
* first, and a failure falls through to the path the caller already passes, so
|
|
48
|
+
* a host that does not answer it behaves exactly as it does today.
|
|
49
|
+
*/
|
|
50
|
+
export const BUDDY_CONFIG_PATH = "/v3/config" as const;
|
|
51
|
+
|
|
40
52
|
/** Envelope code the console directory answers on success. */
|
|
41
53
|
const BUDDY_OK_CODE = 0;
|
|
42
54
|
|
|
@@ -92,13 +104,33 @@ export async function fetchBuddyDirectoryModels(args: {
|
|
|
92
104
|
readonly fetcher?: typeof fetch | undefined;
|
|
93
105
|
}): Promise<readonly ModelDefinition[] | null> {
|
|
94
106
|
const fetcher = args.fetcher ?? globalThis.fetch;
|
|
107
|
+
const primary = await fetchBuddyDirectoryOnce(args, fetcher, BUDDY_CONFIG_PATH);
|
|
108
|
+
if (primary !== null) return primary;
|
|
109
|
+
// Both references rank `/v3/config` above the personal-models path, but this
|
|
110
|
+
// repo has only ever called the latter, so the fallback keeps today's
|
|
111
|
+
// behaviour intact for a host that answers one and not the other.
|
|
112
|
+
return await fetchBuddyDirectoryOnce(args, fetcher, args.modelsPath);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Reads one directory path; `null` on any transport, status, or shape miss. */
|
|
116
|
+
async function fetchBuddyDirectoryOnce(
|
|
117
|
+
args: {
|
|
118
|
+
readonly siteUrl: string;
|
|
119
|
+
readonly providerId: string;
|
|
120
|
+
readonly credential: string;
|
|
121
|
+
readonly endpoint: string | undefined;
|
|
122
|
+
readonly signal?: AbortSignal | undefined;
|
|
123
|
+
},
|
|
124
|
+
fetcher: typeof fetch,
|
|
125
|
+
path: string,
|
|
126
|
+
): Promise<readonly ModelDefinition[] | null> {
|
|
95
127
|
// The directory scores by account: an access token's `sub` is the uid. An
|
|
96
128
|
// opaque API key carries no identity, and the endpoint still answers for it,
|
|
97
129
|
// so the header is declared absent rather than guessed.
|
|
98
130
|
const uid = buddyAccountUid(args.credential);
|
|
99
131
|
let response: Response;
|
|
100
132
|
try {
|
|
101
|
-
response = await fetcher(`${siteOrigin(args.siteUrl)}${
|
|
133
|
+
response = await fetcher(`${siteOrigin(args.siteUrl)}${path}`, {
|
|
102
134
|
method: "GET",
|
|
103
135
|
headers: {
|
|
104
136
|
accept: "application/json",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ProviderDispatchContext } from "../../provider-contracts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Which upstream client a buddy provider presents itself as.
|
|
5
|
+
*
|
|
6
|
+
* `desktop` is what every buddy provider sends today and stays the default for
|
|
7
|
+
* all four. `cli` is the identity the reference gateways use for CLI traffic: a
|
|
8
|
+
* different header set, a different User-Agent formula, and a different CN
|
|
9
|
+
* upstream.
|
|
10
|
+
*
|
|
11
|
+
* Nothing flips to `cli` implicitly. Being wrong here is what gets an account
|
|
12
|
+
* blocked upstream, so a provider changes identity only when an operator or an
|
|
13
|
+
* account says so.
|
|
14
|
+
*/
|
|
15
|
+
export type BuddyIdentity = "desktop" | "cli";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the identity one buddy dispatch presents.
|
|
19
|
+
*
|
|
20
|
+
* Precedence is account then provider: an account authorized as a CLI keeps
|
|
21
|
+
* that identity even when the provider default changes, because the upstream
|
|
22
|
+
* recorded it at login. The provider-level flag is
|
|
23
|
+
* `compatibilityProfile.cli_identity`, already declared, validated, and
|
|
24
|
+
* defaulted — it just never reached these adapters before.
|
|
25
|
+
*/
|
|
26
|
+
export function resolveBuddyIdentity(
|
|
27
|
+
context: ProviderDispatchContext | undefined,
|
|
28
|
+
profileIdentity?: boolean | undefined,
|
|
29
|
+
): BuddyIdentity {
|
|
30
|
+
const accountRaw = context?.credential.auth_state?.["cliIdentity"];
|
|
31
|
+
if (accountRaw === true) return "cli";
|
|
32
|
+
if (accountRaw === false) return "desktop";
|
|
33
|
+
return profileIdentity === true ? "cli" : "desktop";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The upstream's `X-User-Id` for a buddy dispatch.
|
|
38
|
+
*
|
|
39
|
+
* The reference CLI sends the literal `anonymous` when it has no uid rather
|
|
40
|
+
* than omitting the header, so an unauthenticated dispatch still looks like a
|
|
41
|
+
* client rather than like a caller that forgot a header.
|
|
42
|
+
*/
|
|
43
|
+
export function buddyUserId(context?: ProviderDispatchContext): string {
|
|
44
|
+
const accountId = context?.credential.account_id;
|
|
45
|
+
return accountId !== undefined && accountId.length > 0 ? accountId : "anonymous";
|
|
46
|
+
}
|
|
@@ -280,7 +280,43 @@ export class BuddyOAuthClient extends OAuthDeviceFlow {
|
|
|
280
280
|
reason: `${this.#variant.providerId} token response omitted accessToken`,
|
|
281
281
|
};
|
|
282
282
|
}
|
|
283
|
-
|
|
283
|
+
// The profile nickname is a second, authorized request the reference makes
|
|
284
|
+
// once the token lands — the JWT carries the email but not always a
|
|
285
|
+
// display name. Best-effort by design: a login must not fail because the
|
|
286
|
+
// profile endpoint was unreachable, so every miss falls back to the label
|
|
287
|
+
// the token itself yields.
|
|
288
|
+
const nickname = await this.fetchAccountNickname(deviceAuthId, access);
|
|
289
|
+
if (nickname === undefined) return { status: "complete", result: tokenResult(this.#variant, payload) };
|
|
290
|
+
const result = tokenResult(this.#variant, payload);
|
|
291
|
+
return {
|
|
292
|
+
status: "complete",
|
|
293
|
+
result: { ...result, accountLabel: result.accountLabel ?? nickname },
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/** Reads the account profile nickname, or `undefined` on any miss. */
|
|
298
|
+
private async fetchAccountNickname(
|
|
299
|
+
deviceAuthId: string,
|
|
300
|
+
accessToken: string,
|
|
301
|
+
): Promise<string | undefined> {
|
|
302
|
+
try {
|
|
303
|
+
// Both references call `/v2/plugin/login/account` with the token after
|
|
304
|
+
// the poll succeeds; the poll URL is the same versioned plugin root, so
|
|
305
|
+
// the profile path is derived from it rather than declared per variant.
|
|
306
|
+
const url = `${this.#variant.devicePollUrl.replace("/plugin/auth/token", "/plugin/login/account")}?state=${encodeURIComponent(deviceAuthId)}`;
|
|
307
|
+
const response = await this.fetchFn(url, {
|
|
308
|
+
method: "GET",
|
|
309
|
+
headers: {
|
|
310
|
+
...(await devicePollHeaders(this.#variant)),
|
|
311
|
+
authorization: `Bearer ${accessToken}`,
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
if (!response.ok) return undefined;
|
|
315
|
+
const profile = buddyResponseData((await response.json()) as unknown);
|
|
316
|
+
return nonEmptyTrimmedString(profile?.nickname);
|
|
317
|
+
} catch {
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
284
320
|
}
|
|
285
321
|
|
|
286
322
|
override async refresh(refreshToken: string, signal?: AbortSignal): Promise<OAuthTokenRefreshResult> {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Deliberately not a request-path store: this is written by a maintenance pass
|
|
11
11
|
* and read by the console. Nothing here can fail a dispatch.
|
|
12
12
|
*/
|
|
13
|
-
import { and, desc, eq, inArray, sql } from "drizzle-orm";
|
|
13
|
+
import { and, desc, eq, gte, inArray, sql } from "drizzle-orm";
|
|
14
14
|
import type { CartethyiaDatabase } from "../../../persistence/db-handle";
|
|
15
15
|
import { buddyUsageSnapshots } from "../../../persistence/schema";
|
|
16
16
|
import type { BuddyUsageRow } from "./buddy-usage-shared";
|
|
@@ -23,6 +23,11 @@ export interface BuddyUsageSnapshotRow extends BuddyUsageRow {
|
|
|
23
23
|
/** Days of usage retained. The upstream's own window is 30. */
|
|
24
24
|
const RETENTION_DAYS = 30;
|
|
25
25
|
|
|
26
|
+
/** Oldest day a stored bucket can hold, as the `YYYY-MM-DD` key the table uses. */
|
|
27
|
+
function retentionCutoff(now: Date = new Date()): string {
|
|
28
|
+
return new Date(now.getTime() - RETENTION_DAYS * 86_400_000).toISOString().slice(0, 10);
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
/**
|
|
27
32
|
* Upserts one account's usage buckets.
|
|
28
33
|
*
|
|
@@ -72,7 +77,31 @@ export async function saveBuddyUsageSnapshots(
|
|
|
72
77
|
}
|
|
73
78
|
|
|
74
79
|
/**
|
|
75
|
-
*
|
|
80
|
+
* Most (day, model) buckets one day can hold, used only to bound the read.
|
|
81
|
+
*
|
|
82
|
+
* The renderer keeps {@link DEFAULT_LIMIT_PER_ACCOUNT} entries per account plus
|
|
83
|
+
* every bucket of the newest day, so this is a ceiling on a pathological table
|
|
84
|
+
* rather than a number the page depends on. Set well above any real model count
|
|
85
|
+
* so the cap can only ever trigger on a table that grew without pruning.
|
|
86
|
+
*/
|
|
87
|
+
const MODELS_PER_DAY_CEILING = 64;
|
|
88
|
+
|
|
89
|
+
/** Buckets per account the console renders. */
|
|
90
|
+
const DEFAULT_LIMIT_PER_ACCOUNT = 30;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Reads each account's stored usage, newest day first.
|
|
94
|
+
*
|
|
95
|
+
* Bounded on both axes, because it used to be bounded on neither: with no day
|
|
96
|
+
* filter and no `LIMIT`, an account fetched every bucket it had ever stored
|
|
97
|
+
* (~1500 rows for a 30-day window) to render 30 of them, on the route the
|
|
98
|
+
* dashboard polls.
|
|
99
|
+
*
|
|
100
|
+
* - The day window is semantic, not a truncation: {@link pruneBuddyUsageSnapshots}
|
|
101
|
+
* already drops everything older, so no row it excludes could have been
|
|
102
|
+
* rendered anyway.
|
|
103
|
+
* - The row ceiling is the backstop. It is sized per account, so one large
|
|
104
|
+
* account cannot starve the others in a shared `LIMIT`.
|
|
76
105
|
*
|
|
77
106
|
* `numeric` comes back from the driver as a string, so the credit is parsed
|
|
78
107
|
* rather than trusted; an unparseable row is reported as 0 instead of being
|
|
@@ -81,7 +110,7 @@ export async function saveBuddyUsageSnapshots(
|
|
|
81
110
|
export async function readBuddyUsageSnapshots(
|
|
82
111
|
db: CartethyiaDatabase,
|
|
83
112
|
accountIds: readonly string[],
|
|
84
|
-
limitPerAccount =
|
|
113
|
+
limitPerAccount = DEFAULT_LIMIT_PER_ACCOUNT,
|
|
85
114
|
): Promise<Map<string, readonly BuddyUsageSnapshotRow[]>> {
|
|
86
115
|
const result = new Map<string, BuddyUsageSnapshotRow[]>();
|
|
87
116
|
if (accountIds.length === 0) return result;
|
|
@@ -102,8 +131,14 @@ export async function readBuddyUsageSnapshots(
|
|
|
102
131
|
syncedAt: buddyUsageSnapshots.syncedAt,
|
|
103
132
|
})
|
|
104
133
|
.from(buddyUsageSnapshots)
|
|
105
|
-
.where(
|
|
106
|
-
|
|
134
|
+
.where(
|
|
135
|
+
and(
|
|
136
|
+
inArray(buddyUsageSnapshots.accountId, [...accountIds]),
|
|
137
|
+
gte(buddyUsageSnapshots.dayKey, retentionCutoff()),
|
|
138
|
+
),
|
|
139
|
+
)
|
|
140
|
+
.orderBy(desc(buddyUsageSnapshots.dayKey))
|
|
141
|
+
.limit(accountIds.length * limitPerAccount * MODELS_PER_DAY_CEILING);
|
|
107
142
|
} catch {
|
|
108
143
|
return result;
|
|
109
144
|
}
|
|
@@ -106,6 +106,10 @@ export const CODEBUDDY_CN_RAW: readonly BuddyRawEntry[] = [
|
|
|
106
106
|
["glm-5.3-flash", "GLM 5.3 Flash", true, true, 1_000_000, 131_072],
|
|
107
107
|
["glm-5v-turbo", "GLM 5v Turbo", true, true, 200_000, 131_072],
|
|
108
108
|
["minimax-m3", "MiniMax M3", true, true, 512_000, 512_000],
|
|
109
|
+
// 1M context, reasoning always on (upstream states both); vision inherited
|
|
110
|
+
// from the M3 row, which is the same family.
|
|
111
|
+
["minimax-m3.1-flash", "MiniMax M3.1 Flash", true, true, 1_000_000, 512_000],
|
|
112
|
+
["mimo-v2.6-pro", "MiMo V2.6 Pro", true, true, 1_000_000, 512_000],
|
|
109
113
|
["kimi-k2.8-preview", "Kimi K2.8 Preview", true, true, 1_048_576, 65_536],
|
|
110
114
|
["kimi-k2.7", "Kimi K2.7", true, true, 256_000, 65_536],
|
|
111
115
|
["kimi-k2.6", "Kimi K2.6", true, true, 256_000, 262_144],
|