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
|
@@ -87,6 +87,36 @@ export function createNetworkPoolRoutes(config: NetworkPoolConfig): Elysia {
|
|
|
87
87
|
.delete("/:poolId", async ({ request, params }) => {
|
|
88
88
|
return await factory.deletePool(config.accessResolver(request), params.poolId);
|
|
89
89
|
})
|
|
90
|
+
.post(
|
|
91
|
+
"/bulk/create",
|
|
92
|
+
{ body: t.Object({ targets: t.Array(createPoolBody, { minItems: 1, maxItems: MAX_BATCH_PROBE_TARGETS }) }) },
|
|
93
|
+
async ({ request, body, set }) => {
|
|
94
|
+
set.status = 200;
|
|
95
|
+
return await factory.createPoolBatch(
|
|
96
|
+
config.accessResolver(request),
|
|
97
|
+
body.targets as CreateNetworkPoolRequest[],
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
.post(
|
|
102
|
+
"/bulk/delete",
|
|
103
|
+
{ body: t.Object({ ids: t.Array(t.String(), { minItems: 1 }) }) },
|
|
104
|
+
async ({ request, body }) => {
|
|
105
|
+
return await factory.deletePoolBatch(config.accessResolver(request), body.ids);
|
|
106
|
+
},
|
|
107
|
+
)
|
|
108
|
+
.post(
|
|
109
|
+
"/bulk/status",
|
|
110
|
+
{
|
|
111
|
+
body: t.Object({
|
|
112
|
+
ids: t.Array(t.String(), { minItems: 1 }),
|
|
113
|
+
status: literalUnion(POOL_STATUSES),
|
|
114
|
+
}),
|
|
115
|
+
},
|
|
116
|
+
async ({ request, body }) => {
|
|
117
|
+
return await factory.setPoolStatusBatch(config.accessResolver(request), body.ids, body.status);
|
|
118
|
+
},
|
|
119
|
+
)
|
|
90
120
|
.get("/:poolId/health-events", async ({ request, params }) => {
|
|
91
121
|
return await factory.listPoolHealthEvents(config.accessResolver(request), params.poolId);
|
|
92
122
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Drizzle-backed console persistence for network pools.
|
|
2
|
-
import { and, asc, eq, sql } from "drizzle-orm";
|
|
2
|
+
import { and, asc, eq, inArray, sql } from "drizzle-orm";
|
|
3
3
|
import type { CartethyiaDatabase } from "../../../persistence/db-handle";
|
|
4
4
|
import { networkPools, poolRoutingSettings } from "../../../persistence/schema";
|
|
5
5
|
import {
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
recoverNetworkPool,
|
|
35
35
|
} from "../../../network/pool-health-machine";
|
|
36
36
|
import { drainPoolByteDelta, recordPoolBytes } from "../../../network/pool/byte-accounting";
|
|
37
|
+
import * as poolCooldownStore from "../../../network/pool-cooldown-store";
|
|
37
38
|
// Cloudflare's trace endpoint answers with plain `key=value` lines including
|
|
38
39
|
// `ip=`, the address the request egressed from. Dialing it THROUGH the pool
|
|
39
40
|
// therefore reports the pool's public address — which is what an operator
|
|
@@ -255,7 +256,7 @@ export class DrizzleNetworkPoolStore implements NetworkPoolStore {
|
|
|
255
256
|
reason: error instanceof Error ? error.message : "Failed to build pool agent",
|
|
256
257
|
};
|
|
257
258
|
}
|
|
258
|
-
return await this.dialProviderProbe(agent, poolId, providerId, poolId);
|
|
259
|
+
return await this.dialProviderProbe(agent, poolId, providerId, poolId, rec.endpoint);
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
/**
|
|
@@ -295,13 +296,19 @@ export class DrizzleNetworkPoolStore implements NetworkPoolStore {
|
|
|
295
296
|
*
|
|
296
297
|
* `label` is what the result reports (a pool id, or a pasted endpoint that
|
|
297
298
|
* has no row yet). `poolId` is the row to bank the verdict on — omitted for
|
|
298
|
-
* an ad-hoc probe, because there is nothing to attach it to.
|
|
299
|
+
* an ad-hoc probe, because there is nothing to attach it to. `endpoint` is
|
|
300
|
+
* the address the verdict describes, recorded beside it so
|
|
301
|
+
* `storedProviderProbe` can verify it later — it must be the pool's *current
|
|
302
|
+
* endpoint*, never the label: a verdict banked against the pool id fails the
|
|
303
|
+
* endpoint comparison on read and is hidden as "never probed", which is
|
|
304
|
+
* exactly the disappearing-verdict report.
|
|
299
305
|
*/
|
|
300
306
|
private async dialProviderProbe(
|
|
301
307
|
agent: PoolAgent,
|
|
302
308
|
label: string,
|
|
303
309
|
providerId: string,
|
|
304
310
|
poolId?: string,
|
|
311
|
+
endpoint?: string,
|
|
305
312
|
): Promise<PoolProviderProbeResult> {
|
|
306
313
|
const spec = await buildProviderProbeRequest(providerId);
|
|
307
314
|
if (!spec) {
|
|
@@ -343,7 +350,7 @@ export class DrizzleNetworkPoolStore implements NetworkPoolStore {
|
|
|
343
350
|
latencyMs,
|
|
344
351
|
...(verdict.reason === undefined ? {} : { reason: verdict.reason }),
|
|
345
352
|
};
|
|
346
|
-
if (poolId !== undefined) await this.persistProviderProbe(poolId, label, result);
|
|
353
|
+
if (poolId !== undefined) await this.persistProviderProbe(poolId, endpoint ?? label, result);
|
|
347
354
|
return result;
|
|
348
355
|
}
|
|
349
356
|
|
|
@@ -403,12 +410,24 @@ export class DrizzleNetworkPoolStore implements NetworkPoolStore {
|
|
|
403
410
|
}
|
|
404
411
|
|
|
405
412
|
async create(record: NetworkPoolRecord): Promise<void> {
|
|
406
|
-
|
|
407
|
-
|
|
413
|
+
await this.createMany([record]).then(() => undefined);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Inserts every record in one statement.
|
|
418
|
+
*
|
|
419
|
+
* A batch import used to be one round trip per proxy, so a long paste took
|
|
420
|
+
* minutes and the dialog sat there while the operator waited. Drizzle emits a
|
|
421
|
+
* single multi-row INSERT, which makes the cost independent of the paste
|
|
422
|
+
* length.
|
|
423
|
+
*/
|
|
424
|
+
async createMany(records: readonly NetworkPoolRecord[]): Promise<number> {
|
|
425
|
+
if (records.length === 0) return 0;
|
|
426
|
+
const values = records.map((record) => ({
|
|
408
427
|
id: record.id,
|
|
409
428
|
tenantId: record.tenantId,
|
|
410
429
|
createdAt: new Date(record.createdAt),
|
|
411
|
-
kind,
|
|
430
|
+
kind: record.kind === "https" ? "http" : record.kind,
|
|
412
431
|
endpointConfig: {
|
|
413
432
|
endpoint: record.endpoint,
|
|
414
433
|
...(record.label ? { label: record.label } : {}),
|
|
@@ -423,7 +442,50 @@ export class DrizzleNetworkPoolStore implements NetworkPoolStore {
|
|
|
423
442
|
consecutiveFailures: 0,
|
|
424
443
|
...(record.quotaBytes !== undefined ? { quotaBytes: record.quotaBytes } : {}),
|
|
425
444
|
...(record.family !== undefined ? { family: record.family } : {}),
|
|
426
|
-
});
|
|
445
|
+
}));
|
|
446
|
+
await this.db.insert(networkPools).values(values);
|
|
447
|
+
return values.length;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Sets one status on every named pool in a single statement.
|
|
452
|
+
*
|
|
453
|
+
* Bulk enable/disable was a loop of per-row updates — one round trip each,
|
|
454
|
+
* and one snapshot invalidation each. A tenant-wide selection is exactly the
|
|
455
|
+
* case where that is felt.
|
|
456
|
+
*/
|
|
457
|
+
async updateManyStatus(
|
|
458
|
+
tenantId: string,
|
|
459
|
+
poolIds: readonly string[],
|
|
460
|
+
status: NetworkPoolRecord["status"],
|
|
461
|
+
): Promise<number> {
|
|
462
|
+
if (poolIds.length === 0) return 0;
|
|
463
|
+
const rows = await this.db
|
|
464
|
+
.update(networkPools)
|
|
465
|
+
.set({ status })
|
|
466
|
+
.where(
|
|
467
|
+
and(
|
|
468
|
+
eq(networkPools.tenantId, tenantId),
|
|
469
|
+
inArray(networkPools.id, [...poolIds]),
|
|
470
|
+
),
|
|
471
|
+
)
|
|
472
|
+
.returning({ id: networkPools.id });
|
|
473
|
+
return rows.length;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/** Deletes every named pool in one statement. */
|
|
477
|
+
async deleteMany(tenantId: string, poolIds: readonly string[]): Promise<number> {
|
|
478
|
+
if (poolIds.length === 0) return 0;
|
|
479
|
+
const rows = await this.db
|
|
480
|
+
.delete(networkPools)
|
|
481
|
+
.where(
|
|
482
|
+
and(
|
|
483
|
+
eq(networkPools.tenantId, tenantId),
|
|
484
|
+
inArray(networkPools.id, [...poolIds]),
|
|
485
|
+
),
|
|
486
|
+
)
|
|
487
|
+
.returning({ id: networkPools.id });
|
|
488
|
+
return rows.length;
|
|
427
489
|
}
|
|
428
490
|
|
|
429
491
|
async update(
|
|
@@ -513,6 +575,34 @@ export class DrizzleNetworkPoolStore implements NetworkPoolStore {
|
|
|
513
575
|
return listNetworkPoolHealthEvents(this.db, tenantId, poolId);
|
|
514
576
|
}
|
|
515
577
|
|
|
578
|
+
async dropProviderCooldownMarker(
|
|
579
|
+
tenantId: string,
|
|
580
|
+
poolId: string,
|
|
581
|
+
providerId: string,
|
|
582
|
+
onlyBlocked: boolean,
|
|
583
|
+
): Promise<void> {
|
|
584
|
+
if ((await this.get(tenantId, poolId)) === undefined) return;
|
|
585
|
+
await poolCooldownStore.dropProviderCooldownMarker(this.db, poolId, providerId, onlyBlocked);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
async dropAllProviderCooldownMarkers(
|
|
589
|
+
tenantId: string,
|
|
590
|
+
poolId: string,
|
|
591
|
+
): Promise<void> {
|
|
592
|
+
if ((await this.get(tenantId, poolId)) === undefined) return;
|
|
593
|
+
await poolCooldownStore.dropAllProviderCooldownMarkers(this.db, poolId);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
async recordProviderProbeCooldown(
|
|
597
|
+
tenantId: string,
|
|
598
|
+
poolId: string,
|
|
599
|
+
providerId: string,
|
|
600
|
+
marker: { until: number; reason: string; blocked?: boolean },
|
|
601
|
+
): Promise<void> {
|
|
602
|
+
if ((await this.get(tenantId, poolId)) === undefined) return;
|
|
603
|
+
await poolCooldownStore.recordProbeVerdict(this.db, poolId, providerId, marker);
|
|
604
|
+
}
|
|
605
|
+
|
|
516
606
|
async recover(tenantId: string, poolId: string): Promise<boolean> {
|
|
517
607
|
return recoverNetworkPool(this.db, tenantId, poolId);
|
|
518
608
|
}
|
package/src/main.ts
CHANGED
|
@@ -49,7 +49,6 @@ const app = boot
|
|
|
49
49
|
telemetryBuffer: boot.deps.telemetryBuffer,
|
|
50
50
|
resolveOAuthRefresher: boot.deps.resolveOAuthRefresher,
|
|
51
51
|
oauthRefreshService: boot.deps.oauthRefreshService,
|
|
52
|
-
modelStrikes: boot.deps.modelStrikes,
|
|
53
52
|
maxBodyBytes: resolveMaxBodyBytes(),
|
|
54
53
|
scheduledTasks: boot.deps.scheduledTasks,
|
|
55
54
|
// The sampler is constructed in the dependency graph and already
|
|
@@ -78,7 +77,6 @@ const app = boot
|
|
|
78
77
|
redis: boot.deps.redis,
|
|
79
78
|
oauthRefreshService: boot.deps.oauthRefreshService,
|
|
80
79
|
admissionService: boot.deps.admissionService,
|
|
81
|
-
modelStrikes: boot.deps.modelStrikes,
|
|
82
80
|
readRoutingAccountInflight: boot.deps.readRoutingAccountInflight,
|
|
83
81
|
// The same three writers the shutdown coordinator drains, so a manual
|
|
84
82
|
// flush from the console does exactly what a graceful stop would do
|
|
@@ -120,6 +118,16 @@ function shutdown(signal: "SIGINT" | "SIGTERM", reason: "SIGINT" | "SIGTERM" | "
|
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
if (boot) {
|
|
121
|
+
// `bun --hot` re-runs this module against the cached boot object; stop the
|
|
122
|
+
// previous listener before rebinding so a reload does not stack two servers
|
|
123
|
+
// on the same port.
|
|
124
|
+
if (boot.server && typeof boot.server.stop === "function") {
|
|
125
|
+
try {
|
|
126
|
+
boot.server.stop();
|
|
127
|
+
} catch {
|
|
128
|
+
// Best-effort on reload; the bind below would fail loudly if it stuck.
|
|
129
|
+
}
|
|
130
|
+
}
|
|
123
131
|
boot.server = app.listen(
|
|
124
132
|
{
|
|
125
133
|
port,
|
|
@@ -151,6 +159,12 @@ if (boot) {
|
|
|
151
159
|
// the lease sweep and the health sweep should not run before the listener
|
|
152
160
|
// exists to serve traffic.
|
|
153
161
|
boot.deps.scheduledTasks.start();
|
|
162
|
+
// Warm the route snapshot before the first request lands: the first /v1/*
|
|
163
|
+
// request otherwise pays the full catalog build synchronously (ten+ SELECTs).
|
|
164
|
+
// A failure here is a soft miss — the next request rebuilds as before.
|
|
165
|
+
void boot.deps.snapshotService.getSnapshot().catch((error: unknown) => {
|
|
166
|
+
log.warn("[startup] initial route snapshot warm failed", error as Error);
|
|
167
|
+
});
|
|
154
168
|
if (!globalThis.__cartethyiaSignalsRegistered) {
|
|
155
169
|
globalThis.__cartethyiaSignalsRegistered = true;
|
|
156
170
|
process.on("SIGINT", () => shutdown("SIGINT"));
|