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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cartethyia",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "A powerful, self-hosted reverse proxy for OpenAI- and Anthropic-compatible AI clients, powered by native Bun and Elysia. It serves both protocols from a single server, routes every model across any configured provider, and translates requests and responses in real time — streaming and prompt caching included. Underneath it runs a full delivery engine: per-account health tracking, quota and cooldown enforcement, automatic failover across pools and providers, usage accounting, and telemetry. Point OpenCode, Cline, Claude Code, Codex, or any compatible client at Cartethyia and it keeps its native protocol while the gateway absorbs every provider-specific difference behind it. Runs on embedded SQLite or external PostgreSQL with optional Redis coordination, ships as a global CLI with a system-tray console, and needs only Bun 1.4+ alongside Node.js/npm.",
|
|
5
5
|
"license": "GPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,6 @@ import { exportBackup, resetConsoleAccount } from "./admin";
|
|
|
18
18
|
import { printUpdateInstructions, runDetachedUpdate } from "./update";
|
|
19
19
|
import { acquireController } from "./controller";
|
|
20
20
|
import { restoreControllerAfterFailedHandoff } from "./controller";
|
|
21
|
-
import { attachGateway as attachRunningGateway } from "./instance";
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
23
|
* Seconds to keep the update notice on screen before returning to the shell.
|
|
@@ -316,7 +315,11 @@ async function runMenu(handoff: { readonly token: string; readonly parentPid: nu
|
|
|
316
315
|
// would stop the very process the tray just adopted, which is why the menu
|
|
317
316
|
// appeared to hand over a gateway that was not listening.
|
|
318
317
|
if (handedOff) return;
|
|
319
|
-
|
|
318
|
+
// An attached (externally owned) gateway is left running for its owner; our
|
|
319
|
+
// own child is drained before the menu returns to the shell. `attachGateway`
|
|
320
|
+
// is deliberately NOT probed again here: it would always see our own child's
|
|
321
|
+
// lock and turn a clean drain into a rough kill on the exit backstop.
|
|
322
|
+
if (runningAttached !== null) {
|
|
320
323
|
detachAttached();
|
|
321
324
|
return;
|
|
322
325
|
}
|
package/scripts/cli/tray.ts
CHANGED
|
@@ -64,15 +64,16 @@ export async function startTray(): Promise<void> {
|
|
|
64
64
|
const handoff = inheritedControllerHandoff();
|
|
65
65
|
const controller = acquireController("tray", handoff);
|
|
66
66
|
const releaseController = (): void => controller.release();
|
|
67
|
-
const failedHandoff = (): void => {
|
|
68
|
-
if (handoff) restoreControllerAfterFailedHandoff(handoff);
|
|
69
|
-
};
|
|
70
|
-
process.once("exit", failedHandoff);
|
|
71
67
|
process.once("exit", releaseController);
|
|
72
68
|
try {
|
|
73
69
|
await runTray();
|
|
70
|
+
} catch (error) {
|
|
71
|
+
// Only a tray that never became ready restores the menu's lease. After a
|
|
72
|
+
// successful handoff the tray owns the controller; restoring it on a later
|
|
73
|
+
// normal exit would pin a controller record to the long-gone menu pid.
|
|
74
|
+
if (handoff) restoreControllerAfterFailedHandoff(handoff);
|
|
75
|
+
throw error;
|
|
74
76
|
} finally {
|
|
75
|
-
process.removeListener("exit", failedHandoff);
|
|
76
77
|
controller.release();
|
|
77
78
|
process.removeListener("exit", releaseController);
|
|
78
79
|
}
|
|
@@ -174,7 +175,21 @@ async function runTray(): Promise<void> {
|
|
|
174
175
|
// over HTTP before it ever reaches for `kill()`, so detaching costs the
|
|
175
176
|
// exit path nothing: the tray can still stop the gateway on Exit.
|
|
176
177
|
adoptedGateway = await attachGateway(port, drainToken);
|
|
177
|
-
if (adoptedGateway === null)
|
|
178
|
+
if (adoptedGateway === null) {
|
|
179
|
+
gateway = await startGateway(port, drainToken, { detached: true });
|
|
180
|
+
} else {
|
|
181
|
+
// The adopted gateway was started by the menu as a non-detached child of
|
|
182
|
+
// the menu's console. When the menu exits — and especially when the
|
|
183
|
+
// operator closes that terminal window afterwards — Windows delivers
|
|
184
|
+
// CTRL_CLOSE to the whole console group and the gateway (handling
|
|
185
|
+
// SIGTERM) shuts down with it: "Hide to tray" left nothing serving. The
|
|
186
|
+
// menu cannot hand the same process off to another console, so re-cycle
|
|
187
|
+
// it into a detached gateway now, before reporting ready, so the tray
|
|
188
|
+
// owns a gateway that is not attached to any console after the handoff.
|
|
189
|
+
await stopAttachedGateway(adoptedGateway, drainToken);
|
|
190
|
+
adoptedGateway = null;
|
|
191
|
+
gateway = await startGateway(port, drainToken, { detached: true });
|
|
192
|
+
}
|
|
178
193
|
// The launcher that spawned this tray is blocked on a signal file: it
|
|
179
194
|
// cannot read our stdio, because the tray is detached. Without this write
|
|
180
195
|
// it waits out its 60 s deadline and reports a failure for a tray that is
|
package/src/boot/app.ts
CHANGED
|
@@ -30,8 +30,8 @@ import { ProxyRequestStateStore } from "../transport/request/state";
|
|
|
30
30
|
import { fastPathname } from "../transport/pathname";
|
|
31
31
|
import {
|
|
32
32
|
handleProviderProxyRequest,
|
|
33
|
-
type ProviderProxyHandlerDeps,
|
|
34
33
|
} from "../transport/dispatch/proxy-request";
|
|
34
|
+
import type { GatewayHandlerDeps } from "../transport/dispatch/handler-deps";
|
|
35
35
|
import { createResponsesCompactHandler } from "../transport/dispatch/responses-compact";
|
|
36
36
|
import { createSystemoneHandler } from "../transport/dispatch/systemone";
|
|
37
37
|
import { createWebsearchHandler } from "../transport/dispatch/websearch";
|
|
@@ -45,7 +45,6 @@ import {
|
|
|
45
45
|
import { createTokenCountHandler } from "../transport/dispatch/token-count";
|
|
46
46
|
|
|
47
47
|
import { createTransportPipeline } from "../transport/guards/pipeline";
|
|
48
|
-
import { defaultProcessConcurrencyController } from "../transport/guards/concurrency-guard";
|
|
49
48
|
import { createDrainHandler, isLoopbackPeer, tokenMatches } from "../transport/drain-endpoint";
|
|
50
49
|
import { createConsoleAccountResetHandler } from "../console/auth/account-reset";
|
|
51
50
|
import { resetConsoleAuthState } from "../console/auth/account-reset-store";
|
|
@@ -61,7 +60,6 @@ import type { ValidatedNetworkBindingFactory } from "../network/pool/resolver";
|
|
|
61
60
|
import { metrics } from "../observability/metrics";
|
|
62
61
|
import type { RuntimeMetricsSampler } from "../observability/runtime-metrics";
|
|
63
62
|
import { API_CONTENT_SECURITY_POLICY, X_FRAME_OPTIONS } from "../security/outbound-headers";
|
|
64
|
-
import type { ModelStrikeService } from "../security/model-abuse";
|
|
65
63
|
|
|
66
64
|
|
|
67
65
|
import type { TelemetryBatchBuffer } from "../observability/telemetry-buffer";
|
|
@@ -112,7 +110,6 @@ export interface ProductionAppDeps {
|
|
|
112
110
|
readonly db: CartethyiaDatabase;
|
|
113
111
|
readonly proxyPreparer: ProxyRequestPreparer;
|
|
114
112
|
readonly resolveProviderAdapter: (providerId: string) => Promise<ProviderAdapter | undefined>;
|
|
115
|
-
readonly providerAdapters?: ReadonlyMap<string, ProviderAdapter>;
|
|
116
113
|
/** Live lookup of a provider's SSRF-validated upstream host. */
|
|
117
114
|
readonly byokUpstreamHosts: { readonly get: (providerId: string) => ByokUpstreamHost | undefined };
|
|
118
115
|
readonly networkBindingFactory: ValidatedNetworkBindingFactory;
|
|
@@ -125,7 +122,6 @@ export interface ProductionAppDeps {
|
|
|
125
122
|
readonly resolveOAuthRefresher: (providerId: string) => Promise<OAuthTokenRefresher | undefined>;
|
|
126
123
|
readonly oauthRefreshService: OAuthRefreshService;
|
|
127
124
|
/** Graduated strikes for repeated invalid-model requests. */
|
|
128
|
-
readonly modelStrikes?: ModelStrikeService;
|
|
129
125
|
/**
|
|
130
126
|
* The console control plane. Optional so reduced compositions (route-only
|
|
131
127
|
* shell, console stubs) stay valid; production always mounts it. Without
|
|
@@ -245,10 +241,6 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
245
241
|
deps.mode === "production" ? deps.shutdownCoordinator : undefined,
|
|
246
242
|
);
|
|
247
243
|
deps.runtimeMetricsSampler?.bindInFlight(() => requestStateStore.inFlightCount());
|
|
248
|
-
// The concurrency ceiling is derived (memory limit ÷ body budget), so it is
|
|
249
|
-
// published as a gauge: an operator reading "shedding at 16 in flight" needs
|
|
250
|
-
// to see that 16 IS the limit on this box, not that the process is broken.
|
|
251
|
-
deps.runtimeMetricsSampler?.bindConcurrencyLimit(defaultProcessConcurrencyController.limit());
|
|
252
244
|
// Shutdown ordering: abort in-flight proxy controllers first so the
|
|
253
245
|
// bounded drain observes cancellation and finalizers run before
|
|
254
246
|
// telemetry flush and pool close. The reason is threaded through so the
|
|
@@ -282,6 +274,9 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
282
274
|
backstopTasks?.register({
|
|
283
275
|
name: "inflight-backstop",
|
|
284
276
|
intervalMs: INFLIGHT_BACKSTOP_INTERVAL_MS,
|
|
277
|
+
// Same stagger rationale as account-health-sweep: keep the 30s cluster
|
|
278
|
+
// from aligning under the single-flight gate.
|
|
279
|
+
initialDelayMs: 15_000,
|
|
285
280
|
run: () => {
|
|
286
281
|
requestStateStore.sweepOverdueInFlight(
|
|
287
282
|
Date.now(),
|
|
@@ -392,7 +387,6 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
392
387
|
...(deps.verifiedHttps ? { verifiedHttps: true } : {}),
|
|
393
388
|
shutdownCoordinator: deps.shutdownCoordinator,
|
|
394
389
|
telemetry: deps.telemetryBuffer,
|
|
395
|
-
...(deps.modelStrikes ? { modelStrikes: deps.modelStrikes } : {}),
|
|
396
390
|
...(deps.consoleApi?.redis ? { redis: deps.consoleApi.redis } : {}),
|
|
397
391
|
// Bound at construction so the guard holds the sampler's live snapshot
|
|
398
392
|
// rather than a value captured at boot.
|
|
@@ -406,22 +400,27 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
406
400
|
(await deps.snapshotService.getSnapshot())?.invokeDisabledTenants?.has(tenantId),
|
|
407
401
|
});
|
|
408
402
|
transportPipeline.mountRoot(app);
|
|
409
|
-
|
|
403
|
+
// One dependency bundle for every gateway handler. Proxy, generation,
|
|
404
|
+
// responses-compact, system one, web search, and token count all receive
|
|
405
|
+
// the same wiring — a handler dep is added once, here, not in five
|
|
406
|
+
// literals.
|
|
407
|
+
const gatewayDeps: GatewayHandlerDeps = {
|
|
410
408
|
db: deps.db,
|
|
411
|
-
providerAdapters: deps.providerAdapters ?? new Map(),
|
|
412
409
|
resolveProviderAdapter: deps.resolveProviderAdapter,
|
|
413
410
|
stateStore: requestStateStore,
|
|
414
411
|
proxyPreparer: deps.proxyPreparer,
|
|
415
412
|
snapshotService: deps.snapshotService,
|
|
416
413
|
networkBindingFactory: deps.networkBindingFactory,
|
|
417
|
-
byokUpstreamHosts: deps.byokUpstreamHosts,
|
|
418
414
|
poolSelector: deps.poolSelector,
|
|
419
415
|
telemetryBuffer: deps.telemetryBuffer,
|
|
420
416
|
resolveOAuthRefresher: deps.resolveOAuthRefresher,
|
|
421
417
|
oauthRefreshService: deps.oauthRefreshService,
|
|
422
418
|
};
|
|
423
419
|
const proxyHandler = ({ request }: { request: Request }) =>
|
|
424
|
-
handleProviderProxyRequest(request,
|
|
420
|
+
handleProviderProxyRequest(request, {
|
|
421
|
+
...gatewayDeps,
|
|
422
|
+
byokUpstreamHosts: deps.byokUpstreamHosts,
|
|
423
|
+
});
|
|
425
424
|
|
|
426
425
|
const publicModelStore = new PublicModelCatalogStore(deps.db);
|
|
427
426
|
const queryAllowedModels = (auth: {
|
|
@@ -483,16 +482,7 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
483
482
|
};
|
|
484
483
|
|
|
485
484
|
const handleResponsesCompact = createResponsesCompactHandler({
|
|
486
|
-
|
|
487
|
-
providerAdapters: deps.providerAdapters ?? new Map(),
|
|
488
|
-
resolveProviderAdapter: deps.resolveProviderAdapter,
|
|
489
|
-
proxyPreparer: deps.proxyPreparer,
|
|
490
|
-
stateStore: requestStateStore,
|
|
491
|
-
poolSelector: deps.poolSelector,
|
|
492
|
-
networkBindingFactory: deps.networkBindingFactory,
|
|
493
|
-
snapshotService: deps.snapshotService,
|
|
494
|
-
resolveOAuthRefresher: deps.resolveOAuthRefresher,
|
|
495
|
-
oauthRefreshService: deps.oauthRefreshService,
|
|
485
|
+
...gatewayDeps,
|
|
496
486
|
// The compact handler completes its attempt through `completeAttempt`,
|
|
497
487
|
// which marks the request completed and finalizes telemetry itself —
|
|
498
488
|
// so the afterResponse lifecycle skips it. Without the buffer here the
|
|
@@ -501,48 +491,14 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
501
491
|
});
|
|
502
492
|
|
|
503
493
|
const handleSystemone = createSystemoneHandler({
|
|
504
|
-
|
|
505
|
-
providerAdapters: deps.providerAdapters ?? new Map(),
|
|
506
|
-
resolveProviderAdapter: deps.resolveProviderAdapter,
|
|
507
|
-
proxyPreparer: deps.proxyPreparer,
|
|
508
|
-
stateStore: requestStateStore,
|
|
509
|
-
poolSelector: deps.poolSelector,
|
|
510
|
-
networkBindingFactory: deps.networkBindingFactory,
|
|
511
|
-
snapshotService: deps.snapshotService,
|
|
512
|
-
resolveOAuthRefresher: deps.resolveOAuthRefresher,
|
|
513
|
-
oauthRefreshService: deps.oauthRefreshService,
|
|
494
|
+
...gatewayDeps,
|
|
514
495
|
// Same reasoning as compact: the handler finalizes telemetry itself, so
|
|
515
496
|
// the buffer must be threaded here or the route emits no row.
|
|
516
497
|
telemetryBuffer: deps.telemetryBuffer,
|
|
517
498
|
});
|
|
518
499
|
|
|
519
|
-
const handleWebsearch = createWebsearchHandler(
|
|
520
|
-
|
|
521
|
-
providerAdapters: deps.providerAdapters ?? new Map(),
|
|
522
|
-
resolveProviderAdapter: deps.resolveProviderAdapter,
|
|
523
|
-
proxyPreparer: deps.proxyPreparer,
|
|
524
|
-
stateStore: requestStateStore,
|
|
525
|
-
poolSelector: deps.poolSelector,
|
|
526
|
-
networkBindingFactory: deps.networkBindingFactory,
|
|
527
|
-
snapshotService: deps.snapshotService,
|
|
528
|
-
resolveOAuthRefresher: deps.resolveOAuthRefresher,
|
|
529
|
-
oauthRefreshService: deps.oauthRefreshService,
|
|
530
|
-
telemetryBuffer: deps.telemetryBuffer,
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
const generationDeps = {
|
|
534
|
-
db: deps.db,
|
|
535
|
-
providerAdapters: deps.providerAdapters ?? new Map(),
|
|
536
|
-
resolveProviderAdapter: deps.resolveProviderAdapter,
|
|
537
|
-
proxyPreparer: deps.proxyPreparer,
|
|
538
|
-
stateStore: requestStateStore,
|
|
539
|
-
poolSelector: deps.poolSelector,
|
|
540
|
-
networkBindingFactory: deps.networkBindingFactory,
|
|
541
|
-
snapshotService: deps.snapshotService,
|
|
542
|
-
resolveOAuthRefresher: deps.resolveOAuthRefresher,
|
|
543
|
-
oauthRefreshService: deps.oauthRefreshService,
|
|
544
|
-
telemetryBuffer: deps.telemetryBuffer,
|
|
545
|
-
};
|
|
500
|
+
const handleWebsearch = createWebsearchHandler(gatewayDeps);
|
|
501
|
+
const generationDeps = gatewayDeps;
|
|
546
502
|
const handleImageGeneration = createImageGenerationHandler(generationDeps);
|
|
547
503
|
// Mounted with no model behind it on purpose: the surface exists so it can
|
|
548
504
|
// be finished when an upstream is known, rather than 404ing like a typo.
|
|
@@ -660,6 +616,11 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
660
616
|
});
|
|
661
617
|
}
|
|
662
618
|
|
|
619
|
+
// One share-link store for both surfaces: the public share router and the
|
|
620
|
+
// console's API-key/share domain wrap the same table, and one instance
|
|
621
|
+
// keeps the "one owner per store" convention.
|
|
622
|
+
const shareStore = new DrizzleShareLinkStore(deps.db);
|
|
623
|
+
|
|
663
624
|
// `peerAddresses` is populated by the root `beforeHandle` above from
|
|
664
625
|
// `server.requestIP`. The console login route needs it to key its lockout
|
|
665
626
|
// bucket, and the trusted-proxy boundary decides whether an
|
|
@@ -669,6 +630,7 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
669
630
|
app.use(
|
|
670
631
|
createConsoleRouter({
|
|
671
632
|
...deps.consoleApi,
|
|
633
|
+
...(shareStore ? { shareStore } : {}),
|
|
672
634
|
stateStore: requestStateStore,
|
|
673
635
|
resolvePeerAddress: (request) => peerAddresses.get(request) ?? null,
|
|
674
636
|
trustedProxyBoundary: deps.trustedProxyBoundary,
|
|
@@ -681,7 +643,7 @@ export function createGatewayApp(deps: GatewayAppDeps) {
|
|
|
681
643
|
app.use(
|
|
682
644
|
createShareRouter({
|
|
683
645
|
db: deps.db,
|
|
684
|
-
shareStore
|
|
646
|
+
shareStore,
|
|
685
647
|
stats: createShareStatsPort({ db: deps.db, redis: deps.consoleApi?.redis }),
|
|
686
648
|
resolveClientIp: (request) => {
|
|
687
649
|
const peer = peerAddresses.get(request);
|