cartethyia 2.5.9 → 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 +15 -42
- package/README.md +11 -10
- package/dist/dashboard/assets/{BannedPage-Brvuj_Eb.js → BannedPage-l6XMnfr9.js} +1 -1
- package/dist/dashboard/assets/BannedPage-l6XMnfr9.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-CqfXtI3y.js → CliToolDetailPage-DwOzAW45.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DwOzAW45.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-GQeS91bg.js → CliToolsPage-BT3Up3QA.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BT3Up3QA.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BDRsTXBB.js → CombosPage-6kYIUpzR.js} +1 -1
- package/dist/dashboard/assets/CombosPage-6kYIUpzR.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-zP8AFHX0.js → ConsoleLogPage-zRnj1mlR.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-zRnj1mlR.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-BmfrNZ14.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-DoreIgm8.js → LoginPage-CbphLvjg.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CbphLvjg.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-C7pDb41R.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-BnoPgA7w.js → ProvidersPage-Dfb2896L.js} +1 -1
- package/dist/dashboard/assets/ProvidersPage-Dfb2896L.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-Bq_TGgdb.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-Day3mCOn.js → SetupPage-D4g6vOGc.js} +1 -1
- package/dist/dashboard/assets/SetupPage-D4g6vOGc.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-DQxllnB5.js → SortableList-C93i14BD.js} +1 -1
- package/dist/dashboard/assets/SortableList-C93i14BD.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-uMExoWu1.js → StudioPage-SgQpymjm.js} +1 -1
- package/dist/dashboard/assets/{StudioPage-uMExoWu1.js.gz → StudioPage-SgQpymjm.js.gz} +0 -0
- package/dist/dashboard/assets/{UsagePage-DXa1oR-4.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-BIt446yE.js → app-2KhtHCv9.js} +1 -1
- package/dist/dashboard/assets/{app-BIt446yE.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-CR72dasT.js → badge-CKsF123d.js} +1 -1
- package/dist/dashboard/assets/badge-CKsF123d.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CI9_eSfO.js → banner-8j7uChA9.js} +1 -1
- package/dist/dashboard/assets/banner-8j7uChA9.js.gz +0 -0
- package/dist/dashboard/assets/{card-DS7CQEsO.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-611pSsaX.js → clipboard-button-uL5aYLfW.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-uL5aYLfW.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-k37exjNt.js → dialog-C07hr5_G.js} +1 -1
- package/dist/dashboard/assets/dialog-C07hr5_G.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CX7N8ucR.js → drawer-BPO1TcKH.js} +1 -1
- package/dist/dashboard/assets/drawer-BPO1TcKH.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CTP8AyiS.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-sltk1qUi.js → github-badge-DmQreSDd.js} +1 -1
- package/dist/dashboard/assets/github-badge-DmQreSDd.js.gz +0 -0
- package/dist/dashboard/assets/{index-z3zDOSMM.js → index-Bblu6erR.js} +2 -2
- package/dist/dashboard/assets/index-Bblu6erR.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BhY2sSnO.js → inline-C9dCYaBZ.js} +1 -1
- package/dist/dashboard/assets/inline-C9dCYaBZ.js.gz +0 -0
- package/dist/dashboard/assets/{input-V1umFiBk.js → input-CjCnXweJ.js} +1 -1
- package/dist/dashboard/assets/input-CjCnXweJ.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BBOYycyS.js → layout-V6y8DAkl.js} +1 -1
- package/dist/dashboard/assets/layout-V6y8DAkl.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-1zzZYM0B.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-DkfMR5Qs.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-C6MMiaio.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-BHTfXdz_.js → stack-_gfTdLVB.js} +1 -1
- package/dist/dashboard/assets/stack-_gfTdLVB.js.gz +0 -0
- package/dist/dashboard/assets/{state-mPDRlQkl.js → state-2c5V4zo7.js} +1 -1
- package/dist/dashboard/assets/state-2c5V4zo7.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DOmJxg7H.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 -97
- package/scripts/cli/admin.ts +126 -125
- 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 +308 -275
- package/scripts/cli/controller.ts +145 -0
- package/scripts/cli/doctor.ts +1 -1
- package/scripts/cli/env.ts +99 -99
- package/scripts/cli/gateway.ts +264 -261
- package/scripts/{health.ts → cli/health.ts} +4 -4
- package/scripts/cli/instance.ts +234 -224
- package/scripts/cli/main.ts +188 -164
- package/scripts/cli/platform.ts +64 -64
- package/scripts/cli/prompt.ts +275 -107
- package/scripts/cli/services.ts +88 -88
- package/scripts/cli/setup.ts +445 -445
- package/scripts/cli/start.ts +85 -82
- 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 +192 -208
- 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/package-paths.ts +24 -0
- 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/remote-support/service.ts +270 -114
- 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/routing/pools/store.ts +1 -1
- 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/repository-updates.ts +40 -39
- 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/registry.ts +2 -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 +14 -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/capabilities.ts +4 -0
- 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/github/github.ts +3 -1
- 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/opencode/provider.ts +2 -0
- 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-headers.ts +17 -48
- 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/trae/trae.ts +22 -24
- 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/provider-probe.ts +3 -0
- 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-Brvuj_Eb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CqfXtI3y.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-GQeS91bg.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BDRsTXBB.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-zP8AFHX0.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BmfrNZ14.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-Dn3M6WZc.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-Dn3M6WZc.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-DoreIgm8.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-C7pDb41R.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CvvD1Ugk.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CvvD1Ugk.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-Clbn1gsW.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-Clbn1gsW.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BnoPgA7w.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-Bq_TGgdb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-D9DHXvom.js +0 -1
- package/dist/dashboard/assets/QuotaPage-D9DHXvom.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-7xV8WkWL.js +0 -1
- package/dist/dashboard/assets/SettingsPage-7xV8WkWL.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-Day3mCOn.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-DQxllnB5.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DXa1oR-4.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-CR72dasT.js.gz +0 -0
- package/dist/dashboard/assets/banner-CI9_eSfO.js.gz +0 -0
- package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-611pSsaX.js.gz +0 -0
- package/dist/dashboard/assets/dialog-k37exjNt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CX7N8ucR.js.gz +0 -0
- package/dist/dashboard/assets/entry-B9Xvtnfj.js +0 -1
- package/dist/dashboard/assets/entry-B9Xvtnfj.js.gz +0 -0
- package/dist/dashboard/assets/entry-ByMGkR3C.js +0 -4
- package/dist/dashboard/assets/entry-ByMGkR3C.js.gz +0 -0
- package/dist/dashboard/assets/entry-CTP8AyiS.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
- package/dist/dashboard/assets/index-z3zDOSMM.js.gz +0 -0
- package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
- package/dist/dashboard/assets/input-V1umFiBk.js.gz +0 -0
- package/dist/dashboard/assets/layout-BBOYycyS.js.gz +0 -0
- package/dist/dashboard/assets/list-row-1zzZYM0B.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-DkfMR5Qs.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-C6MMiaio.js.gz +0 -0
- package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
- package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
- package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
- package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dem0lXQj.js.gz +0 -0
- package/scripts/build/aot.ts +0 -143
- package/scripts/build/build.ts +0 -24
- package/scripts/build/compile.ts +0 -88
- package/scripts/build/restart.ts +0 -120
- package/scripts/build/start.ts +0 -25
- package/src/observability/event-compaction.ts +0 -317
- package/src/observability/event-day-index.ts +0 -440
|
@@ -87,6 +87,9 @@ export async function buildProviderProbeRequest(
|
|
|
87
87
|
): Promise<ProviderProbeRequest | undefined> {
|
|
88
88
|
if (!isProbeableProvider(providerId)) return undefined;
|
|
89
89
|
|
|
90
|
+
// dynamic-import: cycle break -- opencode/provider transitively imports
|
|
91
|
+
// this module through the discovery helper; a static import deadlocks at
|
|
92
|
+
// load time.
|
|
90
93
|
const { OPENCODE_FREE_SPEC } = await import("./integrations/opencode/provider");
|
|
91
94
|
const spec = OPENCODE_FREE_SPEC;
|
|
92
95
|
const source = probeRequest();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { decodeJwtPayload } from "../authentication/oauth-flow-store";
|
|
2
|
+
import { asCoercedNumber, asRecord as sharedAsRecord } from "../../shared/coerce";
|
|
2
3
|
|
|
3
4
|
export interface ProviderQuotaWindow {
|
|
4
5
|
readonly kind: string;
|
|
@@ -112,9 +113,7 @@ function creditWindowBalance(
|
|
|
112
113
|
const TIMEOUT_MS = 15_000;
|
|
113
114
|
|
|
114
115
|
export function record(value: unknown): Record<string, unknown> | null {
|
|
115
|
-
return
|
|
116
|
-
? (value as Record<string, unknown>)
|
|
117
|
-
: null;
|
|
116
|
+
return sharedAsRecord(value) ?? null;
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
export function text(value: unknown): string | null {
|
|
@@ -122,10 +121,7 @@ export function text(value: unknown): string | null {
|
|
|
122
121
|
}
|
|
123
122
|
|
|
124
123
|
export function number(value: unknown): number | null {
|
|
125
|
-
|
|
126
|
-
if (typeof value === "string" && value.trim() && Number.isFinite(Number(value)))
|
|
127
|
-
return Number(value);
|
|
128
|
-
return null;
|
|
124
|
+
return asCoercedNumber(value) ?? null;
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
export function isoDate(value: unknown): string | null {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { asRecord } from "../../shared/coerce";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Declarative web-search provider adapters.
|
|
3
5
|
*
|
|
@@ -42,12 +44,6 @@ export interface SearchProviderSpec {
|
|
|
42
44
|
readonly normalize: (data: unknown) => readonly WebSearchResult[];
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
46
|
-
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
47
|
-
? (value as Record<string, unknown>)
|
|
48
|
-
: undefined;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
47
|
function stringField(record: Record<string, unknown> | undefined, key: string): string {
|
|
52
48
|
const value = record?.[key];
|
|
53
49
|
return typeof value === "string" ? value : "";
|
|
@@ -44,6 +44,16 @@ export interface AdmissionReserveRequest {
|
|
|
44
44
|
readonly lifetimeBudget: number | null;
|
|
45
45
|
readonly lifetimeConsumed: number;
|
|
46
46
|
readonly concurrencyLimit: number | null;
|
|
47
|
+
/**
|
|
48
|
+
* Hidden allowance added on top of `concurrencyLimit`.
|
|
49
|
+
*
|
|
50
|
+
* The configured limit is what an operator tunes and what the error names;
|
|
51
|
+
* this is deliberate slack so a run that lands a few requests over does not
|
|
52
|
+
* get refused at the number it was told. Effective max is
|
|
53
|
+
* `concurrencyLimit + concurrencyTolerance`. Only requests *beyond* that are
|
|
54
|
+
* refused — never ones already admitted.
|
|
55
|
+
*/
|
|
56
|
+
readonly concurrencyTolerance?: number | null | undefined;
|
|
47
57
|
readonly tenantId: string;
|
|
48
58
|
readonly tenantConcurrencyLimit: number | null;
|
|
49
59
|
/**
|
|
@@ -20,6 +20,16 @@ interface InMemoryReservation {
|
|
|
20
20
|
readonly monthlyKey: string;
|
|
21
21
|
readonly tracksLifetime: boolean;
|
|
22
22
|
readonly tracksConcurrency: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The key the concurrency counter was incremented under.
|
|
25
|
+
*
|
|
26
|
+
* Not `apiKeyId`: a share child reserves under its own id while the
|
|
27
|
+
* reservation is recorded against its parent, so charging and refunding
|
|
28
|
+
* through `apiKeyId` incremented one counter and decremented another. The
|
|
29
|
+
* child's count then never fell — after `limit` requests it was permanently
|
|
30
|
+
* full and refused everything, which is the "never invoked again" symptom.
|
|
31
|
+
*/
|
|
32
|
+
readonly concurrencyKey: string;
|
|
23
33
|
readonly tenantId: string;
|
|
24
34
|
readonly tracksTenantConcurrency: boolean;
|
|
25
35
|
state: "active" | "committed" | "released";
|
|
@@ -36,9 +46,57 @@ const TERMINAL_RESERVATION_CAP = 10_000;
|
|
|
36
46
|
const COUNTER_MAP_CAP = 20_000;
|
|
37
47
|
|
|
38
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Per-key RPM timestamp queue.
|
|
51
|
+
*
|
|
52
|
+
* Entries are appended in nondecreasing `now` order (requests are admitted
|
|
53
|
+
* under the store's exclusive gate, each stamped with its own `now`), so the
|
|
54
|
+
* window prefix is monotone: pruning advances a head index past every entry
|
|
55
|
+
* `<= cutoff` without copying the surviving suffix, and the array is compacted
|
|
56
|
+
* only when the consumed prefix exceeds half of it. Per request this is O(1)
|
|
57
|
+
* amortized instead of the previous per-request full-array rewrite.
|
|
58
|
+
*
|
|
59
|
+
* Exposed surface mirrors what the reserve path needs: `length` (window count
|
|
60
|
+
* for the limit check), `push` (append on admit), and `prune` (advance the
|
|
61
|
+
* window). `purge()` drops the whole key from the outer map.
|
|
62
|
+
*/
|
|
63
|
+
class RpmTimestampQueue {
|
|
64
|
+
private entries: number[] = [];
|
|
65
|
+
private head = 0;
|
|
66
|
+
|
|
67
|
+
get length(): number {
|
|
68
|
+
return this.entries.length - this.head;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
push(now: number): void {
|
|
72
|
+
this.entries.push(now);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Drops every entry `<= cutoff`. An entry exactly one window old is expired
|
|
77
|
+
* (the existing exact-boundary semantics: `cutoff = now - window`, so an
|
|
78
|
+
* entry at `now - window` equals the cutoff and is dropped).
|
|
79
|
+
*/
|
|
80
|
+
prune(now: number, windowMs: number): void {
|
|
81
|
+
const cutoff = now - windowMs;
|
|
82
|
+
while (this.head < this.entries.length && this.entries[this.head]! <= cutoff) {
|
|
83
|
+
this.head += 1;
|
|
84
|
+
}
|
|
85
|
+
if (this.head > this.entries.length / 2) {
|
|
86
|
+
this.entries = this.entries.slice(this.head);
|
|
87
|
+
this.head = 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** True when no live entries remain — the caller deletes the bucket. */
|
|
92
|
+
isEmpty(): boolean {
|
|
93
|
+
return this.length === 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
39
97
|
/** Atomic single-process admission store used by tests and single-process development. */
|
|
40
98
|
export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
41
|
-
private readonly rpmTimestamps = new Map<string,
|
|
99
|
+
private readonly rpmTimestamps = new Map<string, RpmTimestampQueue>();
|
|
42
100
|
private readonly daily = new Map<string, number>();
|
|
43
101
|
private readonly monthly = new Map<string, number>();
|
|
44
102
|
private readonly lifetime = new Map<string, number>();
|
|
@@ -145,8 +203,19 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
|
145
203
|
lifetime + request.estimatedTokens > request.lifetimeBudget
|
|
146
204
|
)
|
|
147
205
|
throw reasonToGatewayError("lifetime-token-budget", { limit: request.lifetimeBudget });
|
|
148
|
-
|
|
149
|
-
|
|
206
|
+
// The tolerance is slack above the configured limit, so the ceiling is
|
|
207
|
+
// the sum. It widens admission only: requests already inside are never
|
|
208
|
+
// revisited, and the refusal still names the configured limit.
|
|
209
|
+
const concurrencyCeiling =
|
|
210
|
+
request.concurrencyLimit !== null
|
|
211
|
+
? request.concurrencyLimit + Math.max(0, request.concurrencyTolerance ?? 0)
|
|
212
|
+
: null;
|
|
213
|
+
if (concurrencyCeiling !== null && concurrent >= concurrencyCeiling)
|
|
214
|
+
throw reasonToGatewayError("concurrency-limit", {
|
|
215
|
+
limit: request.concurrencyLimit,
|
|
216
|
+
tolerance: request.concurrencyTolerance ?? 0,
|
|
217
|
+
effectiveLimit: concurrencyCeiling,
|
|
218
|
+
});
|
|
150
219
|
if (
|
|
151
220
|
request.tenantConcurrencyLimit != null &&
|
|
152
221
|
tenantConcurrent >= request.tenantConcurrencyLimit
|
|
@@ -182,6 +251,7 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
|
182
251
|
monthlyKey,
|
|
183
252
|
tracksLifetime: request.lifetimeBudget != null,
|
|
184
253
|
tracksConcurrency: request.concurrencyLimit != null,
|
|
254
|
+
concurrencyKey: rpmConcId,
|
|
185
255
|
tenantId: request.tenantId,
|
|
186
256
|
tracksTenantConcurrency: request.tenantConcurrencyLimit != null,
|
|
187
257
|
state: "active",
|
|
@@ -205,7 +275,7 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
|
205
275
|
this.adjust(this.daily, reservation.dailyKey, delta, reservation.tracksDaily);
|
|
206
276
|
this.adjust(this.monthly, reservation.monthlyKey, delta, reservation.tracksMonthly);
|
|
207
277
|
this.adjust(this.lifetime, apiKeyId, delta, reservation.tracksLifetime);
|
|
208
|
-
if (reservation.tracksConcurrency) this.decrement(this.concurrent,
|
|
278
|
+
if (reservation.tracksConcurrency) this.decrement(this.concurrent, reservation.concurrencyKey);
|
|
209
279
|
if (reservation.tracksTenantConcurrency)
|
|
210
280
|
this.decrement(this.tenantConcurrent, reservation.tenantId);
|
|
211
281
|
reservation.state = "committed";
|
|
@@ -276,7 +346,7 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
|
276
346
|
}
|
|
277
347
|
|
|
278
348
|
/** Caps a bucketed counter map; oldest-inserted buckets evicted first. */
|
|
279
|
-
private evictCounter(store: Map<string, number> | Map<string,
|
|
349
|
+
private evictCounter(store: Map<string, number> | Map<string, RpmTimestampQueue>): void {
|
|
280
350
|
if (store.size < COUNTER_MAP_CAP) return;
|
|
281
351
|
let toEvict = store.size - COUNTER_MAP_CAP + 1;
|
|
282
352
|
for (const key of store.keys()) {
|
|
@@ -290,7 +360,7 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
|
290
360
|
this.adjust(this.daily, reservation.dailyKey, -reservation.reserved, reservation.tracksDaily);
|
|
291
361
|
this.adjust(this.monthly, reservation.monthlyKey, -reservation.reserved, reservation.tracksMonthly);
|
|
292
362
|
this.adjust(this.lifetime, reservation.apiKeyId, -reservation.reserved, reservation.tracksLifetime);
|
|
293
|
-
if (reservation.tracksConcurrency) this.decrement(this.concurrent, reservation.
|
|
363
|
+
if (reservation.tracksConcurrency) this.decrement(this.concurrent, reservation.concurrencyKey);
|
|
294
364
|
if (reservation.tracksTenantConcurrency)
|
|
295
365
|
this.decrement(this.tenantConcurrent, reservation.tenantId);
|
|
296
366
|
reservation.state = "released";
|
|
@@ -316,21 +386,26 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
|
|
|
316
386
|
private value(store: ReadonlyMap<string, number>, key: string): number {
|
|
317
387
|
return store.get(key) ?? 0;
|
|
318
388
|
}
|
|
319
|
-
private pruneRpm(apiKeyId: string, now: number):
|
|
320
|
-
const cutoff = now - (this.options.windowMs ?? 60_000);
|
|
389
|
+
private pruneRpm(apiKeyId: string, now: number): RpmTimestampQueue {
|
|
321
390
|
const existing = this.rpmTimestamps.get(apiKeyId);
|
|
322
391
|
if (!existing) {
|
|
323
|
-
const fresh
|
|
392
|
+
const fresh = new RpmTimestampQueue();
|
|
324
393
|
this.rpmTimestamps.set(apiKeyId, fresh);
|
|
325
394
|
this.evictCounter(this.rpmTimestamps);
|
|
326
395
|
return fresh;
|
|
327
396
|
}
|
|
328
|
-
//
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
397
|
+
// Amortized: advances the head past expired entries; compaction of the
|
|
398
|
+
// consumed prefix happens only when it exceeds half the array.
|
|
399
|
+
existing.prune(now, this.options.windowMs ?? 60_000);
|
|
400
|
+
if (existing.isEmpty()) {
|
|
401
|
+
// Drop the emptied bucket so the map cannot pin one dead queue per key
|
|
402
|
+
// the process ever served, then hand the caller a fresh queue — the
|
|
403
|
+
// caller pushes this request's timestamp into whatever it gets back, and
|
|
404
|
+
// pushing into the detached object would silently drop the admission.
|
|
405
|
+
const fresh = new RpmTimestampQueue();
|
|
406
|
+
this.rpmTimestamps.set(apiKeyId, fresh);
|
|
407
|
+
return fresh;
|
|
332
408
|
}
|
|
333
|
-
existing.length = write;
|
|
334
409
|
return existing;
|
|
335
410
|
}
|
|
336
411
|
private requireReservation(
|