cartethyia 2.7.2 → 2.7.4
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 +2 -0
- package/dist/dashboard/assets/{BannedPage-XaUmiBrC.js → BannedPage-ChG5svFb.js} +1 -1
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +1 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +1 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-CXGS_Ct-.js → CombosPage-DCgm5g6g.js} +1 -1
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
- package/dist/dashboard/assets/{HealthEventsModal-BKtAPYVF.js → HealthEventsModal-DzSWzE_j.js} +1 -1
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-BdmRLnq2.js → LoginPage-U6AKaJcF.js} +1 -1
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BH8Tehdi.js → ModelPicker-BMS2t8BA.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +1 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js +9 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js +1 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +1 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js +1 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-Dqf4zpS-.js → SortableList-ClzpwyET.js} +1 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Byj2lAEm.js → StudioPage-Cq5tW7hW.js} +3 -3
- package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +56 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js +1 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
- package/dist/dashboard/assets/app-a159k0ub.css +2 -0
- package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
- package/dist/dashboard/assets/arrow-up-59ms1iiT.js +1 -0
- package/dist/dashboard/assets/arrow-up-59ms1iiT.js.gz +0 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js +15 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DC2L43Mj.js → badge-D9CS6dZk.js} +1 -1
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BBVcb0J3.js → banner-DympBNq4.js} +1 -1
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/{card-Cca1XC6G.js → card-ibRWU_uT.js} +1 -1
- package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js +1 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DUzEbynq.js → clipboard-button-DJm-9pz7.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-DFvWhwTa.js → dialog-8fiE6tec.js} +1 -1
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js +1 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/{entry-Bqy8RFvM.js → entry-BSAsYsmV.js} +1 -1
- package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js +4 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js +1 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
- package/dist/dashboard/assets/{concurrency-BDF0ok7y.js → fingerprint-pattern-BWuHtbW4.js} +1 -1
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CWWZ-uCZ.js → formatters-D-MTJxMr.js} +1 -1
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-C9e8Ts7e.js → github-badge-CPK47xQx.js} +1 -1
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/{index-DFVFrnWW.js → index-DBNPOfhV.js} +2 -2
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BFUcvllj.js → inline-BT0zntEr.js} +1 -1
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/{input-C_ILAvBb.js → input-Da2ZViWg.js} +1 -1
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/{layout-CBIyT6Rt.js → layout-BXNeLw6M.js} +1 -1
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-ebJ_-Nsb.js → list-row-BycOrrIV.js} +1 -1
- package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js +1 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +1 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-sMD965oO.js → mutation-Rr0TIvcj.js} +1 -1
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js +1 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BO9dKaFr.js → numbers-CEagj6ZZ.js} +2 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CfL_Zdoh.js → query-keys-BloKtaXJ.js} +1 -1
- package/dist/dashboard/assets/query-keys-BloKtaXJ.js.gz +0 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js +1 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js +1 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
- package/dist/dashboard/assets/{select-DBNVLdUu.js → select-BIYIBkMU.js} +2 -2
- package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
- package/dist/dashboard/assets/settings-2-Ds9DQp0t.js +1 -0
- package/dist/dashboard/assets/settings-2-Ds9DQp0t.js.gz +0 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js +1 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
- package/dist/dashboard/assets/{stack-EMrOMt4I.js → stack-DfgnFDWY.js} +1 -1
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/{state-CWoo7ty5.js → state-CkfdYWel.js} +1 -1
- package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
- package/dist/dashboard/assets/{switch-CCjT6IkF.js → switch-SYm237HG.js} +1 -1
- package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-DjkLHUcE.js → useMutation-BQqCRNIi.js} +1 -1
- package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
- package/dist/dashboard/index.html +3 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +118 -115
- package/migrations/full-postgres/0026_add_qoder_native_identity.sql +20 -0
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +21 -0
- package/migrations/full-postgres/0028_add_family_template_key_telemetry.sql +40 -0
- package/migrations/full-postgres/0029_null_share_child_policy_columns.sql +38 -0
- package/migrations/full-postgres/0030_add_api_key_max_children.sql +10 -0
- package/migrations/full-postgres/0031_tenant_system_prompts.sql +16 -0
- package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
- package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
- package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
- package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
- package/migrations/lite-sqlite3/0026_add_qoder_native_identity.sql +15 -0
- package/migrations/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +21 -0
- package/migrations/lite-sqlite3/0028_add_family_template_key_telemetry.sql +40 -0
- package/migrations/lite-sqlite3/0029_null_share_child_policy_columns.sql +38 -0
- package/migrations/lite-sqlite3/0030_add_api_key_max_children.sql +10 -0
- package/migrations/lite-sqlite3/0031_tenant_system_prompts.sql +10 -0
- package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
- package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
- package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
- package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -0
- package/package.json +2 -1
- package/src/boot/app.ts +9 -8
- package/src/config/network.ts +7 -3
- package/src/console/api-keys/bucket-spend.ts +7 -7
- package/src/console/api-keys/contracts.ts +475 -410
- package/src/console/api-keys/routes.ts +211 -23
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/account-reset.ts +4 -4
- package/src/console/auth/session.ts +3 -3
- package/src/console/backup/contracts.ts +2 -0
- package/src/console/backup/export-endpoint.ts +14 -17
- package/src/console/backup/routes.ts +43 -11
- package/src/console/backup/service.ts +11 -6
- package/src/console/backup/store.ts +384 -88
- package/src/console/cli-tools/routes.ts +3 -3
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +4 -4
- package/src/console/dashboard-assets.ts +16 -1
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +4 -2
- package/src/console/observability/contracts.ts +4 -0
- package/src/console/observability/live.ts +3 -3
- package/src/console/observability/logs.ts +3 -3
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/store.ts +16 -16
- package/src/console/providers/catalog/contracts.ts +43 -22
- package/src/console/providers/catalog/provider-operations.ts +17 -2
- package/src/console/providers/catalog/routes.ts +3 -3
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1523 -1292
- package/src/console/providers/detail/routes.ts +3 -3
- package/src/console/providers/oauth/routes.ts +3 -3
- package/src/console/quota/account-quota-tenant.ts +34 -2
- package/src/console/quota/account-quota.ts +4 -1
- package/src/console/quota/account-test-egress.ts +4 -4
- package/src/console/quota/native-identity.ts +189 -0
- package/src/console/remote-support/contracts.ts +12 -6
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +11 -8
- package/src/console/routing/pools/operations.ts +14 -7
- package/src/console/routing/pools/probe-verdict.ts +8 -3
- package/src/console/routing/pools/relay-deploy.ts +9 -9
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/routes.ts +3 -3
- package/src/console/share/share-router.ts +51 -18
- package/src/console/share/share-stats.ts +158 -49
- package/src/console/share/share-usage.ts +24 -7
- package/src/console/shared/read-through-cache.ts +38 -2
- package/src/console/system-prompt/contracts.ts +102 -0
- package/src/console/system-prompt/routes.ts +165 -0
- package/src/console/updates/routes.ts +7 -4
- package/src/main.ts +11 -0
- package/src/network/outbound-fetch.ts +75 -4
- package/src/network/pool/resolver.ts +39 -39
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +21 -1
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/ssrf.ts +4 -4
- package/src/observability/event-query.ts +437 -22
- package/src/observability/telemetry-status.ts +1 -1
- package/src/persistence/db-pg.ts +42 -0
- package/src/persistence/db-sqlite.ts +7 -2
- package/src/persistence/readiness.ts +18 -6
- package/src/persistence/schema.ts +162 -1
- package/src/persistence/stores/api-key-store.ts +849 -581
- package/src/persistence/stores/share-store.ts +65 -13
- package/src/persistence/stores/telemetry-store.ts +58 -2
- package/src/persistence/system-prompt-store.ts +104 -0
- package/src/protocol/codecs.ts +6 -6
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-generation.ts +2 -2
- package/src/protocol/reasoning.ts +65 -1
- package/src/protocol/request/chat.ts +1 -0
- package/src/protocol/response/chat.ts +2 -2
- package/src/protocol/response/codex.ts +1 -1
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +5 -5
- package/src/protocol/response/responses.ts +2 -2
- package/src/protocol/sse-decoder.ts +14 -3
- package/src/protocol/translation/capabilities.ts +2 -2
- package/src/protocol/upstream/send-claude-messages.ts +3 -3
- package/src/providers/adapters/base-adapter.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +2 -2
- package/src/providers/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/configured-provider.ts +1 -1
- package/src/providers/discovery/probe-phases.ts +2 -2
- package/src/providers/discovery/probing-service.ts +12 -12
- package/src/providers/integrations/agentrouter/agentrouter.ts +2 -3
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- package/src/providers/integrations/antigravity/antigravity.ts +33 -47
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +30 -2
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +22 -1
- package/src/providers/integrations/buddy/buddy-media.ts +21 -17
- package/src/providers/integrations/buddy/codebuddy/provider.ts +6 -2
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -2
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-credentials.ts +1 -1
- package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
- package/src/providers/integrations/claude/claude.ts +3 -10
- package/src/providers/integrations/cline/cline.ts +8 -1
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +4 -4
- package/src/providers/integrations/commandcode/quota.ts +5 -1
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -11
- package/src/providers/integrations/cursor/cursor.ts +15 -15
- package/src/providers/integrations/factory/factory.ts +4 -4
- package/src/providers/integrations/gemini.ts +11 -11
- package/src/providers/integrations/github/github.ts +26 -7
- package/src/providers/integrations/grok/grok.ts +2 -6
- package/src/providers/integrations/hermes.ts +5 -1
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo.ts +4 -0
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- package/src/providers/integrations/kiro/kiro.ts +10 -10
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/openrouter/provider.ts +4 -0
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +47 -9
- package/src/providers/integrations/qoder/qoder-checkin.ts +242 -51
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +157 -0
- package/src/providers/integrations/qoder/qoder-oauth.ts +12 -3
- package/src/providers/integrations/qoder/qoder-realm.ts +15 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +287 -0
- package/src/providers/integrations/qoder/qoder-virtual.ts +2 -2
- package/src/providers/integrations/qoder/qoder.ts +192 -24
- package/src/providers/integrations/tokenharbor.ts +2 -2
- package/src/providers/integrations/trae/trae.ts +6 -9
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/operations/account-error-classification.ts +6 -8
- package/src/providers/operations/account-health-service.ts +14 -16
- package/src/providers/operations/client-versions.ts +37 -22
- package/src/providers/operations/provider-catalog-service.ts +4 -4
- package/src/providers/operations/provider-credential-service.ts +16 -4
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +55 -3
- package/src/providers/provider-credential-resolver.ts +1 -1
- package/src/providers/provider-registry.ts +4 -4
- package/src/providers/quota/quota-contracts.ts +24 -10
- package/src/providers/quota/refresh.ts +2 -2
- package/src/providers/search/search-provider.ts +5 -5
- package/src/security/abuse.ts +4 -4
- package/src/security/access-control.ts +19 -0
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/api-key-auth.ts +18 -5
- package/src/shared/coerce.ts +19 -0
- package/src/transport/dispatch/attempt-finalize.ts +4 -3
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/empty-stream.ts +6 -6
- package/src/transport/dispatch/generation.ts +9 -9
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/proxy-request.ts +38 -9
- package/src/transport/dispatch/responses-compact.ts +11 -11
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/finalize.ts +9 -8
- package/src/transport/dispatch/streaming/stream.ts +16 -1
- package/src/transport/dispatch/systemone.ts +8 -8
- package/src/transport/dispatch/token-count.ts +9 -9
- package/src/transport/dispatch/upstream.ts +10 -0
- package/src/transport/dispatch/websearch.ts +6 -6
- package/src/transport/drain-endpoint.ts +2 -2
- package/src/transport/failure-policy.ts +13 -6
- package/src/transport/guards/auth-guard.ts +6 -5
- package/src/transport/guards/body-policy.ts +4 -4
- package/src/transport/guards/error-lifecycle.ts +18 -3
- package/src/transport/guards/guard-errors.ts +7 -3
- package/src/transport/guards/headroom-guard.ts +1 -1
- package/src/transport/guards/pipeline.ts +6 -6
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +3 -3
- package/src/transport/request/preparer.ts +37 -21
- package/src/transport/request/state.ts +4 -7
- package/src/transport/request/system-prompt-injection.ts +89 -0
- package/src/transport/request/tenant-preferences.ts +43 -0
- package/src/transport/routing/admission.ts +13 -3
- package/src/transport/routing/route-catalog.ts +104 -2
- package/src/transport/routing/route-model.ts +60 -7
- package/src/transport/routing/router.ts +306 -256
- package/src/transport/shutdown-notice.ts +19 -7
- package/src/transport/surface/completion.ts +1 -1
- package/src/transport/surface/messages/encode.ts +1 -1
- package/src/workers/daily-checkin.ts +2 -0
- package/dist/dashboard/assets/BannedPage-XaUmiBrC.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CqD7QiLM.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-CqD7QiLM.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-0XUo4UMn.js +0 -1
- package/dist/dashboard/assets/CliToolsPage-0XUo4UMn.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CXGS_Ct-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DGnGNYnM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-DGnGNYnM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-DAG5J9EY.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-DAG5J9EY.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BKtAPYVF.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-BdmRLnq2.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BH8Tehdi.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CqMxibJB.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CqMxibJB.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CqMh2NRX.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-CqMh2NRX.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-B9uWu4Nz.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-B9uWu4Nz.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BoWOhpDO.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BoWOhpDO.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-7P2n--Fv.js +0 -1
- package/dist/dashboard/assets/QuotaPage-7P2n--Fv.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CxZ1fTkN.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CxZ1fTkN.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-Co12Zzaw.js +0 -1
- package/dist/dashboard/assets/SetupPage-Co12Zzaw.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-Dqf4zpS-.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Byj2lAEm.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-CTkLAuRc.js +0 -56
- package/dist/dashboard/assets/UsagePage-CTkLAuRc.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-CUi6UXsR.js +0 -1
- package/dist/dashboard/assets/api-keys-CUi6UXsR.js.gz +0 -0
- package/dist/dashboard/assets/app-KvsUJUMF.css +0 -2
- package/dist/dashboard/assets/app-KvsUJUMF.css.gz +0 -0
- package/dist/dashboard/assets/assert-67xXH5rf.js +0 -1
- package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
- package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
- package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
- package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js +0 -1
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
- package/dist/dashboard/assets/concurrency-BDF0ok7y.js.gz +0 -0
- package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CFM2sMX1.js +0 -1
- package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
- package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
- package/dist/dashboard/assets/entry-ClCMCWWQ.js +0 -4
- package/dist/dashboard/assets/entry-ClCMCWWQ.js.gz +0 -0
- package/dist/dashboard/assets/entry-_xHo5x6r.js +0 -1
- package/dist/dashboard/assets/entry-_xHo5x6r.js.gz +0 -0
- package/dist/dashboard/assets/formatters-CWWZ-uCZ.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
- package/dist/dashboard/assets/index-DFVFrnWW.js.gz +0 -0
- package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
- package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
- package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
- package/dist/dashboard/assets/list-row-ebJ_-Nsb.js.gz +0 -0
- package/dist/dashboard/assets/live-D0mm--ME.js +0 -1
- package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BO9dKaFr.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CfL_Zdoh.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/routing-BnIpi1IJ.js +0 -1
- package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
- package/dist/dashboard/assets/select-DBNVLdUu.js.gz +0 -0
- package/dist/dashboard/assets/settings-BAFhDgX8.js +0 -1
- package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
- package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
- package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
- package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-DjkLHUcE.js.gz +0 -0
- /package/dist/dashboard/assets/{app-BaWd0puM.js → app-BayTTy01.js} +0 -0
- /package/dist/dashboard/assets/{app-BaWd0puM.js.gz → app-BayTTy01.js.gz} +0 -0
|
@@ -89,12 +89,15 @@ async function runReadinessChecks(
|
|
|
89
89
|
|
|
90
90
|
// 1. Check database connectivity via simple query
|
|
91
91
|
let dbOk = false;
|
|
92
|
+
let dbTimedOut = false;
|
|
92
93
|
try {
|
|
93
94
|
const result = await withTimeoutCheck(
|
|
94
95
|
() => db.execute(sql`SELECT 1`),
|
|
95
96
|
"Database connectivity check",
|
|
96
97
|
);
|
|
97
|
-
if (result
|
|
98
|
+
if (result === "timeout") {
|
|
99
|
+
dbTimedOut = true;
|
|
100
|
+
} else {
|
|
98
101
|
dbOk = true;
|
|
99
102
|
}
|
|
100
103
|
} catch {
|
|
@@ -107,7 +110,10 @@ async function runReadinessChecks(
|
|
|
107
110
|
db: "disconnected",
|
|
108
111
|
migrations: "pending",
|
|
109
112
|
redis: "disconnected",
|
|
110
|
-
|
|
113
|
+
// A timed-out probe under load is not evidence the database is down —
|
|
114
|
+
// it is the probe itself failing to get a backend in time. The guard
|
|
115
|
+
// reads this to call it overload rather than a dependency failure.
|
|
116
|
+
reason: dbTimedOut ? "database probe timed out" : "database not connected",
|
|
111
117
|
};
|
|
112
118
|
}
|
|
113
119
|
|
|
@@ -115,13 +121,16 @@ async function runReadinessChecks(
|
|
|
115
121
|
// Readiness requires every discovered migration to have a ledger row; a
|
|
116
122
|
// reachable ledger alone is not proof the upgrade finished.
|
|
117
123
|
let migrationsApplied = false;
|
|
124
|
+
let migrationsTimedOut = false;
|
|
118
125
|
try {
|
|
119
126
|
const result = await withTimeoutCheck(
|
|
120
127
|
() => readMigrationLedgerStatus(db),
|
|
121
128
|
"Migrations check",
|
|
122
129
|
);
|
|
123
130
|
|
|
124
|
-
if (result
|
|
131
|
+
if (result === "timeout") {
|
|
132
|
+
migrationsTimedOut = true;
|
|
133
|
+
} else {
|
|
125
134
|
migrationsApplied = result.applied;
|
|
126
135
|
}
|
|
127
136
|
} catch {
|
|
@@ -134,18 +143,21 @@ async function runReadinessChecks(
|
|
|
134
143
|
db: "connected",
|
|
135
144
|
migrations: "pending",
|
|
136
145
|
redis: "disconnected",
|
|
137
|
-
reason: "migrations not yet applied",
|
|
146
|
+
reason: migrationsTimedOut ? "migrations probe timed out" : "migrations not yet applied",
|
|
138
147
|
};
|
|
139
148
|
}
|
|
140
149
|
|
|
141
150
|
// 3. Check Redis. The memory backend is healthy by construction — there is
|
|
142
151
|
// no connection to probe — so it passes without a round trip.
|
|
143
152
|
let redisOk = redisBackend === "memory";
|
|
153
|
+
let redisTimedOut = false;
|
|
144
154
|
|
|
145
155
|
if (redisBackend === "redis" && redis) {
|
|
146
156
|
try {
|
|
147
157
|
const result = await withTimeoutCheck(() => redis.ping(), "Redis connectivity check");
|
|
148
|
-
if (result
|
|
158
|
+
if (result === "timeout") {
|
|
159
|
+
redisTimedOut = true;
|
|
160
|
+
} else if (result === "PONG") {
|
|
149
161
|
redisOk = true;
|
|
150
162
|
}
|
|
151
163
|
} catch {
|
|
@@ -159,7 +171,7 @@ async function runReadinessChecks(
|
|
|
159
171
|
db: "connected",
|
|
160
172
|
migrations: "applied",
|
|
161
173
|
redis: "disconnected",
|
|
162
|
-
reason: "redis not connected",
|
|
174
|
+
reason: redisTimedOut ? "redis probe timed out" : "redis not connected",
|
|
163
175
|
};
|
|
164
176
|
}
|
|
165
177
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { desc, sql } from "drizzle-orm";
|
|
3
3
|
import {
|
|
4
4
|
bigint, boolean, check, customType, index, integer, jsonb, numeric, pgEnum, pgTable,
|
|
5
|
-
primaryKey, text, timestamp, uniqueIndex, uuid, type AnyPgColumn,
|
|
5
|
+
primaryKey, text, timestamp, unique, uniqueIndex, uuid, type AnyPgColumn,
|
|
6
6
|
} from "drizzle-orm/pg-core";
|
|
7
7
|
|
|
8
8
|
export const TENANT_STATUSES = ["active", "suspended", "deleted"] as const;
|
|
@@ -183,6 +183,32 @@ export const providers = pgTable(
|
|
|
183
183
|
// tenant-owned/BYOK. The concurrency ceiling lives in provider routing
|
|
184
184
|
// (`provider_routing_settings.max_inflight`) and network pools
|
|
185
185
|
// (`network_pools.max_inflight`); there is no per-account override.
|
|
186
|
+
/**
|
|
187
|
+
* A Qoder native machine identity (UMID) bound to one account.
|
|
188
|
+
*
|
|
189
|
+
* The device identity is a deterministic function of a seed file
|
|
190
|
+
* (`~/.config/.locale_cfg`): the `runtime-info` bridge reads that seed and
|
|
191
|
+
* derives `machineToken`/`machineType`/`machineCode`. The daily 100-credit
|
|
192
|
+
* campaign does not gate grants on this identity. A persisted seed allows the
|
|
193
|
+
* vendor bridge to replay the same native identity where another Qoder surface
|
|
194
|
+
* requires it.
|
|
195
|
+
*
|
|
196
|
+
* `seed` is the exact seed-file content the identity was minted from, stored
|
|
197
|
+
* so the same device identity can be replayed (restore seed → bridge → same
|
|
198
|
+
* token). It is not a credential, but it is per-account device material and
|
|
199
|
+
* should not be shared between accounts. Campaign grant eligibility is
|
|
200
|
+
* independent of `machineToken`.
|
|
201
|
+
*/
|
|
202
|
+
export interface NativeIdentityRecord {
|
|
203
|
+
readonly machineToken: string;
|
|
204
|
+
readonly machineType: string;
|
|
205
|
+
readonly machineCode: string;
|
|
206
|
+
/** The seed-file content this identity was minted from, if captured. */
|
|
207
|
+
readonly seed?: string;
|
|
208
|
+
/** How this identity was produced: the genuine SG bridge or the fallback. */
|
|
209
|
+
readonly source?: "runtime-info" | "generated";
|
|
210
|
+
}
|
|
211
|
+
|
|
186
212
|
export const providerAccounts = pgTable("provider_accounts", {
|
|
187
213
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
188
214
|
providerId: text("provider_id")
|
|
@@ -270,6 +296,18 @@ export const providerAccounts = pgTable("provider_accounts", {
|
|
|
270
296
|
*/
|
|
271
297
|
quotaPlan: text("quota_plan"),
|
|
272
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Qoder native machine identity bound to this account, as one JSON object
|
|
301
|
+
* (see {@link NativeIdentityRecord}). `null` means the account has no bound
|
|
302
|
+
* identity: the check-in mints one on first use.
|
|
303
|
+
*
|
|
304
|
+
* Deliberately a dedicated column, not a key inside `auth_state`: the
|
|
305
|
+
* device token is queryable ("which device is taken by whom") and enforced
|
|
306
|
+
* unique by the partial index below, and it must survive backup/restore
|
|
307
|
+
* like any other non-secret column.
|
|
308
|
+
*/
|
|
309
|
+
nativeIdentity: jsonb("native_identity").$type<NativeIdentityRecord | null>(),
|
|
310
|
+
|
|
273
311
|
},
|
|
274
312
|
(table) => [
|
|
275
313
|
uniqueIndex("provider_accounts_identity_uidx").on(
|
|
@@ -290,6 +328,17 @@ export const providerAccounts = pgTable("provider_accounts", {
|
|
|
290
328
|
// predicate that does not constrain `provider_id`. This one matches the
|
|
291
329
|
// hot listing path.
|
|
292
330
|
index("provider_accounts_tenant_id_idx").on(table.tenantId),
|
|
331
|
+
// One Qoder device identity per account: the partial unique index on the
|
|
332
|
+
// extracted `machineToken` guarantees two accounts never share a device,
|
|
333
|
+
// which is what makes the daily 100-credit grant reusable per account
|
|
334
|
+
// instead of colliding on a device identity. `NULL` rows (unbound
|
|
335
|
+
// accounts) are excluded so the uniqueness only applies to bound
|
|
336
|
+
// identities. The Postgres migration spells the expression
|
|
337
|
+
// `(native_identity ->> 'machineToken')`; the SQLite migration spells it
|
|
338
|
+
// `json_extract(native_identity, '$.machineToken')`.
|
|
339
|
+
uniqueIndex("provider_accounts_native_identity_token_uidx")
|
|
340
|
+
.on(sql`(${table.nativeIdentity} ->> 'machineToken')`)
|
|
341
|
+
.where(sql`${table.nativeIdentity} IS NOT NULL`),
|
|
293
342
|
],
|
|
294
343
|
);
|
|
295
344
|
|
|
@@ -521,6 +570,49 @@ export const networkPools = pgTable("network_pools", {
|
|
|
521
570
|
],
|
|
522
571
|
);
|
|
523
572
|
|
|
573
|
+
/**
|
|
574
|
+
* A pool's account-equivalent routing entity for ip-scoped, credential-less
|
|
575
|
+
* providers (OpenCode Free today).
|
|
576
|
+
*
|
|
577
|
+
* These providers own no `provider_accounts` rows — the rate limit belongs to
|
|
578
|
+
* the egress address, not to a credential. Materializing one row per (pool,
|
|
579
|
+
* ip-scoped provider) lets the account health machine, routing eligibility, and
|
|
580
|
+
* the provider-detail accounts UI treat each egress like an account: the row
|
|
581
|
+
* carries the same health state machine and cooldown columns, so a spent egress
|
|
582
|
+
* is excluded from the plan the same way a cooling account is, and the operator
|
|
583
|
+
* sees it in the provider's Accounts card with a "Pool" badge.
|
|
584
|
+
*
|
|
585
|
+
* The row is an *account-equivalent*, not an account: it resolves no credential
|
|
586
|
+
* (`credential_kind` is fixed to `none`-style egress), is skipped by the quota
|
|
587
|
+
* refresh and identity sweeps (they filter on real credential kinds), and is
|
|
588
|
+
* owned by its pool — deleting the pool cascades the row.
|
|
589
|
+
*/
|
|
590
|
+
export const providerPoolAccounts = pgTable(
|
|
591
|
+
"provider_pool_accounts",
|
|
592
|
+
{
|
|
593
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
594
|
+
tenantId: tenantRefRequired(),
|
|
595
|
+
networkPoolId: uuid("network_pool_id")
|
|
596
|
+
.notNull()
|
|
597
|
+
.references(() => networkPools.id, { onDelete: "cascade" }),
|
|
598
|
+
providerId: text("provider_id").notNull(),
|
|
599
|
+
label: text("label").notNull(),
|
|
600
|
+
...healthColumns(),
|
|
601
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
602
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
603
|
+
},
|
|
604
|
+
(table) => [
|
|
605
|
+
unique("provider_pool_accounts_pool_provider_uidx").on(
|
|
606
|
+
table.networkPoolId,
|
|
607
|
+
table.providerId,
|
|
608
|
+
table.tenantId,
|
|
609
|
+
),
|
|
610
|
+
index("provider_pool_accounts_tenant_status_idx").on(table.tenantId, table.status),
|
|
611
|
+
index("provider_pool_accounts_provider_status_idx").on(table.providerId, table.status),
|
|
612
|
+
],
|
|
613
|
+
);
|
|
614
|
+
export type ProviderPoolAccount = typeof providerPoolAccounts.$inferSelect;
|
|
615
|
+
|
|
524
616
|
|
|
525
617
|
// Account and network-pool health events share one table. The entity kind
|
|
526
618
|
// selects exactly one owner FK, and the CHECK constraint below preserves
|
|
@@ -766,6 +858,13 @@ export const apiKeys = pgTable(
|
|
|
766
858
|
.notNull()
|
|
767
859
|
.default(0),
|
|
768
860
|
maxConcurrentRequests: integer("max_concurrent_requests"),
|
|
861
|
+
/**
|
|
862
|
+
* Slot cap for a share template: the maximum number of concurrently
|
|
863
|
+
* active child keys it may mint. `null` = unlimited (legacy behavior).
|
|
864
|
+
* Enforced at mint time in `issueSharedApiKey`; the console exposes it as
|
|
865
|
+
* the template's "slots".
|
|
866
|
+
*/
|
|
867
|
+
maxChildren: integer("max_children"),
|
|
769
868
|
/**
|
|
770
869
|
* `whitelist` = only the names in `modelList` may be used (empty = all);
|
|
771
870
|
* `blacklist` = the names in `modelList` are refused (empty = none). One
|
|
@@ -790,6 +889,21 @@ export const apiKeys = pgTable(
|
|
|
790
889
|
createdAt: createdAtColumn(),
|
|
791
890
|
enabled: boolean("enabled").notNull().default(true),
|
|
792
891
|
revokedAt: timestamp("revoked_at", { withTimezone: true }),
|
|
892
|
+
/**
|
|
893
|
+
* Ban state. A ban is distinct from a revoke: it records the operator's
|
|
894
|
+
* reason (`banReason`) so the console can show it, and it is fully
|
|
895
|
+
* reversible — unban clears both columns, leaving no metadata behind.
|
|
896
|
+
* Banned keys are rejected by the auth path exactly like revoked keys.
|
|
897
|
+
*/
|
|
898
|
+
bannedAt: timestamp("banned_at", { withTimezone: true }),
|
|
899
|
+
banReason: text("ban_reason"),
|
|
900
|
+
/**
|
|
901
|
+
* When the ban lifts on its own, if it is not permanent. `null` means the
|
|
902
|
+
* ban does not lapse (until an operator unbans it). The auth path treats a
|
|
903
|
+
* key as banned only while `banned_at` is set and `banned_until` is either
|
|
904
|
+
* null or in the future — so a timed ban expires without SQL.
|
|
905
|
+
*/
|
|
906
|
+
bannedUntil: timestamp("banned_until", { withTimezone: true }),
|
|
793
907
|
/**
|
|
794
908
|
* The tenant's mandatory gateway key. Seeded at first boot whether or not
|
|
795
909
|
* `CARTETHYIA_API_KEY` was configured, and the one key the console refuses
|
|
@@ -1126,6 +1240,26 @@ export const consoleSettings = pgTable("console_settings", {
|
|
|
1126
1240
|
updatedAt: updatedAtColumn(),
|
|
1127
1241
|
});
|
|
1128
1242
|
|
|
1243
|
+
// Tenant-scoped system prompt injection (append/override). One row per
|
|
1244
|
+
// tenant; `global` NULL means never configured, distinct from an explicit
|
|
1245
|
+
// disabled setting. Providers/models are JSON object maps keyed by
|
|
1246
|
+
// providerId and `providerId::modelId` respectively — see
|
|
1247
|
+
// `src/console/system-prompt/contracts.ts` for the value shapes and the
|
|
1248
|
+
// resolution rules implemented by the dispatch-path transform.
|
|
1249
|
+
export const tenantSystemPrompts = pgTable("tenant_system_prompts", {
|
|
1250
|
+
tenantId: tenantRefPrimaryKey(),
|
|
1251
|
+
global: jsonb("global").$type<import("../console/system-prompt/contracts").PromptSetting | null>(),
|
|
1252
|
+
providers: jsonb("providers")
|
|
1253
|
+
.notNull()
|
|
1254
|
+
.default({})
|
|
1255
|
+
.$type<Record<string, import("../console/system-prompt/contracts").ProviderPromptEntry>>(),
|
|
1256
|
+
models: jsonb("models")
|
|
1257
|
+
.notNull()
|
|
1258
|
+
.default({})
|
|
1259
|
+
.$type<Record<string, import("../console/system-prompt/contracts").PromptSetting>>(),
|
|
1260
|
+
updatedAt: updatedAtColumn(),
|
|
1261
|
+
});
|
|
1262
|
+
|
|
1129
1263
|
// InferHub `config_read` key. One row for the whole deployment.
|
|
1130
1264
|
//
|
|
1131
1265
|
// Deliberately NOT `provider_accounts.auth_state`: that field is documented as
|
|
@@ -1229,6 +1363,14 @@ export const telemetryEvents = pgTable(
|
|
|
1229
1363
|
networkPoolId: uuid("network_pool_id"),
|
|
1230
1364
|
endpoint: text("endpoint"),
|
|
1231
1365
|
apiKeyId: uuid("api_key_id"),
|
|
1366
|
+
/**
|
|
1367
|
+
* The share-template key this event belongs to (the template itself, or
|
|
1368
|
+
* the parent of the child key that carried the request). Denormalized at
|
|
1369
|
+
* write time so family rollups survive the key row being deleted — an
|
|
1370
|
+
* `EXISTS` join against `api_keys` tied history to key lifetime. NULL for
|
|
1371
|
+
* requests that ran under no share template.
|
|
1372
|
+
*/
|
|
1373
|
+
familyTemplateKeyId: uuid("family_template_key_id"),
|
|
1232
1374
|
userAgent: text("user_agent"),
|
|
1233
1375
|
clientIp: text("client_ip"),
|
|
1234
1376
|
latencyMs: integer("latency_ms"),
|
|
@@ -1317,6 +1459,14 @@ export const telemetryEvents = pgTable(
|
|
|
1317
1459
|
desc(table.createdAt),
|
|
1318
1460
|
desc(table.id),
|
|
1319
1461
|
),
|
|
1462
|
+
// Share-family rollup: equality on the denormalized template, keyset
|
|
1463
|
+
// range+order. Backs both the family totals and the hourly chart reads.
|
|
1464
|
+
index("telemetry_events_tenant_family_created_id_idx").on(
|
|
1465
|
+
table.tenantId,
|
|
1466
|
+
table.familyTemplateKeyId,
|
|
1467
|
+
desc(table.createdAt),
|
|
1468
|
+
desc(table.id),
|
|
1469
|
+
),
|
|
1320
1470
|
index("telemetry_events_request_id_idx").on(table.requestId),
|
|
1321
1471
|
index("telemetry_events_tenant_account_created_idx").on(
|
|
1322
1472
|
table.tenantId,
|
|
@@ -1373,6 +1523,13 @@ export const telemetryUsageTotals = pgTable(
|
|
|
1373
1523
|
tenantId: tenantRefRequired(),
|
|
1374
1524
|
identityType: text("identity_type").$type<TelemetryUsageIdentityType>().notNull(),
|
|
1375
1525
|
entityId: uuid("entity_id").notNull(),
|
|
1526
|
+
/**
|
|
1527
|
+
* For `api_key` identities, the share-template key this key belongs to
|
|
1528
|
+
* (the template itself, or the parent of a minted child). Denormalized so
|
|
1529
|
+
* family reads do not depend on the key row surviving; NULL for `account`
|
|
1530
|
+
* identities and for keys outside a share family.
|
|
1531
|
+
*/
|
|
1532
|
+
familyTemplateKeyId: uuid("family_template_key_id"),
|
|
1376
1533
|
requests: bigint("requests", { mode: "number" }).notNull().default(0),
|
|
1377
1534
|
errors: bigint("errors", { mode: "number" }).notNull().default(0),
|
|
1378
1535
|
inputTokens: bigint("input_tokens", { mode: "number" }).notNull().default(0),
|
|
@@ -1389,6 +1546,10 @@ export const telemetryUsageTotals = pgTable(
|
|
|
1389
1546
|
"telemetry_usage_totals_identity_type_check",
|
|
1390
1547
|
sql`${table.identityType} IN ('account', 'api_key')`,
|
|
1391
1548
|
),
|
|
1549
|
+
index("telemetry_usage_totals_tenant_family_idx").on(
|
|
1550
|
+
table.tenantId,
|
|
1551
|
+
table.familyTemplateKeyId,
|
|
1552
|
+
),
|
|
1392
1553
|
],
|
|
1393
1554
|
);
|
|
1394
1555
|
|