cartethyia 2.7.9 → 2.8.1
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 +6 -5
- package/dist/dashboard/assets/{BannedPage-BxoG1MrL.js → BannedPage-Dq530awD.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Dq530awD.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-ixwgKk53.js → CliToolDetailPage-DZzaS-7S.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZzaS-7S.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BmttNV3U.js → CliToolsPage-DaZZ3cqP.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-DaZZ3cqP.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BE3qwwfC.js → CombosPage-BlC_xdkX.js} +1 -1
- package/dist/dashboard/assets/CombosPage-BlC_xdkX.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CRZdmMIX.js → ConsoleLogPage-D-rqeVtG.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-D-rqeVtG.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-Dv_FJ6Er.js → CustomizationPage-7xT5yg2E.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-7xT5yg2E.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-BOoO8rpz.js → InjectSystemPromptPanel-6Teoq9Se.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-6Teoq9Se.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-ChJuNNVN.js → LoginPage-CZuI0MAR.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CZuI0MAR.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BZAJtPg1.js → ModelPicker-C1hNTlkr.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C1hNTlkr.js.gz +0 -0
- package/dist/dashboard/assets/{OverviewPage-BE40s3u5.js → OverviewPage-0yfhSI1C.js} +1 -1
- package/dist/dashboard/assets/OverviewPage-0yfhSI1C.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js.gz +0 -0
- package/dist/dashboard/assets/{ProviderIcon-CQ6bPUf_.js → ProviderIcon-Ddhm1InL.js} +1 -1
- package/dist/dashboard/assets/ProviderIcon-Ddhm1InL.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js +9 -0
- package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js +1 -0
- package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-C5HPWqEv.js → SettingsPage-BzZAvYSX.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-BzZAvYSX.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-CFNcATJJ.js → SetupPage--s-EfEIL.js} +1 -1
- package/dist/dashboard/assets/SetupPage--s-EfEIL.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-YoD4tY5l.js → StudioPage-BjXFGSK4.js} +1 -1
- package/dist/dashboard/assets/StudioPage-BjXFGSK4.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-DxjaAhb_.js → UsagePage-CP8F8BN7.js} +1 -1
- package/dist/dashboard/assets/UsagePage-CP8F8BN7.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-BTlkq_Uk.js → api-keys-2hc12Uz2.js} +1 -1
- package/dist/dashboard/assets/api-keys-2hc12Uz2.js.gz +0 -0
- package/dist/dashboard/assets/app-DGXbNfAR.css +2 -0
- package/dist/dashboard/assets/app-DGXbNfAR.css.gz +0 -0
- package/dist/dashboard/assets/assert-BMcj1xZE.js +1 -0
- package/dist/dashboard/assets/assert-BMcj1xZE.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DdbT_7Am.js → badge-DkRUuVfz.js} +1 -1
- package/dist/dashboard/assets/badge-DkRUuVfz.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CsGN-nbm.js → banner-CDjW841Q.js} +1 -1
- package/dist/dashboard/assets/banner-CDjW841Q.js.gz +0 -0
- package/dist/dashboard/assets/{card-mgZ_TLLZ.js → card-Bto5UlL9.js} +1 -1
- package/dist/dashboard/assets/card-Bto5UlL9.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-A1-v8-03.js → cli-tools-DaH6g9hL.js} +1 -1
- package/dist/dashboard/assets/cli-tools-DaH6g9hL.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-CJ4Zty89.js → clipboard-button-BYKBCzjk.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BYKBCzjk.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-B5L2jPQ_.js → dialog-DL0Zftwv.js} +1 -1
- package/dist/dashboard/assets/dialog-DL0Zftwv.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-DkjUouAj.js → drawer-Dpx_UXaS.js} +1 -1
- package/dist/dashboard/assets/drawer-Dpx_UXaS.js.gz +0 -0
- package/dist/dashboard/assets/{entry-B-LVLV6o.js → entry-BV7-1NoM.js} +1 -1
- package/dist/dashboard/assets/entry-BV7-1NoM.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CAhdYl3B.js → entry-CGvdNU6r.js} +1 -1
- package/dist/dashboard/assets/entry-CGvdNU6r.js.gz +0 -0
- package/dist/dashboard/assets/entry-DScKYvZj.js +4 -0
- package/dist/dashboard/assets/entry-DScKYvZj.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CrsdLVsn.js → formatters-BS3DZlZj.js} +1 -1
- package/dist/dashboard/assets/formatters-BS3DZlZj.js.gz +0 -0
- package/dist/dashboard/assets/{index-BU64Lqvp.js → index-SQnvvTWX.js} +2 -2
- package/dist/dashboard/assets/index-SQnvvTWX.js.gz +0 -0
- package/dist/dashboard/assets/{inline-B2aDLyyg.js → inline-Dl-cuLK0.js} +1 -1
- package/dist/dashboard/assets/inline-Dl-cuLK0.js.gz +0 -0
- package/dist/dashboard/assets/{input-BCVkdR9d.js → input-Bfx0EzRc.js} +1 -1
- package/dist/dashboard/assets/input-Bfx0EzRc.js.gz +0 -0
- package/dist/dashboard/assets/{layout-DNcAdMK-.js → layout-BxhbQ_JS.js} +1 -1
- package/dist/dashboard/assets/layout-BxhbQ_JS.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-DgrIH0hw.js → list-row-D49Y4ptn.js} +1 -1
- package/dist/dashboard/assets/list-row-D49Y4ptn.js.gz +0 -0
- package/dist/dashboard/assets/{live-Cae01iu8.js → live-CbVTdX9V.js} +1 -1
- package/dist/dashboard/assets/live-CbVTdX9V.js.gz +0 -0
- package/dist/dashboard/assets/{network-CRib7H_2.js → network-JGvDveof.js} +1 -1
- package/dist/dashboard/assets/network-JGvDveof.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BKQE8Xpz.js → numbers-Dw6kiew-.js} +1 -1
- package/dist/dashboard/assets/numbers-Dw6kiew-.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-ecPvG_8g.js → pagination-iUoI8GeE.js} +1 -1
- package/dist/dashboard/assets/pagination-iUoI8GeE.js.gz +0 -0
- package/dist/dashboard/assets/providers/sensenova-intl.png +0 -0
- package/dist/dashboard/assets/providers/sensenova.png +0 -0
- package/dist/dashboard/assets/providers/zro.svg +3 -0
- package/dist/dashboard/assets/providers/zro.svg.gz +0 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js +1 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js.gz +0 -0
- package/dist/dashboard/assets/{routing-Ckm1UXuC.js → routing-8jZr-3WE.js} +1 -1
- package/dist/dashboard/assets/routing-8jZr-3WE.js.gz +0 -0
- package/dist/dashboard/assets/{select-ChoFWyKz.js → select-oO1FxMVb.js} +2 -2
- package/dist/dashboard/assets/select-oO1FxMVb.js.gz +0 -0
- package/dist/dashboard/assets/{settings-CKjFPlKW.js → settings-CLr3kdIx.js} +1 -1
- package/dist/dashboard/assets/settings-CLr3kdIx.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DWCwU3fh.js → stack-Y3pDteZr.js} +1 -1
- package/dist/dashboard/assets/stack-Y3pDteZr.js.gz +0 -0
- package/dist/dashboard/assets/{state-Cg3VL5J_.js → state-CArX_Iak.js} +1 -1
- package/dist/dashboard/assets/state-CArX_Iak.js.gz +0 -0
- package/dist/dashboard/assets/{switch-Db70BMix.js → switch-DwlwmDO-.js} +1 -1
- package/dist/dashboard/assets/switch-DwlwmDO-.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BqdE0LuM.js → useMutation-DJ9GYEgf.js} +1 -1
- package/dist/dashboard/assets/useMutation-DJ9GYEgf.js.gz +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +54 -53
- package/migrations/full-postgres/0046_add_accounts_quota_plan_fetched_at.sql +7 -0
- package/migrations/full-postgres/0047_add_provider_device_flow_proxy.sql +17 -0
- package/migrations/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
- package/migrations/lite-sqlite3/0047_add_provider_device_flow_proxy.sql +19 -0
- package/package.json +1 -1
- package/src/boot/app.ts +11 -14
- package/src/boot/dependencies.ts +5 -7
- package/src/boot/flush.ts +20 -0
- package/src/boot/lifecycle.ts +7 -5
- package/src/config/providers.ts +6 -5
- package/src/config/routing.ts +26 -0
- package/src/config/spec-metadata.ts +72 -0
- package/src/config/spec.ts +28 -8
- package/src/console/api-keys/contracts.ts +12 -1
- package/src/console/api-keys/routes.ts +40 -28
- package/src/console/auth/account-reset.ts +7 -9
- package/src/console/backup/contracts.ts +4 -0
- package/src/console/backup/export-endpoint.ts +7 -5
- package/src/console/backup/nine-router.ts +71 -10
- package/src/console/backup/service.ts +8 -1
- package/src/console/cli-tools/service.ts +6 -12
- package/src/console/console-router-guards.ts +23 -16
- package/src/console/console-router.ts +1 -1
- package/src/console/domain-registration.ts +7 -4
- package/src/console/inferhub/client.ts +1 -1
- package/src/console/inferhub/normalize.ts +24 -28
- package/src/console/inferhub/types.ts +3 -0
- package/src/console/ip-bans/routes.ts +7 -13
- package/src/console/observability/live.ts +2 -2
- package/src/console/observability/store.ts +0 -53
- package/src/console/providers/catalog/contracts.ts +9 -3
- package/src/console/providers/catalog/model-operations.ts +2 -3
- package/src/console/providers/catalog/provider-operations.ts +1 -1
- package/src/console/providers/catalog/routes.ts +3 -2
- package/src/console/providers/catalog/store.ts +1914 -1902
- package/src/console/providers/detail/routes.ts +1 -0
- package/src/console/providers/detail/store.ts +4 -0
- package/src/console/providers/oauth/callback-listener.ts +30 -11
- package/src/console/providers/oauth/device-egress.ts +123 -0
- package/src/console/providers/oauth/routes.ts +123 -16
- package/src/console/quota/account-quota-global.ts +14 -24
- package/src/console/quota/account-quota-shared.ts +49 -0
- package/src/console/quota/account-quota-tenant.ts +11 -23
- package/src/console/quota/account-test-egress.ts +2 -2
- package/src/console/quota/daily-growth-job.ts +1 -1
- package/src/console/quota/quota-view.ts +19 -3
- package/src/console/routing/pools/contracts.ts +1 -1
- package/src/console/routing/pools/operations.ts +32 -47
- package/src/console/routing/pools/probe-verdict.ts +2 -2
- package/src/console/routing/pools/relay-deploy.ts +1 -1
- package/src/console/routing/pools/store.ts +4 -4
- package/src/console/shared/errors.ts +33 -6
- package/src/main.ts +2 -3
- package/src/network/client.ts +67 -0
- package/src/network/egress/bidi-session.ts +322 -0
- package/src/network/egress/dial.ts +201 -0
- package/src/network/egress/factory.ts +191 -0
- package/src/network/{outbound-fetch.ts → egress/fetch.ts} +195 -29
- package/src/network/egress/tls-profile.ts +123 -0
- package/src/network/egress/ws.ts +175 -0
- package/src/network/pool/{byte-accounting.ts → accounting.ts} +3 -2
- package/src/network/{types.ts → pool/agent-config.ts} +1 -1
- package/src/network/pool/agent.ts +2 -2
- package/src/network/{pool-cooldown-store.ts → pool/cooldown-store.ts} +95 -20
- package/src/network/{pool-health-machine.ts → pool/health.ts} +205 -6
- package/src/network/pool/resolver.ts +10 -849
- package/src/network/pool/selector.ts +184 -41
- package/src/network/ssrf.ts +7 -7
- package/src/network/{retry.ts → util/retry.ts} +1 -1
- package/src/network/{rate-limit-verdict.ts → verdict.ts} +1 -1
- package/src/observability/event-log.ts +7 -361
- package/src/observability/performance-metrics.ts +9 -0
- package/src/observability/runtime-metrics.ts +14 -9
- package/src/observability/telemetry-buffer.ts +16 -26
- package/src/observability/telemetry-reconciliation.ts +9 -37
- package/src/observability/telemetry-row.ts +125 -0
- package/src/persistence/db-mode.ts +4 -1
- package/src/persistence/dialect.ts +18 -0
- package/src/persistence/migrate.ts +6 -3
- package/src/persistence/schema.ts +17 -0
- package/src/persistence/ttl-cache.ts +21 -3
- package/src/protocol/codecs.ts +59 -2
- package/src/protocol/dsml.ts +34 -86
- package/src/protocol/markup-stream-parser.ts +195 -0
- package/src/protocol/reasoning-text.ts +19 -0
- package/src/protocol/request/chat.ts +10 -10
- package/src/protocol/request/gemini.ts +8 -2
- package/src/protocol/request/messages.ts +34 -22
- package/src/protocol/response/chat.ts +12 -20
- package/src/protocol/response/messages.ts +34 -7
- package/src/protocol/response/omp-tool-call-markup.ts +43 -86
- package/src/protocol/response/responses.ts +18 -2
- package/src/protocol/stop-reason.ts +23 -1
- package/src/protocol/think-split.ts +112 -0
- package/src/protocol/translation/dialect/qwen.ts +26 -58
- package/src/protocol/translation/quirks.ts +15 -0
- package/src/protocol/upstream/send-claude-messages.ts +2 -2
- package/src/providers/adapters/compatible-adapter.ts +76 -12
- package/src/providers/authentication/oauth-client.ts +40 -6
- package/src/providers/authentication/oauth-device-flow.ts +105 -11
- package/src/providers/authentication/oauth-flow-store.ts +82 -1
- package/src/providers/authentication/oauth-refresh-service.ts +766 -758
- package/src/providers/configured-provider.ts +148 -0
- package/src/providers/default-registry.ts +137 -36
- package/src/providers/discovery/discovery-types.ts +7 -0
- package/src/providers/discovery/probe-phases.ts +20 -6
- package/src/providers/discovery/probing-service.ts +22 -2
- package/src/providers/integrations/alibabacp/alibabacp-models.ts +1 -2
- package/src/providers/integrations/{dashscope-models.ts → alibabacp/dashscope-models.ts} +2 -2
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +16 -1
- package/src/providers/integrations/buddy/account.ts +969 -0
- package/src/providers/integrations/buddy/capabilities.ts +12 -12
- package/src/providers/integrations/buddy/{buddy-catalog-shared.ts → catalog.ts} +198 -136
- package/src/providers/integrations/buddy/{buddy-chat-shared.ts → chat.ts} +176 -20
- package/src/providers/integrations/buddy/codebuddy/index.ts +429 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +41 -26
- package/src/providers/integrations/buddy/headers.ts +311 -0
- package/src/providers/integrations/buddy/lifecycle.ts +1018 -0
- package/src/providers/integrations/buddy/{buddy-media.ts → media.ts} +1 -1
- package/src/providers/integrations/claude/claude-quota.ts +14 -17
- package/src/providers/integrations/cline/cline-oauth.ts +10 -5
- package/src/providers/integrations/cline/cline.ts +5 -6
- package/src/providers/integrations/clixad/clixad-oauth.ts +98 -0
- package/src/providers/integrations/clixad/clixad-quota.ts +132 -0
- package/src/providers/integrations/clixad/provider.ts +145 -0
- package/src/providers/integrations/codex/codex-oauth.ts +8 -5
- package/src/providers/integrations/commandcode/quota.ts +22 -28
- package/src/providers/integrations/cursor/cursor-auth.ts +1 -9
- package/src/providers/integrations/cursor/cursor-exec.ts +9 -2
- package/src/providers/integrations/cursor/cursor-hardening.ts +279 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +605 -6
- package/src/providers/integrations/cursor/cursor-request.ts +26 -12
- package/src/providers/integrations/cursor/cursor-shared.ts +8 -5
- package/src/providers/integrations/cursor/cursor.ts +574 -110
- package/src/providers/integrations/cursor/protocol/messages.ts +22 -29
- package/src/providers/integrations/cursor/protocol/protobuf-schema.ts +37 -0
- package/src/providers/integrations/deepai/deepai-catalog.ts +149 -0
- package/src/providers/integrations/deepai/deepai-common.ts +145 -0
- package/src/providers/integrations/deepai/deepai-oauth.ts +129 -0
- package/src/providers/integrations/deepai/deepai-quota.ts +97 -0
- package/src/providers/integrations/deepai/provider.ts +42 -0
- package/src/providers/integrations/devin/devin-auth.ts +7 -0
- package/src/providers/integrations/devin/protocol/devin-proto.ts +1 -27
- package/src/providers/integrations/factory/factory-oauth.ts +33 -51
- package/src/providers/integrations/freebuff/assets/official-system-manager.txt +88 -0
- package/src/providers/integrations/freebuff/assets/official-system-worker.txt +57 -0
- package/src/providers/integrations/freebuff/assets/official-tools.json +1070 -0
- package/src/providers/integrations/freebuff/freebuff-catalog.ts +120 -0
- package/src/providers/integrations/freebuff/freebuff-constants.ts +1233 -0
- package/src/providers/integrations/freebuff/freebuff-discovery.ts +108 -0
- package/src/providers/integrations/freebuff/freebuff-oauth.ts +240 -0
- package/src/providers/integrations/freebuff/freebuff-quota.ts +260 -0
- package/src/providers/integrations/freebuff/freebuff-virtual.ts +89 -0
- package/src/providers/integrations/freebuff/freebuff.ts +682 -0
- package/src/providers/integrations/freepi/freepi-catalog.ts +5 -0
- package/src/providers/integrations/freepi/freepi-discovery.ts +2 -2
- package/src/providers/integrations/freepi/freepi-headers.ts +2 -2
- package/src/providers/integrations/freepi/freepi-protocol.ts +11 -2
- package/src/providers/integrations/freepi/freepi-realm.ts +0 -3
- package/src/providers/integrations/freepi/freepi-session.ts +158 -0
- package/src/providers/integrations/freepi/freepi.ts +80 -54
- package/src/providers/integrations/github/github-discovery.ts +30 -13
- package/src/providers/integrations/github/github-oauth.ts +217 -44
- package/src/providers/integrations/github/github-quota.ts +22 -5
- package/src/providers/integrations/github/github.ts +40 -32
- package/src/providers/integrations/grok/grok-oauth.ts +52 -49
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +10 -17
- package/src/providers/integrations/grok/grok-turn-index.ts +11 -16
- package/src/providers/integrations/hermes/hermes-oauth.ts +3 -3
- package/src/providers/integrations/{hermes.ts → hermes/hermes.ts} +42 -13
- package/src/providers/integrations/hermes/index.ts +2 -0
- package/src/providers/integrations/kilo/kilo-oauth.ts +4 -4
- package/src/providers/integrations/kilo/kilo.ts +1 -1
- package/src/providers/integrations/kimi/kimi-oauth.ts +3 -3
- package/src/providers/integrations/kiro/kiro-catalog.ts +17 -1
- package/src/providers/integrations/kiro/kiro-discovery.ts +10 -12
- package/src/providers/integrations/kiro/kiro-oauth.ts +2 -2
- package/src/providers/integrations/kiro/kiro-quota.ts +8 -4
- package/src/providers/integrations/kiro/kiro.ts +15 -19
- package/src/providers/integrations/muse/muse-oauth.ts +5 -5
- package/src/providers/integrations/ollamacloud/index.ts +2 -0
- package/src/providers/integrations/{ollamacloud-models.ts → ollamacloud/models.ts} +2 -2
- package/src/providers/integrations/{ollamacloud-quota.ts → ollamacloud/quota.ts} +3 -3
- package/src/providers/integrations/opencode/fingerprint.ts +1 -1
- package/src/providers/integrations/opencode/opencode-go-quota.ts +2 -8
- package/src/providers/integrations/openrouter/provider.ts +1 -1
- package/src/providers/integrations/perch/perch-credential.ts +25 -0
- package/src/providers/integrations/perch/perch-protocol.ts +0 -6
- package/src/providers/integrations/perch/perch-quota.ts +2 -16
- package/src/providers/integrations/perch/perch.ts +6 -16
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +19 -60
- package/src/providers/integrations/qoder/qoder-adapter.ts +20 -125
- package/src/providers/integrations/qoder/qoder-auth.ts +109 -30
- package/src/providers/integrations/qoder/qoder-catalog.ts +21 -6
- package/src/providers/integrations/qoder/qoder-chat.ts +32 -29
- package/src/providers/integrations/qoder/qoder-checkin.ts +5 -5
- package/src/providers/integrations/qoder/qoder-cosy.ts +37 -9
- package/src/providers/integrations/qoder/qoder-oauth.ts +9 -2
- package/src/providers/integrations/qoder/qoder-realm.ts +13 -36
- package/src/providers/integrations/qoder/qoder-sse.ts +447 -68
- package/src/providers/integrations/qoder/qoder-types.ts +9 -0
- package/src/providers/integrations/qoder/qoder.ts +3 -26
- package/src/providers/integrations/sensenova/provider.ts +144 -0
- package/src/providers/integrations/trae/trae-protocol.ts +9 -5
- package/src/providers/integrations/trae/trae-quota.ts +21 -29
- package/src/providers/integrations/trae/trae-realm.ts +38 -0
- package/src/providers/integrations/trae/trae.ts +7 -24
- package/src/providers/integrations/vercel/provider.ts +117 -0
- package/src/providers/integrations/vercel/vercel-quota.ts +96 -0
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode-start-plan/gifts.ts +1 -1
- package/src/providers/integrations/zcode-start-plan/oauth.ts +3 -3
- package/src/providers/integrations/zcode-start-plan/provider.ts +226 -23
- package/src/providers/integrations/zcode-start-plan/quota.ts +19 -2
- package/src/providers/integrations/zro/zro.ts +205 -0
- package/src/providers/operations/account-error-classification.ts +199 -307
- package/src/providers/operations/account-health-service.ts +82 -1
- package/src/providers/operations/account-refresh-status.ts +36 -37
- package/src/providers/operations/account-tier.ts +15 -16
- package/src/providers/operations/client-version-resolver.ts +1 -1
- package/src/providers/operations/client-versions.ts +100 -81
- package/src/providers/operations/cooldown-rules.ts +11 -16
- package/src/providers/operations/oauth-refresh-lead.ts +46 -22
- package/src/providers/operations/{model-catalog-cache.ts → provider-caches.ts} +68 -16
- package/src/providers/operations/provider-catalog-service.ts +1 -1
- package/src/providers/operations/provider-credential-service.ts +118 -51
- package/src/providers/operations/provider-rules/github.ts +48 -0
- package/src/providers/operations/provider-rules/grok.ts +33 -0
- package/src/providers/operations/provider-rules/inception.ts +49 -0
- package/src/providers/operations/provider-rules/index.ts +32 -0
- package/src/providers/operations/provider-rules/perch.ts +37 -0
- package/src/providers/operations/provider-rules/qoder.ts +70 -0
- package/src/providers/operations/provider-rules/trae.ts +81 -0
- package/src/providers/operations/session-resolution.ts +17 -1
- package/src/providers/provider-contracts.ts +6 -4
- package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
- package/src/providers/provider-metadata.ts +70 -10
- package/src/providers/provider-probe.ts +15 -1
- package/src/providers/provider-registry.ts +42 -33
- package/src/providers/quota/quota-contracts.ts +2 -0
- package/src/providers/quota/quota-limit-windows.ts +16 -5
- package/src/providers/quota/quota-support.ts +1 -1
- package/src/providers/quota/quota-window-parser.ts +90 -18
- package/src/providers/quota/refresh.ts +100 -21
- package/src/security/api-key-auth-cache.ts +1 -1
- package/src/security/api-key-auth.ts +6 -2
- package/src/security/ip-boundary.ts +1 -1
- package/src/transport/dispatch/attempt-finalize.ts +15 -14
- package/src/transport/dispatch/attempt-loop.ts +73 -19
- package/src/transport/dispatch/generation.ts +2 -8
- package/src/transport/dispatch/handler-deps.ts +1 -1
- package/src/transport/dispatch/leases.ts +1 -1
- package/src/transport/dispatch/native-shared.ts +25 -0
- package/src/transport/dispatch/proxy-request.ts +8 -46
- package/src/transport/dispatch/responses-compact.ts +2 -8
- package/src/transport/dispatch/retry-policy.ts +1 -1
- package/src/transport/dispatch/streaming/finalize.ts +10 -7
- package/src/transport/dispatch/streaming/stream.ts +9 -37
- package/src/transport/dispatch/systemone.ts +2 -8
- package/src/transport/dispatch/token-count.ts +2 -6
- package/src/transport/dispatch/upstream.ts +63 -0
- package/src/transport/drain-endpoint.ts +31 -4
- package/src/transport/failure-policy.ts +16 -30
- package/src/transport/guards/body-policy.ts +7 -1
- package/src/transport/guards/error-lifecycle.ts +13 -1
- package/src/transport/guards/request-context.ts +22 -14
- package/src/transport/request/preparer.ts +81 -71
- package/src/transport/routing/bounded-lru.ts +14 -0
- package/src/transport/routing/drain-reserve.ts +129 -0
- package/src/transport/routing/plan-gate.ts +7 -1
- package/src/transport/routing/round-robin.ts +60 -0
- package/src/transport/routing/route-catalog.ts +123 -111
- package/src/transport/routing/route-model.ts +51 -9
- package/src/transport/routing/router.ts +393 -32
- package/src/transport/shutdown-notice.ts +1 -1
- package/src/transport/surface/adapters.ts +11 -2
- package/src/transport/surface/chat/adapter.ts +2 -2
- package/src/transport/surface/chat/encode.ts +47 -4
- package/src/transport/surface/chat/parse.ts +2 -12
- package/src/transport/surface/completion.ts +44 -33
- package/src/transport/surface/content-parts.ts +21 -0
- package/src/transport/surface/messages/adapter.ts +7 -1
- package/src/transport/surface/messages/encode.ts +11 -3
- package/src/transport/surface/messages/parse.ts +2 -1
- package/src/transport/surface/messages/stream.ts +33 -17
- package/src/transport/surface/responses/encode.ts +22 -5
- package/src/transport/surface/responses/parse.ts +3 -11
- package/src/workers/buddy-growth-tasks.ts +8 -8
- package/src/workers/daily-checkin.ts +4 -4
- package/src/workers/quota-refresh-sweep.ts +1 -1
- package/src/workers/zcode-gift-claim.ts +1 -1
- package/dist/dashboard/assets/BannedPage-BxoG1MrL.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-ixwgKk53.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-BmttNV3U.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BE3qwwfC.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-BOoO8rpz.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-ChJuNNVN.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BZAJtPg1.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BE40s3u5.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js +0 -8
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js +0 -1
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-CFNcATJJ.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-YoD4tY5l.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DxjaAhb_.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BTlkq_Uk.js.gz +0 -0
- package/dist/dashboard/assets/app-BX2nnKqs.css +0 -2
- package/dist/dashboard/assets/app-BX2nnKqs.css.gz +0 -0
- package/dist/dashboard/assets/assert-CndthXFQ.js +0 -1
- package/dist/dashboard/assets/assert-CndthXFQ.js.gz +0 -0
- package/dist/dashboard/assets/badge-DdbT_7Am.js.gz +0 -0
- package/dist/dashboard/assets/banner-CsGN-nbm.js.gz +0 -0
- package/dist/dashboard/assets/card-mgZ_TLLZ.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-A1-v8-03.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-CJ4Zty89.js.gz +0 -0
- package/dist/dashboard/assets/dialog-B5L2jPQ_.js.gz +0 -0
- package/dist/dashboard/assets/drawer-DkjUouAj.js.gz +0 -0
- package/dist/dashboard/assets/entry-B-LVLV6o.js.gz +0 -0
- package/dist/dashboard/assets/entry-CAhdYl3B.js.gz +0 -0
- package/dist/dashboard/assets/entry-D2xD0Tmd.js +0 -4
- package/dist/dashboard/assets/entry-D2xD0Tmd.js.gz +0 -0
- package/dist/dashboard/assets/formatters-CrsdLVsn.js.gz +0 -0
- package/dist/dashboard/assets/index-BU64Lqvp.js.gz +0 -0
- package/dist/dashboard/assets/inline-B2aDLyyg.js.gz +0 -0
- package/dist/dashboard/assets/input-BCVkdR9d.js.gz +0 -0
- package/dist/dashboard/assets/layout-DNcAdMK-.js.gz +0 -0
- package/dist/dashboard/assets/list-row-DgrIH0hw.js.gz +0 -0
- package/dist/dashboard/assets/live-Cae01iu8.js.gz +0 -0
- package/dist/dashboard/assets/network-CRib7H_2.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BKQE8Xpz.js.gz +0 -0
- package/dist/dashboard/assets/pagination-ecPvG_8g.js.gz +0 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js +0 -1
- package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
- package/dist/dashboard/assets/routing-Ckm1UXuC.js.gz +0 -0
- package/dist/dashboard/assets/select-ChoFWyKz.js.gz +0 -0
- package/dist/dashboard/assets/settings-CKjFPlKW.js.gz +0 -0
- package/dist/dashboard/assets/stack-DWCwU3fh.js.gz +0 -0
- package/dist/dashboard/assets/state-Cg3VL5J_.js.gz +0 -0
- package/dist/dashboard/assets/switch-Db70BMix.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BqdE0LuM.js.gz +0 -0
- package/src/network/pool-health.ts +0 -210
- package/src/providers/bundled-discovery-providers.ts +0 -98
- package/src/providers/configured-openai-providers.ts +0 -120
- package/src/providers/integrations/buddy/buddy-checkin.ts +0 -521
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +0 -76
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -130
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +0 -234
- package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -496
- package/src/providers/integrations/buddy/buddy-identity.ts +0 -300
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +0 -341
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +0 -417
- package/src/providers/integrations/buddy/buddy-server-tools.ts +0 -240
- package/src/providers/integrations/buddy/buddy-usage-shared.ts +0 -221
- package/src/providers/integrations/buddy/buddy-usage-store.ts +0 -181
- package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +0 -37
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +0 -185
- package/src/providers/integrations/buddy/codebuddy/oauth.ts +0 -47
- package/src/providers/integrations/buddy/codebuddy/provider.ts +0 -175
- package/src/providers/integrations/buddy/codebuddy/quota.ts +0 -154
- package/src/providers/integrations/qoder/chat-proto.ts +0 -328
- package/src/providers/integrations/qoder/qoder-grpc.ts +0 -871
- package/src/providers/integrations/qoder/qoder-ide.ts +0 -588
- package/src/providers/operations/model-discovery-cache.ts +0 -34
- package/src/providers/operations/probe-fetch.ts +0 -15
- package/src/providers/operations/provider-version-cache.ts +0 -30
- package/src/providers/provider-capabilities.ts +0 -33
- package/src/providers/provider-credential-envelope.ts +0 -43
- /package/dist/dashboard/assets/{app-B7kIWFm5.js → app-C0gTXEoN.js} +0 -0
- /package/dist/dashboard/assets/{app-B7kIWFm5.js.gz → app-C0gTXEoN.js.gz} +0 -0
- /package/src/network/{http2-bidi.ts → bidi.ts} +0 -0
- /package/src/network/pool/{pool-scripts.ts → scripts.ts} +0 -0
- /package/src/network/pool/{pool-state.ts → state.ts} +0 -0
- /package/src/network/{backoff.ts → util/backoff.ts} +0 -0
- /package/src/network/{deduplication.ts → util/dedupe.ts} +0 -0
- /package/src/network/{ip-utils.ts → util/ip.ts} +0 -0
|
@@ -196,6 +196,7 @@ export async function recordAccountFailure(
|
|
|
196
196
|
// 1m limit must keep its short cooldown, not park the account for 24h).
|
|
197
197
|
const autoDisableTarget =
|
|
198
198
|
AUTO_DISABLE_TARGET_CATEGORIES.has(effective.category) &&
|
|
199
|
+
effective.modelScoped !== true &&
|
|
199
200
|
effective.status === "cooldown" &&
|
|
200
201
|
effective.mutatesAccount &&
|
|
201
202
|
options?.origin === "upstream";
|
|
@@ -230,7 +231,10 @@ export async function recordAccountFailure(
|
|
|
230
231
|
// D02: when the auto-disable intercept fired, the target category must not
|
|
231
232
|
// sink into a model-scoped cooldown — the outcome is an account-wide
|
|
232
233
|
// disable.
|
|
233
|
-
const shouldModelCooldown =
|
|
234
|
+
const shouldModelCooldown =
|
|
235
|
+
!autoDisableActive &&
|
|
236
|
+
modelId !== undefined &&
|
|
237
|
+
(isThrottle || effective.modelScoped === true);
|
|
234
238
|
// The account-wide streak, escalated for a provider-stated window. Read once
|
|
235
239
|
// so the model-scoped and account-wide paths below cannot disagree about it:
|
|
236
240
|
// this is the count *before* this failure, which the UPDATE below increments.
|
|
@@ -694,6 +698,83 @@ async function writeHealthEvent(
|
|
|
694
698
|
await client.insert(healthEvents).values({ id: randomUUID(), ...row });
|
|
695
699
|
}
|
|
696
700
|
|
|
701
|
+
/**
|
|
702
|
+
* The one internal seam that applies a health verdict to an account row.
|
|
703
|
+
*
|
|
704
|
+
* Every producer that persists account-state semantics — dispatch failure
|
|
705
|
+
* classification, OAuth refresh definitive failure, quota refresh parking —
|
|
706
|
+
* converges here instead of writing `status`/`cooldownUntil`/error fields
|
|
707
|
+
* independently. Producers may still classify differently; they may not
|
|
708
|
+
* persist account-state semantics separately.
|
|
709
|
+
*
|
|
710
|
+
* This writes the account-wide health state plus a health audit row, inside the
|
|
711
|
+
* caller's transaction (`client`). It returns `true` when the account row was
|
|
712
|
+
* actually updated (i.e. the account exists and is not operator-disabled with
|
|
713
|
+
* `preserveOperatorDisable`), so the caller knows whether routing must be
|
|
714
|
+
* invalidated (routesVisible) or the lease released.
|
|
715
|
+
*/
|
|
716
|
+
export async function applyAccountVerdict(
|
|
717
|
+
client: CartethyiaDatabase,
|
|
718
|
+
verdict: {
|
|
719
|
+
readonly accountId: string;
|
|
720
|
+
readonly status: "cooldown" | "disabled";
|
|
721
|
+
readonly reason: string;
|
|
722
|
+
readonly category: string | null;
|
|
723
|
+
readonly cooldownUntil?: Date | null;
|
|
724
|
+
/** When true, an operator-disable (status `disabled`, no deadline) is left untouched. */
|
|
725
|
+
readonly preserveOperatorDisable?: boolean;
|
|
726
|
+
/** Health event transition status (defaults to the verdict status). */
|
|
727
|
+
readonly fromStatus?: "active" | "cooldown" | "disabled" | null;
|
|
728
|
+
readonly modelId?: string | null;
|
|
729
|
+
readonly createdAt?: Date;
|
|
730
|
+
},
|
|
731
|
+
): Promise<boolean> {
|
|
732
|
+
return withTransaction(
|
|
733
|
+
client,
|
|
734
|
+
async (tx) => {
|
|
735
|
+
const rows = await tx
|
|
736
|
+
.select({
|
|
737
|
+
status: providerAccounts.status,
|
|
738
|
+
cooldownUntil: providerAccounts.cooldownUntil,
|
|
739
|
+
})
|
|
740
|
+
.from(providerAccounts)
|
|
741
|
+
.where(eq(providerAccounts.id, verdict.accountId))
|
|
742
|
+
.limit(1);
|
|
743
|
+
const row = rows[0];
|
|
744
|
+
if (!row) return false;
|
|
745
|
+
if (verdict.preserveOperatorDisable === true) {
|
|
746
|
+
const isOperatorDisable = row.status === "disabled" && row.cooldownUntil == null;
|
|
747
|
+
if (isOperatorDisable) return false;
|
|
748
|
+
}
|
|
749
|
+
const now = verdict.createdAt ?? new Date();
|
|
750
|
+
await tx
|
|
751
|
+
.update(providerAccounts)
|
|
752
|
+
.set({
|
|
753
|
+
status: verdict.status,
|
|
754
|
+
lastError: (verdict.reason ?? "Account failed").slice(0, 500),
|
|
755
|
+
lastErrorCategory: verdict.category ?? "check_failed",
|
|
756
|
+
lastErrorAt: now,
|
|
757
|
+
...(verdict.cooldownUntil === undefined
|
|
758
|
+
? {}
|
|
759
|
+
: { cooldownUntil: verdict.cooldownUntil }),
|
|
760
|
+
})
|
|
761
|
+
.where(eq(providerAccounts.id, verdict.accountId));
|
|
762
|
+
await writeHealthEvent(tx, {
|
|
763
|
+
entityKind: "account",
|
|
764
|
+
accountId: verdict.accountId,
|
|
765
|
+
fromStatus: verdict.fromStatus ?? (row.status as "active" | "cooldown" | "disabled" | null),
|
|
766
|
+
toStatus: verdict.status,
|
|
767
|
+
reason: verdict.reason,
|
|
768
|
+
errorCategory: verdict.category,
|
|
769
|
+
modelId: verdict.modelId ?? null,
|
|
770
|
+
createdAt: now,
|
|
771
|
+
});
|
|
772
|
+
return true;
|
|
773
|
+
},
|
|
774
|
+
false,
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
|
|
697
778
|
export async function reportAttemptOutcome(
|
|
698
779
|
db: CartethyiaDatabase,
|
|
699
780
|
report: AttemptHealthReport,
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* report `"active"` just because a refresh succeeded.
|
|
10
10
|
*/
|
|
11
11
|
import { randomUUID } from "node:crypto";
|
|
12
|
-
import { eq } from "drizzle-orm";
|
|
13
12
|
import type { CartethyiaDatabase } from "../../persistence/db-handle";
|
|
14
|
-
import { healthEvents
|
|
13
|
+
import { healthEvents } from "../../persistence/schema";
|
|
15
14
|
import { pushStructuredConsoleLog } from "../../observability/log-ring";
|
|
15
|
+
import { loadAccountWithOauthState } from "./provider-credential-service";
|
|
16
16
|
import type { OAuthRefreshService, OAuthTokenRefresher } from "../authentication/oauth-refresh-service";
|
|
17
17
|
|
|
18
18
|
export type RefreshAccountStatusCode =
|
|
@@ -21,6 +21,7 @@ export type RefreshAccountStatusCode =
|
|
|
21
21
|
| "not_oauth"
|
|
22
22
|
| "static_token"
|
|
23
23
|
| "no_refresher"
|
|
24
|
+
| "auth_invalidated"
|
|
24
25
|
| "refresh_failed";
|
|
25
26
|
|
|
26
27
|
export interface RefreshAccountStatusOutcome {
|
|
@@ -54,6 +55,7 @@ interface LoadedAccount {
|
|
|
54
55
|
readonly credentialKind: string;
|
|
55
56
|
readonly status: string;
|
|
56
57
|
readonly staticToken: boolean;
|
|
58
|
+
readonly lastErrorCategory: string | null;
|
|
57
59
|
readonly refreshCiphertext: Buffer | null;
|
|
58
60
|
readonly expiresAt: Date | null;
|
|
59
61
|
}
|
|
@@ -62,47 +64,34 @@ async function loadAccount(
|
|
|
62
64
|
db: CartethyiaDatabase,
|
|
63
65
|
accountId: string,
|
|
64
66
|
): Promise<LoadedAccount | undefined> {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
)
|
|
82
|
-
: selectBuilder;
|
|
83
|
-
const rows = await query.where(eq(providerAccounts.id, accountId)).limit(1);
|
|
84
|
-
return rows[0];
|
|
67
|
+
const loaded = await loadAccountWithOauthState(db, accountId, {
|
|
68
|
+
includeStatus: true,
|
|
69
|
+
includeLastErrorCategory: true,
|
|
70
|
+
includeExpiry: true,
|
|
71
|
+
});
|
|
72
|
+
if (!loaded || loaded.status === undefined || loaded.expiresAt === undefined) return undefined;
|
|
73
|
+
return {
|
|
74
|
+
id: loaded.id,
|
|
75
|
+
providerId: loaded.providerId,
|
|
76
|
+
credentialKind: loaded.credentialKind,
|
|
77
|
+
status: loaded.status,
|
|
78
|
+
staticToken: loaded.staticToken,
|
|
79
|
+
lastErrorCategory: loaded.lastErrorCategory ?? null,
|
|
80
|
+
refreshCiphertext: loaded.refreshCiphertext,
|
|
81
|
+
expiresAt: loaded.expiresAt,
|
|
82
|
+
};
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
async function readStatusAfter(
|
|
88
86
|
db: CartethyiaDatabase,
|
|
89
87
|
accountId: string,
|
|
90
88
|
): Promise<{ status: string; expiresAt: Date | null } | undefined> {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const query =
|
|
98
|
-
"leftJoin" in selectBuilder
|
|
99
|
-
? selectBuilder.leftJoin(
|
|
100
|
-
providerOauthStates,
|
|
101
|
-
eq(providerOauthStates.providerAccountId, providerAccounts.id),
|
|
102
|
-
)
|
|
103
|
-
: selectBuilder;
|
|
104
|
-
const rows = await query.where(eq(providerAccounts.id, accountId)).limit(1);
|
|
105
|
-
return rows[0];
|
|
89
|
+
const loaded = await loadAccountWithOauthState(db, accountId, {
|
|
90
|
+
includeStatus: true,
|
|
91
|
+
includeExpiry: true,
|
|
92
|
+
});
|
|
93
|
+
if (!loaded || loaded.status === undefined || loaded.expiresAt === undefined) return undefined;
|
|
94
|
+
return { status: loaded.status, expiresAt: loaded.expiresAt };
|
|
106
95
|
}
|
|
107
96
|
|
|
108
97
|
/** Non-mutating health event: records the attempt, never changes status. */
|
|
@@ -152,6 +141,16 @@ export async function refreshAccountStatus(
|
|
|
152
141
|
}
|
|
153
142
|
const statusBefore = account.status;
|
|
154
143
|
|
|
144
|
+
if (account.status === "disabled" && account.lastErrorCategory === "auth_invalidated") {
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
tokenRefreshed: false,
|
|
148
|
+
statusAfter: statusBefore,
|
|
149
|
+
code: "auth_invalidated",
|
|
150
|
+
error: "auth_invalidated",
|
|
151
|
+
category: "This account was rejected by the provider and requires re-authentication; automatic refresh is disabled.",
|
|
152
|
+
};
|
|
153
|
+
}
|
|
155
154
|
if (account.credentialKind !== "oauth") {
|
|
156
155
|
return {
|
|
157
156
|
ok: false,
|
|
@@ -8,24 +8,22 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The mapping is deliberately conservative, following the same posture as
|
|
10
10
|
* `plan-gate.ts`: a tier is only claimed when the string proves it. "free"
|
|
11
|
-
* requires
|
|
12
|
-
* signal, and "paid" is only assigned for providers whose
|
|
13
|
-
* evidenced (Trae, the buddy family, Cursor). Everything else
|
|
14
|
-
* provider, an unrecognized plan, a `null` plan — resolves to
|
|
15
|
-
* keeps the legacy behavior intact (unknown tier ⇒ no rule
|
|
16
|
-
* constants drive the cooldown).
|
|
11
|
+
* requires the shared free marker set (exported there), "pro" requires a
|
|
12
|
+
* team/enterprise/org signal, and "paid" is only assigned for providers whose
|
|
13
|
+
* plan strings are evidenced (Trae, the buddy family, Cursor). Everything else
|
|
14
|
+
* — an unknown provider, an unrecognized plan, a `null` plan — resolves to
|
|
15
|
+
* `null`, which keeps the legacy behavior intact (unknown tier ⇒ no rule
|
|
16
|
+
* applies ⇒ the old constants drive the cooldown).
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { FREE_PLAN_MARKERS } from "../../transport/routing/plan-gate";
|
|
20
|
+
import { BUDDY_PROVIDER_IDS } from "../provider-metadata";
|
|
21
|
+
import { QODER_CHECKIN_PROVIDER_IDS } from "../integrations/qoder/qoder-checkin";
|
|
22
|
+
import { TRAE_PROVIDER_IDS } from "../integrations/trae/trae-realm";
|
|
23
|
+
|
|
19
24
|
/** The three-tier taxonomy for cooldown rules. `null` = unknown. */
|
|
20
25
|
export type AccountTier = "free" | "paid" | "pro" | null;
|
|
21
26
|
|
|
22
|
-
const TRAE_PROVIDER_IDS: ReadonlySet<string> = new Set(["trae", "traecn"]);
|
|
23
|
-
const BUDDY_PROVIDER_IDS: ReadonlySet<string> = new Set([
|
|
24
|
-
"cb",
|
|
25
|
-
"cbcn",
|
|
26
|
-
]);
|
|
27
|
-
const QODER_PROVIDER_IDS: ReadonlySet<string> = new Set(["qoder", "qodercn"]);
|
|
28
|
-
|
|
29
27
|
/** Team/enterprise/org signals that prove a "pro" tier. */
|
|
30
28
|
const PRO_PLAN_MARKERS: readonly string[] = ["team", "enterprise", "org", "pro"];
|
|
31
29
|
|
|
@@ -41,10 +39,11 @@ export function mapPlanToTier(providerId: string, plan: string | null): AccountT
|
|
|
41
39
|
const lower = (plan ?? "").trim().toLowerCase();
|
|
42
40
|
if (lower.length === 0) return null;
|
|
43
41
|
// Free is only claimed when the string proves it — the same marker set the
|
|
44
|
-
// routing plan-gate uses, so the two cannot disagree
|
|
45
|
-
|
|
42
|
+
// routing plan-gate uses (imported, not copied), so the two cannot disagree
|
|
43
|
+
// about an account.
|
|
44
|
+
if (FREE_PLAN_MARKERS.some((marker) => lower.includes(marker))) return "free";
|
|
46
45
|
|
|
47
|
-
if (
|
|
46
|
+
if ((QODER_CHECKIN_PROVIDER_IDS as readonly string[]).includes(providerId.toLowerCase())) {
|
|
48
47
|
// Qoder's `userType` is `personal_standard` by default; team/enterprise/
|
|
49
48
|
// org suffixes prove a higher tier. `personal_standard` itself is not
|
|
50
49
|
// verified against the taxonomy, so it stays unknown rather than guessed.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Discovery is owned by the background client-version monitor. Request paths
|
|
12
12
|
* only call the synchronous `get`/`snapshot` accessors and never fetch.
|
|
13
13
|
*/
|
|
14
|
-
import { getCachedVersion, resetVersionCacheForTesting } from "./provider-
|
|
14
|
+
import { getCachedVersion, resetVersionCacheForTesting } from "./provider-caches";
|
|
15
15
|
import type { OutboundFetch } from "../provider-contracts";
|
|
16
16
|
import { composeAbortSignal } from "../authentication/oauth-flow-store";
|
|
17
17
|
|
|
@@ -16,28 +16,19 @@ import {
|
|
|
16
16
|
buildGrokShellUserAgent,
|
|
17
17
|
} from "./cli-platform";
|
|
18
18
|
|
|
19
|
-
async function qoderVersion(response: Response): Promise<string | null> {
|
|
20
|
-
try {
|
|
21
|
-
const parsed = (await response.json()) as { version?: unknown };
|
|
22
|
-
return isSemverish(parsed.version) ? parsed.version.trim() : null;
|
|
23
|
-
} catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
19
|
/**
|
|
29
20
|
* Newest Trae IDE version from the official changelog.
|
|
30
21
|
*
|
|
31
|
-
* Trae publishes no npm package and no release API, so the changelog
|
|
22
|
+
* Trae publishes no npm package and no release API, so the changelog was the
|
|
32
23
|
* only machine-readable source of the current client version. It matters
|
|
33
24
|
* upstream: intl `llm_raw_chat` answers `4015` unless the request carries the
|
|
34
25
|
* *current* client version, so a stale pin is an outage, not a cosmetic drift.
|
|
35
26
|
*
|
|
36
|
-
* The page
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
27
|
+
* The page is now an SPA (2026-11-11): its HTML no longer embeds the release
|
|
28
|
+
* data, so this parser returns null and the pinned fallback carries the wire
|
|
29
|
+
* identity until a machine-readable feed exists again (see
|
|
30
|
+
* `VERSION_SOURCES.trae`). The parser is kept for when the page re-exposes
|
|
31
|
+
* its entries.
|
|
41
32
|
*/
|
|
42
33
|
async function traeVersion(response: Response): Promise<string | null> {
|
|
43
34
|
try {
|
|
@@ -67,11 +58,6 @@ async function traeVersion(response: Response): Promise<string | null> {
|
|
|
67
58
|
}
|
|
68
59
|
}
|
|
69
60
|
|
|
70
|
-
async function clineClientVersion(response: Response): Promise<string | null> {
|
|
71
|
-
const data = (await response.json()) as { version?: unknown };
|
|
72
|
-
return isSemverish(data.version) ? data.version.trim() : null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
61
|
/**
|
|
76
62
|
* Newest Cursor build from the official download API, as the IDE's own header
|
|
77
63
|
* spells it.
|
|
@@ -95,29 +81,6 @@ async function cursorVersion(response: Response): Promise<string | null> {
|
|
|
95
81
|
}
|
|
96
82
|
}
|
|
97
83
|
|
|
98
|
-
async function clineSdkVersion(response: Response): Promise<string | null> {
|
|
99
|
-
const data = (await response.json()) as {
|
|
100
|
-
version?: unknown;
|
|
101
|
-
"dist-tags"?: { latest?: unknown };
|
|
102
|
-
};
|
|
103
|
-
const candidate = data.version ?? data["dist-tags"]?.latest;
|
|
104
|
-
return isSemverish(candidate) ? candidate.trim() : null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function kimiVersion(response: Response): Promise<string | null> {
|
|
108
|
-
const data = (await response.json()) as { info?: { version?: unknown } };
|
|
109
|
-
return isSemverish(data.info?.version) ? data.info.version.trim() : null;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async function kiroCaskVersion(response: Response): Promise<string | null> {
|
|
113
|
-
try {
|
|
114
|
-
const data = (await response.json()) as { version?: unknown };
|
|
115
|
-
return isSemverish(data.version) ? data.version.trim() : null;
|
|
116
|
-
} catch {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
84
|
async function codeBuddyCnVersion(response: Response): Promise<string | null> {
|
|
122
85
|
try {
|
|
123
86
|
const data = (await response.json()) as { version?: unknown };
|
|
@@ -216,11 +179,24 @@ const KIRO_SYSTEM_VERSION = "win32#10.0.22631";
|
|
|
216
179
|
/** Node version the observed Kiro client reports (Electron's bundled Node). */
|
|
217
180
|
const KIRO_NODE_VERSION = "24.18.0";
|
|
218
181
|
|
|
182
|
+
/** Clixad gateway's own CLI version: `cli_latest` on `/v1/models`. */
|
|
183
|
+
async function clixadVersion(response: Response): Promise<string | null> {
|
|
184
|
+
const body = await response.text().catch(() => "");
|
|
185
|
+
if (body.length === 0) return null;
|
|
186
|
+
try {
|
|
187
|
+
const parsed = JSON.parse(body) as { cli_latest?: unknown };
|
|
188
|
+
const candidate = parsed.cli_latest;
|
|
189
|
+
return typeof candidate === "string" && isSemverish(candidate) ? candidate.trim() : null;
|
|
190
|
+
} catch {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
219
195
|
/** Ordered upstream sources and pinned fallbacks for every client version. */
|
|
220
196
|
export const VERSION_SOURCES = {
|
|
221
197
|
antigravity: {
|
|
222
198
|
key: "antigravity",
|
|
223
|
-
fallback: "2.
|
|
199
|
+
fallback: "2.31.0",
|
|
224
200
|
sources: [
|
|
225
201
|
{
|
|
226
202
|
url: "https://antigravity-hub-auto-updater-974169037036.us-central1.run.app/manifest/latest-arm64-mac.yml",
|
|
@@ -236,12 +212,7 @@ export const VERSION_SOURCES = {
|
|
|
236
212
|
// `@qoder-ai/qodercli/latest`) may report a newer CLI, but the CLI and
|
|
237
213
|
// IDE are different products — the chat surface identity is the IDE's.
|
|
238
214
|
fallback: "1.1.80",
|
|
239
|
-
sources: [
|
|
240
|
-
{
|
|
241
|
-
url: "https://registry.npmjs.org/@qoder-ai/qodercli/latest",
|
|
242
|
-
extract: qoderVersion,
|
|
243
|
-
},
|
|
244
|
-
],
|
|
215
|
+
sources: [{ url: "https://registry.npmjs.org/@qoder-ai/qodercli/latest" }],
|
|
245
216
|
},
|
|
246
217
|
opencode: {
|
|
247
218
|
key: "opencode",
|
|
@@ -249,7 +220,7 @@ export const VERSION_SOURCES = {
|
|
|
249
220
|
// under `@opencode/cli`, and this feed is what its own installer reads.
|
|
250
221
|
// Fallback = the current latest release; raise it whenever the package
|
|
251
222
|
// moves so a cold process does not present a stale client build.
|
|
252
|
-
fallback: "2.2.
|
|
223
|
+
fallback: "2.2.7",
|
|
253
224
|
minVersion: "2.0.0",
|
|
254
225
|
sources: [{ url: "https://opencode.ai/update/api/latest/cli/npm" }],
|
|
255
226
|
},
|
|
@@ -274,49 +245,45 @@ export const VERSION_SOURCES = {
|
|
|
274
245
|
fallback: "4.1.26",
|
|
275
246
|
minVersion: "4.1.23",
|
|
276
247
|
sources: [
|
|
277
|
-
{
|
|
278
|
-
url: "https://raw.githubusercontent.com/cline/cline/main/apps/vscode/package.json",
|
|
279
|
-
extract: clineClientVersion,
|
|
280
|
-
},
|
|
248
|
+
{ url: "https://raw.githubusercontent.com/cline/cline/main/apps/vscode/package.json" },
|
|
281
249
|
],
|
|
282
250
|
},
|
|
283
251
|
clineSdk: {
|
|
284
252
|
key: "cline-sdk",
|
|
285
253
|
fallback: "0.2.0",
|
|
286
|
-
sources: [{ url: "https://registry.npmjs.org/@cline/sdk/latest"
|
|
254
|
+
sources: [{ url: "https://registry.npmjs.org/@cline/sdk/latest" }],
|
|
287
255
|
},
|
|
288
256
|
clineCli: {
|
|
289
257
|
key: "cline-cli",
|
|
290
258
|
fallback: "3.0.74",
|
|
291
|
-
sources: [{ url: "https://registry.npmjs.org/cline/latest"
|
|
259
|
+
sources: [{ url: "https://registry.npmjs.org/cline/latest" }],
|
|
292
260
|
},
|
|
293
261
|
codex: {
|
|
294
262
|
key: "codex",
|
|
295
|
-
fallback: "0.167.
|
|
263
|
+
fallback: "0.167.1",
|
|
296
264
|
sources: [{ url: "https://registry.npmjs.org/@openai/codex/latest" }],
|
|
297
265
|
},
|
|
298
266
|
kimiCli: {
|
|
299
267
|
key: "kimi-cli",
|
|
300
268
|
fallback: "1.52.0",
|
|
301
|
-
sources: [{ url: "https://pypi.org/pypi/kimi-cli/json"
|
|
269
|
+
sources: [{ url: "https://pypi.org/pypi/kimi-cli/json" }],
|
|
302
270
|
},
|
|
303
271
|
kiro: {
|
|
304
272
|
key: "kiro",
|
|
305
|
-
fallback: "1.4.
|
|
273
|
+
fallback: "1.4.154",
|
|
306
274
|
sources: [
|
|
307
275
|
{
|
|
308
276
|
// Kiro's downloads page exposes no stable version string. Homebrew
|
|
309
277
|
// tracks the official installer URL and exposes its version as JSON;
|
|
310
278
|
// keep the product page parser as a fallback.
|
|
311
279
|
url: "https://formulae.brew.sh/api/cask/kiro.json",
|
|
312
|
-
extract: kiroCaskVersion,
|
|
313
280
|
},
|
|
314
281
|
{ url: "https://kiro.dev/downloads/", extract: kiroVersion },
|
|
315
282
|
],
|
|
316
283
|
},
|
|
317
284
|
codebuddy: {
|
|
318
285
|
key: "codebuddy",
|
|
319
|
-
fallback: "2.
|
|
286
|
+
fallback: "2.183.0",
|
|
320
287
|
sources: [
|
|
321
288
|
{ url: "https://registry.npmjs.org/@tencent-ai/codebuddy-code/latest" },
|
|
322
289
|
{ url: "https://registry.npmmirror.com/@tencent-ai/codebuddy-code/latest" },
|
|
@@ -324,7 +291,7 @@ export const VERSION_SOURCES = {
|
|
|
324
291
|
},
|
|
325
292
|
codebuddyCn: {
|
|
326
293
|
key: "codebuddy-cn",
|
|
327
|
-
fallback: "4.12.
|
|
294
|
+
fallback: "4.12.4.43368774",
|
|
328
295
|
sources: [
|
|
329
296
|
{
|
|
330
297
|
// Official CN builds are listed by Homebrew's maintained cask feed;
|
|
@@ -339,7 +306,7 @@ export const VERSION_SOURCES = {
|
|
|
339
306
|
// Current `@anthropic-ai/claude-code` release, so the billing
|
|
340
307
|
// `cc_version=` suffix and the `claude-cli/` User-Agent stay on what
|
|
341
308
|
// upstream ships.
|
|
342
|
-
fallback: "2.1.
|
|
309
|
+
fallback: "2.1.322",
|
|
343
310
|
sources: [{ url: "https://registry.npmjs.org/@anthropic-ai/claude-code/latest" }],
|
|
344
311
|
},
|
|
345
312
|
claudeSdk: {
|
|
@@ -366,21 +333,22 @@ export const VERSION_SOURCES = {
|
|
|
366
333
|
},
|
|
367
334
|
kilo: {
|
|
368
335
|
key: "kilo-code",
|
|
369
|
-
fallback: "7.8.
|
|
336
|
+
fallback: "7.8.28",
|
|
370
337
|
sources: [{ url: "https://open-vsx.org/api/kilocode/kilo-code" }],
|
|
371
338
|
},
|
|
372
339
|
muse: {
|
|
373
340
|
key: "muse-code",
|
|
374
|
-
fallback: "1.4.
|
|
341
|
+
fallback: "1.4.15-R8339.1",
|
|
375
342
|
sources: [{ url: "https://api.meta.ai/muse-code/channels/muse-stable" }],
|
|
376
343
|
},
|
|
377
344
|
trae: {
|
|
378
345
|
key: "trae",
|
|
379
|
-
// Fallback = the
|
|
380
|
-
//
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
|
|
346
|
+
// Fallback = the current desktop release per the official winget manifest
|
|
347
|
+
// (ByteDance.Trae 3.6.13). The docs changelog renders as an SPA and no
|
|
348
|
+
// longer exposes its newest entries to the parser below, so it is not a
|
|
349
|
+
// reliable discovery source right now — raise this pin when the desktop
|
|
350
|
+
// build moves.
|
|
351
|
+
fallback: "3.6.13",
|
|
384
352
|
sources: [
|
|
385
353
|
{
|
|
386
354
|
url: "https://docs.trae.ai/ide/changelog?_lang=en",
|
|
@@ -391,24 +359,63 @@ export const VERSION_SOURCES = {
|
|
|
391
359
|
freepi: {
|
|
392
360
|
key: "freepi",
|
|
393
361
|
// The free-pi CLI version — the `x-client-version` the gateway reports.
|
|
394
|
-
// Fallback = the
|
|
395
|
-
|
|
362
|
+
// Fallback = the current npm latest (0.6.19 as of 2026-11-12); a cold
|
|
363
|
+
// process sends it until the monitor's first successful discovery.
|
|
364
|
+
fallback: "0.6.19",
|
|
396
365
|
sources: [{ url: "https://registry.npmjs.org/free-pi-cli/latest" }],
|
|
397
366
|
},
|
|
398
367
|
perch: {
|
|
399
368
|
key: "perch",
|
|
400
369
|
// The official Perch CLI, spawned by the adapter for hosted inference.
|
|
401
|
-
|
|
370
|
+
// Fallback = the current npm latest (2.4.128 as of 2026-11-11); a cold
|
|
371
|
+
// process sends it until the monitor's first successful discovery.
|
|
372
|
+
fallback: "2.4.128",
|
|
402
373
|
sources: [{ url: "https://registry.npmjs.org/perchai-cli/latest" }],
|
|
403
374
|
},
|
|
375
|
+
clixad: {
|
|
376
|
+
key: "clixad",
|
|
377
|
+
// The Clixad gateway publishes the CLI build it is paired with as
|
|
378
|
+
// `cli_latest` on `/v1/models` (unauthenticated). Fallback = the version
|
|
379
|
+
// the 0.0.1-beta.50 bundle shipped (verified live 2026-11-11); a cold
|
|
380
|
+
// process sends it until the monitor's first successful discovery.
|
|
381
|
+
fallback: "0.0.1-beta.50",
|
|
382
|
+
sources: [
|
|
383
|
+
{
|
|
384
|
+
url: "https://clixad.onrender.com/v1/models",
|
|
385
|
+
extract: clixadVersion,
|
|
386
|
+
},
|
|
387
|
+
],
|
|
388
|
+
},
|
|
389
|
+
freebuff: {
|
|
390
|
+
key: "freebuff",
|
|
391
|
+
// No machine-readable public feed exists for Freebuff Desktop. GitHub
|
|
392
|
+
// releases only publish Codecane (a separate CLI line) staging builds,
|
|
393
|
+
// npm `freebuff` is the CLI (a different product), and the site's
|
|
394
|
+
// download links are client-rendered with no stable asset path.
|
|
395
|
+
// Fallback = the version unpacked from the official Windows installer
|
|
396
|
+
// during the wire audit (2026-11-09, Freebuff Desktop 0.0.201). Raise it
|
|
397
|
+
// when the next installer bundle is audited.
|
|
398
|
+
fallback: "0.0.201",
|
|
399
|
+
sources: [],
|
|
400
|
+
},
|
|
401
|
+
deepai: {
|
|
402
|
+
key: "deepai",
|
|
403
|
+
// No machine-readable public feed exists for the DeepAI Code desktop app
|
|
404
|
+
// (macOS/Windows only, no npm/CLI line). Fallback = the version unpacked
|
|
405
|
+
// from the audited bundle (2026-11-11, DeepAI Code 0.3.35). Raise it
|
|
406
|
+
// when the next bundle is audited. Pinned-only by design for the same
|
|
407
|
+
// reason as `freebuff`.
|
|
408
|
+
fallback: "0.3.35",
|
|
409
|
+
sources: [],
|
|
410
|
+
},
|
|
404
411
|
cursor: {
|
|
405
412
|
key: "cursor",
|
|
406
|
-
// Fallback = the
|
|
407
|
-
// Discovery replaces it within one monitor tick; it
|
|
408
|
-
// process sends before the first successful fetch.
|
|
409
|
-
// `FALLBACK_CLIENT_VERSION` in the cursor adapter so the
|
|
410
|
-
// request header always send one identity.
|
|
411
|
-
fallback: "cli-3.29.
|
|
413
|
+
// Fallback = the newest stable build from the official download API
|
|
414
|
+
// (cli-3.29.15-86776fc). Discovery replaces it within one monitor tick; it
|
|
415
|
+
// is only what a cold process sends before the first successful fetch.
|
|
416
|
+
// Kept equal to `FALLBACK_CLIENT_VERSION` in the cursor adapter so the
|
|
417
|
+
// badge and the request header always send one identity.
|
|
418
|
+
fallback: "cli-3.29.15-86776fc",
|
|
412
419
|
sources: [
|
|
413
420
|
{
|
|
414
421
|
url: "https://cursor.com/api/download?platform=win32-x64-user&releaseTrack=stable",
|
|
@@ -422,7 +429,7 @@ export const VERSION_SOURCES = {
|
|
|
422
429
|
// comment this replaced claimed no semver existed and pinned a date tag
|
|
423
430
|
// (`v2026.9.24`) as the version — a tag, not a release, and not the
|
|
424
431
|
// identity the client sends.
|
|
425
|
-
fallback: "0.23.
|
|
432
|
+
fallback: "0.23.1",
|
|
426
433
|
sources: [
|
|
427
434
|
{
|
|
428
435
|
url: "https://api.github.com/repos/NousResearch/hermes-agent/releases/latest",
|
|
@@ -449,6 +456,9 @@ const resolvers = {
|
|
|
449
456
|
trae: createClientVersionResolver({ ...VERSION_SOURCES.trae, client: "trae" }),
|
|
450
457
|
freepi: createClientVersionResolver({ ...VERSION_SOURCES.freepi, client: "freepi" }),
|
|
451
458
|
perch: createClientVersionResolver({ ...VERSION_SOURCES.perch, client: "perch" }),
|
|
459
|
+
clixad: createClientVersionResolver({ ...VERSION_SOURCES.clixad, client: "clixad" }),
|
|
460
|
+
freebuff: createClientVersionResolver({ ...VERSION_SOURCES.freebuff, client: "freebuff" }),
|
|
461
|
+
deepai: createClientVersionResolver({ ...VERSION_SOURCES.deepai, client: "deepai" }),
|
|
452
462
|
cursor: createClientVersionResolver({ ...VERSION_SOURCES.cursor, client: "cursor" }),
|
|
453
463
|
opencode: createClientVersionResolver({ ...VERSION_SOURCES.opencode, client: "opencode" }),
|
|
454
464
|
commandcode: createClientVersionResolver({ ...VERSION_SOURCES.commandcode, client: "command-code" }),
|
|
@@ -470,6 +480,11 @@ const resolvers = {
|
|
|
470
480
|
} satisfies Record<keyof typeof VERSION_SOURCES, ClientVersionResolver>;
|
|
471
481
|
const PROVIDER_VERSION_RESOLVERS: Readonly<Record<string, ClientVersionResolver>> = {
|
|
472
482
|
antigravity: resolvers.antigravity,
|
|
483
|
+
freepi: resolvers.freepi,
|
|
484
|
+
perch: resolvers.perch,
|
|
485
|
+
clixad: resolvers.clixad,
|
|
486
|
+
freebuff: resolvers.freebuff,
|
|
487
|
+
deepai: resolvers.deepai,
|
|
473
488
|
grok: resolvers.grok,
|
|
474
489
|
xai: resolvers.grok,
|
|
475
490
|
opencode: resolvers.opencode,
|
|
@@ -583,6 +598,10 @@ export const getQoderVersion = accessor("qoder").get;
|
|
|
583
598
|
export const getHermesVersion = accessor("hermes").get;
|
|
584
599
|
export const getTraeVersion = accessor("trae").get;
|
|
585
600
|
export const getAntigravityVersion = accessor("antigravity").get;
|
|
601
|
+
export const getFreepiVersion = accessor("freepi").get;
|
|
602
|
+
export const getPerchVersion = accessor("perch").get;
|
|
603
|
+
export const getFreebuffVersion = accessor("freebuff").get;
|
|
604
|
+
export const getDeepAIVersion = accessor("deepai").get;
|
|
586
605
|
|
|
587
606
|
export const getOpenCodeVersion = accessor("opencode").get;
|
|
588
607
|
|
|
@@ -28,24 +28,19 @@ type ProviderRules = Record<string, CategoryRules>;
|
|
|
28
28
|
const DAY = 24 * 60 * 60 * 1000;
|
|
29
29
|
const MINUTE = 60 * 1000;
|
|
30
30
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
pro: 15 * MINUTE,
|
|
37
|
-
},
|
|
31
|
+
const TRAE_RULES: CategoryRules = {
|
|
32
|
+
model_unreachable: {
|
|
33
|
+
free: DAY,
|
|
34
|
+
paid: 15 * MINUTE,
|
|
35
|
+
pro: 15 * MINUTE,
|
|
38
36
|
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const COOLDOWN_RULES: ProviderRules = {
|
|
40
|
+
trae: TRAE_RULES,
|
|
39
41
|
// Trae CN is the same upstream product under a second realm id — the
|
|
40
|
-
// classifier already treats the two identically
|
|
41
|
-
|
|
42
|
-
traecn: {
|
|
43
|
-
model_unreachable: {
|
|
44
|
-
free: DAY,
|
|
45
|
-
paid: 15 * MINUTE,
|
|
46
|
-
pro: 15 * MINUTE,
|
|
47
|
-
},
|
|
48
|
-
},
|
|
42
|
+
// classifier already treats the two identically, so the rules alias.
|
|
43
|
+
traecn: TRAE_RULES,
|
|
49
44
|
};
|
|
50
45
|
|
|
51
46
|
/**
|