cartethyia 2.6.7 → 2.7.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 +1 -7
- package/README.md +25 -2
- package/dist/dashboard/assets/{BannedPage-Dskhyp0l.js → BannedPage-D-J75hBM.js} +1 -1
- package/dist/dashboard/assets/BannedPage-D-J75hBM.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage--SJhk7qQ.js → CliToolDetailPage-CVe6RaBH.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-CVe6RaBH.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-C203VT-c.js → CliToolsPage-Dd8ZSamp.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-Dd8ZSamp.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BcS7kGG1.js → CombosPage-QoJ6foxo.js} +1 -1
- package/dist/dashboard/assets/CombosPage-QoJ6foxo.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DpNRay4C.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-DpNRay4C.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-uujbBYwC.js → CustomizationPage-CKUFTcW4.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-CKUFTcW4.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-CzSLiDzr.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-CzSLiDzr.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-DubdQcvX.js +1 -0
- package/dist/dashboard/assets/LoginPage-DubdQcvX.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-CA1kLs45.js → ModelPicker-BH8Tehdi.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-BH8Tehdi.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-DuWzAQFL.js +1 -0
- package/dist/dashboard/assets/OverviewPage-DuWzAQFL.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-BKEKe2Fm.js +4 -0
- package/dist/dashboard/assets/ProviderDetailPage-BKEKe2Fm.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-Bwotu8UJ.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-Bwotu8UJ.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-D7hpWbg9.js +9 -0
- package/dist/dashboard/assets/ProxyPage-D7hpWbg9.js.gz +0 -0
- package/dist/dashboard/assets/{QuotaPage-BueSWX5D.js → QuotaPage-ATpaxrbl.js} +1 -1
- package/dist/dashboard/assets/QuotaPage-ATpaxrbl.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CETophpx.js +1 -0
- package/dist/dashboard/assets/SettingsPage-CETophpx.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BdgECjqq.js +1 -0
- package/dist/dashboard/assets/SetupPage-BdgECjqq.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-DrKeMcGN.js → SortableList-CAK-EN9z.js} +1 -1
- package/dist/dashboard/assets/SortableList-CAK-EN9z.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-qjuYtccc.js → StudioPage-B7W2_RhT.js} +3 -3
- package/dist/dashboard/assets/StudioPage-B7W2_RhT.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-6T4EFDjW.js +56 -0
- package/dist/dashboard/assets/UsagePage-6T4EFDjW.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-C23S9sgp.js → api-keys-CUi6UXsR.js} +1 -1
- package/dist/dashboard/assets/api-keys-CUi6UXsR.js.gz +0 -0
- package/dist/dashboard/assets/app-KvsUJUMF.css +2 -0
- package/dist/dashboard/assets/app-KvsUJUMF.css.gz +0 -0
- package/dist/dashboard/assets/{assert-DU6qrMA_.js → assert-67xXH5rf.js} +1 -1
- package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
- package/dist/dashboard/assets/{badge-Bkz_-RrM.js → badge-DC2L43Mj.js} +1 -1
- package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
- package/dist/dashboard/assets/{banner-C-7y3VKV.js → banner-BBVcb0J3.js} +1 -1
- package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
- package/dist/dashboard/assets/{card-BOPBuBzD.js → card-Cca1XC6G.js} +1 -1
- package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-BaFUuFFF.js → cli-tools-KvsWa1Jl.js} +1 -1
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-e-Mlk0FH.js → clipboard-button-DUzEbynq.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-Iec_ywbD.js → dialog-DFvWhwTa.js} +1 -1
- package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bs8MIIHc.js → drawer-CFM2sMX1.js} +1 -1
- package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
- package/dist/dashboard/assets/{entry-DOddwoc0.js → entry-BLBLxX0h.js} +3 -3
- package/dist/dashboard/assets/entry-BLBLxX0h.js.gz +0 -0
- package/dist/dashboard/assets/{entry-DcobaKFu.js → entry-Bqy8RFvM.js} +1 -1
- package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
- package/dist/dashboard/assets/{entry-BRszm4_Z.js → entry-_xHo5x6r.js} +1 -1
- package/dist/dashboard/assets/entry-_xHo5x6r.js.gz +0 -0
- package/dist/dashboard/assets/formatters-mpBPqAQ8.js +1 -0
- package/dist/dashboard/assets/formatters-mpBPqAQ8.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-BuDsrsPn.js → github-badge-C9e8Ts7e.js} +1 -1
- package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
- package/dist/dashboard/assets/{index-BeLRhsmt.js → index-D6QzEC_n.js} +2 -2
- package/dist/dashboard/assets/index-D6QzEC_n.js.gz +0 -0
- package/dist/dashboard/assets/{inline-DToMICwl.js → inline-BFUcvllj.js} +1 -1
- package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
- package/dist/dashboard/assets/{input-WlyHWeG2.js → input-C_ILAvBb.js} +1 -1
- package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
- package/dist/dashboard/assets/{layout-DaJ5baJr.js → layout-CBIyT6Rt.js} +1 -1
- package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-B3oSK13z.js → list-row-ebJ_-Nsb.js} +1 -1
- package/dist/dashboard/assets/list-row-ebJ_-Nsb.js.gz +0 -0
- package/dist/dashboard/assets/{live-ta6GMb-8.js → live-D0mm--ME.js} +1 -1
- package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +1 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-g_fduiNw.js → mutation-sMD965oO.js} +1 -1
- package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-Dulqgys5.js → numbers-BO9dKaFr.js} +1 -1
- package/dist/dashboard/assets/numbers-BO9dKaFr.js.gz +0 -0
- package/dist/dashboard/assets/providers/inception.svg +5 -0
- package/dist/dashboard/assets/providers/inception.svg.gz +0 -0
- package/dist/dashboard/assets/{query-keys-UETqfytp.js → query-keys-CfL_Zdoh.js} +1 -1
- package/dist/dashboard/assets/query-keys-CfL_Zdoh.js.gz +0 -0
- package/dist/dashboard/assets/{routing-BPUo-W8d.js → routing-BnIpi1IJ.js} +1 -1
- package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
- package/dist/dashboard/assets/{select-BfZ3SCTM.js → select-Cj5Nw43g.js} +1 -1
- package/dist/dashboard/assets/select-Cj5Nw43g.js.gz +0 -0
- package/dist/dashboard/assets/settings-BAFhDgX8.js +1 -0
- package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
- package/dist/dashboard/assets/{stack-B1w5BM0u.js → stack-EMrOMt4I.js} +1 -1
- package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
- package/dist/dashboard/assets/{state-DhZBfWgx.js → state-CWoo7ty5.js} +1 -1
- package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
- package/dist/dashboard/assets/{switch-yD7D99Lg.js → switch-CCjT6IkF.js} +1 -1
- package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-EDFRkn1i.js → useMutation-DjkLHUcE.js} +1 -1
- package/dist/dashboard/assets/useMutation-DjkLHUcE.js.gz +0 -0
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +55 -54
- package/migrations/full-postgres/0024_add_pool_provider_cooldowns.sql +12 -0
- package/migrations/full-postgres/0025_add_pool_random_strategy.sql +3 -0
- package/migrations/lite-sqlite3/0024_add_pool_provider_cooldowns.sql +12 -0
- package/migrations/lite-sqlite3/0025_add_pool_random_strategy.sql +20 -0
- package/package.json +1 -1
- package/scripts/cli/console-menu.ts +5 -2
- package/scripts/cli/tray.ts +21 -6
- package/src/boot/app.ts +24 -62
- package/src/boot/dependencies.ts +732 -750
- package/src/config/cooldowns.ts +16 -0
- package/src/config/providers.ts +13 -1
- package/src/config/resources.ts +13 -80
- package/src/config/security.ts +2 -38
- package/src/config/spec.ts +16 -23
- package/src/console/console-router.ts +7 -7
- package/src/console/domain-registration.ts +19 -12
- package/src/console/providers/catalog/catalog-projections.ts +2 -6
- package/src/console/providers/catalog/contracts.ts +19 -0
- package/src/console/providers/catalog/provider-operations.ts +38 -0
- package/src/console/providers/catalog/routes.ts +14 -0
- package/src/console/providers/catalog/store-helpers.ts +326 -0
- package/src/console/providers/catalog/store.ts +1292 -1563
- package/src/console/quota/account-quota-global.ts +2 -2
- package/src/console/quota/account-quota-shared.ts +1 -1
- package/src/console/quota/account-quota-tenant.ts +35 -12
- package/src/console/quota/quota-view.ts +2 -2
- package/src/console/remote-support/contracts.ts +3 -1
- package/src/console/remote-support/service.ts +115 -6
- package/src/console/routing/pools/contracts.ts +41 -1
- package/src/console/routing/pools/operations.ts +183 -4
- package/src/console/routing/pools/relay-deploy.ts +17 -4
- package/src/console/routing/pools/routes.ts +30 -0
- package/src/console/routing/pools/store.ts +98 -8
- package/src/main.ts +16 -2
- package/src/network/outbound-fetch.ts +226 -365
- package/src/network/pool/agent.ts +8 -0
- package/src/network/pool/pool-state.ts +7 -0
- package/src/network/pool/selector.ts +110 -2
- package/src/network/pool-cooldown-store.ts +252 -0
- package/src/network/pool-health-machine.ts +5 -3
- package/src/network/pool-health.ts +36 -9
- package/src/observability/event-query.ts +57 -0
- package/src/observability/metrics.ts +15 -5
- package/src/observability/runtime-metrics.ts +30 -15
- package/src/persistence/health-event-flush.ts +2 -0
- package/src/persistence/schema.ts +19 -0
- package/src/persistence/usage-flush.ts +8 -3
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/dsml.ts +377 -0
- package/src/protocol/gateway-error.ts +0 -1
- package/src/{providers/provider-reasoning.ts → protocol/reasoning.ts} +10 -9
- package/src/protocol/request/chat.ts +7 -7
- package/src/protocol/request/codex.ts +2 -2
- package/src/protocol/request/gemini.ts +1 -1
- package/src/protocol/request/messages.ts +6 -6
- package/src/protocol/request/responses.ts +7 -7
- package/src/protocol/response/dsml.ts +12 -133
- package/src/{transport → protocol}/translation/attachment-integrity.ts +2 -2
- package/src/{transport → protocol}/translation/cache-controls.ts +1 -1
- package/src/{transport → protocol}/translation/capabilities.ts +2 -2
- package/src/{transport → protocol}/translation/normalize.ts +1 -1
- package/src/{transport → protocol}/translation/quirks.ts +1 -1
- package/src/{transport → protocol}/translation/search.ts +1 -1
- package/src/{transport → protocol}/translation/thinking.ts +23 -1
- package/src/{transport → protocol}/translation/tool-id.ts +1 -1
- package/src/{transport → protocol}/translation/tool-repair.ts +2 -2
- package/src/protocol/upstream-parsing.ts +176 -0
- package/src/providers/adapters/compatible-adapter.ts +11 -2
- package/src/providers/authentication/oauth-refresh-service.ts +9 -5
- package/src/providers/default-registry.ts +21 -5
- package/src/providers/discovery/probe-phases.ts +16 -3
- package/src/providers/discovery/probing-service.ts +4 -1
- package/src/providers/integrations/anthropic.ts +1 -1
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -4
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +141 -8
- package/src/providers/integrations/buddy/buddy-checkin.ts +5 -1
- package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -82
- package/src/providers/integrations/buddy/buddy-identity.ts +25 -0
- package/src/providers/integrations/buddy/buddy-server-tools.ts +240 -0
- package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +36 -0
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +6 -31
- package/src/providers/integrations/buddy/codebuddy/provider.ts +2 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +19 -4
- package/src/providers/integrations/buddy/turing-device-token.ts +262 -0
- package/src/providers/integrations/buddy/workbuddy/provider.ts +2 -0
- package/src/providers/integrations/buddy/workbuddy/shared.ts +56 -3
- package/src/providers/integrations/claude/claude.ts +1 -1
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +1 -1
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex.ts +1 -1
- package/src/providers/integrations/commandcode/commandcode.ts +134 -104
- package/src/providers/integrations/commandcode/discovery.ts +6 -5
- package/src/providers/integrations/factory/factory.ts +1 -1
- package/src/providers/integrations/github/github.ts +1 -1
- package/src/providers/integrations/grok/grok.ts +1 -1
- package/src/providers/integrations/inception/provider.ts +91 -0
- package/src/providers/integrations/inferhub.ts +1 -1
- package/src/providers/integrations/kiro/kiro-request.ts +1 -1
- package/src/providers/integrations/mistral.ts +193 -19
- package/src/providers/integrations/opencode/fingerprint.ts +19 -2
- package/src/providers/integrations/opencode/prompt.ts +111 -0
- package/src/providers/integrations/opencode/provider.ts +101 -23
- package/src/providers/integrations/opencode/tool-definitions.ts +4 -4
- package/src/providers/integrations/qoder/qoder-checkin.ts +303 -0
- package/src/providers/integrations/qoder/qoder.ts +1641 -884
- package/src/providers/integrations/shared/install-id.ts +2 -1
- package/src/providers/integrations/trae/trae-cache.ts +110 -0
- package/src/providers/integrations/trae/trae-oauth.ts +29 -4
- package/src/providers/integrations/trae/trae-protocol.ts +2 -1
- package/src/providers/integrations/trae/trae.ts +106 -23
- package/src/providers/operations/account-error-classification.ts +1660 -0
- package/src/providers/operations/account-health-service.ts +621 -2097
- package/src/providers/operations/account-reset-service.ts +2 -0
- package/src/providers/provider-contracts.ts +0 -2
- package/src/providers/provider-metadata.ts +25 -4
- package/src/providers/provider-probe.ts +2 -2
- package/src/{console → providers}/quota/cache.ts +1 -1
- package/src/{console → providers}/quota/refresh.ts +5 -5
- package/src/security/abuse.ts +17 -0
- package/src/transport/dispatch/attempt-finalize.ts +114 -12
- package/src/transport/dispatch/attempt-loop.ts +3 -0
- package/src/transport/dispatch/empty-stream.ts +224 -217
- package/src/transport/dispatch/generation.ts +37 -55
- package/src/transport/dispatch/handler-deps.ts +32 -0
- package/src/transport/dispatch/leases.ts +9 -4
- package/src/transport/dispatch/proxy-request.ts +6 -30
- package/src/transport/dispatch/responses-compact.ts +22 -43
- package/src/transport/dispatch/streaming/finalize.ts +3 -0
- package/src/transport/dispatch/streaming/stream.ts +0 -8
- package/src/transport/dispatch/systemone.ts +22 -42
- package/src/transport/dispatch/token-count.ts +23 -39
- package/src/transport/dispatch/upstream.ts +1 -3
- package/src/transport/dispatch/websearch.ts +22 -41
- package/src/transport/failure-policy.ts +59 -178
- package/src/transport/guards/abuse-guard.ts +10 -0
- package/src/transport/guards/auth-guard.ts +0 -18
- package/src/transport/guards/error-lifecycle.ts +1 -1
- package/src/transport/guards/pipeline.ts +0 -6
- package/src/transport/guards/request-context.ts +18 -91
- package/src/transport/request/degradation.ts +20 -1
- package/src/transport/request/inflight.ts +4 -95
- package/src/transport/request/preparer.ts +6 -6
- package/src/transport/request/state.ts +66 -38
- package/src/transport/request/tenant-preferences.ts +1 -1
- package/src/transport/routing/route-catalog.ts +41 -31
- package/src/transport/routing/router.ts +2 -2
- package/src/transport/surface/messages/parse.ts +1 -1
- package/src/workers/buddy-growth-tasks.ts +346 -425
- package/src/workers/daily-checkin.ts +17 -6
- package/src/workers/quota-refresh-sweep.ts +2 -2
- package/src/workers/scheduler.ts +17 -1
- package/dist/dashboard/assets/BannedPage-Dskhyp0l.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage--SJhk7qQ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-C203VT-c.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BcS7kGG1.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-ChmiSLwO.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-ChmiSLwO.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-uujbBYwC.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-fKAWd-OQ.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-fKAWd-OQ.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-DoOUthbG.js +0 -1
- package/dist/dashboard/assets/LoginPage-DoOUthbG.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-CA1kLs45.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-C5Z-UBz1.js +0 -1
- package/dist/dashboard/assets/OverviewPage-C5Z-UBz1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CFu1qGcT.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-CFu1qGcT.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CnlJZbxF.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-CnlJZbxF.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-B9mBTweh.js +0 -7
- package/dist/dashboard/assets/ProxyPage-B9mBTweh.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-BueSWX5D.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-B0x00MVY.js +0 -1
- package/dist/dashboard/assets/SettingsPage-B0x00MVY.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-DQ9oDRpi.js +0 -1
- package/dist/dashboard/assets/SetupPage-DQ9oDRpi.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-DrKeMcGN.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-qjuYtccc.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Be7aNviQ.js +0 -56
- package/dist/dashboard/assets/UsagePage-Be7aNviQ.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C23S9sgp.js.gz +0 -0
- package/dist/dashboard/assets/app-BUSiYL6F.css +0 -2
- package/dist/dashboard/assets/app-BUSiYL6F.css.gz +0 -0
- package/dist/dashboard/assets/assert-DU6qrMA_.js.gz +0 -0
- package/dist/dashboard/assets/badge-Bkz_-RrM.js.gz +0 -0
- package/dist/dashboard/assets/banner-C-7y3VKV.js.gz +0 -0
- package/dist/dashboard/assets/card-BOPBuBzD.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-BaFUuFFF.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-e-Mlk0FH.js.gz +0 -0
- package/dist/dashboard/assets/cog-CdWhsajs.js +0 -1
- package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
- package/dist/dashboard/assets/dialog-Iec_ywbD.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bs8MIIHc.js.gz +0 -0
- package/dist/dashboard/assets/entry-BRszm4_Z.js.gz +0 -0
- package/dist/dashboard/assets/entry-DOddwoc0.js.gz +0 -0
- package/dist/dashboard/assets/entry-DcobaKFu.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-BuDsrsPn.js.gz +0 -0
- package/dist/dashboard/assets/index-BeLRhsmt.js.gz +0 -0
- package/dist/dashboard/assets/inline-DToMICwl.js.gz +0 -0
- package/dist/dashboard/assets/input-WlyHWeG2.js.gz +0 -0
- package/dist/dashboard/assets/layout-DaJ5baJr.js.gz +0 -0
- package/dist/dashboard/assets/list-row-B3oSK13z.js.gz +0 -0
- package/dist/dashboard/assets/live-ta6GMb-8.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-BmYTmbAk.js +0 -1
- package/dist/dashboard/assets/model-bans-BmYTmbAk.js.gz +0 -0
- package/dist/dashboard/assets/mutation-g_fduiNw.js.gz +0 -0
- package/dist/dashboard/assets/numbers-Dulqgys5.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-UETqfytp.js.gz +0 -0
- package/dist/dashboard/assets/routing-BPUo-W8d.js.gz +0 -0
- package/dist/dashboard/assets/select-BfZ3SCTM.js.gz +0 -0
- package/dist/dashboard/assets/settings--3hxSyry.js +0 -1
- package/dist/dashboard/assets/settings--3hxSyry.js.gz +0 -0
- package/dist/dashboard/assets/stack-B1w5BM0u.js.gz +0 -0
- package/dist/dashboard/assets/state-DhZBfWgx.js.gz +0 -0
- package/dist/dashboard/assets/switch-yD7D99Lg.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-EDFRkn1i.js.gz +0 -0
- package/src/console/admin/model-abuse/contracts.ts +0 -38
- package/src/console/admin/model-abuse/routes.ts +0 -97
- package/src/security/model-abuse.ts +0 -704
- package/src/transport/guards/concurrency-guard.ts +0 -125
- /package/dist/dashboard/assets/{app-MdVfwraB.js → app-BaWd0puM.js} +0 -0
- /package/dist/dashboard/assets/{app-MdVfwraB.js.gz → app-BaWd0puM.js.gz} +0 -0
|
@@ -1,101 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The registry is *owned* by the `ProxyRequestStateStore` (`state.ts`), which
|
|
8
|
-
* is also the one place that evicts a request, so a flight cannot outlive its
|
|
9
|
-
* state. A separate process-global counter alongside the store's
|
|
10
|
-
* `liveControllers` map would be a second registry able to disagree with it: a
|
|
11
|
-
* flight the store had already torn down would stay counted there forever.
|
|
12
|
-
*
|
|
13
|
-
* The store hands each entry an `expiresAtMs` (the request's hard deadline). A
|
|
14
|
-
* periodic backstop sweep reads `overdue()` and force-releases any flight whose
|
|
15
|
-
* deadline has passed, so the gauge settles even if an abort path never fires.
|
|
16
|
-
*
|
|
17
|
-
* Pub/sub lets the console push the live snapshot over SSE instead of polling.
|
|
18
|
-
* Process-local: each gateway instance reports its own flights.
|
|
2
|
+
* The live "in flight" snapshot shape, shared by the store, the console live
|
|
3
|
+
* domain, and the dashboard. Derived from the request state store's own
|
|
4
|
+
* `liveControllers` map — the single registry that already owns a request's
|
|
5
|
+
* lifetime — so the gauge cannot disagree with what is actually running.
|
|
19
6
|
*/
|
|
20
|
-
import { metrics } from "../../observability/metrics";
|
|
21
|
-
|
|
22
7
|
export interface InFlightSnapshot {
|
|
23
8
|
readonly inFlight: number;
|
|
24
9
|
readonly uniqueIps: number;
|
|
25
10
|
}
|
|
26
|
-
|
|
27
|
-
interface Flight {
|
|
28
|
-
readonly clientIp: string;
|
|
29
|
-
/** Hard deadline after which the backstop sweep releases this flight. */
|
|
30
|
-
expiresAtMs: number;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface InFlightRegistry {
|
|
34
|
-
/** Register a flight once its dispatch leases are acquired. Idempotent per id. */
|
|
35
|
-
track(requestId: string, clientIp: string, expiresAtMs: number): void;
|
|
36
|
-
/** Release a flight. Idempotent; an unknown id is a no-op. */
|
|
37
|
-
untrack(requestId: string): void;
|
|
38
|
-
/** Re-arm a flight's hard deadline (streaming swaps the pre-stream budget). */
|
|
39
|
-
extend(requestId: string, expiresAtMs: number): void;
|
|
40
|
-
snapshot(): InFlightSnapshot;
|
|
41
|
-
count(): number;
|
|
42
|
-
/** Ids whose deadline plus the sweep grace has elapsed — the backstop's worklist. */
|
|
43
|
-
overdue(nowMs: number, graceMs: number): readonly string[];
|
|
44
|
-
subscribe(listener: (snapshot: InFlightSnapshot) => void): () => void;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function createInFlightRegistry(): InFlightRegistry {
|
|
48
|
-
const flights = new Map<string, Flight>();
|
|
49
|
-
const listeners = new Set<(snapshot: InFlightSnapshot) => void>();
|
|
50
|
-
|
|
51
|
-
const snapshot = (): InFlightSnapshot => {
|
|
52
|
-
let uniqueIps = 0;
|
|
53
|
-
const seen = new Set<string>();
|
|
54
|
-
for (const flight of flights.values()) {
|
|
55
|
-
if (!seen.has(flight.clientIp)) {
|
|
56
|
-
seen.add(flight.clientIp);
|
|
57
|
-
uniqueIps += 1;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return { inFlight: flights.size, uniqueIps };
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const publish = (): void => {
|
|
64
|
-
const current = snapshot();
|
|
65
|
-
metrics.proxy_in_flight.set(current.inFlight);
|
|
66
|
-
for (const listener of listeners) listener(current);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
track(requestId, clientIp, expiresAtMs) {
|
|
71
|
-
flights.set(requestId, { clientIp: clientIp.length > 0 ? clientIp : "unknown", expiresAtMs });
|
|
72
|
-
publish();
|
|
73
|
-
},
|
|
74
|
-
untrack(requestId) {
|
|
75
|
-
if (!flights.delete(requestId)) return;
|
|
76
|
-
publish();
|
|
77
|
-
},
|
|
78
|
-
extend(requestId, expiresAtMs) {
|
|
79
|
-
const flight = flights.get(requestId);
|
|
80
|
-
if (flight === undefined) return;
|
|
81
|
-
flight.expiresAtMs = expiresAtMs;
|
|
82
|
-
},
|
|
83
|
-
snapshot,
|
|
84
|
-
count() {
|
|
85
|
-
return flights.size;
|
|
86
|
-
},
|
|
87
|
-
overdue(nowMs, graceMs) {
|
|
88
|
-
const ids: string[] = [];
|
|
89
|
-
for (const [requestId, flight] of flights) {
|
|
90
|
-
if (nowMs >= flight.expiresAtMs + graceMs) ids.push(requestId);
|
|
91
|
-
}
|
|
92
|
-
return ids;
|
|
93
|
-
},
|
|
94
|
-
subscribe(listener) {
|
|
95
|
-
listeners.add(listener);
|
|
96
|
-
return () => {
|
|
97
|
-
listeners.delete(listener);
|
|
98
|
-
};
|
|
99
|
-
},
|
|
100
|
-
};
|
|
101
|
-
}
|
|
@@ -5,14 +5,14 @@ import type { ApiKeyAdmissionService } from "../../security/admission/service";
|
|
|
5
5
|
import type { RouteCandidate as RouteCandidate, InMemoryRouteSnapshotService, RoutePlan } from "../routing/route-model";
|
|
6
6
|
import type { RouteContinuationAffinity } from "../routing/route-model";
|
|
7
7
|
import { resolveAliasTarget, type RoutingEngine } from "../routing/router";
|
|
8
|
-
import { projectForRoute, routeCapabilitiesFor } from "
|
|
9
|
-
import type { RequiredCapability } from "
|
|
8
|
+
import { projectForRoute, routeCapabilitiesFor } from "../../protocol/translation/capabilities";
|
|
9
|
+
import type { RequiredCapability } from "../../protocol/translation/capabilities";
|
|
10
10
|
import { isModelAllowed, type ResolvedApiKey } from "../../security/api-key-auth";
|
|
11
11
|
import { allowsCliToolMappings } from "../../security/cli-client-fingerprint";
|
|
12
|
-
import { dropIncompleteToolRounds, repairRequestToolCalls } from "
|
|
13
|
-
import { sanitizeRequestToolIds } from "
|
|
14
|
-
import { dropCorruptAttachments } from "
|
|
15
|
-
import { parseThinkingSuffix, withThinkingSuffixIntent } from "
|
|
12
|
+
import { dropIncompleteToolRounds, repairRequestToolCalls } from "../../protocol/translation/tool-repair";
|
|
13
|
+
import { sanitizeRequestToolIds } from "../../protocol/translation/tool-id";
|
|
14
|
+
import { dropCorruptAttachments } from "../../protocol/translation/attachment-integrity";
|
|
15
|
+
import { parseThinkingSuffix, withThinkingSuffixIntent } from "../../protocol/translation/thinking";
|
|
16
16
|
import { nativeServicePathFor } from "../contracts";
|
|
17
17
|
import { log } from "../../observability/logger";
|
|
18
18
|
import { BUDDY_PROVIDER_IDS } from "../../providers/provider-metadata";
|
|
@@ -5,8 +5,8 @@ import type { ResolvedApiKey } from "../../security/api-key-auth";
|
|
|
5
5
|
import type { PreparedProxyRequest } from "./preparer";
|
|
6
6
|
import type { PayloadCaptureState, TelemetryPayloadCapture } from "../../observability/payload-capture";
|
|
7
7
|
import type { TelemetryPayloadDepth, TelemetryPayloadMode } from "../../console/settings/contracts";
|
|
8
|
-
import { createInFlightRegistry, type InFlightSnapshot } from "./inflight";
|
|
9
8
|
import { log } from "../../observability/logger";
|
|
9
|
+
import type { InFlightSnapshot } from "./inflight";
|
|
10
10
|
import { fastPathname } from "../pathname";
|
|
11
11
|
|
|
12
12
|
export interface ProxyRequestOutcome {
|
|
@@ -182,15 +182,39 @@ export interface RequestTracker {
|
|
|
182
182
|
* shutdown coordination, which waits on tracked requests (or aborts them
|
|
183
183
|
* past the grace window) instead of relying on connection close events.
|
|
184
184
|
*/
|
|
185
|
+
/**
|
|
186
|
+
* Minimal pub/sub over a store's snapshot. Polling already re-reads
|
|
187
|
+
* `inFlightSnapshot()`, so this only pushes the same derived value to the
|
|
188
|
+
* console's SSE stream; no second registry behind it.
|
|
189
|
+
*/
|
|
190
|
+
function subscribeInFlightSnapshot(
|
|
191
|
+
store: { inFlightSnapshot(): InFlightSnapshot },
|
|
192
|
+
listener: (snapshot: InFlightSnapshot) => void,
|
|
193
|
+
): () => void {
|
|
194
|
+
const timers = new Set<ReturnType<typeof setTimeout>>();
|
|
195
|
+
const push = (): void => listener(store.inFlightSnapshot());
|
|
196
|
+
push();
|
|
197
|
+
const handle = setInterval(push, 1_000);
|
|
198
|
+
(handle as unknown as { unref?: () => void })?.unref?.();
|
|
199
|
+
return () => {
|
|
200
|
+
clearInterval(handle);
|
|
201
|
+
for (const t of timers) clearTimeout(t);
|
|
202
|
+
timers.clear();
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
185
206
|
export class ProxyRequestStateStore {
|
|
186
207
|
private readonly states = new WeakMap<Request, ProxyRequestState>();
|
|
187
208
|
private readonly liveControllers = new Map<string, AbortController>();
|
|
188
209
|
/**
|
|
189
|
-
* The in-flight gauge
|
|
190
|
-
*
|
|
191
|
-
*
|
|
210
|
+
* The in-flight gauge is derived from the same map that owns a request's
|
|
211
|
+
* lifetime. There is no second registry: a count that disagreed with
|
|
212
|
+
* `liveControllers` was the ghost — entries that outlived the request they
|
|
213
|
+
* described. The deadline each flight last armed is kept alongside, so the
|
|
214
|
+
* backstop sweep still finds requests whose abort path never fired.
|
|
192
215
|
*/
|
|
193
|
-
private readonly
|
|
216
|
+
private readonly inFlightDeadlines = new Map<string, number>();
|
|
217
|
+
private readonly inFlightIps = new Map<string, string>();
|
|
194
218
|
|
|
195
219
|
constructor(private readonly tracker?: RequestTracker) {}
|
|
196
220
|
|
|
@@ -199,43 +223,38 @@ export class ProxyRequestStateStore {
|
|
|
199
223
|
}
|
|
200
224
|
|
|
201
225
|
inFlightSnapshot(): InFlightSnapshot {
|
|
202
|
-
|
|
226
|
+
let uniqueIps = 0;
|
|
227
|
+
const seen = new Set<string>();
|
|
228
|
+
for (const ip of this.inFlightIps.values()) {
|
|
229
|
+
if (!seen.has(ip)) {
|
|
230
|
+
seen.add(ip);
|
|
231
|
+
uniqueIps += 1;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return { inFlight: this.inFlightDeadlines.size, uniqueIps };
|
|
203
235
|
}
|
|
204
236
|
|
|
205
237
|
/** Live flight count for this store. */
|
|
206
238
|
inFlightCount(): number {
|
|
207
|
-
return this.
|
|
239
|
+
return this.inFlightDeadlines.size;
|
|
208
240
|
}
|
|
209
241
|
|
|
210
242
|
subscribeInFlight(listener: (snapshot: InFlightSnapshot) => void): () => void {
|
|
211
|
-
return this
|
|
243
|
+
return subscribeInFlightSnapshot(this, listener);
|
|
212
244
|
}
|
|
213
245
|
|
|
214
246
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* that neither pulls, cancels, nor aborts
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Releases every flight past its deadline. Two tiers, because aborting the
|
|
226
|
-
* controller unwinds the fetch but only *releases* the flight if some path
|
|
227
|
-
* observes the abort:
|
|
228
|
-
*
|
|
229
|
-
* - Past `expiresAtMs + graceMs`: abort the controller, which unblocks a
|
|
230
|
-
* paused read and fires the release in `dispatch/proxy-request`.
|
|
231
|
-
* - Past `expiresAtMs + hardGraceMs`: the abort did not release it, so
|
|
232
|
-
* force-drop the gauge entry. The fetch is already torn down by the abort,
|
|
233
|
-
* so leaving the entry would only mean a permanently wrong number — the
|
|
234
|
-
* exact defect this backstop exists to end. Logged, never silent.
|
|
247
|
+
* Releases every flight past its deadline. Aborting the controller unwinds
|
|
248
|
+
* the fetch and lets the request's own `cleanup` run, which drops the
|
|
249
|
+
* flight's entry with it. A request nothing observes — a half-closed socket
|
|
250
|
+
* that neither pulls, cancels, nor aborts — never runs that cleanup, so
|
|
251
|
+
* after a further grace window the sweep drops the entry itself: the fetch
|
|
252
|
+
* is already torn down by the abort, and a permanently wrong number is the
|
|
253
|
+
* exact defect this backstop exists to end. Logged, never silent.
|
|
235
254
|
*/
|
|
236
255
|
sweepOverdueInFlight(nowMs: number, graceMs: number, hardGraceMs: number): number {
|
|
237
|
-
const
|
|
238
|
-
|
|
256
|
+
for (const [requestId, deadline] of this.inFlightDeadlines) {
|
|
257
|
+
if (nowMs < deadline + graceMs) continue;
|
|
239
258
|
const controller = this.liveControllers.get(requestId);
|
|
240
259
|
try {
|
|
241
260
|
if (controller && !controller.signal.aborted) {
|
|
@@ -246,14 +265,19 @@ export class ProxyRequestStateStore {
|
|
|
246
265
|
} catch {
|
|
247
266
|
}
|
|
248
267
|
}
|
|
249
|
-
|
|
250
|
-
for (const requestId of
|
|
268
|
+
let forced = 0;
|
|
269
|
+
for (const [requestId, deadline] of this.inFlightDeadlines) {
|
|
270
|
+
if (nowMs < deadline + hardGraceMs) continue;
|
|
271
|
+
this.inFlightDeadlines.delete(requestId);
|
|
272
|
+
this.inFlightIps.delete(requestId);
|
|
273
|
+
forced += 1;
|
|
274
|
+
}
|
|
275
|
+
if (forced > 0) {
|
|
251
276
|
log.error(
|
|
252
|
-
`[inflight-backstop] force-releasing
|
|
277
|
+
`[inflight-backstop] force-releasing ${forced} flight(s): abort did not release them within ${hardGraceMs}ms`,
|
|
253
278
|
);
|
|
254
|
-
this.inFlight.untrack(requestId);
|
|
255
279
|
}
|
|
256
|
-
return
|
|
280
|
+
return forced;
|
|
257
281
|
}
|
|
258
282
|
|
|
259
283
|
abortAll(reason?: unknown): void {
|
|
@@ -325,7 +349,8 @@ export class ProxyRequestStateStore {
|
|
|
325
349
|
startProviderFlight: () => {
|
|
326
350
|
if (cleaned || providerFlightStarted) return;
|
|
327
351
|
providerFlightStarted = true;
|
|
328
|
-
this.
|
|
352
|
+
this.inFlightDeadlines.set(requestId, state.deadlineMs);
|
|
353
|
+
this.inFlightIps.set(requestId, state.clientIdentity?.address || "unknown");
|
|
329
354
|
},
|
|
330
355
|
releaseIngressBody: () => {
|
|
331
356
|
state.ingressBody = undefined;
|
|
@@ -342,7 +367,7 @@ export class ProxyRequestStateStore {
|
|
|
342
367
|
// request that legitimately extends its budget must move the flight's
|
|
343
368
|
// deadline too — otherwise the sweep would force-release a healthy
|
|
344
369
|
// long stream the moment the pre-stream budget elapsed.
|
|
345
|
-
this.
|
|
370
|
+
if (providerFlightStarted) this.inFlightDeadlines.set(requestId, state.deadlineMs);
|
|
346
371
|
armDeadline(ms);
|
|
347
372
|
},
|
|
348
373
|
cleanup: () => {
|
|
@@ -351,7 +376,10 @@ export class ProxyRequestStateStore {
|
|
|
351
376
|
// Every step is guarded: one throwing cleanup must not skip the
|
|
352
377
|
// remaining cleanups, the abort, or the map eviction (leak).
|
|
353
378
|
try {
|
|
354
|
-
if (providerFlightStarted)
|
|
379
|
+
if (providerFlightStarted) {
|
|
380
|
+
this.inFlightDeadlines.delete(state.requestId);
|
|
381
|
+
this.inFlightIps.delete(state.requestId);
|
|
382
|
+
}
|
|
355
383
|
} catch {
|
|
356
384
|
}
|
|
357
385
|
try {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import type { CartethyiaDatabase } from "../../persistence/db-handle";
|
|
11
11
|
import type { CanonicalRequest } from "../../protocol/canonical-model";
|
|
12
12
|
import type { PreparedProxyRequest } from "./preparer";
|
|
13
|
-
import { normalizeThinkingConfig } from "
|
|
13
|
+
import { normalizeThinkingConfig } from "../../protocol/translation/thinking";
|
|
14
14
|
import { compressRequest } from "./rtk/compress-request";
|
|
15
15
|
import { preferencesReaderFor } from "../../persistence/tenant-preferences";
|
|
16
16
|
import { resolveUpstreamTimeoutMs } from "../../config/timeouts";
|
|
@@ -741,43 +741,53 @@ class RouteCatalogRepository {
|
|
|
741
741
|
: {}),
|
|
742
742
|
};
|
|
743
743
|
if (account.status === "cooldown") {
|
|
744
|
-
//
|
|
745
|
-
//
|
|
746
|
-
//
|
|
744
|
+
// A row that still says `cooldown` stays excluded until the sweeper
|
|
745
|
+
// flips it back to `active`. An *expired* deadline used to read as
|
|
746
|
+
// healthy here (the comment below's "pure read" reasoning), which let
|
|
747
|
+
// routing redial the account in the window between the deadline
|
|
748
|
+
// elapsing and the next 30s sweep — reproducing the refusal that
|
|
749
|
+
// cooled it and logging a fresh `cooldown → cooldown` row each time
|
|
750
|
+
// (the operator's "still hit a cooled-down account" report). The
|
|
751
|
+
// sweep is the only exit from `cooldown`; until it runs the row is
|
|
752
|
+
// not proof the account can serve.
|
|
747
753
|
//
|
|
748
754
|
// `forceDisableCooldown` skips the exclusion entirely. The cooldown
|
|
749
755
|
// is still real and still recorded — it simply stops deciding
|
|
750
756
|
// routing. That is what makes the setting reversible: nothing was
|
|
751
757
|
// written, so turning it off needs no cleanup, and Health still
|
|
752
758
|
// reports the truth about the account.
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
759
|
+
const overrideActive =
|
|
760
|
+
rowTenantId === null
|
|
761
|
+
? anyTenantOverrides
|
|
762
|
+
: cooldownOverrideTenants.has(rowTenantId);
|
|
763
|
+
const accountDeadline = account.cooldownUntil;
|
|
764
|
+
const unexpired =
|
|
765
|
+
accountDeadline !== null && accountDeadline.getTime() > Date.now();
|
|
766
|
+
if (overrideActive) {
|
|
767
|
+
// The account is still cooling — this only stops it from being
|
|
768
|
+
// excluded. `plan()` reads `cooldown_until` to answer the
|
|
769
|
+
// all-cooling case, so it stays populated either way.
|
|
770
|
+
//
|
|
771
|
+
// Neither `health_status` nor `cooldown_kind` is set: the
|
|
772
|
+
// evaluator excludes a hard cooldown on `health_status ===
|
|
773
|
+
// "cooldown"` alone, so stamping it here would keep excluding
|
|
774
|
+
// the very accounts the override exists to reach — a spent quota
|
|
775
|
+
// or a policy block, which are the ones an operator actually
|
|
776
|
+
// wants to override.
|
|
777
|
+
if (unexpired) candidate.cooldown_until = accountDeadline!.getTime();
|
|
778
|
+
} else {
|
|
779
|
+
candidate.health_status = "cooldown";
|
|
780
|
+
candidate.cooldown_kind = hardCooldownCategory(account.lastErrorCategory)
|
|
781
|
+
? "hard"
|
|
782
|
+
: "soft";
|
|
783
|
+
// The deadline rides with the exclusion it explains. `plan()`
|
|
784
|
+
// reads it to answer the all-cooling case with the real reset
|
|
785
|
+
// instead of a bare 429, so a client backs off for the window
|
|
786
|
+
// that is actually open rather than inventing one. An expired
|
|
787
|
+
// deadline carries no reset — the sweep is about to recover the
|
|
788
|
+
// row, and quoting a past instant would tell the client to retry
|
|
789
|
+
// "immediately" for a wait that is already over.
|
|
790
|
+
if (unexpired) candidate.cooldown_until = accountDeadline!.getTime();
|
|
781
791
|
}
|
|
782
792
|
}
|
|
783
793
|
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
candidateSupportsRequest,
|
|
23
23
|
type RequiredCapability,
|
|
24
|
-
} from "
|
|
24
|
+
} from "../../protocol/translation/capabilities";
|
|
25
25
|
import { planAllowsCandidate } from "./plan-gate";
|
|
26
26
|
import { InMemoryAdmissionController, admissionKey } from "./admission";
|
|
27
27
|
import { ReservationManager } from "./reservations";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
routeCandidateIndex,
|
|
33
33
|
} from "./candidate-index";
|
|
34
34
|
import { totalRemainingCredit, totalRemainingPercent, type ProviderQuotaWindow } from "../../providers/quota/quota-contracts";
|
|
35
|
-
import { getCachedQuotaEntry, quotaLens } from "../../
|
|
35
|
+
import { getCachedQuotaEntry, quotaLens } from "../../providers/quota/cache";
|
|
36
36
|
import type { RedisClient } from "../../persistence/redis";
|
|
37
37
|
import { sharedClaudeSlowLanes } from "../../providers/integrations/claude/claude-slow-lane";
|
|
38
38
|
|
|
@@ -6,7 +6,7 @@ import { parseToolDefinition } from "../dialects";
|
|
|
6
6
|
import { canContainToolResult } from "../../../protocol/canonical-model";
|
|
7
7
|
import { MessagesLedgerError } from "./errors";
|
|
8
8
|
import { finiteNumber, stringValue } from "../../../protocol/codecs";
|
|
9
|
-
import { LEVEL_TO_BUDGET } from "
|
|
9
|
+
import { LEVEL_TO_BUDGET } from "../../../protocol/translation/thinking";
|
|
10
10
|
|
|
11
11
|
export interface MessagesParseOptions {
|
|
12
12
|
/** Explicit Claude model generation (for example `4.6` or `4.7`). */
|