cartethyia 2.5.10 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +8 -0
- package/dist/dashboard/assets/{BannedPage-Cd30Z0b9.js → BannedPage-l6XMnfr9.js} +1 -1
- package/dist/dashboard/assets/BannedPage-l6XMnfr9.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-wf5u-ww6.js → CliToolDetailPage-DwOzAW45.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DwOzAW45.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-DykPvuck.js → CliToolsPage-BT3Up3QA.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BT3Up3QA.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-DwvSD3vs.js → CombosPage-6kYIUpzR.js} +1 -1
- package/dist/dashboard/assets/CombosPage-6kYIUpzR.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CIr7KDex.js → ConsoleLogPage-zRnj1mlR.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-zRnj1mlR.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-82X0DDdH.js → CustomizationPage-C7m-H1Rz.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-C7m-H1Rz.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-C8MR_BdB.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-C8MR_BdB.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-CS5mPuVF.js → LoginPage-CbphLvjg.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CbphLvjg.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-C0UCUsVJ.js → ModelPicker-DVny4S5_.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DVny4S5_.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-DABu2Wgt.js +1 -0
- package/dist/dashboard/assets/OverviewPage-DABu2Wgt.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-C15x9q13.js +3 -0
- package/dist/dashboard/assets/ProviderDetailPage-C15x9q13.js.gz +0 -0
- package/dist/dashboard/assets/{ProvidersPage-vdja5ZPK.js → ProvidersPage-Dfb2896L.js} +1 -1
- package/dist/dashboard/assets/ProvidersPage-Dfb2896L.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-BB4CNm4-.js → ProxyPage-BaCIdAUt.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BaCIdAUt.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-BsdoCIw1.js +1 -0
- package/dist/dashboard/assets/QuotaPage-BsdoCIw1.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-KVJFh3Ip.js +1 -0
- package/dist/dashboard/assets/SettingsPage-KVJFh3Ip.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-FadUOl9S.js → SetupPage-D4g6vOGc.js} +1 -1
- package/dist/dashboard/assets/SetupPage-D4g6vOGc.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-Cfy6_Khv.js → SortableList-C93i14BD.js} +1 -1
- package/dist/dashboard/assets/SortableList-C93i14BD.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-CM92fgJf.js → StudioPage-SgQpymjm.js} +1 -1
- package/dist/dashboard/assets/{StudioPage-CM92fgJf.js.gz → StudioPage-SgQpymjm.js.gz} +0 -0
- package/dist/dashboard/assets/{UsagePage-BT4MyQeT.js → UsagePage-BFME-eba.js} +2 -2
- package/dist/dashboard/assets/UsagePage-BFME-eba.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-DQYLQxpW.js → api-keys-C23S9sgp.js} +1 -1
- package/dist/dashboard/assets/api-keys-C23S9sgp.js.gz +0 -0
- package/dist/dashboard/assets/{app-B7pVRhJ1.js → app-2KhtHCv9.js} +1 -1
- package/dist/dashboard/assets/{app-B7pVRhJ1.js.gz → app-2KhtHCv9.js.gz} +0 -0
- package/dist/dashboard/assets/app-CEeaMHOy.css +2 -0
- package/dist/dashboard/assets/app-CEeaMHOy.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C9FD_JwJ.js → assert-DU6qrMA_.js} +1 -1
- package/dist/dashboard/assets/assert-DU6qrMA_.js.gz +0 -0
- package/dist/dashboard/assets/{badge-Bvyr7D0u.js → badge-CKsF123d.js} +1 -1
- package/dist/dashboard/assets/badge-CKsF123d.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DIvKAZih.js → banner-8j7uChA9.js} +1 -1
- package/dist/dashboard/assets/banner-8j7uChA9.js.gz +0 -0
- package/dist/dashboard/assets/{card-D5_gYIS_.js → card-CdsSlWA3.js} +1 -1
- package/dist/dashboard/assets/card-CdsSlWA3.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-CNqzrfdb.js → cli-tools-BaFUuFFF.js} +1 -1
- package/dist/dashboard/assets/cli-tools-BaFUuFFF.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-B6vDBtbm.js → clipboard-button-uL5aYLfW.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-uL5aYLfW.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-CpjrgdwJ.js → dialog-C07hr5_G.js} +1 -1
- package/dist/dashboard/assets/dialog-C07hr5_G.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-BWmt3b5y.js → drawer-BPO1TcKH.js} +1 -1
- package/dist/dashboard/assets/drawer-BPO1TcKH.js.gz +0 -0
- package/dist/dashboard/assets/{entry-C_oakV3z.js → entry-Bz_CtDfC.js} +1 -1
- package/dist/dashboard/assets/entry-Bz_CtDfC.js.gz +0 -0
- package/dist/dashboard/assets/entry-CwPRKk0d.js +4 -0
- package/dist/dashboard/assets/entry-CwPRKk0d.js.gz +0 -0
- package/dist/dashboard/assets/entry-GJRbmrpA.js +1 -0
- package/dist/dashboard/assets/entry-GJRbmrpA.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-RRHHWGxh.js → github-badge-DmQreSDd.js} +1 -1
- package/dist/dashboard/assets/github-badge-DmQreSDd.js.gz +0 -0
- package/dist/dashboard/assets/{index-Bhey_rg_.js → index-Bblu6erR.js} +2 -2
- package/dist/dashboard/assets/index-Bblu6erR.js.gz +0 -0
- package/dist/dashboard/assets/{inline-C2_EQ5Uf.js → inline-C9dCYaBZ.js} +1 -1
- package/dist/dashboard/assets/inline-C9dCYaBZ.js.gz +0 -0
- package/dist/dashboard/assets/{input-BMRlQ450.js → input-CjCnXweJ.js} +1 -1
- package/dist/dashboard/assets/input-CjCnXweJ.js.gz +0 -0
- package/dist/dashboard/assets/{layout-XR5xP8ew.js → layout-V6y8DAkl.js} +1 -1
- package/dist/dashboard/assets/layout-V6y8DAkl.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-Cw07dioc.js → list-row-CM1AaG_y.js} +1 -1
- package/dist/dashboard/assets/list-row-CM1AaG_y.js.gz +0 -0
- package/dist/dashboard/assets/{live-BivGfuUs.js → live-ta6GMb-8.js} +1 -1
- package/dist/dashboard/assets/live-ta6GMb-8.js.gz +0 -0
- package/dist/dashboard/assets/{model-bans-CmffjLuG.js → model-bans-BmYTmbAk.js} +1 -1
- package/dist/dashboard/assets/model-bans-BmYTmbAk.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-46P0oWMe.js → mutation-g_fduiNw.js} +1 -1
- package/dist/dashboard/assets/mutation-g_fduiNw.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-DrdA9oSM.js → numbers-BOevJzdz.js} +1 -1
- package/dist/dashboard/assets/numbers-BOevJzdz.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-BFhGpwR1.js → query-keys-UETqfytp.js} +1 -1
- package/dist/dashboard/assets/query-keys-UETqfytp.js.gz +0 -0
- package/dist/dashboard/assets/{routing-CAb4F37R.js → routing-BPUo-W8d.js} +1 -1
- package/dist/dashboard/assets/routing-BPUo-W8d.js.gz +0 -0
- package/dist/dashboard/assets/{select-CxVVB__N.js → select-C980c4cz.js} +1 -1
- package/dist/dashboard/assets/select-C980c4cz.js.gz +0 -0
- package/dist/dashboard/assets/{settings-DNX9sydi.js → settings--3hxSyry.js} +1 -1
- package/dist/dashboard/assets/settings--3hxSyry.js.gz +0 -0
- package/dist/dashboard/assets/{stack-uPOwM9Hs.js → stack-_gfTdLVB.js} +1 -1
- package/dist/dashboard/assets/stack-_gfTdLVB.js.gz +0 -0
- package/dist/dashboard/assets/{state-D1Yz79iL.js → state-2c5V4zo7.js} +1 -1
- package/dist/dashboard/assets/state-2c5V4zo7.js.gz +0 -0
- package/dist/dashboard/assets/{switch-sevsRrRo.js → switch-Dkke7Naf.js} +1 -1
- package/dist/dashboard/assets/switch-Dkke7Naf.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dem0lXQj.js → useMutation-EDFRkn1i.js} +1 -1
- package/dist/dashboard/assets/useMutation-EDFRkn1i.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 +51 -51
- package/migrations/README.md +52 -52
- package/migrations/full-postgres/0020_add_telemetry_event_analytics.sql +77 -0
- package/migrations/full-postgres/0021_add_api_key_concurrency_tolerance.sql +13 -0
- package/migrations/full-postgres/0022_add_inferhub_config_key.sql +17 -0
- package/migrations/full-postgres/0023_drop_api_key_concurrency_tolerance.sql +13 -0
- package/migrations/lite-sqlite3/0020_add_telemetry_event_analytics.sql +69 -0
- package/migrations/lite-sqlite3/0021_add_api_key_concurrency_tolerance.sql +13 -0
- package/migrations/lite-sqlite3/0022_add_inferhub_config_key.sql +17 -0
- package/migrations/lite-sqlite3/0023_drop_api_key_concurrency_tolerance.sql +13 -0
- package/package.json +96 -95
- package/scripts/cli/admin.ts +126 -128
- package/scripts/cli/autostart.ts +237 -237
- package/scripts/cli/background.ts +120 -110
- package/scripts/cli/bin/carte.cjs +8 -8
- package/scripts/cli/bin/cartethyia.cjs +167 -167
- package/scripts/cli/console-menu.ts +39 -30
- package/scripts/cli/controller.ts +145 -0
- package/scripts/cli/env.ts +99 -99
- package/scripts/cli/gateway.ts +264 -260
- package/scripts/cli/instance.ts +234 -224
- package/scripts/cli/main.ts +188 -167
- package/scripts/cli/platform.ts +64 -64
- package/scripts/cli/prompt.ts +217 -79
- package/scripts/cli/services.ts +88 -88
- package/scripts/cli/setup.ts +445 -445
- package/scripts/cli/start.ts +85 -85
- package/scripts/cli/startup-signal.ts +23 -23
- package/scripts/cli/telemetry.ts +70 -0
- package/scripts/cli/tray/index.ts +263 -263
- package/scripts/cli/tray/windows.ps1 +107 -107
- package/scripts/cli/tray.ts +29 -4
- package/scripts/cli/update.ts +39 -39
- package/scripts/cli/version.ts +67 -67
- package/scripts/cli/wordmark.ts +58 -58
- package/src/boot/app.ts +16 -1
- package/src/boot/dependencies.ts +128 -25
- package/src/config/resources.ts +137 -0
- package/src/config/runtime.ts +133 -76
- package/src/config/spec.ts +30 -29
- package/src/config/telemetry.ts +0 -25
- package/src/console/api-keys/bucket-spend.ts +14 -17
- package/src/console/api-keys/contracts.ts +410 -410
- package/src/console/api-keys/routes.ts +12 -0
- package/src/console/audit/store.ts +2 -3
- package/src/console/auth/setup-service.ts +8 -1
- package/src/console/backup/routes.ts +7 -0
- package/src/console/backup/service.ts +463 -463
- package/src/console/backup/store.ts +16 -11
- package/src/console/backup/validate.ts +1 -4
- package/src/console/cli-tools/fs-ops.ts +18 -2
- package/src/console/data-management/contracts.ts +1 -8
- package/src/console/data-management/operations.ts +61 -48
- package/src/console/data-management/routes.ts +4 -2
- package/src/console/domain-registration.ts +25 -3
- package/src/console/inferhub/client.ts +139 -0
- package/src/console/inferhub/key-store.ts +129 -0
- package/src/console/inferhub/normalize.ts +347 -0
- package/src/console/inferhub/routes.ts +411 -0
- package/src/console/inferhub/store.ts +109 -0
- package/src/console/inferhub/types.ts +183 -0
- package/src/console/observability/contracts.ts +2 -41
- package/src/console/observability/store.ts +176 -371
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/store.ts +23 -36
- package/src/console/quota/account-quota-shared.ts +52 -52
- package/src/console/quota/account-quota-tenant.ts +16 -24
- package/src/console/quota/refresh.ts +441 -441
- package/src/console/routing/pools/import-parse.ts +206 -206
- package/src/console/routing/pools/operations.ts +543 -543
- package/src/console/routing/pools/probe-verdict.ts +132 -132
- package/src/console/routing/pools/routes.ts +181 -181
- package/src/console/settings/contracts.ts +42 -40
- package/src/console/settings/store.ts +25 -25
- package/src/console/share/share-stats.ts +22 -4
- package/src/console/share/share-usage.ts +30 -4
- package/src/console/shared/cursor.ts +15 -0
- package/src/console/updates/routes.ts +12 -0
- package/src/main.ts +13 -5
- package/src/network/pool/resolver.ts +1104 -1104
- package/src/observability/client-name.ts +22 -0
- package/src/observability/event-log.ts +5 -29
- package/src/observability/event-query.ts +690 -0
- package/src/observability/log-ring.ts +26 -2
- package/src/observability/log-sanitize.ts +118 -0
- package/src/observability/logger.ts +17 -13
- package/src/observability/metrics.ts +35 -0
- package/src/observability/payload-capture.ts +114 -41
- package/src/observability/payload-store.ts +249 -24
- package/src/observability/raw-event-writer.ts +118 -0
- package/src/observability/runtime-metrics.ts +71 -1
- package/src/observability/telemetry-buffer.ts +100 -17
- package/src/observability/telemetry-reconciliation.ts +417 -0
- package/src/persistence/boot.ts +20 -9
- package/src/persistence/db-pg.ts +13 -0
- package/src/persistence/db-sqlite.ts +569 -497
- package/src/persistence/dialect.ts +3 -2
- package/src/persistence/migrate.ts +181 -181
- package/src/persistence/schema.ts +1496 -1406
- package/src/persistence/shared-cache.ts +5 -1
- package/src/persistence/stores/api-key-store.ts +581 -581
- package/src/persistence/stores/telemetry-store.ts +124 -63
- package/src/protocol/reasoning-text.ts +30 -0
- package/src/protocol/response/chat.ts +33 -7
- package/src/protocol/response/codex.ts +14 -2
- package/src/protocol/response/messages.ts +5 -2
- package/src/providers/authentication/oauth-flow-store.ts +3 -10
- package/src/providers/bundled-discovery-providers.ts +122 -122
- package/src/providers/default-registry.ts +10 -0
- package/src/providers/discovery/catalog/catalog-blob.ts +18 -18
- package/src/providers/discovery/models-dev-catalog.ts +354 -354
- package/src/providers/discovery/probe-phases.ts +43 -7
- package/src/providers/discovery/probing-service.ts +70 -32
- package/src/providers/integrations/antigravity/antigravity.ts +9 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +85 -17
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +934 -934
- package/src/providers/integrations/buddy/buddy-checkin.ts +5 -9
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +3 -7
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +3 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +57 -49
- package/src/providers/integrations/buddy/codebuddy/provider.ts +180 -180
- package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -206
- package/src/providers/integrations/buddy/workbuddy/quota.ts +161 -161
- package/src/providers/integrations/claude/claude-quota.ts +2 -2
- package/src/providers/integrations/claude/claude-user-profiles.ts +3 -2
- package/src/providers/integrations/claude/claude.ts +3 -4
- package/src/providers/integrations/cline/cline.ts +94 -8
- package/src/providers/integrations/codex/codex.ts +61 -37
- package/src/providers/integrations/cursor/cursor-catalog.ts +368 -368
- package/src/providers/integrations/cursor/cursor-http2.ts +300 -300
- package/src/providers/integrations/cursor/cursor-identity.ts +2 -4
- package/src/providers/integrations/cursor/cursor-request.ts +11 -0
- package/src/providers/integrations/cursor/cursor.ts +29 -17
- package/src/providers/integrations/cursor/protocol/framing.ts +129 -129
- package/src/providers/integrations/cursor/protocol/messages.ts +2380 -2380
- package/src/providers/integrations/cursor/protocol/struct.ts +305 -305
- package/src/providers/integrations/cursor/protocol/tool-canonical.ts +275 -0
- package/src/providers/integrations/grok/grok-quota.ts +279 -279
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +73 -73
- package/src/providers/integrations/grok/grok-ratelimit.ts +218 -218
- package/src/providers/integrations/hermes.ts +7 -1
- package/src/providers/integrations/inferhub.ts +201 -73
- package/src/providers/integrations/kilo/kilo.ts +152 -152
- package/src/providers/integrations/kiro/kiro-machine-id.ts +2 -4
- package/src/providers/integrations/openrouter/provider.ts +129 -129
- package/src/providers/integrations/qoder/qoder-quota.ts +193 -192
- package/src/providers/integrations/qoder/qoder-realm.ts +106 -106
- package/src/providers/integrations/trae/trae-oauth.ts +4 -26
- package/src/providers/integrations/trae/trae-quota.ts +389 -384
- package/src/providers/integrations/trae/trae-realm.ts +15 -2
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +100 -24
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/operations/account-health-service.ts +605 -279
- package/src/providers/provider-metadata.ts +12 -1
- package/src/providers/provider-model-definition.ts +373 -373
- package/src/providers/quota/quota-contracts.ts +3 -7
- package/src/providers/search/search-provider.ts +2 -6
- package/src/security/admission/contracts.ts +10 -0
- package/src/security/admission/in-memory-store.ts +89 -14
- package/src/security/admission/lua.ts +191 -182
- package/src/security/admission/redis-store.ts +30 -0
- package/src/security/admission/service.ts +18 -0
- package/src/security/api-key-auth-cache.ts +96 -0
- package/src/security/api-key-auth.ts +11 -100
- package/src/security/client-router-fingerprint.ts +3 -7
- package/src/security/ip-boundary.ts +7 -3
- package/src/shared/coerce.ts +67 -0
- package/src/shared/hash.ts +6 -0
- package/src/shared/time.ts +7 -0
- package/src/transport/dispatch/attempt-finalize.ts +26 -138
- package/src/transport/dispatch/attempt-loop.ts +103 -81
- package/src/transport/dispatch/capture-policy.ts +78 -0
- package/src/transport/dispatch/proxy-request.ts +4 -2
- package/src/transport/dispatch/streaming/encoder.ts +111 -5
- package/src/transport/dispatch/streaming/stream.ts +19 -2
- package/src/transport/dispatch/streaming/thinking-loop.ts +300 -0
- package/src/transport/failure-policy.ts +27 -0
- package/src/transport/guards/abuse-guard.ts +2 -2
- package/src/transport/guards/auth-guard.ts +17 -0
- package/src/transport/guards/body-policy.ts +3 -2
- package/src/transport/guards/concurrency-guard.ts +89 -13
- package/src/transport/guards/early-rejection-capture.ts +43 -3
- package/src/transport/guards/error-lifecycle.ts +10 -2
- package/src/transport/guards/guard-errors.ts +23 -0
- package/src/transport/guards/headroom-guard.ts +41 -7
- package/src/transport/guards/pipeline.ts +24 -0
- package/src/transport/guards/request-context.ts +2 -1
- package/src/transport/routing/admission.ts +51 -9
- package/src/transport/routing/bounded-lru.ts +49 -0
- package/src/transport/routing/candidate-index.ts +88 -0
- package/src/transport/routing/reservations.ts +121 -7
- package/src/transport/routing/round-robin.ts +10 -22
- package/src/transport/routing/route-catalog.ts +26 -13
- package/src/transport/routing/route-model.ts +22 -2
- package/src/transport/routing/router.ts +53 -31
- package/src/transport/surface/chat/encode.ts +2 -3
- package/src/transport/surface/chat/parse.ts +2 -1
- package/src/transport/surface/dialects.ts +11 -3
- package/src/transport/surface/messages/encode.ts +2 -1
- package/src/transport/surface/messages/parse.ts +3 -1
- package/src/transport/surface/messages/stream.ts +2 -6
- package/src/workers/maintenance-lease.ts +200 -0
- package/src/workers/scheduler.ts +101 -1
- package/dist/dashboard/assets/BannedPage-Cd30Z0b9.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-wf5u-ww6.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-DykPvuck.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DwvSD3vs.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CIr7KDex.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-82X0DDdH.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BYPucTTn.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-BYPucTTn.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-CS5mPuVF.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-C0UCUsVJ.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Dk_ew3YU.js +0 -1
- package/dist/dashboard/assets/OverviewPage-Dk_ew3YU.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CAiRn2Q0.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-CAiRn2Q0.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-vdja5ZPK.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BB4CNm4-.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-FEc4iNyq.js +0 -1
- package/dist/dashboard/assets/QuotaPage-FEc4iNyq.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-Dlfi5L4N.js +0 -1
- package/dist/dashboard/assets/SettingsPage-Dlfi5L4N.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-FadUOl9S.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-Cfy6_Khv.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BT4MyQeT.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-DQYLQxpW.js.gz +0 -0
- package/dist/dashboard/assets/app-CX_Z8cMs.css +0 -2
- package/dist/dashboard/assets/app-CX_Z8cMs.css.gz +0 -0
- package/dist/dashboard/assets/assert-C9FD_JwJ.js.gz +0 -0
- package/dist/dashboard/assets/badge-Bvyr7D0u.js.gz +0 -0
- package/dist/dashboard/assets/banner-DIvKAZih.js.gz +0 -0
- package/dist/dashboard/assets/card-D5_gYIS_.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-B6vDBtbm.js.gz +0 -0
- package/dist/dashboard/assets/dialog-CpjrgdwJ.js.gz +0 -0
- package/dist/dashboard/assets/drawer-BWmt3b5y.js.gz +0 -0
- package/dist/dashboard/assets/entry-B-gvimrg.js +0 -1
- package/dist/dashboard/assets/entry-B-gvimrg.js.gz +0 -0
- package/dist/dashboard/assets/entry-C_oakV3z.js.gz +0 -0
- package/dist/dashboard/assets/entry-Dj0cHfEc.js +0 -4
- package/dist/dashboard/assets/entry-Dj0cHfEc.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-RRHHWGxh.js.gz +0 -0
- package/dist/dashboard/assets/index-Bhey_rg_.js.gz +0 -0
- package/dist/dashboard/assets/inline-C2_EQ5Uf.js.gz +0 -0
- package/dist/dashboard/assets/input-BMRlQ450.js.gz +0 -0
- package/dist/dashboard/assets/layout-XR5xP8ew.js.gz +0 -0
- package/dist/dashboard/assets/list-row-Cw07dioc.js.gz +0 -0
- package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
- package/dist/dashboard/assets/mutation-46P0oWMe.js.gz +0 -0
- package/dist/dashboard/assets/numbers-DrdA9oSM.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
- package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
- package/dist/dashboard/assets/select-CxVVB__N.js.gz +0 -0
- package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
- package/dist/dashboard/assets/stack-uPOwM9Hs.js.gz +0 -0
- package/dist/dashboard/assets/state-D1Yz79iL.js.gz +0 -0
- package/dist/dashboard/assets/switch-sevsRrRo.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dem0lXQj.js.gz +0 -0
- package/src/observability/event-compaction.ts +0 -317
- package/src/observability/event-day-index.ts +0 -439
|
Binary file
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
import { and, asc, eq, inArray, isNull, or, sql, type SQL } from "drizzle-orm";
|
|
3
3
|
import { ConsoleDomainError } from "../../shared/errors";
|
|
4
4
|
import { parseCustomProviderId, isBundledProviderId } from "../../../providers/provider-contracts";
|
|
5
|
+
import {
|
|
6
|
+
asRecord,
|
|
7
|
+
firstNonEmptyString as firstString,
|
|
8
|
+
tryParseJson as safeParseJson,
|
|
9
|
+
} from "../../../shared/coerce";
|
|
5
10
|
import type { ModelDefinition } from "../../../providers/provider-model-definition";
|
|
6
11
|
import type { ProviderRegistry } from "../../../providers/provider-registry";
|
|
7
12
|
import { BUNDLED_PROVIDER_MODULES } from "../../../providers/default-registry";
|
|
@@ -10,8 +15,7 @@ import { globalOrOwnedBy, ownedByOnly } from "../../../persistence/tenant-scope"
|
|
|
10
15
|
import { nextSortIndex, reorderSortIndex } from "../../../persistence/sort-order";
|
|
11
16
|
import type { CartethyiaDatabase } from "../../../persistence/db-handle";
|
|
12
17
|
import { buddyTaskLedger, models, providerAccounts, providerOauthStates, providers, telemetryUsageTotals, tenantDisabledModels } from "../../../persistence/schema";
|
|
13
|
-
import {
|
|
14
|
-
import { isGatewayError } from "../../../observability/telemetry-status";
|
|
18
|
+
import { breakdownTelemetry } from "../../../observability/event-query";
|
|
15
19
|
import type { WireFamily } from "../../../protocol/canonical-model";
|
|
16
20
|
import { listAccountHealthEvents, recoverAccount, deleteAccountHealthEvents, type AccountHealthEventRecord } from "../../../providers/operations/account-health-service";
|
|
17
21
|
import { invalidateCredentialCache } from "../../../providers/operations/provider-credential-service";
|
|
@@ -39,14 +43,6 @@ const OAUTH_ACCESS_FIELDS = ["accessToken", "access_token", "access", "token"] a
|
|
|
39
43
|
/** Field names a pasted OAuth credential may carry its refresh token under. */
|
|
40
44
|
const OAUTH_REFRESH_FIELDS = ["refreshToken", "refresh_token", "refresh"] as const;
|
|
41
45
|
|
|
42
|
-
function firstString(record: Record<string, unknown>, fields: readonly string[]): string | undefined {
|
|
43
|
-
for (const field of fields) {
|
|
44
|
-
const value = record[field];
|
|
45
|
-
if (typeof value === "string" && value.trim().length > 0) return value.trim();
|
|
46
|
-
}
|
|
47
|
-
return undefined;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
46
|
/** Parses an expiry field that may be an ISO string, an epoch ms, or epoch seconds. */
|
|
51
47
|
function parseExpiry(value: unknown): Date | undefined {
|
|
52
48
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
@@ -203,12 +199,6 @@ function pastedAuthState(
|
|
|
203
199
|
};
|
|
204
200
|
}
|
|
205
201
|
|
|
206
|
-
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
207
|
-
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
208
|
-
? (value as Record<string, unknown>)
|
|
209
|
-
: undefined;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
202
|
/**
|
|
213
203
|
* Adds or removes the `image` input modality on a stored modalities blob.
|
|
214
204
|
*
|
|
@@ -235,15 +225,6 @@ export function withImageModality(stored: string | null | undefined, image: bool
|
|
|
235
225
|
});
|
|
236
226
|
}
|
|
237
227
|
|
|
238
|
-
function safeParseJson(value: string | null | undefined): unknown {
|
|
239
|
-
if (typeof value !== "string" || value.length === 0) return undefined;
|
|
240
|
-
try {
|
|
241
|
-
return JSON.parse(value) as unknown;
|
|
242
|
-
} catch {
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
228
|
/** Normalizes a text column read as `unknown` back to a string or null. */
|
|
248
229
|
function asStoredText(value: unknown): string | null {
|
|
249
230
|
return typeof value === "string" ? value : null;
|
|
@@ -957,17 +938,23 @@ export class DrizzleProviderCatalogStore implements ProviderCatalogStore {
|
|
|
957
938
|
const todayStart = new Date();
|
|
958
939
|
todayStart.setUTCHours(0, 0, 0, 0);
|
|
959
940
|
const accountIds = rows.map((row) => row.id);
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
941
|
+
// Today's per-account usage is one GROUP BY, not a read of every event
|
|
942
|
+
// since midnight. `breakdownTelemetry("account")` is capped at 100 groups;
|
|
943
|
+
// a page of accounts never exceeds it, and the lookup below is by id, so a
|
|
944
|
+
// group that fell outside the cap simply reads as "no usage today" — the
|
|
945
|
+
// same value an account with no traffic gets.
|
|
946
|
+
const todayGroups = await breakdownTelemetry(this.db, tenantId, "account", todayStart);
|
|
947
|
+
const todayByAccount = new Map(
|
|
948
|
+
todayGroups.map((group) => [
|
|
949
|
+
group.key,
|
|
950
|
+
{
|
|
951
|
+
requests: group.requests,
|
|
952
|
+
errors: group.errors,
|
|
953
|
+
inputTokens: group.inputTokens,
|
|
954
|
+
outputTokens: group.outputTokens,
|
|
955
|
+
},
|
|
956
|
+
]),
|
|
957
|
+
);
|
|
971
958
|
const [lifetimeRows] = await Promise.all([
|
|
972
959
|
this.db
|
|
973
960
|
.select()
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import type { ConsoleAccessResolver } from "../auth/access";
|
|
2
|
-
import type { AuditRecorder } from "../auth/audit-recorder";
|
|
3
|
-
import { markClineApiKeyCredential } from "../../providers/integrations/cline/cline-quota";
|
|
4
|
-
import { type QuotaRefreshDeps } from "./refresh";
|
|
5
|
-
import type { AccountTestEgressDeps } from "./account-test-egress";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Dependencies shared by the tenant-scoped and global-admin account/quota route
|
|
9
|
-
* groups. Both groups are composed onto one Elysia instance by
|
|
10
|
-
* `createAccountQuotaRoutes`.
|
|
11
|
-
*/
|
|
12
|
-
export interface AccountQuotaRoutesDeps extends QuotaRefreshDeps {
|
|
13
|
-
readonly poolSelector?: AccountTestEgressDeps["poolSelector"];
|
|
14
|
-
readonly networkBindingFactory?: AccountTestEgressDeps["networkBindingFactory"];
|
|
15
|
-
readonly accessResolver: ConsoleAccessResolver;
|
|
16
|
-
readonly snapshotInvalidator?: { invalidate(): Promise<number> };
|
|
17
|
-
/** Records privileged account mutations (e.g. hard deletion) to `admin_audit_log`. */
|
|
18
|
-
readonly auditRecorder?: AuditRecorder | undefined;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const ACCOUNT_STATUSES = ["active", "cooldown", "disabled"] as const;
|
|
22
|
-
export type AccountStatus = (typeof ACCOUNT_STATUSES)[number];
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Wraps a stored api_key credential in the envelope its collector expects.
|
|
26
|
-
*
|
|
27
|
-
* Exported because every refresh path needs it, and the ones that omit it
|
|
28
|
-
* fail in a way that looks like the credential is dead: an unmarked `cline`
|
|
29
|
-
* `sk_...` key takes the OAuth branch, gets `workos:` prepended, and is
|
|
30
|
-
* refused with a message naming a version problem. The scheduled sweep once
|
|
31
|
-
* omitted it, so a working account was cooled with `quota_fetch_failed` every
|
|
32
|
-
* minute while refreshing fine from the console.
|
|
33
|
-
*/
|
|
34
|
-
export function markProviderApiKeyCredential(providerId: string, credential: string): string {
|
|
35
|
-
return providerId === "cline" ? markClineApiKeyCredential(credential) : credential;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Builds the refresh dependency bundle from the route deps, binding the
|
|
40
|
-
* provider-specific credential normalisation (`cline` API keys) once so every
|
|
41
|
-
* caller refreshes through the same wiring.
|
|
42
|
-
*/
|
|
43
|
-
export function createQuotaRefreshDeps(deps: AccountQuotaRoutesDeps): QuotaRefreshDeps {
|
|
44
|
-
return {
|
|
45
|
-
db: deps.db,
|
|
46
|
-
redis: deps.redis,
|
|
47
|
-
providerRegistry: deps.providerRegistry,
|
|
48
|
-
resolveCredential: deps.resolveCredential,
|
|
49
|
-
...(deps.snapshotInvalidator ? { snapshotInvalidator: deps.snapshotInvalidator } : {}),
|
|
50
|
-
markApiKeyCredential: markProviderApiKeyCredential,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
1
|
+
import type { ConsoleAccessResolver } from "../auth/access";
|
|
2
|
+
import type { AuditRecorder } from "../auth/audit-recorder";
|
|
3
|
+
import { markClineApiKeyCredential } from "../../providers/integrations/cline/cline-quota";
|
|
4
|
+
import { type QuotaRefreshDeps } from "./refresh";
|
|
5
|
+
import type { AccountTestEgressDeps } from "./account-test-egress";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Dependencies shared by the tenant-scoped and global-admin account/quota route
|
|
9
|
+
* groups. Both groups are composed onto one Elysia instance by
|
|
10
|
+
* `createAccountQuotaRoutes`.
|
|
11
|
+
*/
|
|
12
|
+
export interface AccountQuotaRoutesDeps extends QuotaRefreshDeps {
|
|
13
|
+
readonly poolSelector?: AccountTestEgressDeps["poolSelector"];
|
|
14
|
+
readonly networkBindingFactory?: AccountTestEgressDeps["networkBindingFactory"];
|
|
15
|
+
readonly accessResolver: ConsoleAccessResolver;
|
|
16
|
+
readonly snapshotInvalidator?: { invalidate(): Promise<number> };
|
|
17
|
+
/** Records privileged account mutations (e.g. hard deletion) to `admin_audit_log`. */
|
|
18
|
+
readonly auditRecorder?: AuditRecorder | undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const ACCOUNT_STATUSES = ["active", "cooldown", "disabled"] as const;
|
|
22
|
+
export type AccountStatus = (typeof ACCOUNT_STATUSES)[number];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Wraps a stored api_key credential in the envelope its collector expects.
|
|
26
|
+
*
|
|
27
|
+
* Exported because every refresh path needs it, and the ones that omit it
|
|
28
|
+
* fail in a way that looks like the credential is dead: an unmarked `cline`
|
|
29
|
+
* `sk_...` key takes the OAuth branch, gets `workos:` prepended, and is
|
|
30
|
+
* refused with a message naming a version problem. The scheduled sweep once
|
|
31
|
+
* omitted it, so a working account was cooled with `quota_fetch_failed` every
|
|
32
|
+
* minute while refreshing fine from the console.
|
|
33
|
+
*/
|
|
34
|
+
export function markProviderApiKeyCredential(providerId: string, credential: string): string {
|
|
35
|
+
return providerId === "cline" ? markClineApiKeyCredential(credential) : credential;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Builds the refresh dependency bundle from the route deps, binding the
|
|
40
|
+
* provider-specific credential normalisation (`cline` API keys) once so every
|
|
41
|
+
* caller refreshes through the same wiring.
|
|
42
|
+
*/
|
|
43
|
+
export function createQuotaRefreshDeps(deps: AccountQuotaRoutesDeps): QuotaRefreshDeps {
|
|
44
|
+
return {
|
|
45
|
+
db: deps.db,
|
|
46
|
+
redis: deps.redis,
|
|
47
|
+
providerRegistry: deps.providerRegistry,
|
|
48
|
+
resolveCredential: deps.resolveCredential,
|
|
49
|
+
...(deps.snapshotInvalidator ? { snapshotInvalidator: deps.snapshotInvalidator } : {}),
|
|
50
|
+
markApiKeyCredential: markProviderApiKeyCredential,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -115,7 +115,6 @@ async function runAccountCheckin(
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
/** Bound on accounts one manual daily-growth batch may cover. */
|
|
118
|
-
const DAILY_GROWTH_MAX_IDS = 100;
|
|
119
118
|
/** Concurrent accounts inside one manual daily-growth batch. */
|
|
120
119
|
const DAILY_GROWTH_CONCURRENCY = 3;
|
|
121
120
|
|
|
@@ -253,8 +252,17 @@ function checkinStateMessage(result: DailyCheckinResult): string {
|
|
|
253
252
|
}
|
|
254
253
|
}
|
|
255
254
|
|
|
255
|
+
/**
|
|
256
|
+
* How many accounts are refreshed at once.
|
|
257
|
+
*
|
|
258
|
+
* This is the bound, not a cap on how many may be requested. A tenant with
|
|
259
|
+
* several hundred accounts used to be refused outright at 100 — "accountIds
|
|
260
|
+
* exceeds the limit of 100" — so refreshing the whole fleet meant hand-batching
|
|
261
|
+
* in the UI. Concurrency is what actually protects the upstream and the
|
|
262
|
+
* gateway, and it does so regardless of how many ids arrive, so the request is
|
|
263
|
+
* accepted at any size and drained through this many workers.
|
|
264
|
+
*/
|
|
256
265
|
const QUOTA_REFRESH_CONCURRENCY = 5;
|
|
257
|
-
const QUOTA_REFRESH_MAX_IDS = 100;
|
|
258
266
|
|
|
259
267
|
/**
|
|
260
268
|
* Registers the tenant-scoped account/quota routes onto `app`. Every route here
|
|
@@ -547,13 +555,6 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
547
555
|
set.status = 400;
|
|
548
556
|
return { error: "accountIds must be a non-empty array", code: "invalid_request" };
|
|
549
557
|
}
|
|
550
|
-
if (ids.length > QUOTA_REFRESH_MAX_IDS) {
|
|
551
|
-
set.status = 400;
|
|
552
|
-
return {
|
|
553
|
-
error: `accountIds exceeds the limit of ${QUOTA_REFRESH_MAX_IDS}`,
|
|
554
|
-
code: "invalid_request",
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
558
|
const accounts = await db
|
|
558
559
|
.select({
|
|
559
560
|
accountId: providerAccounts.id,
|
|
@@ -668,16 +669,11 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
668
669
|
active: t.Boolean(),
|
|
669
670
|
}),
|
|
670
671
|
},
|
|
671
|
-
async ({ request, body
|
|
672
|
+
async ({ request, body }) => {
|
|
672
673
|
const access = requireTenantScope(accessResolver(request), "dashboard:write");
|
|
674
|
+
// No size cap: a tenant-wide enable/disable is a legitimate single
|
|
675
|
+
// request, and the UPDATE is one statement over `inArray` either way.
|
|
673
676
|
if (body.ids.length === 0) return { ok: true, updated: 0 };
|
|
674
|
-
if (body.ids.length > QUOTA_REFRESH_MAX_IDS) {
|
|
675
|
-
set.status = 400;
|
|
676
|
-
return {
|
|
677
|
-
error: `ids exceeds the limit of ${QUOTA_REFRESH_MAX_IDS}`,
|
|
678
|
-
code: "invalid_request",
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
677
|
const status = body.active ? ("active" as const) : ("disabled" as const);
|
|
682
678
|
const updated = await db
|
|
683
679
|
.update(providerAccounts)
|
|
@@ -780,13 +776,9 @@ export function registerAccountQuotaTenantRoutes(
|
|
|
780
776
|
code: "not_found",
|
|
781
777
|
};
|
|
782
778
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
error: `accountIds exceeds the limit of ${DAILY_GROWTH_MAX_IDS}`,
|
|
787
|
-
code: "invalid_request",
|
|
788
|
-
};
|
|
789
|
-
}
|
|
779
|
+
// No size cap, for the same reason as the quota refresh: the work is
|
|
780
|
+
// already drained through a bounded worker pool, so refusing the request
|
|
781
|
+
// protected nothing and just forced the operator to batch by hand.
|
|
790
782
|
// One egress rotator for the whole request, exactly as the sweep builds
|
|
791
783
|
// it, so consecutive accounts leave from consecutive pools.
|
|
792
784
|
const rotator =
|