cartethyia 2.7.9 → 2.8.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 +3 -2
- package/dist/dashboard/assets/{BannedPage-BxoG1MrL.js → BannedPage-Cc0vKpMG.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-ixwgKk53.js → CliToolDetailPage-Bqj2aa1T.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-Bqj2aa1T.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BmttNV3U.js → CliToolsPage-CXsaOAO2.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-CXsaOAO2.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BE3qwwfC.js → CombosPage-BeLpJ4ma.js} +1 -1
- package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CRZdmMIX.js → ConsoleLogPage-DnV0uZ3m.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-Dv_FJ6Er.js → CustomizationPage-CBxAjo63.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-BOoO8rpz.js → InjectSystemPromptPanel-BWFLECmz.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-BWFLECmz.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-ChJuNNVN.js → LoginPage-CgoPc5B9.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CgoPc5B9.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BZAJtPg1.js → ModelPicker-D9bFQern.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-D9bFQern.js.gz +0 -0
- package/dist/dashboard/assets/{OverviewPage-BE40s3u5.js → OverviewPage-B_p4tL8k.js} +1 -1
- package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js.gz +0 -0
- package/dist/dashboard/assets/{ProviderIcon-CQ6bPUf_.js → ProviderIcon-D_0PiZtg.js} +1 -1
- package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-BJ87Pp0U.js → ProxyPage-BwNC_-Cx.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BwNC_-Cx.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js +1 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-C5HPWqEv.js → SettingsPage-CctTga2C.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-CctTga2C.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-CFNcATJJ.js → SetupPage-febLU4r1.js} +1 -1
- package/dist/dashboard/assets/SetupPage-febLU4r1.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-YoD4tY5l.js → StudioPage-M6fvR5Wz.js} +1 -1
- package/dist/dashboard/assets/StudioPage-M6fvR5Wz.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-DxjaAhb_.js → UsagePage-nyeuRqz9.js} +1 -1
- package/dist/dashboard/assets/UsagePage-nyeuRqz9.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-BTlkq_Uk.js → api-keys-BFOlvrJC.js} +1 -1
- package/dist/dashboard/assets/api-keys-BFOlvrJC.js.gz +0 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css +2 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css.gz +0 -0
- package/dist/dashboard/assets/assert-CqTLw5e7.js +1 -0
- package/dist/dashboard/assets/assert-CqTLw5e7.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DdbT_7Am.js → badge-C83EqLB0.js} +1 -1
- package/dist/dashboard/assets/badge-C83EqLB0.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CsGN-nbm.js → banner-D1xn7pIe.js} +1 -1
- package/dist/dashboard/assets/banner-D1xn7pIe.js.gz +0 -0
- package/dist/dashboard/assets/{card-mgZ_TLLZ.js → card-DU3Lq5Lm.js} +1 -1
- package/dist/dashboard/assets/card-DU3Lq5Lm.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-A1-v8-03.js → cli-tools-Dw1U_drK.js} +1 -1
- package/dist/dashboard/assets/cli-tools-Dw1U_drK.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-CJ4Zty89.js → clipboard-button-CEL5Sg_J.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-CEL5Sg_J.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-B5L2jPQ_.js → dialog-BjFR5UHy.js} +1 -1
- package/dist/dashboard/assets/dialog-BjFR5UHy.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-DkjUouAj.js → drawer-HvBW0AjI.js} +1 -1
- package/dist/dashboard/assets/drawer-HvBW0AjI.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js +4 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js.gz +0 -0
- package/dist/dashboard/assets/{entry-B-LVLV6o.js → entry-CECVELyy.js} +1 -1
- package/dist/dashboard/assets/entry-CECVELyy.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CAhdYl3B.js → entry-DYYofQ7W.js} +1 -1
- package/dist/dashboard/assets/entry-DYYofQ7W.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CrsdLVsn.js → formatters-DLW4i8zK.js} +1 -1
- package/dist/dashboard/assets/formatters-DLW4i8zK.js.gz +0 -0
- package/dist/dashboard/assets/{index-BU64Lqvp.js → index-1-fCqe64.js} +2 -2
- package/dist/dashboard/assets/index-1-fCqe64.js.gz +0 -0
- package/dist/dashboard/assets/{inline-B2aDLyyg.js → inline-DGvU2oLK.js} +1 -1
- package/dist/dashboard/assets/inline-DGvU2oLK.js.gz +0 -0
- package/dist/dashboard/assets/{input-BCVkdR9d.js → input-iNnO1X2K.js} +1 -1
- package/dist/dashboard/assets/input-iNnO1X2K.js.gz +0 -0
- package/dist/dashboard/assets/{layout-DNcAdMK-.js → layout-0q8UGypb.js} +1 -1
- package/dist/dashboard/assets/layout-0q8UGypb.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-DgrIH0hw.js → list-row-C0w2bQjJ.js} +1 -1
- package/dist/dashboard/assets/list-row-C0w2bQjJ.js.gz +0 -0
- package/dist/dashboard/assets/{live-Cae01iu8.js → live-M5aJ_xCa.js} +1 -1
- package/dist/dashboard/assets/live-M5aJ_xCa.js.gz +0 -0
- package/dist/dashboard/assets/{network-CRib7H_2.js → network-BKeQGT3K.js} +1 -1
- package/dist/dashboard/assets/network-BKeQGT3K.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BKQE8Xpz.js → numbers-CivAk3da.js} +1 -1
- package/dist/dashboard/assets/numbers-CivAk3da.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-ecPvG_8g.js → pagination-CpzvI5ep.js} +1 -1
- package/dist/dashboard/assets/pagination-CpzvI5ep.js.gz +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-BFQX2VBc.js} +1 -1
- package/dist/dashboard/assets/routing-BFQX2VBc.js.gz +0 -0
- package/dist/dashboard/assets/{select-ChoFWyKz.js → select-CXbck0jG.js} +2 -2
- package/dist/dashboard/assets/select-CXbck0jG.js.gz +0 -0
- package/dist/dashboard/assets/{settings-CKjFPlKW.js → settings-C_XvMHh9.js} +1 -1
- package/dist/dashboard/assets/settings-C_XvMHh9.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DWCwU3fh.js → stack-DggRiCxE.js} +1 -1
- package/dist/dashboard/assets/stack-DggRiCxE.js.gz +0 -0
- package/dist/dashboard/assets/{state-Cg3VL5J_.js → state-ClFzfbYp.js} +1 -1
- package/dist/dashboard/assets/state-ClFzfbYp.js.gz +0 -0
- package/dist/dashboard/assets/{switch-Db70BMix.js → switch-CTIFxKqS.js} +1 -1
- package/dist/dashboard/assets/switch-CTIFxKqS.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BqdE0LuM.js → useMutation-BClG3yWj.js} +1 -1
- package/dist/dashboard/assets/useMutation-BClG3yWj.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/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
- package/package.json +1 -1
- package/src/boot/app.ts +10 -13
- package/src/boot/dependencies.ts +1 -1
- package/src/boot/flush.ts +20 -0
- package/src/boot/lifecycle.ts +7 -5
- package/src/config/routing.ts +26 -0
- package/src/config/spec-metadata.ts +72 -0
- package/src/config/spec.ts +20 -0
- 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/cli-tools/service.ts +6 -12
- package/src/console/console-router-guards.ts +23 -16
- package/src/console/domain-registration.ts +0 -2
- 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/store.ts +0 -53
- package/src/console/providers/catalog/contracts.ts +2 -2
- package/src/console/providers/catalog/discover-constants.ts +6 -0
- package/src/console/providers/catalog/routes.ts +1 -0
- package/src/console/providers/catalog/store.ts +21 -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 +6 -18
- package/src/console/quota/quota-view.ts +19 -3
- package/src/console/routing/pools/operations.ts +31 -46
- package/src/console/shared/errors.ts +33 -6
- package/src/main.ts +2 -3
- package/src/network/pool/byte-accounting.ts +3 -2
- package/src/network/pool/selector.ts +182 -39
- package/src/network/pool-cooldown-store.ts +89 -14
- package/src/network/pool-health.ts +49 -61
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/ssrf.ts +6 -6
- 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 +15 -25
- 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 +8 -0
- package/src/persistence/ttl-cache.ts +20 -2
- package/src/protocol/codecs.ts +1 -1
- 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 +3 -4
- package/src/protocol/response/chat.ts +12 -20
- 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/providers/adapters/compatible-adapter.ts +71 -12
- package/src/providers/authentication/oauth-client.ts +1 -1
- package/src/providers/authentication/oauth-device-flow.ts +98 -8
- package/src/providers/authentication/oauth-refresh-service.ts +30 -49
- package/src/providers/configured-provider.ts +148 -0
- package/src/providers/default-registry.ts +61 -36
- package/src/providers/discovery/probe-phases.ts +14 -4
- package/src/providers/discovery/probing-service.ts +15 -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 +5 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +173 -17
- package/src/providers/integrations/buddy/buddy-identity.ts +19 -6
- package/src/providers/integrations/buddy/capabilities.ts +2 -2
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +3 -0
- package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +37 -22
- package/src/providers/integrations/claude/claude-quota.ts +14 -17
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/commandcode/quota.ts +22 -28
- package/src/providers/integrations/cursor/cursor-auth.ts +0 -8
- package/src/providers/integrations/cursor/cursor-exec.ts +9 -2
- package/src/providers/integrations/cursor/cursor-request.ts +26 -12
- package/src/providers/integrations/cursor/cursor-shared.ts +7 -4
- package/src/providers/integrations/cursor/cursor.ts +89 -40
- 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/devin/protocol/devin-proto.ts +1 -27
- package/src/providers/integrations/factory/factory-oauth.ts +17 -44
- 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/grok/grok-oauth.ts +48 -45
- 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.ts → hermes/hermes.ts} +9 -9
- package/src/providers/integrations/hermes/index.ts +2 -0
- 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-quota.ts +8 -4
- package/src/providers/integrations/kiro/kiro.ts +15 -19
- 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/opencode-go-quota.ts +2 -8
- package/src/providers/integrations/perch/perch-credential.ts +25 -0
- package/src/providers/integrations/perch/perch-protocol.ts +0 -3
- package/src/providers/integrations/perch/perch-quota.ts +2 -16
- package/src/providers/integrations/perch/perch.ts +3 -13
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +18 -59
- package/src/providers/integrations/qoder/qoder-adapter.ts +1 -12
- package/src/providers/integrations/qoder/qoder-auth.ts +101 -29
- package/src/providers/integrations/qoder/qoder-catalog.ts +20 -5
- package/src/providers/integrations/qoder/qoder-chat.ts +7 -21
- package/src/providers/integrations/qoder/qoder-checkin.ts +4 -4
- package/src/providers/integrations/qoder/qoder-grpc.ts +0 -1
- package/src/providers/integrations/qoder/qoder-ide.ts +0 -107
- package/src/providers/integrations/qoder/qoder.ts +0 -1
- package/src/providers/integrations/trae/trae-protocol.ts +9 -5
- package/src/providers/integrations/trae/trae-quota.ts +6 -28
- package/src/providers/integrations/trae/trae-realm.ts +38 -0
- package/src/providers/integrations/trae/trae.ts +7 -24
- 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 +204 -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 +22 -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 +5 -51
- package/src/providers/operations/cooldown-rules.ts +11 -16
- 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 +102 -32
- 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/provider-contracts.ts +4 -2
- package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
- package/src/providers/provider-metadata.ts +40 -10
- package/src/providers/provider-probe.ts +15 -1
- package/src/providers/provider-registry.ts +42 -33
- 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 +75 -18
- package/src/security/api-key-auth-cache.ts +1 -1
- package/src/security/api-key-auth.ts +6 -2
- package/src/transport/dispatch/attempt-finalize.ts +14 -13
- package/src/transport/dispatch/attempt-loop.ts +71 -17
- package/src/transport/dispatch/generation.ts +2 -8
- 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/streaming/finalize.ts +9 -6
- package/src/transport/dispatch/streaming/stream.ts +8 -36
- 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/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/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.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/providers/bundled-discovery-providers.ts +0 -98
- package/src/providers/configured-openai-providers.ts +0 -120
- 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-DIXLjojg.js} +0 -0
- /package/dist/dashboard/assets/{app-B7kIWFm5.js.gz → app-DIXLjojg.js.gz} +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 =
|
|
@@ -62,47 +62,32 @@ async function loadAccount(
|
|
|
62
62
|
db: CartethyiaDatabase,
|
|
63
63
|
accountId: string,
|
|
64
64
|
): Promise<LoadedAccount | undefined> {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
providerOauthStates,
|
|
80
|
-
eq(providerOauthStates.providerAccountId, providerAccounts.id),
|
|
81
|
-
)
|
|
82
|
-
: selectBuilder;
|
|
83
|
-
const rows = await query.where(eq(providerAccounts.id, accountId)).limit(1);
|
|
84
|
-
return rows[0];
|
|
65
|
+
const loaded = await loadAccountWithOauthState(db, accountId, {
|
|
66
|
+
includeStatus: true,
|
|
67
|
+
includeExpiry: true,
|
|
68
|
+
});
|
|
69
|
+
if (!loaded || loaded.status === undefined || loaded.expiresAt === undefined) return undefined;
|
|
70
|
+
return {
|
|
71
|
+
id: loaded.id,
|
|
72
|
+
providerId: loaded.providerId,
|
|
73
|
+
credentialKind: loaded.credentialKind,
|
|
74
|
+
status: loaded.status,
|
|
75
|
+
staticToken: loaded.staticToken,
|
|
76
|
+
refreshCiphertext: loaded.refreshCiphertext,
|
|
77
|
+
expiresAt: loaded.expiresAt,
|
|
78
|
+
};
|
|
85
79
|
}
|
|
86
80
|
|
|
87
81
|
async function readStatusAfter(
|
|
88
82
|
db: CartethyiaDatabase,
|
|
89
83
|
accountId: string,
|
|
90
84
|
): 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];
|
|
85
|
+
const loaded = await loadAccountWithOauthState(db, accountId, {
|
|
86
|
+
includeStatus: true,
|
|
87
|
+
includeExpiry: true,
|
|
88
|
+
});
|
|
89
|
+
if (!loaded || loaded.status === undefined || loaded.expiresAt === undefined) return undefined;
|
|
90
|
+
return { status: loaded.status, expiresAt: loaded.expiresAt };
|
|
106
91
|
}
|
|
107
92
|
|
|
108
93
|
/** Non-mutating health event: records the attempt, never changes status. */
|
|
@@ -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,15 +16,6 @@ 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
|
*
|
|
@@ -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 };
|
|
@@ -236,12 +199,7 @@ export const VERSION_SOURCES = {
|
|
|
236
199
|
// `@qoder-ai/qodercli/latest`) may report a newer CLI, but the CLI and
|
|
237
200
|
// IDE are different products — the chat surface identity is the IDE's.
|
|
238
201
|
fallback: "1.1.80",
|
|
239
|
-
sources: [
|
|
240
|
-
{
|
|
241
|
-
url: "https://registry.npmjs.org/@qoder-ai/qodercli/latest",
|
|
242
|
-
extract: qoderVersion,
|
|
243
|
-
},
|
|
244
|
-
],
|
|
202
|
+
sources: [{ url: "https://registry.npmjs.org/@qoder-ai/qodercli/latest" }],
|
|
245
203
|
},
|
|
246
204
|
opencode: {
|
|
247
205
|
key: "opencode",
|
|
@@ -274,21 +232,18 @@ export const VERSION_SOURCES = {
|
|
|
274
232
|
fallback: "4.1.26",
|
|
275
233
|
minVersion: "4.1.23",
|
|
276
234
|
sources: [
|
|
277
|
-
{
|
|
278
|
-
url: "https://raw.githubusercontent.com/cline/cline/main/apps/vscode/package.json",
|
|
279
|
-
extract: clineClientVersion,
|
|
280
|
-
},
|
|
235
|
+
{ url: "https://raw.githubusercontent.com/cline/cline/main/apps/vscode/package.json" },
|
|
281
236
|
],
|
|
282
237
|
},
|
|
283
238
|
clineSdk: {
|
|
284
239
|
key: "cline-sdk",
|
|
285
240
|
fallback: "0.2.0",
|
|
286
|
-
sources: [{ url: "https://registry.npmjs.org/@cline/sdk/latest"
|
|
241
|
+
sources: [{ url: "https://registry.npmjs.org/@cline/sdk/latest" }],
|
|
287
242
|
},
|
|
288
243
|
clineCli: {
|
|
289
244
|
key: "cline-cli",
|
|
290
245
|
fallback: "3.0.74",
|
|
291
|
-
sources: [{ url: "https://registry.npmjs.org/cline/latest"
|
|
246
|
+
sources: [{ url: "https://registry.npmjs.org/cline/latest" }],
|
|
292
247
|
},
|
|
293
248
|
codex: {
|
|
294
249
|
key: "codex",
|
|
@@ -298,7 +253,7 @@ export const VERSION_SOURCES = {
|
|
|
298
253
|
kimiCli: {
|
|
299
254
|
key: "kimi-cli",
|
|
300
255
|
fallback: "1.52.0",
|
|
301
|
-
sources: [{ url: "https://pypi.org/pypi/kimi-cli/json"
|
|
256
|
+
sources: [{ url: "https://pypi.org/pypi/kimi-cli/json" }],
|
|
302
257
|
},
|
|
303
258
|
kiro: {
|
|
304
259
|
key: "kiro",
|
|
@@ -309,7 +264,6 @@ export const VERSION_SOURCES = {
|
|
|
309
264
|
// tracks the official installer URL and exposes its version as JSON;
|
|
310
265
|
// keep the product page parser as a fallback.
|
|
311
266
|
url: "https://formulae.brew.sh/api/cask/kiro.json",
|
|
312
|
-
extract: kiroCaskVersion,
|
|
313
267
|
},
|
|
314
268
|
{ url: "https://kiro.dev/downloads/", extract: kiroVersion },
|
|
315
269
|
],
|
|
@@ -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
|
/**
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* `bundledModelCatalog` is called during startup seeding and again whenever a
|
|
5
|
-
* caller rebuilds the routing/console catalog. Caching the loader *promise*
|
|
6
|
-
* (not just the resolved value) makes concurrent and repeated calls for one
|
|
7
|
-
* provider share a single load, and lets the dynamic catalog imports run once
|
|
8
|
-
* per process. A rejected load is evicted so a later call can retry.
|
|
2
|
+
* In-process caches for model catalogs, model discovery, and client/provider versions.
|
|
9
3
|
*/
|
|
4
|
+
|
|
10
5
|
import type { ModelDefinition } from "../provider-model-definition";
|
|
11
6
|
import { trackModelCatalogLoad } from "../../observability/performance-metrics";
|
|
12
7
|
import { resolveRedisClient } from "../../persistence/redis";
|
|
13
8
|
import { cachedRead } from "../../console/shared/read-through-cache";
|
|
9
|
+
import { TtlCacheFamily } from "../../persistence/ttl-cache";
|
|
10
|
+
import { retryWithBackoff } from "../../network/retry";
|
|
11
|
+
|
|
12
|
+
/* -------------------------------------------------------------------------- */
|
|
13
|
+
/* 1. Model Catalog Cache */
|
|
14
|
+
/* -------------------------------------------------------------------------- */
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Provider entries retained before the least-recently-used catalog is evicted.
|
|
@@ -37,8 +38,7 @@ const catalogCache = new Map<string, Promise<readonly ModelDefinition[]>>();
|
|
|
37
38
|
/**
|
|
38
39
|
* Evicts the least-recently-used provider before inserting a new one once the
|
|
39
40
|
* cache is at its bound. `Map` preserves insertion order and every cache hit
|
|
40
|
-
* re-inserts its entry at the tail, so the head is the LRU key.
|
|
41
|
-
* bound the process-lifetime cache pinned one catalog per provider forever.
|
|
41
|
+
* re-inserts its entry at the tail, so the head is the LRU key.
|
|
42
42
|
*/
|
|
43
43
|
function evictLeastRecentlyUsedCatalog(maxEntries: number): void {
|
|
44
44
|
if (catalogCache.size < maxEntries) return;
|
|
@@ -87,13 +87,65 @@ export function resetModelCatalogCacheForTesting(): void {
|
|
|
87
87
|
catalogCache.clear();
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
/**
|
|
91
|
-
* Live entry count, for the `/metrics` gauge.
|
|
92
|
-
*
|
|
93
|
-
* Exported so a rebuild that saturates the cap is visible from outside the
|
|
94
|
-
* process: before this, every in-process cache except the quota tier was
|
|
95
|
-
* invisible, and growth could only be found with a heap dump.
|
|
96
|
-
*/
|
|
90
|
+
/** Live entry count, for the `/metrics` gauge. */
|
|
97
91
|
export function modelCatalogCacheSize(): number {
|
|
98
92
|
return catalogCache.size;
|
|
99
93
|
}
|
|
94
|
+
|
|
95
|
+
/* -------------------------------------------------------------------------- */
|
|
96
|
+
/* 2. Model Discovery Cache */
|
|
97
|
+
/* -------------------------------------------------------------------------- */
|
|
98
|
+
|
|
99
|
+
const MODEL_DISCOVERY_CACHE_TTL_MS = 10 * 60 * 1000;
|
|
100
|
+
const discoveryCaches = new TtlCacheFamily<readonly ModelDefinition[]>({
|
|
101
|
+
defaultTtlMs: MODEL_DISCOVERY_CACHE_TTL_MS,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export interface CachedModelDiscoveryOptions {
|
|
105
|
+
readonly ttlMs?: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Returns cached models, retrying null/empty loads on the next call. */
|
|
109
|
+
export async function getCachedModelDiscovery(
|
|
110
|
+
key: string,
|
|
111
|
+
loader: () => Promise<readonly ModelDefinition[] | null>,
|
|
112
|
+
options: CachedModelDiscoveryOptions = {},
|
|
113
|
+
): Promise<readonly ModelDefinition[] | null> {
|
|
114
|
+
return discoveryCaches.for(options.ttlMs).load(key, loader, {
|
|
115
|
+
namespace: "model-discovery",
|
|
116
|
+
shouldCache: (models) => models.length > 0,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Drops all cached discoveries. Test-only. */
|
|
121
|
+
export function resetModelDiscoveryCacheForTesting(): void {
|
|
122
|
+
discoveryCaches.clear();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* -------------------------------------------------------------------------- */
|
|
126
|
+
/* 3. Provider Version Cache */
|
|
127
|
+
/* -------------------------------------------------------------------------- */
|
|
128
|
+
|
|
129
|
+
const VERSION_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
130
|
+
const versionCaches = new TtlCacheFamily<string>({ defaultTtlMs: VERSION_CACHE_TTL_MS });
|
|
131
|
+
|
|
132
|
+
export interface CachedVersionOptions {
|
|
133
|
+
readonly ttlMs?: number;
|
|
134
|
+
readonly maxRetries?: number;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export async function getCachedVersion(
|
|
138
|
+
key: string,
|
|
139
|
+
loader: () => Promise<string | null>,
|
|
140
|
+
options: CachedVersionOptions = {},
|
|
141
|
+
): Promise<string | null> {
|
|
142
|
+
const loadWithRetry = () => retryWithBackoff(loader, { maxRetries: options.maxRetries ?? 2 });
|
|
143
|
+
return versionCaches.for(options.ttlMs).load(key, loadWithRetry, {
|
|
144
|
+
namespace: "provider-version",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Drops all cached versions. Test-only. */
|
|
149
|
+
export function resetVersionCacheForTesting(): void {
|
|
150
|
+
versionCaches.clear();
|
|
151
|
+
}
|
|
@@ -10,7 +10,7 @@ import { ProviderRegistry } from "../provider-registry";
|
|
|
10
10
|
import { OpenAICompatibleAdapter } from "../adapters/compatible-adapter";
|
|
11
11
|
import { resolveByokWireProfile } from "./byok-wire-profile";
|
|
12
12
|
import { BUNDLED_PROVIDER_MODULES } from "../default-registry";
|
|
13
|
-
import { getCachedModels } from "./
|
|
13
|
+
import { getCachedModels } from "./provider-caches";
|
|
14
14
|
import { seedBundledModels } from "./provider-catalog-seeder";
|
|
15
15
|
import type { CartethyiaDatabase } from "../../persistence/db-handle";
|
|
16
16
|
import { providers } from "../../persistence/schema";
|