cartethyia 2.5.4 → 2.5.7
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-DE2607Tb.js} +1 -1
- package/dist/dashboard/assets/BannedPage-DE2607Tb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-Duv6mfrl.js +1 -0
- package/dist/dashboard/assets/CliToolDetailPage-Duv6mfrl.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BV6pxVQo.js → CliToolsPage-C2PNYWzk.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-C2PNYWzk.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-TXP9OfAM.js +1 -0
- package/dist/dashboard/assets/CombosPage-TXP9OfAM.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CW-wPmJ6.js → ConsoleLogPage-B-9xnAQN.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-B-9xnAQN.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-0p8uX7vB.js → CustomizationPage-xeax9nJt.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-xeax9nJt.js.gz +0 -0
- package/dist/dashboard/assets/{HealthEventsModal-BjqSMfko.js → HealthEventsModal-Df4jjaHJ.js} +1 -1
- package/dist/dashboard/assets/HealthEventsModal-Df4jjaHJ.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-BvzCx8Kr.js → LoginPage-Dyojsm84.js} +1 -1
- package/dist/dashboard/assets/LoginPage-Dyojsm84.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-BJfg4ow6.js +1 -0
- package/dist/dashboard/assets/OverviewPage-BJfg4ow6.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-ChCX1gmT.js +3 -0
- package/dist/dashboard/assets/ProviderDetailPage-ChCX1gmT.js.gz +0 -0
- package/dist/dashboard/assets/{ProvidersPage-Js9jUPSb.js → ProvidersPage-DeWSOEUO.js} +1 -1
- package/dist/dashboard/assets/ProvidersPage-DeWSOEUO.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CkpWln2S.js +7 -0
- package/dist/dashboard/assets/ProxyPage-CkpWln2S.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-B3VOgQmt.js +1 -0
- package/dist/dashboard/assets/QuotaPage-B3VOgQmt.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-C_klIZom.js +1 -0
- package/dist/dashboard/assets/SettingsPage-C_klIZom.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-DDbMQsoo.js → SetupPage-BYph-InK.js} +1 -1
- package/dist/dashboard/assets/SetupPage-BYph-InK.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-CB3Z7VTf.js → SortableList-CvyQCYWJ.js} +1 -1
- package/dist/dashboard/assets/SortableList-CvyQCYWJ.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-D95UCPHI.js → StudioPage-Cm1JYilI.js} +3 -3
- package/dist/dashboard/assets/StudioPage-Cm1JYilI.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DlFnc3_S.js +56 -0
- package/dist/dashboard/assets/UsagePage-DlFnc3_S.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-Bog0p925.js +4 -0
- package/dist/dashboard/assets/entry-Bog0p925.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/{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-CZQIrdoX.js} +2 -2
- package/dist/dashboard/assets/index-CZQIrdoX.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-BPpSsBgL.js} +1 -1
- package/dist/dashboard/assets/select-BPpSsBgL.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 +95 -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
|
@@ -608,7 +608,7 @@ function describeResetCode(code: string): string {
|
|
|
608
608
|
/**
|
|
609
609
|
* Writes the outcome to `health_events` and, on success, restores the account to
|
|
610
610
|
* `active` so it rejoins dispatch rotation immediately rather than waiting out a
|
|
611
|
-
* cooldown that
|
|
611
|
+
* cooldown that the reset has already cleared.
|
|
612
612
|
*/
|
|
613
613
|
async function recordResetActivity(
|
|
614
614
|
db: CartethyiaDatabase,
|
|
@@ -332,9 +332,9 @@ export const VERSION_SOURCES = {
|
|
|
332
332
|
fallback: "1.3.11",
|
|
333
333
|
sources: [
|
|
334
334
|
{
|
|
335
|
-
// Kiro's downloads page
|
|
336
|
-
//
|
|
337
|
-
//
|
|
335
|
+
// Kiro's downloads page exposes no stable version string. Homebrew
|
|
336
|
+
// tracks the official installer URL and exposes its version as JSON;
|
|
337
|
+
// keep the product page parser as a fallback.
|
|
338
338
|
url: "https://formulae.brew.sh/api/cask/kiro.json",
|
|
339
339
|
extract: kiroCaskVersion,
|
|
340
340
|
},
|
|
@@ -488,8 +488,8 @@ const PROVIDER_VERSION_RESOLVERS: Readonly<Record<string, ClientVersionResolver>
|
|
|
488
488
|
"opencode-zen": resolvers.opencode,
|
|
489
489
|
"opencode-go": resolvers.opencode,
|
|
490
490
|
// The identity this provider is dispatched under is the CLI's, so the route
|
|
491
|
-
// identity reports the CLI version
|
|
492
|
-
//
|
|
491
|
+
// identity reports the CLI version, not the VS Code extension manifest
|
|
492
|
+
// (`clineClient`).
|
|
493
493
|
cline: resolvers.clineCli,
|
|
494
494
|
codex: resolvers.codex,
|
|
495
495
|
qoder: resolvers.qoder,
|
|
@@ -670,7 +670,7 @@ export function buildCodeBuddyUserAgent(
|
|
|
670
670
|
): string {
|
|
671
671
|
// 1:1 with codebuddy2api's identity_headers(): the CLI profile uses ONE version
|
|
672
672
|
// (the npm CLI package pin) for both halves, and the IDE profile uses the other
|
|
673
|
-
// product's version.
|
|
673
|
+
// product's version. Using `version` for both would make "CLI" produce
|
|
674
674
|
// `CLI/<ide> CodeBuddy/<ide>` — a CLI claiming the desktop build.
|
|
675
675
|
const resolved = identity === "CLI" ? cnVersion : version;
|
|
676
676
|
return `${identity}/${resolved} CodeBuddy/${resolved}`;
|
|
@@ -34,10 +34,9 @@ export function buildCustomCodexCliHeaders(): Record<string, string> {
|
|
|
34
34
|
*
|
|
35
35
|
* This is the route-level default for a provider whose operator set no client
|
|
36
36
|
* identity of their own: a bare API key identifies as the Claude Code CLI
|
|
37
|
-
* rather than as nothing.
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* would act on it.
|
|
37
|
+
* rather than as nothing. The Codex CLI identity (`codex_cli_rs/…`) would name
|
|
38
|
+
* a different vendor's client on requests that most often reach neither — an
|
|
39
|
+
* upstream that keys on the client string would act on it.
|
|
41
40
|
*
|
|
42
41
|
* The version comes from the live getter for the same reason
|
|
43
42
|
* {@link buildCustomClaudeCliHeaders} does: the pinned `claude-fingerprint`
|
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
/** Durable materialization of bundled provider model metadata. */
|
|
2
|
-
import { and, eq, sql } from "drizzle-orm";
|
|
3
|
-
import type { CartethyiaDatabase } from "../../persistence/db-handle";
|
|
4
|
-
import { models } from "../../persistence/schema";
|
|
5
|
-
import type { ModelDefinition } from "../provider-model-definition";
|
|
6
|
-
|
|
7
|
-
/** Persists compiled provider model metadata and reconciles drifted capability flags. */
|
|
8
|
-
export async function seedBundledModels(
|
|
9
|
-
db: CartethyiaDatabase,
|
|
10
|
-
builtinModels: ReadonlyMap<string, readonly ModelDefinition[]>,
|
|
11
|
-
): Promise<void> {
|
|
12
|
-
for (const [providerId, definitions] of builtinModels) {
|
|
13
|
-
if (definitions.length === 0) continue;
|
|
14
|
-
// Drop builtin rows the current catalog no longer declares, including rows
|
|
15
|
-
// whose model id is still present but whose endpoint path drifted (e.g. a
|
|
16
|
-
// provider that moved from `/chat/completions` to `/v2/chat/completions`).
|
|
17
|
-
// The unique key is (provider, model, endpoint), so a changed endpoint
|
|
18
|
-
// would otherwise insert a second row and leave the stale route behind —
|
|
19
|
-
// the model list
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
const pairs = definitions.map(
|
|
23
|
-
(definition) => sql`(${definition.modelId}, ${definition.endpointPath})`,
|
|
24
|
-
);
|
|
25
|
-
await db
|
|
26
|
-
.delete(models)
|
|
27
|
-
.where(
|
|
28
|
-
and(
|
|
29
|
-
eq(models.providerId, providerId),
|
|
30
|
-
eq(models.source, "builtin"),
|
|
31
|
-
sql`(${models.modelId}, ${models.endpointPath}) NOT IN (${sql.join(pairs, sql`, `)})`,
|
|
32
|
-
),
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
const now = new Date();
|
|
36
|
-
const seen = new Set<string>();
|
|
37
|
-
const rows = [...builtinModels.entries()].flatMap(([providerId, definitions]) =>
|
|
38
|
-
definitions.flatMap((definition) => {
|
|
39
|
-
const key = `${providerId}\u0000${definition.modelId}\u0000${definition.endpointPath}`;
|
|
40
|
-
if (seen.has(key)) return [];
|
|
41
|
-
seen.add(key);
|
|
42
|
-
return [
|
|
43
|
-
{
|
|
44
|
-
providerId,
|
|
45
|
-
modelId: definition.modelId,
|
|
46
|
-
wireFamily: definition.wireFamily,
|
|
47
|
-
serviceKind: definition.serviceKind ?? "llm",
|
|
48
|
-
endpointPath: definition.endpointPath,
|
|
49
|
-
contextLimit: definition.contextLimit,
|
|
50
|
-
outputLimit: definition.outputLimit,
|
|
51
|
-
modalities: definition.modalities,
|
|
52
|
-
reasoning: definition.reasoning,
|
|
53
|
-
toolCall: definition.toolCall,
|
|
54
|
-
cost: definition.cost,
|
|
55
|
-
// A static row either knows it is refused on a free plan or says
|
|
56
|
-
// nothing. Never coerced to false: the column is three-valued, and
|
|
57
|
-
// "nobody established it" is not the same claim as "served on free".
|
|
58
|
-
proOnly: definition.proOnly ?? null,
|
|
59
|
-
// Same three-valued rule for the inverse: the provider's directory
|
|
60
|
-
// states the tier, so the flag is carried rather than derived.
|
|
61
|
-
freeTier: definition.freeTier ?? null,
|
|
62
|
-
source: "builtin",
|
|
63
|
-
sourceUpdatedAt: now,
|
|
64
|
-
enabled: true,
|
|
65
|
-
},
|
|
66
|
-
];
|
|
67
|
-
}),
|
|
68
|
-
);
|
|
69
|
-
if (rows.length === 0) return;
|
|
70
|
-
// Reconcile static metadata on conflict rather than skipping: capability
|
|
71
|
-
// flags (toolCall/reasoning/webSearch), wire family, limits, and cost can
|
|
72
|
-
// drift on a pre-existing row (e.g. a discovery seeded `tool_call=false`
|
|
73
|
-
// before the static catalog was corrected). `source` is forced back to
|
|
74
|
-
// `builtin`: a fetch upsert may have flipped a builtin row to `discovered`,
|
|
75
|
-
// and the static catalog owns these ids. `enabled` is operator-owned and
|
|
76
|
-
// must never be reset here.
|
|
77
|
-
await db.insert(models).values(rows).onConflictDoUpdate({
|
|
78
|
-
target: [models.providerId, models.modelId, models.endpointPath],
|
|
79
|
-
set: {
|
|
80
|
-
wireFamily: sql`excluded.wire_family`,
|
|
81
|
-
serviceKind: sql`excluded.service_kind`,
|
|
82
|
-
endpointPath: sql`excluded.endpoint_path`,
|
|
83
|
-
contextLimit: sql`excluded.context_limit`,
|
|
84
|
-
outputLimit: sql`excluded.output_limit`,
|
|
85
|
-
modalities: sql`excluded.modalities`,
|
|
86
|
-
reasoning: sql`excluded.reasoning`,
|
|
87
|
-
toolCall: sql`excluded.tool_call`,
|
|
88
|
-
cost: sql`excluded.cost`,
|
|
89
|
-
proOnly: sql`excluded.pro_only`,
|
|
90
|
-
freeTier: sql`excluded.free_tier`,
|
|
91
|
-
source: sql`'builtin'`,
|
|
92
|
-
sourceUpdatedAt: sql`excluded.source_updated_at`,
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
}
|
|
1
|
+
/** Durable materialization of bundled provider model metadata. */
|
|
2
|
+
import { and, eq, sql } from "drizzle-orm";
|
|
3
|
+
import type { CartethyiaDatabase } from "../../persistence/db-handle";
|
|
4
|
+
import { models } from "../../persistence/schema";
|
|
5
|
+
import type { ModelDefinition } from "../provider-model-definition";
|
|
6
|
+
|
|
7
|
+
/** Persists compiled provider model metadata and reconciles drifted capability flags. */
|
|
8
|
+
export async function seedBundledModels(
|
|
9
|
+
db: CartethyiaDatabase,
|
|
10
|
+
builtinModels: ReadonlyMap<string, readonly ModelDefinition[]>,
|
|
11
|
+
): Promise<void> {
|
|
12
|
+
for (const [providerId, definitions] of builtinModels) {
|
|
13
|
+
if (definitions.length === 0) continue;
|
|
14
|
+
// Drop builtin rows the current catalog no longer declares, including rows
|
|
15
|
+
// whose model id is still present but whose endpoint path drifted (e.g. a
|
|
16
|
+
// provider that moved from `/chat/completions` to `/v2/chat/completions`).
|
|
17
|
+
// The unique key is (provider, model, endpoint), so a changed endpoint
|
|
18
|
+
// would otherwise insert a second row and leave the stale route behind —
|
|
19
|
+
// the model list then shows duplicates and probes can hit the dead path.
|
|
20
|
+
// Composite `NOT IN` keeps exactly the (model, endpoint) pairs the catalog
|
|
21
|
+
// owns.
|
|
22
|
+
const pairs = definitions.map(
|
|
23
|
+
(definition) => sql`(${definition.modelId}, ${definition.endpointPath})`,
|
|
24
|
+
);
|
|
25
|
+
await db
|
|
26
|
+
.delete(models)
|
|
27
|
+
.where(
|
|
28
|
+
and(
|
|
29
|
+
eq(models.providerId, providerId),
|
|
30
|
+
eq(models.source, "builtin"),
|
|
31
|
+
sql`(${models.modelId}, ${models.endpointPath}) NOT IN (${sql.join(pairs, sql`, `)})`,
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const now = new Date();
|
|
36
|
+
const seen = new Set<string>();
|
|
37
|
+
const rows = [...builtinModels.entries()].flatMap(([providerId, definitions]) =>
|
|
38
|
+
definitions.flatMap((definition) => {
|
|
39
|
+
const key = `${providerId}\u0000${definition.modelId}\u0000${definition.endpointPath}`;
|
|
40
|
+
if (seen.has(key)) return [];
|
|
41
|
+
seen.add(key);
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
providerId,
|
|
45
|
+
modelId: definition.modelId,
|
|
46
|
+
wireFamily: definition.wireFamily,
|
|
47
|
+
serviceKind: definition.serviceKind ?? "llm",
|
|
48
|
+
endpointPath: definition.endpointPath,
|
|
49
|
+
contextLimit: definition.contextLimit,
|
|
50
|
+
outputLimit: definition.outputLimit,
|
|
51
|
+
modalities: definition.modalities,
|
|
52
|
+
reasoning: definition.reasoning,
|
|
53
|
+
toolCall: definition.toolCall,
|
|
54
|
+
cost: definition.cost,
|
|
55
|
+
// A static row either knows it is refused on a free plan or says
|
|
56
|
+
// nothing. Never coerced to false: the column is three-valued, and
|
|
57
|
+
// "nobody established it" is not the same claim as "served on free".
|
|
58
|
+
proOnly: definition.proOnly ?? null,
|
|
59
|
+
// Same three-valued rule for the inverse: the provider's directory
|
|
60
|
+
// states the tier, so the flag is carried rather than derived.
|
|
61
|
+
freeTier: definition.freeTier ?? null,
|
|
62
|
+
source: "builtin",
|
|
63
|
+
sourceUpdatedAt: now,
|
|
64
|
+
enabled: true,
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
if (rows.length === 0) return;
|
|
70
|
+
// Reconcile static metadata on conflict rather than skipping: capability
|
|
71
|
+
// flags (toolCall/reasoning/webSearch), wire family, limits, and cost can
|
|
72
|
+
// drift on a pre-existing row (e.g. a discovery seeded `tool_call=false`
|
|
73
|
+
// before the static catalog was corrected). `source` is forced back to
|
|
74
|
+
// `builtin`: a fetch upsert may have flipped a builtin row to `discovered`,
|
|
75
|
+
// and the static catalog owns these ids. `enabled` is operator-owned and
|
|
76
|
+
// must never be reset here.
|
|
77
|
+
await db.insert(models).values(rows).onConflictDoUpdate({
|
|
78
|
+
target: [models.providerId, models.modelId, models.endpointPath],
|
|
79
|
+
set: {
|
|
80
|
+
wireFamily: sql`excluded.wire_family`,
|
|
81
|
+
serviceKind: sql`excluded.service_kind`,
|
|
82
|
+
endpointPath: sql`excluded.endpoint_path`,
|
|
83
|
+
contextLimit: sql`excluded.context_limit`,
|
|
84
|
+
outputLimit: sql`excluded.output_limit`,
|
|
85
|
+
modalities: sql`excluded.modalities`,
|
|
86
|
+
reasoning: sql`excluded.reasoning`,
|
|
87
|
+
toolCall: sql`excluded.tool_call`,
|
|
88
|
+
cost: sql`excluded.cost`,
|
|
89
|
+
proOnly: sql`excluded.pro_only`,
|
|
90
|
+
freeTier: sql`excluded.free_tier`,
|
|
91
|
+
source: sql`'builtin'`,
|
|
92
|
+
sourceUpdatedAt: sql`excluded.source_updated_at`,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -134,7 +134,7 @@ export async function seedBundledProviders(db: CartethyiaDatabase): Promise<void
|
|
|
134
134
|
* console-created provider carries a tenant — so an unowned id absent from the
|
|
135
135
|
* bundle is an orphan by construction, and a tenant-owned BYOK row is never in
|
|
136
136
|
* scope. The model seeder prunes its retired rows the same way; this is the
|
|
137
|
-
* provider-level half
|
|
137
|
+
* provider-level half.
|
|
138
138
|
*
|
|
139
139
|
* Separate from {@link seedBundledProviders} rather than folded into it: the
|
|
140
140
|
* harness calls that seeder on import to converge a shared database, and a
|
|
@@ -226,9 +226,8 @@ export async function bundledModelCatalog(
|
|
|
226
226
|
|
|
227
227
|
/**
|
|
228
228
|
* Re-seeds the compiled catalogs, called when a provider gains an account after
|
|
229
|
-
* boot.
|
|
230
|
-
*
|
|
231
|
-
* snapshot must reflect that without waiting for a restart.
|
|
229
|
+
* boot. It runs the same walk as at boot: an account makes the rows routable and
|
|
230
|
+
* the snapshot must reflect that without waiting for a restart.
|
|
232
231
|
*
|
|
233
232
|
* Gated on {@link currentCatalogRevision}: this is the seeder the snapshot
|
|
234
233
|
* builder calls on every rebuild, and the invalidation that triggers it is a
|
|
@@ -415,18 +415,14 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
|
|
|
415
415
|
/**
|
|
416
416
|
* Web search is a route of its own, never a model capability.
|
|
417
417
|
*
|
|
418
|
-
*
|
|
419
|
-
* proven", and a `providerSupportsWebSearch` helper that consulted it. Both are
|
|
420
|
-
* gone. A model row no longer advertises search, and a provider serves search
|
|
418
|
+
* A model row does not advertise search, and a provider serves search
|
|
421
419
|
* purely by declaring a `serviceKind: "websearch"` catalog row — which is what
|
|
422
420
|
* Exa, Parallel, and Gemini do. Those rows answer `POST /v1/search` and are
|
|
423
421
|
* never reached from a chat turn.
|
|
424
422
|
*
|
|
425
|
-
*
|
|
426
|
-
* deliberately does not derive `web_search`, so no chat request
|
|
427
|
-
* filtered or degraded by it.
|
|
428
|
-
* (Codex, Antigravity) into the fallback candidate list as if they were search
|
|
429
|
-
* routes, and to show a badge in the console. The fallback is gone too: a chat
|
|
423
|
+
* A search flag is not a capability gate: `deriveRequiredCapabilities`
|
|
424
|
+
* deliberately does not derive `web_search`, so no chat request is
|
|
425
|
+
* filtered or degraded by it. A chat
|
|
430
426
|
* turn is dispatched once to the route its model selects, and a hosted search
|
|
431
427
|
* declaration is answered by that upstream, not executed by the gateway.
|
|
432
428
|
*/
|
|
@@ -38,8 +38,8 @@ export interface ProviderModule {
|
|
|
38
38
|
* `upstream_host` is the SSRF-validated network-binding target for this
|
|
39
39
|
* provider — carried on the same registration object as the adapter loader
|
|
40
40
|
* so adding a provider touches one call-site instead of a second map kept
|
|
41
|
-
* in sync by hand elsewhere
|
|
42
|
-
*
|
|
41
|
+
* in sync by hand elsewhere; `providers/operations/provider-catalog-service.ts`
|
|
42
|
+
* derives it from here.
|
|
43
43
|
*/
|
|
44
44
|
export interface ProviderRegistration {
|
|
45
45
|
readonly provider_id: ProviderId;
|
|
@@ -240,11 +240,10 @@ export class ProviderRegistry {
|
|
|
240
240
|
* check — no module is loaded — for list projections that must hide the
|
|
241
241
|
* "Fetch models" control from providers with no discovery endpoint.
|
|
242
242
|
*
|
|
243
|
-
* This is the question the projection should be asking
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* sync, so hiding the control leaves it permanently empty.
|
|
243
|
+
* This is the question the projection should be asking; "is this a builtin?"
|
|
244
|
+
* is not a proxy for it. A builtin that registers a resolver cannot list any
|
|
245
|
+
* model until an operator runs a sync, so hiding the control on the strength
|
|
246
|
+
* of builtin status alone leaves it permanently empty.
|
|
248
247
|
*/
|
|
249
248
|
hasModelDiscovery(providerId: string): boolean {
|
|
250
249
|
return this.#registrations.get(parseProviderId(providerId))?.loadModelDiscovery !== undefined;
|
|
@@ -195,7 +195,7 @@ export function normalizeUsage(input: Record<string, unknown>): UsageRecord {
|
|
|
195
195
|
// the zeroed `*_tokens_details.cached_tokens` those bridges also emit.
|
|
196
196
|
// Flat `cached_tokens` is the intermediate shape `mapGeminiUsage`
|
|
197
197
|
// (Gemini/Antigravity) and CommandCode emit; `cachedContentTokenCount` is
|
|
198
|
-
// Gemini's raw `usageMetadata` field. Both
|
|
198
|
+
// Gemini's raw `usageMetadata` field. Both are consumed here.
|
|
199
199
|
if (
|
|
200
200
|
cached_input_tokens === "unavailable" &&
|
|
201
201
|
typeof input.cached_tokens === "number"
|
package/src/security/abuse.ts
CHANGED
|
@@ -78,10 +78,10 @@ export interface IpAbuseOutcome {
|
|
|
78
78
|
*
|
|
79
79
|
* The store is the only component that knows this: a ban's remainder is its
|
|
80
80
|
* marker's TTL, and a rate-limited window's remainder is the age of its
|
|
81
|
-
* oldest attempt. Both are server state.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
81
|
+
* oldest attempt. Both are server state. Answering every 429 with a fixed
|
|
82
|
+
* `retry-after: 3600` would tell a client hitting a 60-second window to wait
|
|
83
|
+
* sixty times longer than it had to — and tell a client whose ban had nearly
|
|
84
|
+
* elapsed to wait the full hour again.
|
|
85
85
|
*/
|
|
86
86
|
readonly retryAfterMs: number;
|
|
87
87
|
}
|
|
@@ -224,7 +224,7 @@ export class InMemoryIpAbuseStore implements IpAbuseStore {
|
|
|
224
224
|
|
|
225
225
|
/** Evicts the oldest entries of `map` down to `maxKeys` in a single pass so
|
|
226
226
|
* an adversarial fan-out over unique identities cannot pin memory. Deleting
|
|
227
|
-
* one entry at a time
|
|
227
|
+
* one entry at a time is O(1) but starves reclaim. */
|
|
228
228
|
private evictOldest<K, V>(map: Map<K, V>): void {
|
|
229
229
|
if (map.size < this.maxKeys) return;
|
|
230
230
|
let toEvict = map.size - this.maxKeys + 1;
|
|
@@ -251,10 +251,10 @@ export class InMemoryIpAbuseStore implements IpAbuseStore {
|
|
|
251
251
|
/**
|
|
252
252
|
* Outage injection for tests, mirroring the store's own reachability.
|
|
253
253
|
*
|
|
254
|
-
* The service
|
|
254
|
+
* The service does not probe the store before using it: every method below
|
|
255
255
|
* throws when the store is unreachable, and the service's catch maps that to
|
|
256
|
-
* a bounded `admission_unavailable`.
|
|
257
|
-
*
|
|
256
|
+
* a bounded `admission_unavailable`. A separate probe would only add a round
|
|
257
|
+
* trip to every request on the Redis store.
|
|
258
258
|
*/
|
|
259
259
|
private assertAvailable(): void {
|
|
260
260
|
if (this.failing) throw new Error("ip store unavailable");
|
|
@@ -421,7 +421,12 @@ export class IpAbuseProtectionService {
|
|
|
421
421
|
|
|
422
422
|
if (outcome.banned) {
|
|
423
423
|
throw new GatewayError("quota_exceeded", 429, "This address is temporarily banned for too many failed requests. Wait for the ban to lift, then slow down.", {
|
|
424
|
-
|
|
424
|
+
// Distinguishes this from the rate-limited 429 below and from an API
|
|
425
|
+
// key's own budget. It used to be "admission-unavailable", which is
|
|
426
|
+
// the label for an *unreachable* store — so every refusal from this
|
|
427
|
+
// layer claimed an outage that had not happened, and a client could
|
|
428
|
+
// not tell "banned" from "over the window" from "store is down".
|
|
429
|
+
reason: "ip-banned",
|
|
425
430
|
ip,
|
|
426
431
|
route: input.route,
|
|
427
432
|
// Measured by the store: the ban marker's remaining TTL. Carried as
|
|
@@ -433,7 +438,7 @@ export class IpAbuseProtectionService {
|
|
|
433
438
|
|
|
434
439
|
if (outcome.count > this.maxRequestsPerWindow) {
|
|
435
440
|
throw new GatewayError("quota_exceeded", 429, "This address is sending requests faster than the abuse limit allows. Back off and retry after the window rolls over.", {
|
|
436
|
-
reason: "
|
|
441
|
+
reason: "ip-rate-limited",
|
|
437
442
|
ip,
|
|
438
443
|
route: input.route,
|
|
439
444
|
count: outcome.count,
|