cartethyia 2.7.0 → 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 +107 -106
- package/README.md +25 -2
- package/dist/dashboard/assets/{BannedPage-P76QLGJA.js → BannedPage-D-J75hBM.js} +1 -1
- package/dist/dashboard/assets/BannedPage-D-J75hBM.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-DdBggJS9.js → CliToolDetailPage-CVe6RaBH.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-CVe6RaBH.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-aN1iXhhP.js → CliToolsPage-Dd8ZSamp.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-Dd8ZSamp.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-DE-F1nxZ.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-3CUxMy2X.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-DKVslqG3.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-BjldQwIU.js → QuotaPage-ATpaxrbl.js} +1 -1
- package/dist/dashboard/assets/QuotaPage-ATpaxrbl.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-DUIoLRxk.js → SettingsPage-CETophpx.js} +1 -1
- 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-fI7JkdIB.js → SortableList-CAK-EN9z.js} +1 -1
- package/dist/dashboard/assets/SortableList-CAK-EN9z.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-CHVZqskZ.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-DFY_fZU4.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-CwdnZARt.js → assert-67xXH5rf.js} +1 -1
- package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
- package/dist/dashboard/assets/{badge-Dr-uf0Au.js → badge-DC2L43Mj.js} +1 -1
- package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BddmMdoS.js → banner-BBVcb0J3.js} +1 -1
- package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
- package/dist/dashboard/assets/{card-CK0PXWlX.js → card-Cca1XC6G.js} +1 -1
- package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-CcB6mGh2.js → cli-tools-KvsWa1Jl.js} +1 -1
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DGb2P9Yx.js → clipboard-button-DUzEbynq.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-LkfuL50u.js → dialog-DFvWhwTa.js} +1 -1
- package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-ZbEZ_84c.js → drawer-CFM2sMX1.js} +1 -1
- package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CWBY5A0f.js → entry-BLBLxX0h.js} +3 -3
- package/dist/dashboard/assets/entry-BLBLxX0h.js.gz +0 -0
- package/dist/dashboard/assets/{entry-BJfsVMvA.js → entry-Bqy8RFvM.js} +1 -1
- package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CvC1-Zqx.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-BxpznFLt.js → github-badge-C9e8Ts7e.js} +1 -1
- package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
- package/dist/dashboard/assets/{index-CDzP3ovJ.js → index-D6QzEC_n.js} +2 -2
- package/dist/dashboard/assets/index-D6QzEC_n.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Ae13MQ5w.js → inline-BFUcvllj.js} +1 -1
- package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
- package/dist/dashboard/assets/{input-D23fo7cp.js → input-C_ILAvBb.js} +1 -1
- package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
- package/dist/dashboard/assets/{layout-CSsxjj5P.js → layout-CBIyT6Rt.js} +1 -1
- package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-dmbwZMDY.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-BG1oUsZZ.js → live-D0mm--ME.js} +1 -1
- package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-DSF-e4ho.js → mutation-sMD965oO.js} +1 -1
- package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-Bm_aECY7.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-CF56nYIV.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-CeA71n7G.js → routing-BnIpi1IJ.js} +1 -1
- package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
- package/dist/dashboard/assets/{select-KIT0rC6G.js → select-Cj5Nw43g.js} +1 -1
- package/dist/dashboard/assets/select-Cj5Nw43g.js.gz +0 -0
- package/dist/dashboard/assets/{settings-B_2gkePf.js → settings-BAFhDgX8.js} +1 -1
- package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
- package/dist/dashboard/assets/{stack-D7WOSzcX.js → stack-EMrOMt4I.js} +1 -1
- package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
- package/dist/dashboard/assets/{state-BBxtKZOQ.js → state-CWoo7ty5.js} +1 -1
- package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DNS_D5Ea.js → switch-CCjT6IkF.js} +1 -1
- package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BgoxdoMk.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 +54 -53
- 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 +96 -96
- package/scripts/cli/console-menu.ts +5 -2
- package/scripts/cli/tray.ts +21 -6
- package/src/boot/app.ts +684 -714
- package/src/boot/dependencies.ts +65 -62
- package/src/config/cooldowns.ts +16 -0
- package/src/config/providers.ts +13 -1
- package/src/config/resources.ts +70 -70
- package/src/config/security.ts +37 -37
- package/src/config/spec.ts +371 -358
- package/src/console/console-router.ts +233 -225
- package/src/console/domain-registration.ts +398 -381
- 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/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 +183 -167
- 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 +467 -467
- package/src/observability/runtime-metrics.ts +269 -269
- 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 +232 -232
- 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/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 -1458
- 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/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 +109 -109
- package/src/transport/guards/error-lifecycle.ts +1 -1
- package/src/transport/guards/pipeline.ts +220 -220
- package/src/transport/guards/request-context.ts +245 -238
- package/src/transport/request/degradation.ts +20 -1
- package/src/transport/request/inflight.ts +4 -114
- 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-P76QLGJA.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-DdBggJS9.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-aN1iXhhP.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DE-F1nxZ.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-5SpmfLyw.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-5SpmfLyw.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-3CUxMy2X.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BkmJQKC0.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-BkmJQKC0.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-B_0FUKWc.js +0 -1
- package/dist/dashboard/assets/LoginPage-B_0FUKWc.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-DKVslqG3.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D-H4MEiT.js +0 -1
- package/dist/dashboard/assets/OverviewPage-D-H4MEiT.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CEJw6Guo.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-CEJw6Guo.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-CEplAR-i.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-CEplAR-i.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CAN7hy0f.js +0 -7
- package/dist/dashboard/assets/ProxyPage-CAN7hy0f.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-BjldQwIU.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-DUIoLRxk.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-_bCaTM0v.js +0 -1
- package/dist/dashboard/assets/SetupPage-_bCaTM0v.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-fI7JkdIB.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-CHVZqskZ.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DiFBymHj.js +0 -56
- package/dist/dashboard/assets/UsagePage-DiFBymHj.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-DFY_fZU4.js.gz +0 -0
- package/dist/dashboard/assets/app-BOJ1_xUB.css +0 -2
- package/dist/dashboard/assets/app-BOJ1_xUB.css.gz +0 -0
- package/dist/dashboard/assets/assert-CwdnZARt.js.gz +0 -0
- package/dist/dashboard/assets/badge-Dr-uf0Au.js.gz +0 -0
- package/dist/dashboard/assets/banner-BddmMdoS.js.gz +0 -0
- package/dist/dashboard/assets/card-CK0PXWlX.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CcB6mGh2.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DGb2P9Yx.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-LkfuL50u.js.gz +0 -0
- package/dist/dashboard/assets/drawer-ZbEZ_84c.js.gz +0 -0
- package/dist/dashboard/assets/entry-BJfsVMvA.js.gz +0 -0
- package/dist/dashboard/assets/entry-CWBY5A0f.js.gz +0 -0
- package/dist/dashboard/assets/entry-CvC1-Zqx.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-BxpznFLt.js.gz +0 -0
- package/dist/dashboard/assets/index-CDzP3ovJ.js.gz +0 -0
- package/dist/dashboard/assets/inline-Ae13MQ5w.js.gz +0 -0
- package/dist/dashboard/assets/input-D23fo7cp.js.gz +0 -0
- package/dist/dashboard/assets/layout-CSsxjj5P.js.gz +0 -0
- package/dist/dashboard/assets/list-row-dmbwZMDY.js.gz +0 -0
- package/dist/dashboard/assets/live-BG1oUsZZ.js.gz +0 -0
- package/dist/dashboard/assets/mutation-DSF-e4ho.js.gz +0 -0
- package/dist/dashboard/assets/numbers-Bm_aECY7.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CF56nYIV.js.gz +0 -0
- package/dist/dashboard/assets/routing-CeA71n7G.js.gz +0 -0
- package/dist/dashboard/assets/select-KIT0rC6G.js.gz +0 -0
- package/dist/dashboard/assets/settings-B_2gkePf.js.gz +0 -0
- package/dist/dashboard/assets/stack-D7WOSzcX.js.gz +0 -0
- package/dist/dashboard/assets/state-BBxtKZOQ.js.gz +0 -0
- package/dist/dashboard/assets/switch-DNS_D5Ea.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BgoxdoMk.js.gz +0 -0
- /package/dist/dashboard/assets/{app-CaXZ9SCn.js → app-BaWd0puM.js} +0 -0
- /package/dist/dashboard/assets/{app-CaXZ9SCn.js.gz → app-BaWd0puM.js.gz} +0 -0
|
@@ -1,225 +1,233 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Console API composition root: assembles every console route group with
|
|
3
|
-
* explicit persistence boundaries. All dependencies are injected at
|
|
4
|
-
* composition time; concrete Drizzle stores are the defaults, so this file
|
|
5
|
-
* is the single place that knows them.
|
|
6
|
-
*/
|
|
7
|
-
import { Elysia } from "elysia";
|
|
8
|
-
import { log } from "../observability/logger";
|
|
9
|
-
import { resolveConsoleAccess, resolveConsoleUser } from "./auth/session-resolver";
|
|
10
|
-
import { ConsoleCredentialService } from "./auth/credentials";
|
|
11
|
-
import { resolveDefaultGatewayApiKey } from "../config/runtime";
|
|
12
|
-
import { FirstBootSetupService } from "./auth/setup-service";
|
|
13
|
-
import { ConsoleSessionService, defaultSessionCookiePolicy } from "./auth/session-service";
|
|
14
|
-
import { ConsoleLockoutService } from "./auth/lockout";
|
|
15
|
-
import { AuditRecorder } from "./auth/audit-recorder";
|
|
16
|
-
import { createConsoleAuthRoutes } from "./auth/session";
|
|
17
|
-
import { createConsoleCsrfMiddleware } from "./console-router-guards";
|
|
18
|
-
import { createConsoleMutationLimiterMiddleware } from "./console-router-guards";
|
|
19
|
-
import { registerConsoleDomains, type ConsoleDomainContext } from "./domain-registration";
|
|
20
|
-
import type { ConsoleAccessResolver } from "./auth/access";
|
|
21
|
-
import type { CartethyiaDatabase } from "../persistence/db-handle";
|
|
22
|
-
import { createAccessDecision, type AccessDecision } from "../security/access-control";
|
|
23
|
-
import { resolveApiKeyAuthorization } from "../security/api-key-auth";
|
|
24
|
-
import type { LiveInFlightSource } from "./observability/live";
|
|
25
|
-
import type { NetworkPoolSelector } from "../network/pool/selector";
|
|
26
|
-
import type { TelemetryBatchBuffer } from "../observability/telemetry-buffer";
|
|
27
|
-
import type { OAuthRefreshService } from "../providers/authentication/oauth-refresh-service";
|
|
28
|
-
import type { ApiKeyAdmissionService } from "../security/admission/service";
|
|
29
|
-
import type { RedisClient } from "../persistence/redis";
|
|
30
|
-
import { CliToolMappingStore } from "./cli-tools/store";
|
|
31
|
-
import { CliToolService } from "./cli-tools/service";
|
|
32
|
-
import { DrizzleCliToolSecretSource } from "./cli-tools/secret-source";
|
|
33
|
-
import type {
|
|
34
|
-
import type {
|
|
35
|
-
import type {
|
|
36
|
-
import type {
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
readonly
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
readonly
|
|
49
|
-
readonly
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
readonly
|
|
63
|
-
readonly
|
|
64
|
-
readonly
|
|
65
|
-
readonly
|
|
66
|
-
readonly
|
|
67
|
-
readonly
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
readonly
|
|
75
|
-
readonly
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
// `
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Console API composition root: assembles every console route group with
|
|
3
|
+
* explicit persistence boundaries. All dependencies are injected at
|
|
4
|
+
* composition time; concrete Drizzle stores are the defaults, so this file
|
|
5
|
+
* is the single place that knows them.
|
|
6
|
+
*/
|
|
7
|
+
import { Elysia } from "elysia";
|
|
8
|
+
import { log } from "../observability/logger";
|
|
9
|
+
import { resolveConsoleAccess, resolveConsoleUser } from "./auth/session-resolver";
|
|
10
|
+
import { ConsoleCredentialService } from "./auth/credentials";
|
|
11
|
+
import { resolveDefaultGatewayApiKey } from "../config/runtime";
|
|
12
|
+
import { FirstBootSetupService } from "./auth/setup-service";
|
|
13
|
+
import { ConsoleSessionService, defaultSessionCookiePolicy } from "./auth/session-service";
|
|
14
|
+
import { ConsoleLockoutService } from "./auth/lockout";
|
|
15
|
+
import { AuditRecorder } from "./auth/audit-recorder";
|
|
16
|
+
import { createConsoleAuthRoutes } from "./auth/session";
|
|
17
|
+
import { createConsoleCsrfMiddleware } from "./console-router-guards";
|
|
18
|
+
import { createConsoleMutationLimiterMiddleware } from "./console-router-guards";
|
|
19
|
+
import { registerConsoleDomains, type ConsoleDomainContext } from "./domain-registration";
|
|
20
|
+
import type { ConsoleAccessResolver } from "./auth/access";
|
|
21
|
+
import type { CartethyiaDatabase } from "../persistence/db-handle";
|
|
22
|
+
import { createAccessDecision, type AccessDecision } from "../security/access-control";
|
|
23
|
+
import { resolveApiKeyAuthorization } from "../security/api-key-auth";
|
|
24
|
+
import type { LiveInFlightSource } from "./observability/live";
|
|
25
|
+
import type { NetworkPoolSelector } from "../network/pool/selector";
|
|
26
|
+
import type { TelemetryBatchBuffer } from "../observability/telemetry-buffer";
|
|
27
|
+
import type { OAuthRefreshService } from "../providers/authentication/oauth-refresh-service";
|
|
28
|
+
import type { ApiKeyAdmissionService } from "../security/admission/service";
|
|
29
|
+
import type { RedisClient } from "../persistence/redis";
|
|
30
|
+
import { CliToolMappingStore } from "./cli-tools/store";
|
|
31
|
+
import { CliToolService } from "./cli-tools/service";
|
|
32
|
+
import { DrizzleCliToolSecretSource } from "./cli-tools/secret-source";
|
|
33
|
+
import type { ShareLinkStore } from "../persistence/stores/share-store";
|
|
34
|
+
import type { ProviderRegistry } from "../providers/provider-registry";
|
|
35
|
+
import type { BundledProviderCatalog } from "../providers/operations/provider-catalog-service";
|
|
36
|
+
import type { ValidatedNetworkBindingFactory } from "../network/pool/resolver";
|
|
37
|
+
import type { TrustedProxyBoundary } from "../config/network";
|
|
38
|
+
import { gzipResponse } from "./response-compression";
|
|
39
|
+
|
|
40
|
+
export interface ConsoleApiCompositionDeps {
|
|
41
|
+
readonly db: CartethyiaDatabase;
|
|
42
|
+
readonly accessResolver: ConsoleAccessResolver;
|
|
43
|
+
/**
|
|
44
|
+
* Drops the cached route snapshot after a console write changes the catalog.
|
|
45
|
+
* Structurally satisfied by `RouteSnapshotService`; declared here so the
|
|
46
|
+
* console composition root does not import the transport layer.
|
|
47
|
+
*/
|
|
48
|
+
readonly routeSnapshotService: { invalidate(): Promise<number> };
|
|
49
|
+
readonly poolSelector: NetworkPoolSelector;
|
|
50
|
+
readonly telemetryBuffer: TelemetryBatchBuffer;
|
|
51
|
+
/**
|
|
52
|
+
* Queued writers the console can drain on demand (telemetry, usage, health
|
|
53
|
+
* events). Optional for the same reason the other reduced composition
|
|
54
|
+
* surface is: absent means the flush control is not offered rather than the
|
|
55
|
+
* console failing to build.
|
|
56
|
+
*/
|
|
57
|
+
readonly flushBuffers?: { flush(): Promise<void> };
|
|
58
|
+
/**
|
|
59
|
+
* The request state store owns the live in-flight gauge, so the console reads
|
|
60
|
+
* its snapshot/subscription from here rather than a free-standing module.
|
|
61
|
+
*/
|
|
62
|
+
readonly stateStore?: LiveInFlightSource;
|
|
63
|
+
readonly providerRegistry: ProviderRegistry;
|
|
64
|
+
readonly bundledModelCatalog: BundledProviderCatalog;
|
|
65
|
+
readonly networkBindingFactory: ValidatedNetworkBindingFactory;
|
|
66
|
+
readonly redis: RedisClient | undefined;
|
|
67
|
+
readonly oauthRefreshService: OAuthRefreshService;
|
|
68
|
+
/**
|
|
69
|
+
* Share-link store shared with the public share router, so both surfaces
|
|
70
|
+
* wrap the same table through one instance. Optional: absent means the
|
|
71
|
+
* console builds its own store from `db`.
|
|
72
|
+
*/
|
|
73
|
+
readonly shareStore?: ShareLinkStore;
|
|
74
|
+
readonly admissionService: Pick<ApiKeyAdmissionService, "purgeKey">;
|
|
75
|
+
readonly readRoutingAccountInflight?:
|
|
76
|
+
| ((
|
|
77
|
+
providerId: string,
|
|
78
|
+
tenantId: string | null,
|
|
79
|
+
) => Promise<readonly { accountId: string; inflight: number }[]>)
|
|
80
|
+
| undefined;
|
|
81
|
+
readonly resolvePeerAddress?: (request: Request) => string | null;
|
|
82
|
+
readonly trustedProxyBoundary?: TrustedProxyBoundary;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Extracts a bearer API key from a console request, or `undefined`.
|
|
86
|
+
*
|
|
87
|
+
* Deliberately narrower than the proxy surface's `requestToken`: that one also
|
|
88
|
+
* accepts `x-api-key` and throws on a malformed header, because a proxy caller
|
|
89
|
+
* must be told its credential is wrong. Here the header is only an *alternative*
|
|
90
|
+
* to a session cookie, so an absent or unparsable one means "not a key" and the
|
|
91
|
+
* request proceeds as an unauthenticated session request — which the routes
|
|
92
|
+
* then reject with their own 401. Returning `undefined` rather than throwing
|
|
93
|
+
* keeps a browser that sends a stray Authorization header from being told its
|
|
94
|
+
* session is invalid.
|
|
95
|
+
*/
|
|
96
|
+
function readApiKeyBearer(request: Request): string | undefined {
|
|
97
|
+
const authorization = request.headers.get("authorization");
|
|
98
|
+
if (authorization === null) return undefined;
|
|
99
|
+
const match = /^Bearer\s+(\S+)$/i.exec(authorization.trim());
|
|
100
|
+
return match?.[1];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function createConsoleRouter(deps: ConsoleApiCompositionDeps): Elysia {
|
|
104
|
+
const { db, routeSnapshotService, poolSelector, telemetryBuffer, redis } = deps;
|
|
105
|
+
/**
|
|
106
|
+
* Per-request cache: `beforeHandle` resolves the session asynchronously, and
|
|
107
|
+
* the sync `ConsoleAccessResolver` contract reads the decision back out of
|
|
108
|
+
* it. Scoped to this composition rather than the module so two routers in one
|
|
109
|
+
* process (tests, or a second app instance) never share decisions.
|
|
110
|
+
*/
|
|
111
|
+
const sessionAccessCache = new WeakMap<Request, AccessDecision | null>();
|
|
112
|
+
const cookiePolicy = defaultSessionCookiePolicy;
|
|
113
|
+
const credentialService = new ConsoleCredentialService();
|
|
114
|
+
const sessionService = new ConsoleSessionService(db, cookiePolicy);
|
|
115
|
+
const lockoutService = new ConsoleLockoutService(db);
|
|
116
|
+
const setupService = new FirstBootSetupService(db, credentialService);
|
|
117
|
+
// The default gateway key is seeded only when the first-boot wizard runs, so a
|
|
118
|
+
// key set in the environment does nothing until an operator completes setup.
|
|
119
|
+
// Fire and forget: a failed check must not stop the console from mounting.
|
|
120
|
+
void setupService.requiresSetup().then((needsSetup) => {
|
|
121
|
+
if (needsSetup && resolveDefaultGatewayApiKey() !== undefined) {
|
|
122
|
+
log.warn(
|
|
123
|
+
"[setup] CARTETHYIA_API_KEY is set but no console user exists yet; complete the first-boot wizard at /console so the key is seeded",
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}).catch((error: unknown) => {
|
|
127
|
+
log.warn("[setup] could not check first-boot state", error);
|
|
128
|
+
});
|
|
129
|
+
const auditRecorder = new AuditRecorder(db);
|
|
130
|
+
const cliToolService = new CliToolService(
|
|
131
|
+
new CliToolMappingStore(db),
|
|
132
|
+
new DrizzleCliToolSecretSource(db),
|
|
133
|
+
);
|
|
134
|
+
const accessResolver: ConsoleAccessResolver = (request) =>
|
|
135
|
+
deps.accessResolver(request) ?? sessionAccessCache.get(request) ?? undefined;
|
|
136
|
+
const console = new Elysia({ prefix: "/console/api" })
|
|
137
|
+
.use(createConsoleCsrfMiddleware())
|
|
138
|
+
.use(createConsoleMutationLimiterMiddleware())
|
|
139
|
+
.beforeHandle(async ({ request }: { request: Request }) => {
|
|
140
|
+
// The auth routes (`/console/api/auth/*`) resolve the session themselves
|
|
141
|
+
// and never read `accessResolver`, so resolving here too would repeat the
|
|
142
|
+
// session lookup plus its user query on every login/session/logout call
|
|
143
|
+
// for a decision nothing consumes. Skip them.
|
|
144
|
+
if (new URL(request.url).pathname.startsWith("/console/api/auth/")) return;
|
|
145
|
+
const access = await resolveConsoleAccess(db, sessionService, request);
|
|
146
|
+
if (access) {
|
|
147
|
+
sessionAccessCache.set(request, access);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// No session cookie. A tenant API key may still reach the catalog routes
|
|
151
|
+
// it is scoped for — that is what lets a key register a BYOK provider or
|
|
152
|
+
// add a model without a browser session. The key is resolved through the
|
|
153
|
+
// same path `/v1` uses, so scopes and revocation behave identically, and
|
|
154
|
+
// a request carrying no credential at all stays unauthenticated (the
|
|
155
|
+
// routes reject it) rather than falling back to an implicit identity.
|
|
156
|
+
const bearer = readApiKeyBearer(request);
|
|
157
|
+
if (bearer === undefined) return;
|
|
158
|
+
const resolved = await resolveApiKeyAuthorization(db, bearer);
|
|
159
|
+
if (resolved === undefined) return;
|
|
160
|
+
sessionAccessCache.set(
|
|
161
|
+
request,
|
|
162
|
+
createAccessDecision({
|
|
163
|
+
id: resolved.id,
|
|
164
|
+
tenantId: resolved.tenantId,
|
|
165
|
+
scopes: resolved.scopes,
|
|
166
|
+
admissionIdentity: resolved.id,
|
|
167
|
+
}),
|
|
168
|
+
);
|
|
169
|
+
})
|
|
170
|
+
.use(
|
|
171
|
+
createConsoleAuthRoutes(
|
|
172
|
+
db,
|
|
173
|
+
credentialService,
|
|
174
|
+
sessionService,
|
|
175
|
+
lockoutService,
|
|
176
|
+
setupService,
|
|
177
|
+
cookiePolicy,
|
|
178
|
+
deps.trustedProxyBoundary ?? { mode: "disabled" },
|
|
179
|
+
(request) => deps.resolvePeerAddress?.(request) ?? undefined,
|
|
180
|
+
),
|
|
181
|
+
);
|
|
182
|
+
const ctx: ConsoleDomainContext = {
|
|
183
|
+
db,
|
|
184
|
+
accessResolver,
|
|
185
|
+
auditRecorder,
|
|
186
|
+
oauthRefreshService: deps.oauthRefreshService,
|
|
187
|
+
cliToolService,
|
|
188
|
+
redis,
|
|
189
|
+
routeSnapshotService,
|
|
190
|
+
poolSelector,
|
|
191
|
+
telemetryBuffer,
|
|
192
|
+
...(deps.stateStore ? { stateStore: deps.stateStore } : {}),
|
|
193
|
+
...(deps.shareStore ? { shareStore: deps.shareStore } : {}),
|
|
194
|
+
providerRegistry: deps.providerRegistry,
|
|
195
|
+
bundledModelCatalog: deps.bundledModelCatalog,
|
|
196
|
+
networkBindingFactory: deps.networkBindingFactory,
|
|
197
|
+
admissionService: deps.admissionService,
|
|
198
|
+
readRoutingAccountInflight: deps.readRoutingAccountInflight,
|
|
199
|
+
...(deps.flushBuffers ? { flushBuffers: deps.flushBuffers } : {}),
|
|
200
|
+
credentialService,
|
|
201
|
+
// The backup surface re-authenticates the operator, so it needs the current
|
|
202
|
+
// user's hash. Read from the session on the request that asks for it, never
|
|
203
|
+
// cached in a field, so a password change or a deactivated user takes
|
|
204
|
+
// effect on the very next attempt.
|
|
205
|
+
loadConsoleUser: async (request: Request) => {
|
|
206
|
+
const user = await resolveConsoleUser(db, sessionService, request);
|
|
207
|
+
return user === null ? null : { passwordHash: user.passwordHash };
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
registerConsoleDomains(console as unknown as Elysia, ctx);
|
|
211
|
+
// Compress the JSON control plane on the way out.
|
|
212
|
+
//
|
|
213
|
+
// `wrap` is used rather than a lifecycle hook because this Elysia beta does
|
|
214
|
+
// not deliver the response body to them: measured, both `mapResponse` and
|
|
215
|
+
// `afterHandle` receive `responseValue`/`response` as `undefined` for a
|
|
216
|
+
// plain-object route, and Elysia sets no `content-length`, so a hook has
|
|
217
|
+
// nothing to compress and no size to judge. `wrap` sits outside the router
|
|
218
|
+
// and sees the finished `Response`, which is what this needs.
|
|
219
|
+
//
|
|
220
|
+
// Scoped by path *inside* `gzipResponse`, not by this instance: Elysia's
|
|
221
|
+
// `use()` merges a child's `hoc` into the root app's ext, so this wrap is
|
|
222
|
+
// reached by `/v1/*` as well. The allowlist is `/console/api/` + `/metrics`.
|
|
223
|
+
// `/v1/*` is deliberately excluded, because a streaming completion must not
|
|
224
|
+
// be buffered and proxied bodies are the provider's own bytes. See
|
|
225
|
+
// `response-compression.ts` for the full reasoning and the measured win.
|
|
226
|
+
console.wrap(
|
|
227
|
+
(fetch) => (request: Request, ...rest: unknown[]) =>
|
|
228
|
+
Promise.resolve(fetch(request, ...rest)).then((response) =>
|
|
229
|
+
gzipResponse(request, response),
|
|
230
|
+
),
|
|
231
|
+
);
|
|
232
|
+
return console as unknown as Elysia;
|
|
233
|
+
}
|