cartethyia 2.5.4 → 2.5.6
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 +13 -4
- package/README.md +2 -2
- package/dist/dashboard/assets/{BannedPage-C2orBsI2.js → BannedPage-CADDq4IU.js} +1 -1
- package/dist/dashboard/assets/BannedPage-CADDq4IU.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-_z1hID7E.js +1 -0
- package/dist/dashboard/assets/CliToolDetailPage-_z1hID7E.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BV6pxVQo.js → CliToolsPage-DuO1Z7dq.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-DuO1Z7dq.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DNEPi3xU.js +1 -0
- package/dist/dashboard/assets/CombosPage-DNEPi3xU.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CW-wPmJ6.js → ConsoleLogPage-BVdpfiz1.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-BVdpfiz1.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-0p8uX7vB.js → CustomizationPage-BR5HHvbi.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-BR5HHvbi.js.gz +0 -0
- package/dist/dashboard/assets/{HealthEventsModal-BjqSMfko.js → HealthEventsModal-mUfcknqm.js} +1 -1
- package/dist/dashboard/assets/HealthEventsModal-mUfcknqm.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-BvzCx8Kr.js → LoginPage-V5faV9V2.js} +1 -1
- package/dist/dashboard/assets/LoginPage-V5faV9V2.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-C7pDb41R.js +1 -0
- package/dist/dashboard/assets/ModelPicker-C7pDb41R.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BDu20Jdx.js +1 -0
- package/dist/dashboard/assets/OverviewPage-BDu20Jdx.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-Dllr_aFO.js +3 -0
- package/dist/dashboard/assets/ProviderDetailPage-Dllr_aFO.js.gz +0 -0
- package/dist/dashboard/assets/{ProvidersPage-Js9jUPSb.js → ProvidersPage-uPiGVTTK.js} +1 -1
- package/dist/dashboard/assets/ProvidersPage-uPiGVTTK.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BaUkO-4O.js +7 -0
- package/dist/dashboard/assets/ProxyPage-BaUkO-4O.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-o0IFAsFb.js +1 -0
- package/dist/dashboard/assets/QuotaPage-o0IFAsFb.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CYWqbXjp.js +1 -0
- package/dist/dashboard/assets/SettingsPage-CYWqbXjp.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-DDbMQsoo.js → SetupPage-UB690SE2.js} +1 -1
- package/dist/dashboard/assets/SetupPage-UB690SE2.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-CB3Z7VTf.js → SortableList-BLujdX7N.js} +1 -1
- package/dist/dashboard/assets/SortableList-BLujdX7N.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-D95UCPHI.js → StudioPage-D5C2raAc.js} +3 -3
- package/dist/dashboard/assets/StudioPage-D5C2raAc.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-8uIcxa1W.js +56 -0
- package/dist/dashboard/assets/UsagePage-8uIcxa1W.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-DQYLQxpW.js +1 -0
- package/dist/dashboard/assets/api-keys-DQYLQxpW.js.gz +0 -0
- package/dist/dashboard/assets/app-CX_Z8cMs.css +2 -0
- package/dist/dashboard/assets/app-CX_Z8cMs.css.gz +0 -0
- package/dist/dashboard/assets/{assert-Chi7pCnt.js → assert-C9FD_JwJ.js} +1 -1
- package/dist/dashboard/assets/assert-C9FD_JwJ.js.gz +0 -0
- package/dist/dashboard/assets/{badge-D4pQapKj.js → badge-CR72dasT.js} +1 -1
- package/dist/dashboard/assets/badge-CR72dasT.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DH6cg-_B.js → banner-CI9_eSfO.js} +1 -1
- package/dist/dashboard/assets/banner-CI9_eSfO.js.gz +0 -0
- package/dist/dashboard/assets/{card-BKqlUOe4.js → card-DS7CQEsO.js} +1 -1
- package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-fTgljTGA.js → cli-tools-CNqzrfdb.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-D5Ys_sM0.js → clipboard-button-611pSsaX.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-611pSsaX.js.gz +0 -0
- package/dist/dashboard/assets/{fingerprint-pattern-BWuHtbW4.js → concurrency-BDF0ok7y.js} +1 -1
- package/dist/dashboard/assets/concurrency-BDF0ok7y.js.gz +0 -0
- package/dist/dashboard/assets/dialog-k37exjNt.js +1 -0
- package/dist/dashboard/assets/dialog-k37exjNt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CX7N8ucR.js +1 -0
- package/dist/dashboard/assets/drawer-CX7N8ucR.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CQBr6U9c.js → entry-B9Xvtnfj.js} +1 -1
- package/dist/dashboard/assets/entry-B9Xvtnfj.js.gz +0 -0
- package/dist/dashboard/assets/entry-CTP8AyiS.js +1 -0
- package/dist/dashboard/assets/entry-CTP8AyiS.js.gz +0 -0
- package/dist/dashboard/assets/entry-DxBHnauy.js +4 -0
- package/dist/dashboard/assets/entry-DxBHnauy.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-BlptL8Uf.js → github-badge-sltk1qUi.js} +1 -1
- package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
- package/dist/dashboard/assets/{index-js6TJvdr.js → index-CmxZr14F.js} +2 -2
- package/dist/dashboard/assets/index-CmxZr14F.js.gz +0 -0
- package/dist/dashboard/assets/{inline-DUWDSmDV.js → inline-BhY2sSnO.js} +1 -1
- package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
- package/dist/dashboard/assets/{input-LVjgZq4f.js → input-V1umFiBk.js} +1 -1
- package/dist/dashboard/assets/input-V1umFiBk.js.gz +0 -0
- package/dist/dashboard/assets/layout-BBOYycyS.js +1 -0
- package/dist/dashboard/assets/layout-BBOYycyS.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-DupvLfDx.js → list-row-1zzZYM0B.js} +1 -1
- package/dist/dashboard/assets/list-row-1zzZYM0B.js.gz +0 -0
- package/dist/dashboard/assets/{live-C4pEJUqI.js → live-BivGfuUs.js} +1 -1
- package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
- package/dist/dashboard/assets/{model-bans-BRiuufkB.js → model-bans-CmffjLuG.js} +1 -1
- package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-B4ROwk8L.js → mutation-46P0oWMe.js} +1 -1
- package/dist/dashboard/assets/mutation-46P0oWMe.js.gz +0 -0
- package/dist/dashboard/assets/numbers-DkfMR5Qs.js +2 -0
- package/dist/dashboard/assets/numbers-DkfMR5Qs.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-gmjzC3RS.js → query-keys-BFhGpwR1.js} +1 -1
- package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
- package/dist/dashboard/assets/{routing-C7tBT5o-.js → routing-CAb4F37R.js} +1 -1
- package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
- package/dist/dashboard/assets/{select-WUCXorXw.js → select-BYR_5K2c.js} +1 -1
- package/dist/dashboard/assets/select-BYR_5K2c.js.gz +0 -0
- package/dist/dashboard/assets/{settings-C_zKl1GS.js → settings-DNX9sydi.js} +1 -1
- package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
- package/dist/dashboard/assets/{stack-_3O0F8Xn.js → stack-BHTfXdz_.js} +1 -1
- package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
- package/dist/dashboard/assets/{state-BgTxHcJS.js → state-mPDRlQkl.js} +1 -1
- package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DEjTtOWf.js → switch-DOmJxg7H.js} +1 -1
- package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
- package/dist/dashboard/assets/tokens-COzario9.js +1 -0
- package/dist/dashboard/assets/tokens-COzario9.js.gz +0 -0
- package/dist/dashboard/assets/use-modal-focus-By7oJoGd.js +1 -0
- package/dist/dashboard/assets/use-modal-focus-By7oJoGd.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BWSC0UAS.js → useMutation-Dem0lXQj.js} +1 -1
- package/dist/dashboard/assets/useMutation-Dem0lXQj.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 -54
- package/migrations/README.md +52 -52
- package/migrations/lite-sqlite3/0000_baseline.sql +2 -2
- package/package.json +96 -95
- package/scripts/cli/admin.ts +125 -0
- package/scripts/cli/{ui/background.ts → background.ts} +1 -1
- package/scripts/cli/{command/console-menu.ts → console-menu.ts} +275 -244
- package/scripts/cli/doctor.ts +37 -0
- package/scripts/cli/{support/env.ts → env.ts} +99 -99
- package/scripts/cli/{gateway/spawn.ts → gateway.ts} +112 -24
- package/scripts/cli/instance.ts +224 -0
- package/scripts/cli/main.ts +61 -18
- package/scripts/cli/{support/platform.ts → platform.ts} +64 -64
- package/scripts/cli/port.ts +100 -0
- package/scripts/cli/{support/services.ts → services.ts} +88 -88
- package/scripts/cli/{command/setup.ts → setup.ts} +35 -34
- package/scripts/cli/{command/start.ts → start.ts} +10 -5
- package/scripts/cli/{support/startup-signal.ts → startup-signal.ts} +23 -23
- package/scripts/cli/tray/index.ts +62 -12
- package/scripts/cli/{command/tray.ts → tray.ts} +208 -208
- package/scripts/cli/{command/update.ts → update.ts} +39 -39
- package/scripts/cli/version.ts +67 -0
- package/scripts/cli/{ui/wordmark.ts → wordmark.ts} +58 -58
- package/src/boot/app.ts +697 -693
- package/src/boot/dependencies.ts +647 -646
- package/src/boot/timeout.ts +2 -13
- package/src/config/cooldowns.ts +186 -138
- package/src/config/network.ts +8 -14
- package/src/config/providers.ts +7 -10
- package/src/config/runtime.ts +76 -76
- package/src/config/security.ts +15 -0
- package/src/config/spec.ts +20 -30
- package/src/config/telemetry.ts +0 -20
- package/src/config/timeouts.ts +0 -6
- package/src/console/admin/model-abuse/contracts.ts +28 -6
- package/src/console/admin/model-abuse/routes.ts +56 -3
- package/src/console/api-keys/contracts.ts +410 -414
- package/src/console/api-keys/routes.ts +881 -880
- package/src/console/auth/credentials.ts +3 -3
- package/src/console/auth/setup-service.ts +2 -2
- package/src/console/backup/export-endpoint.ts +6 -2
- package/src/console/backup/nine-router.ts +2 -5
- package/src/console/backup/service.ts +4 -0
- package/src/console/backup/store.ts +192 -29
- package/src/console/backup/validate.ts +3 -45
- package/src/console/cli-tools/fs-ops.ts +487 -487
- package/src/console/console-router-guards.ts +1 -1
- package/src/console/data-management/contracts.ts +13 -6
- package/src/console/data-management/operations.ts +23 -18
- package/src/console/data-management/routes.ts +0 -1
- package/src/console/domain-registration.ts +10 -5
- package/src/console/observability/live.ts +22 -0
- package/src/console/observability/store.ts +39 -16
- package/src/console/observability/usage-dimensions.ts +4 -4
- package/src/console/providers/catalog/catalog-projections.ts +6 -7
- package/src/console/providers/catalog/model-operations.ts +5 -2
- package/src/console/providers/catalog/provider-operations.ts +4 -4
- package/src/console/providers/catalog/public-model-store.ts +8 -11
- package/src/console/providers/catalog/store.ts +1553 -1553
- package/src/console/providers/oauth/routes.ts +8 -12
- package/src/console/quota/account-quota-tenant.ts +6 -6
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/contracts.ts +61 -0
- package/src/console/remote-support/routes.ts +65 -0
- package/src/console/remote-support/service.ts +207 -0
- package/src/console/response-compression.ts +0 -3
- package/src/console/routing/pools/probe-result.ts +3 -2
- package/src/console/routing/pools/probe-verdict.ts +132 -132
- package/src/console/routing/pools/store.ts +8 -8
- package/src/console/settings/contracts.ts +58 -2
- package/src/console/settings/store.ts +30 -3
- package/src/console/shared/cursor.ts +8 -8
- package/src/console/shared/errors.ts +1 -3
- package/src/network/http2-bidi.ts +2 -4
- package/src/network/pool/agent.ts +478 -478
- package/src/network/pool/selector.ts +5 -4
- package/src/network/retry.ts +1 -2
- package/src/network/ssrf.ts +5 -4
- package/src/observability/event-compaction.ts +80 -78
- package/src/observability/event-day-index.ts +13 -15
- package/src/observability/event-log.ts +4 -4
- package/src/observability/logger.ts +6 -6
- package/src/observability/payload-capture.ts +151 -33
- package/src/observability/payload-store.ts +397 -440
- package/src/observability/redaction.ts +5 -6
- package/src/observability/request-notify.ts +43 -0
- package/src/observability/telemetry-status.ts +8 -9
- package/src/observability/token-speed.ts +5 -4
- package/src/persistence/db-mode.ts +7 -7
- package/src/persistence/readiness.ts +1 -1
- package/src/persistence/schema.ts +1406 -1402
- package/src/persistence/shared-cache.ts +1 -2
- package/src/persistence/stores/api-key-store.ts +18 -6
- package/src/persistence/stores/share-store.ts +4 -3
- package/src/persistence/stores/telemetry-store.ts +236 -237
- package/src/protocol/canonical-model.ts +11 -3
- package/src/protocol/codecs.ts +138 -4
- package/src/protocol/gateway-error.ts +6 -4
- package/src/protocol/request/chat.ts +21 -1
- package/src/protocol/request/codex.ts +10 -1
- package/src/protocol/request/messages.ts +4 -5
- package/src/protocol/request/responses.ts +9 -1
- package/src/protocol/response/chat.ts +34 -4
- package/src/protocol/response/codex.ts +7 -4
- package/src/protocol/response/dsml.ts +140 -28
- package/src/protocol/response/responses.ts +11 -5
- package/src/protocol/stream-error-frames.ts +4 -5
- package/src/providers/authentication/jwt-validator.ts +9 -10
- package/src/providers/authentication/oauth-refresh-service.ts +9 -11
- package/src/providers/configured-openai-providers.ts +134 -136
- package/src/providers/discovery/catalog/catalog-blob.ts +18 -18
- package/src/providers/discovery/catalog/catalog-format.ts +3 -6
- package/src/providers/discovery/models-dev-catalog.ts +354 -354
- package/src/providers/discovery/probe-phases.ts +4 -4
- package/src/providers/discovery/probe-wire.ts +6 -13
- package/src/providers/discovery/probing-service.ts +1117 -1045
- package/src/providers/integrations/alibabacp/alibabacp.ts +1 -1
- package/src/providers/integrations/antigravity/antigravity-quota.ts +5 -7
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +23 -2
- package/src/providers/integrations/buddy/buddy-checkin.ts +1 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +23 -6
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -1
- package/src/providers/integrations/buddy/buddy-identity.ts +52 -0
- package/src/providers/integrations/buddy/buddy-media.ts +2 -2
- package/src/providers/integrations/buddy/buddy-usage-store.ts +3 -4
- package/src/providers/integrations/buddy/codebuddy/quota.ts +2 -13
- package/src/providers/integrations/buddy/codebuddy/shared.ts +118 -115
- package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -11
- package/src/providers/integrations/buddy/workbuddy/shared.ts +5 -2
- package/src/providers/integrations/claude/claude.ts +608 -608
- package/src/providers/integrations/cline/cline-quota.ts +132 -132
- package/src/providers/integrations/cline/cline.ts +537 -539
- package/src/providers/integrations/codex/codex-oauth.ts +1 -1
- package/src/providers/integrations/commandcode/commandcode.ts +674 -675
- package/src/providers/integrations/commandcode/discovery.ts +117 -116
- package/src/providers/integrations/cursor/cursor-auth.ts +418 -418
- package/src/providers/integrations/cursor/cursor-quota.ts +309 -310
- package/src/providers/integrations/cursor/cursor.ts +11 -163
- package/src/providers/integrations/factory/factory-models.ts +3 -5
- package/src/providers/integrations/grok/grok-install-id.ts +2 -3
- package/src/providers/integrations/grok/grok.ts +6 -7
- package/src/providers/integrations/hermes.ts +14 -18
- package/src/providers/integrations/kiro/kiro-discovery.ts +1 -1
- package/src/providers/integrations/kiro/kiro.ts +1 -1
- package/src/providers/integrations/mistral.ts +6 -6
- package/src/providers/integrations/opencode/fingerprint.ts +3 -3
- package/src/providers/integrations/opencode/provider.ts +8 -8
- package/src/providers/integrations/qoder/qoder-catalog.ts +450 -450
- package/src/providers/integrations/qoder/qoder-oauth.ts +388 -310
- package/src/providers/integrations/qoder/qoder.ts +884 -865
- package/src/providers/integrations/shared/connect.ts +6 -6
- package/src/providers/integrations/trae/trae-catalog.ts +1 -2
- package/src/providers/integrations/trae/trae.ts +2 -2
- package/src/providers/integrations/zcode/oauth.ts +6 -1
- package/src/providers/operations/account-health-service.ts +1528 -1523
- package/src/providers/operations/account-reset-service.ts +1 -1
- package/src/providers/operations/client-versions.ts +6 -6
- package/src/providers/operations/custom-cli-headers.ts +3 -4
- package/src/providers/operations/provider-catalog-seeder.ts +95 -95
- package/src/providers/operations/provider-catalog-service.ts +3 -4
- package/src/providers/provider-metadata.ts +4 -8
- package/src/providers/provider-registry.ts +6 -7
- package/src/providers/provider-usage.ts +1 -1
- package/src/security/abuse.ts +15 -10
- package/src/security/access-control.ts +144 -146
- package/src/security/admission/contracts.ts +11 -0
- package/src/security/admission/in-memory-store.ts +4 -3
- package/src/security/admission/lease-sweep.ts +6 -6
- package/src/security/admission/reasons.ts +5 -1
- package/src/security/admission/redis-store.ts +211 -210
- package/src/security/admission/service.ts +4 -0
- package/src/security/api-key-auth.ts +504 -504
- package/src/security/ip-boundary.ts +155 -15
- package/src/security/model-abuse.ts +366 -94
- package/src/security/outbound-headers.ts +3 -4
- package/src/shared/sleep.ts +4 -0
- package/src/transport/dispatch/attempt-finalize.ts +47 -5
- package/src/transport/dispatch/attempt-loop.ts +531 -530
- package/src/transport/dispatch/stream-bridge.ts +1 -3
- package/src/transport/dispatch/streaming/finalize.ts +1 -1
- package/src/transport/dispatch/streaming/stream.ts +5 -6
- package/src/transport/failure-policy.ts +162 -8
- package/src/transport/guards/auth-guard.ts +7 -4
- package/src/transport/guards/concurrency-guard.ts +0 -5
- package/src/transport/guards/error-lifecycle.ts +13 -6
- package/src/transport/guards/pipeline.ts +15 -3
- package/src/transport/guards/request-context.ts +8 -2
- package/src/transport/request/inflight.ts +5 -6
- package/src/transport/request/preparer.ts +2 -2
- package/src/transport/request/state.ts +12 -8
- package/src/transport/routing/admission.ts +4 -0
- package/src/transport/routing/route-catalog.ts +8 -1
- package/src/transport/routing/route-model.ts +46 -14
- package/src/transport/routing/router.ts +21 -14
- package/src/transport/surface/completion.ts +2 -3
- package/src/transport/surface/dialects.ts +5 -6
- package/src/transport/surface/responses/encode.ts +38 -0
- package/src/transport/surface/responses/parse.ts +4 -0
- package/src/transport/translation/capabilities.ts +2 -3
- package/src/transport/translation/quirks.ts +3 -3
- package/src/workers/buddy-growth-tasks.ts +5 -10
- package/src/workers/daily-checkin.ts +17 -23
- package/src/workers/quota-refresh-sweep.ts +26 -26
- package/dist/dashboard/assets/BannedPage-C2orBsI2.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-DUcZ6pMB.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-DUcZ6pMB.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-BV6pxVQo.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-Bsan4679.js +0 -1
- package/dist/dashboard/assets/CombosPage-Bsan4679.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CW-wPmJ6.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-0p8uX7vB.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BjqSMfko.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-BvzCx8Kr.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BY1aKEkP.js +0 -1
- package/dist/dashboard/assets/ModelPicker-BY1aKEkP.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-DOQpy1y0.js +0 -1
- package/dist/dashboard/assets/OverviewPage-DOQpy1y0.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-ecxyUMzt.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-ecxyUMzt.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-Js9jUPSb.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-J3TBi3Kx.js +0 -7
- package/dist/dashboard/assets/ProxyPage-J3TBi3Kx.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-C1gZS6xr.js +0 -1
- package/dist/dashboard/assets/QuotaPage-C1gZS6xr.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CS86ho5X.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CS86ho5X.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-DDbMQsoo.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-CB3Z7VTf.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-D95UCPHI.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Cnae9SWA.js +0 -56
- package/dist/dashboard/assets/UsagePage-Cnae9SWA.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-VY68Mhd1.js +0 -1
- package/dist/dashboard/assets/api-keys-VY68Mhd1.js.gz +0 -0
- package/dist/dashboard/assets/app-COlK95oi.css +0 -2
- package/dist/dashboard/assets/app-COlK95oi.css.gz +0 -0
- package/dist/dashboard/assets/assert-Chi7pCnt.js.gz +0 -0
- package/dist/dashboard/assets/badge-D4pQapKj.js.gz +0 -0
- package/dist/dashboard/assets/banner-DH6cg-_B.js.gz +0 -0
- package/dist/dashboard/assets/card-BKqlUOe4.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-fTgljTGA.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-D5Ys_sM0.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BYj-8WuK.js +0 -1
- package/dist/dashboard/assets/dialog-BYj-8WuK.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CmXIZ6H1.js +0 -1
- package/dist/dashboard/assets/drawer-CmXIZ6H1.js.gz +0 -0
- package/dist/dashboard/assets/entry-CBg5zeu8.js +0 -1
- package/dist/dashboard/assets/entry-CBg5zeu8.js.gz +0 -0
- package/dist/dashboard/assets/entry-CQBr6U9c.js.gz +0 -0
- package/dist/dashboard/assets/entry-CgdSAzEV.js +0 -4
- package/dist/dashboard/assets/entry-CgdSAzEV.js.gz +0 -0
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-BlptL8Uf.js.gz +0 -0
- package/dist/dashboard/assets/index-js6TJvdr.js.gz +0 -0
- package/dist/dashboard/assets/inline-DUWDSmDV.js.gz +0 -0
- package/dist/dashboard/assets/input-LVjgZq4f.js.gz +0 -0
- package/dist/dashboard/assets/layout-CPfxpsfy.js +0 -1
- package/dist/dashboard/assets/layout-CPfxpsfy.js.gz +0 -0
- package/dist/dashboard/assets/list-row-DupvLfDx.js.gz +0 -0
- package/dist/dashboard/assets/live-C4pEJUqI.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-BRiuufkB.js.gz +0 -0
- package/dist/dashboard/assets/mutation-B4ROwk8L.js.gz +0 -0
- package/dist/dashboard/assets/numbers-YNcHvRY7.js +0 -2
- package/dist/dashboard/assets/numbers-YNcHvRY7.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-gmjzC3RS.js.gz +0 -0
- package/dist/dashboard/assets/routing-C7tBT5o-.js.gz +0 -0
- package/dist/dashboard/assets/select-WUCXorXw.js.gz +0 -0
- package/dist/dashboard/assets/settings-C_zKl1GS.js.gz +0 -0
- package/dist/dashboard/assets/stack-_3O0F8Xn.js.gz +0 -0
- package/dist/dashboard/assets/state-BgTxHcJS.js.gz +0 -0
- package/dist/dashboard/assets/switch-DEjTtOWf.js.gz +0 -0
- package/dist/dashboard/assets/tokens-DDxMbSRL.js +0 -1
- package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
- package/dist/dashboard/assets/use-presence-BSZEBx7U.js +0 -1
- package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BWSC0UAS.js.gz +0 -0
- package/scripts/cli/command/admin.ts +0 -65
- package/scripts/cli/command/doctor.ts +0 -257
- package/scripts/cli/gateway/drain-token.ts +0 -78
- package/scripts/cli/gateway/instance-lock.ts +0 -105
- package/scripts/cli/gateway/stop.ts +0 -51
- package/scripts/cli/support/bun.ts +0 -27
- package/scripts/cli/support/version.ts +0 -37
- /package/dist/dashboard/assets/{app-DCQZRmHY.js → app-BIt446yE.js} +0 -0
- /package/dist/dashboard/assets/{app-DCQZRmHY.js.gz → app-BIt446yE.js.gz} +0 -0
- /package/scripts/cli/{ui/prompt.ts → prompt.ts} +0 -0
|
@@ -3,20 +3,68 @@ import { DrizzleTelemetryStore } from "../persistence/stores/telemetry-store";
|
|
|
3
3
|
import { prunePayloadFrames, writePayloadFrame } from "./payload-store";
|
|
4
4
|
import { resolveTelemetryPayloadMaxBytes } from "../config/telemetry";
|
|
5
5
|
import { preferencesReaderFor } from "../persistence/tenant-preferences";
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
TelemetryPayloadDepth,
|
|
8
|
+
TelemetryPayloadMode,
|
|
9
|
+
TelemetryPayloadRetentionMinutes,
|
|
10
|
+
} from "../console/settings/contracts";
|
|
7
11
|
export type CaptureScope = "tenant" | "debug_session" | "operator_flag";
|
|
8
12
|
|
|
13
|
+
/**
|
|
14
|
+
* How long a captured payload frame lives when the deployment has not chosen.
|
|
15
|
+
*
|
|
16
|
+
* Exported so surfaces that report on disk usage quote the same window the
|
|
17
|
+
* capture path enforces, rather than a second copy of the default that would
|
|
18
|
+
* drift the first time this one changes.
|
|
19
|
+
*/
|
|
20
|
+
export function payloadRetentionMs(): number {
|
|
21
|
+
const raw = Number(process.env.CARTETHYIA_TELEMETRY_PAYLOAD_RETENTION_MS ?? 15 * 60_000);
|
|
22
|
+
if (!Number.isFinite(raw) || raw < 1_000 || raw > MAX_PAYLOAD_RETENTION_MS) return 15 * 60_000;
|
|
23
|
+
return Math.floor(raw);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The longest payload retention a tenant may ask for: seven days.
|
|
28
|
+
*
|
|
29
|
+
* Two things depend on this being a hard ceiling rather than a suggestion.
|
|
30
|
+
*
|
|
31
|
+
* The prune pass deletes a frame file it cannot parse once the file's last
|
|
32
|
+
* write is older than the retention window — that bound is the only thing that
|
|
33
|
+
* makes a damaged file reclaimable at all. A tenant allowed to keep frames for
|
|
34
|
+
* a year while the prune assumed an hour would have live frames deleted out
|
|
35
|
+
* from under them.
|
|
36
|
+
*
|
|
37
|
+
* The disk-usage panel counts a frame as reclaimable once its file is older
|
|
38
|
+
* than the same window. Without a ceiling it would offer a reclaim button for
|
|
39
|
+
* frames that are still live, and the operator would press it and see
|
|
40
|
+
* "nothing to reclaim".
|
|
41
|
+
*/
|
|
42
|
+
export const MAX_PAYLOAD_RETENTION_MS = 7 * 24 * 60 * 60_000;
|
|
43
|
+
|
|
44
|
+
/** Milliseconds one tenant's chosen retention resolves to. */
|
|
45
|
+
export function retentionMsFor(minutes: number | null | undefined): number {
|
|
46
|
+
if (minutes === null || minutes === undefined) return payloadRetentionMs();
|
|
47
|
+
if (!Number.isFinite(minutes)) return payloadRetentionMs();
|
|
48
|
+
return Math.min(Math.max(1_000, Math.floor(minutes * 60_000)), MAX_PAYLOAD_RETENTION_MS);
|
|
49
|
+
}
|
|
50
|
+
|
|
9
51
|
/**
|
|
10
52
|
* Settings-gated payload capture. Request-event metadata is always retained;
|
|
11
53
|
* tenants opt into drawer capture through Settings → Privacy: `metadata`
|
|
12
54
|
* keeps only the Proxy→Provider request line, `full` keeps redacted bodies
|
|
13
|
-
* at the tenant's chosen depth
|
|
55
|
+
* at the tenant's chosen depth, and both live for the tenant's chosen
|
|
56
|
+
* retention. Fail-closed on error.
|
|
14
57
|
*/
|
|
15
58
|
export async function resolvePayloadCapture(
|
|
16
59
|
db: CartethyiaDatabase,
|
|
17
60
|
tenantId: string | null,
|
|
18
61
|
): Promise<
|
|
19
|
-
| {
|
|
62
|
+
| {
|
|
63
|
+
readonly ok: true;
|
|
64
|
+
readonly mode: TelemetryPayloadMode;
|
|
65
|
+
readonly depth: TelemetryPayloadDepth;
|
|
66
|
+
readonly retentionMs: number;
|
|
67
|
+
}
|
|
20
68
|
| { readonly ok: false }
|
|
21
69
|
> {
|
|
22
70
|
if (!tenantId) return { ok: false };
|
|
@@ -24,6 +72,7 @@ export async function resolvePayloadCapture(
|
|
|
24
72
|
const prefs = await preferencesReaderFor(db).readPreferences(tenantId);
|
|
25
73
|
const mode = prefs?.telemetryPayloads;
|
|
26
74
|
const depth = prefs?.telemetryPayloadDepth;
|
|
75
|
+
const retention = prefs?.telemetryPayloadRetentionMinutes;
|
|
27
76
|
return {
|
|
28
77
|
ok: true,
|
|
29
78
|
mode: mode === "full" || mode === "metadata" || mode === "none" ? mode : "none",
|
|
@@ -37,12 +86,13 @@ export async function resolvePayloadCapture(
|
|
|
37
86
|
: depth === "full"
|
|
38
87
|
? "maximum"
|
|
39
88
|
: "minimum",
|
|
89
|
+
retentionMs: retentionMsFor(retention as TelemetryPayloadRetentionMinutes | undefined),
|
|
40
90
|
};
|
|
41
91
|
} catch {
|
|
42
92
|
// A preference read that fails must not invent capture. Off keeps nothing.
|
|
43
93
|
// Reported as its own state rather than silently as `none`: an operator
|
|
44
94
|
// whose capture is off by choice and one whose preference read is failing
|
|
45
|
-
// need different fixes, and both
|
|
95
|
+
// need different fixes, and both would otherwise look like "not configured".
|
|
46
96
|
return { ok: false };
|
|
47
97
|
}
|
|
48
98
|
}
|
|
@@ -99,6 +149,12 @@ export interface PayloadCaptureInput {
|
|
|
99
149
|
* Defaults to the configured capture limit.
|
|
100
150
|
*/
|
|
101
151
|
maxBytes?: number;
|
|
152
|
+
/**
|
|
153
|
+
* How long this frame lives, in ms. Defaults to the tenant's chosen
|
|
154
|
+
* retention, then the deployment default. Bounded by
|
|
155
|
+
* {@link MAX_PAYLOAD_RETENTION_MS} either way.
|
|
156
|
+
*/
|
|
157
|
+
retentionMs?: number;
|
|
102
158
|
scope: CaptureScope;
|
|
103
159
|
/** Links the row to `telemetry_events.request_id`. */
|
|
104
160
|
requestId?: string;
|
|
@@ -147,11 +203,6 @@ export interface StoredPayload {
|
|
|
147
203
|
* capture path enforces, rather than a second copy of the default that would
|
|
148
204
|
* drift the first time this one changes.
|
|
149
205
|
*/
|
|
150
|
-
export function payloadRetentionMs(): number {
|
|
151
|
-
const raw = Number(process.env.CARTETHYIA_TELEMETRY_PAYLOAD_RETENTION_MS ?? 15 * 60_000);
|
|
152
|
-
if (!Number.isFinite(raw) || raw < 1_000 || raw > 7 * 24 * 60 * 60_000) return 15 * 60_000;
|
|
153
|
-
return Math.floor(raw);
|
|
154
|
-
}
|
|
155
206
|
function isCaptureAllowed(input: PayloadCaptureInput): boolean {
|
|
156
207
|
// Exactly one opt-in must be set, and it must be the one `scope` names:
|
|
157
208
|
// two flags at once would silently widen capture beyond the declared scope.
|
|
@@ -209,28 +260,29 @@ function payloadSignals(values: readonly unknown[]): PayloadSignals {
|
|
|
209
260
|
* `maxBytes` (post-redaction, defaulting to the configured capture limit): a
|
|
210
261
|
* body that no longer fits is replaced with a truncation marker — no object
|
|
211
262
|
* store exists, so an oversized body is never referenced, only accounted.
|
|
212
|
-
* Payloads remain redacted and bounded during
|
|
263
|
+
* Payloads remain redacted and bounded during their retention window.
|
|
213
264
|
*
|
|
214
265
|
* Drawer order is the allocation order, and that is deliberate: the cap is a
|
|
215
266
|
* single shared budget, so whatever is accounted first is what survives a
|
|
216
267
|
* large request. `response_body` is the legacy alias of the client response
|
|
217
|
-
* and names no panel of its own, so it is accounted **last** —
|
|
218
|
-
*
|
|
219
|
-
* budget before the Provider Request and Provider Response panels
|
|
220
|
-
*
|
|
268
|
+
* and names no panel of its own, so it is accounted **last** — accounting it
|
|
269
|
+
* earlier lets a large client request plus its own duplicate consume the whole
|
|
270
|
+
* budget before the Provider Request and Provider Response panels are reached,
|
|
271
|
+
* and those two then read empty for a request that did reach an upstream.
|
|
221
272
|
*/
|
|
222
273
|
export function buildPayloadRecord(
|
|
223
274
|
input: PayloadCaptureInput,
|
|
224
275
|
now = new Date(),
|
|
225
276
|
maxBytes = resolveTelemetryPayloadMaxBytes(),
|
|
277
|
+
retentionMs = payloadRetentionMs(),
|
|
226
278
|
): Omit<StoredPayload, "id"> {
|
|
227
|
-
const expiresAt = new Date(now.getTime() +
|
|
279
|
+
const expiresAt = new Date(now.getTime() + retentionMs);
|
|
228
280
|
// Each body is serialized once, in drawer order, and only while the running
|
|
229
|
-
// total still fits the cap.
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
//
|
|
281
|
+
// total still fits the cap. Serializing every body up front to measure them
|
|
282
|
+
// and then serializing the whole record again to store it holds two copies of
|
|
283
|
+
// every body at once — measured at 23 MB of heap for 8 MB of bodies. A body
|
|
284
|
+
// that would cross the cap is never touched: its text is not built and its
|
|
285
|
+
// object is not walked for signals.
|
|
234
286
|
const surfaces: ReadonlyArray<readonly [keyof StoredPayload, unknown]> = [
|
|
235
287
|
["request_body", input.requestBody],
|
|
236
288
|
["provider_request_body", input.providerRequestBody],
|
|
@@ -270,11 +322,11 @@ export function buildPayloadRecord(
|
|
|
270
322
|
serialized.push(text);
|
|
271
323
|
kept.push(body);
|
|
272
324
|
}
|
|
273
|
-
// Only a surface that *had* a body and lost it to the cap is marked.
|
|
274
|
-
//
|
|
275
|
-
//
|
|
276
|
-
//
|
|
277
|
-
//
|
|
325
|
+
// Only a surface that *had* a body and lost it to the cap is marked.
|
|
326
|
+
// Stamping the marker onto every null surface would also mark surfaces that
|
|
327
|
+
// never carried anything — a request that never reached an upstream then
|
|
328
|
+
// reports "truncated" for a provider panel that was never captured, and the
|
|
329
|
+
// stage bitmask counts a marker as captured content.
|
|
278
330
|
const marker = (originalBytes: number): unknown => ({
|
|
279
331
|
_truncated: true,
|
|
280
332
|
_original_bytes: originalBytes,
|
|
@@ -310,14 +362,26 @@ export function buildPayloadRecord(
|
|
|
310
362
|
}
|
|
311
363
|
|
|
312
364
|
/**
|
|
313
|
-
* Postgres-backed redacted request/response payload capture. Payloads
|
|
314
|
-
*
|
|
365
|
+
* Postgres-backed redacted request/response payload capture. Payloads live for
|
|
366
|
+
* the tenant's chosen retention — 15 minutes by default — and are pruned by the
|
|
367
|
+
* sweep.
|
|
315
368
|
|
|
316
369
|
*/
|
|
317
370
|
export class TelemetryPayloadCapture {
|
|
318
371
|
private readonly store: DrizzleTelemetryStore;
|
|
319
372
|
|
|
320
|
-
constructor(
|
|
373
|
+
constructor(
|
|
374
|
+
db: CartethyiaDatabase,
|
|
375
|
+
/**
|
|
376
|
+
* Reads the tenant's chosen retention for captures that arrive without one.
|
|
377
|
+
*
|
|
378
|
+
* Injected rather than imported so the capture path does not depend on the
|
|
379
|
+
* console's settings module, and so a test can pin a retention without
|
|
380
|
+
* touching the database. Absent means every capture uses the deployment
|
|
381
|
+
* default, which is what a probe or a debug session wants anyway.
|
|
382
|
+
*/
|
|
383
|
+
private readonly retentionFor?: (tenantId: string) => Promise<number> | number,
|
|
384
|
+
) {
|
|
321
385
|
this.store = new DrizzleTelemetryStore(db);
|
|
322
386
|
}
|
|
323
387
|
|
|
@@ -327,7 +391,17 @@ export class TelemetryPayloadCapture {
|
|
|
327
391
|
code: "capture_not_opted_in",
|
|
328
392
|
});
|
|
329
393
|
}
|
|
330
|
-
|
|
394
|
+
// A caller that knows the answer passes it; otherwise the tenant's own
|
|
395
|
+
// preference is resolved, and failing that the deployment default. The
|
|
396
|
+
// early-rejection path has no preference to hand and lands here, which is
|
|
397
|
+
// why the default must be the deployment one rather than the shortest.
|
|
398
|
+
const retentionMs = await resolveRetention(input, this.retentionFor);
|
|
399
|
+
const record = buildPayloadRecord(
|
|
400
|
+
input,
|
|
401
|
+
new Date(),
|
|
402
|
+
input.maxBytes ?? resolveTelemetryPayloadMaxBytes(),
|
|
403
|
+
retentionMs,
|
|
404
|
+
);
|
|
331
405
|
const reference = await writePayloadFrame(record, record.expires_at, record._serialized
|
|
332
406
|
? {
|
|
333
407
|
requestId: record.request_id,
|
|
@@ -364,10 +438,54 @@ export class TelemetryPayloadCapture {
|
|
|
364
438
|
deleted += batch;
|
|
365
439
|
if (batch < batchSize) break;
|
|
366
440
|
}
|
|
367
|
-
//
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
|
|
441
|
+
// A file last written before *the longest retention a tenant can choose*
|
|
442
|
+
// closed cannot still hold a live frame — whatever its tenant picked, that
|
|
443
|
+
// frame has expired. Using the deployment default here instead was correct
|
|
444
|
+
// only while every frame shared one window: with a tenant allowed to keep
|
|
445
|
+
// frames for a week, a 15-minute bound would delete files still holding
|
|
446
|
+
// frames their rows address, and the drawer would silently read empty.
|
|
447
|
+
deleted += await prunePayloadFrames(now, payloadPruneBound(now));
|
|
371
448
|
return { deleted };
|
|
372
449
|
}
|
|
373
450
|
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* The cutoff before which a frame file can be deleted wholesale.
|
|
454
|
+
*
|
|
455
|
+
* Every frame expires at most {@link MAX_PAYLOAD_RETENTION_MS} after it is
|
|
456
|
+
* written, so a file last touched before that instant cannot still hold a live
|
|
457
|
+
* frame — and that is the only thing that makes a damaged, unparsable file
|
|
458
|
+
* reclaimable at all. Exported so the bound is pinned without a database: the
|
|
459
|
+
* alternative is a test that deletes a live frame and notices nothing.
|
|
460
|
+
*/
|
|
461
|
+
export function payloadPruneBound(now: Date): Date {
|
|
462
|
+
return new Date(now.getTime() - MAX_PAYLOAD_RETENTION_MS);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* How long one capture's frame should live.
|
|
467
|
+
*
|
|
468
|
+
* Order of authority: the caller's own value, then the tenant's preference,
|
|
469
|
+
* then the deployment default. A failure resolving the tenant's preference
|
|
470
|
+
* falls back rather than throwing — an unknown retention must not turn into a
|
|
471
|
+
* lost capture, and the deployment default is always a valid answer.
|
|
472
|
+
*/
|
|
473
|
+
export async function resolveRetention(
|
|
474
|
+
input: PayloadCaptureInput,
|
|
475
|
+
retentionFor?: (tenantId: string) => Promise<number> | number,
|
|
476
|
+
): Promise<number> {
|
|
477
|
+
if (typeof input.retentionMs === "number" && Number.isFinite(input.retentionMs)) {
|
|
478
|
+
return Math.min(Math.max(1_000, Math.floor(input.retentionMs)), MAX_PAYLOAD_RETENTION_MS);
|
|
479
|
+
}
|
|
480
|
+
if (retentionFor) {
|
|
481
|
+
try {
|
|
482
|
+
const value = await retentionFor(input.tenantId);
|
|
483
|
+
if (Number.isFinite(value)) {
|
|
484
|
+
return Math.min(Math.max(1_000, Math.floor(value)), MAX_PAYLOAD_RETENTION_MS);
|
|
485
|
+
}
|
|
486
|
+
} catch {
|
|
487
|
+
// Falls through to the deployment default below.
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return payloadRetentionMs();
|
|
491
|
+
}
|