cartethyia 2.5.3 → 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-hfCzi-Ux.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-DEDyKBlC.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-bsLuZmYH.js → ConsoleLogPage-BVdpfiz1.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-BVdpfiz1.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-_UWhwziJ.js → CustomizationPage-BR5HHvbi.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-BR5HHvbi.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-mUfcknqm.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-mUfcknqm.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-DDVIfZGW.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-uPiGVTTK.js +1 -0
- 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-D6pmQ86L.js → SetupPage-UB690SE2.js} +1 -1
- package/dist/dashboard/assets/SetupPage-UB690SE2.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-DWvKiuSl.js → SortableList-BLujdX7N.js} +1 -1
- package/dist/dashboard/assets/SortableList-BLujdX7N.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-CmkUrgdj.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-NHwYq95t.js → assert-C9FD_JwJ.js} +1 -1
- package/dist/dashboard/assets/assert-C9FD_JwJ.js.gz +0 -0
- package/dist/dashboard/assets/{badge-6uzDDvqs.js → badge-CR72dasT.js} +1 -1
- package/dist/dashboard/assets/badge-CR72dasT.js.gz +0 -0
- package/dist/dashboard/assets/{banner-4_WNg2WZ.js → banner-CI9_eSfO.js} +1 -1
- package/dist/dashboard/assets/banner-CI9_eSfO.js.gz +0 -0
- package/dist/dashboard/assets/{card--AtFedAq.js → card-DS7CQEsO.js} +1 -1
- package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-B3e7dx3N.js → cli-tools-CNqzrfdb.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-NreUx6c8.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/database-Dz9N3zGd.js +1 -0
- package/dist/dashboard/assets/database-Dz9N3zGd.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-B9Xvtnfj.js +1 -0
- 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-D_eM3IgG.js → github-badge-sltk1qUi.js} +1 -1
- package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
- package/dist/dashboard/assets/{index-BydyKaDz.js → index-CmxZr14F.js} +2 -2
- package/dist/dashboard/assets/index-CmxZr14F.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BcNGF8Gr.js → inline-BhY2sSnO.js} +1 -1
- package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
- package/dist/dashboard/assets/{input-BG41et9G.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-Gh_W4OR_.js → list-row-1zzZYM0B.js} +1 -1
- package/dist/dashboard/assets/list-row-1zzZYM0B.js.gz +0 -0
- package/dist/dashboard/assets/{live-BJGYRBnR.js → live-BivGfuUs.js} +1 -1
- package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-CmffjLuG.js +1 -0
- package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-BkoLM5Ba.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-D7wX2vM5.js → query-keys-BFhGpwR1.js} +1 -1
- package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
- package/dist/dashboard/assets/{routing-CcusqXA7.js → routing-CAb4F37R.js} +1 -1
- package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
- package/dist/dashboard/assets/{select-BO6h8yNv.js → select-BYR_5K2c.js} +2 -2
- package/dist/dashboard/assets/select-BYR_5K2c.js.gz +0 -0
- package/dist/dashboard/assets/{settings-mpmXTgUa.js → settings-DNX9sydi.js} +1 -1
- package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DwLmjUFK.js → stack-BHTfXdz_.js} +1 -1
- package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
- package/dist/dashboard/assets/{state-DYdQmdAl.js → state-mPDRlQkl.js} +1 -1
- package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
- package/dist/dashboard/assets/switch-DOmJxg7H.js +1 -0
- package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
- package/dist/dashboard/assets/terminal-0_IjPWTk.js +1 -0
- package/dist/dashboard/assets/terminal-0_IjPWTk.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-w4u4CVue.js → useMutation-Dem0lXQj.js} +1 -1
- package/dist/dashboard/assets/useMutation-Dem0lXQj.js.gz +0 -0
- package/dist/dashboard/assets/zap-C4EeVW4q.js +1 -0
- package/dist/dashboard/assets/zap-C4EeVW4q.js.gz +0 -0
- package/dist/dashboard/donation/qris-risun-marke.png +0 -0
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +57 -57
- 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/autostart.ts +237 -0
- package/scripts/cli/{ui/background.ts → background.ts} +1 -1
- package/scripts/cli/{command/console-menu.ts → console-menu.ts} +275 -248
- 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 +88 -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/update.ts +40 -0
- package/scripts/cli/version.ts +67 -0
- package/scripts/cli/{ui/wordmark.ts → wordmark.ts} +58 -58
- package/src/boot/app.ts +11 -7
- package/src/boot/dependencies.ts +50 -19
- 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 +52 -7
- package/src/config/telemetry.ts +26 -0
- 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/bucket-spend.ts +15 -4
- 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/contracts.ts +15 -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/console-router.ts +8 -0
- package/src/console/data-management/contracts.ts +100 -0
- package/src/console/data-management/operations.ts +234 -0
- package/src/console/data-management/routes.ts +103 -0
- package/src/console/domain-registration.ts +45 -1
- package/src/console/observability/contracts.ts +524 -485
- package/src/console/observability/live.ts +22 -0
- package/src/console/observability/store.ts +1138 -1018
- package/src/console/observability/usage-dimensions.ts +4 -4
- package/src/console/providers/catalog/catalog-projections.ts +6 -7
- package/src/console/providers/catalog/contracts.ts +6 -0
- package/src/console/providers/catalog/model-operations.ts +5 -2
- package/src/console/providers/catalog/provider-operations.ts +24 -4
- package/src/console/providers/catalog/public-model-store.ts +8 -11
- package/src/console/providers/catalog/routes.ts +7 -0
- package/src/console/providers/catalog/store.ts +1553 -1532
- package/src/console/providers/oauth/routes.ts +8 -12
- package/src/console/quota/account-quota-shared.ts +52 -39
- package/src/console/quota/account-quota-tenant.ts +6 -6
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/quota/refresh.ts +441 -429
- 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/import-parse.ts +206 -0
- package/src/console/routing/pools/operations.ts +543 -501
- 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/routes.ts +181 -164
- package/src/console/routing/pools/store.ts +8 -8
- package/src/console/settings/contracts.ts +95 -2
- package/src/console/settings/store.ts +81 -3
- package/src/console/shared/cursor.ts +8 -8
- package/src/console/shared/errors.ts +1 -3
- package/src/console/updates/routes.ts +16 -0
- package/src/main.ts +10 -0
- 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 +317 -0
- package/src/observability/event-day-index.ts +440 -0
- package/src/observability/event-log.ts +155 -6
- package/src/observability/logger.ts +6 -6
- package/src/observability/payload-capture.ts +158 -33
- package/src/observability/payload-store.ts +82 -61
- 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/health-event-flush.ts +36 -0
- package/src/persistence/readiness.ts +1 -1
- package/src/persistence/schema.ts +75 -29
- 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 +33 -11
- package/src/protocol/canonical-model.ts +11 -3
- package/src/protocol/codecs.ts +139 -6
- package/src/protocol/gateway-error.ts +6 -4
- package/src/protocol/image-clamp.ts +19 -1
- package/src/protocol/registry.ts +8 -0
- package/src/protocol/request/chat.ts +21 -1
- package/src/protocol/request/codex.ts +10 -1
- package/src/protocol/request/gemini.ts +9 -2
- package/src/protocol/request/messages.ts +18 -7
- 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/adapters/compatible-adapter.ts +3 -0
- package/src/providers/authentication/jwt-validator.ts +9 -10
- package/src/providers/authentication/oauth-refresh-service.ts +9 -11
- package/src/providers/bundled-discovery-providers.ts +122 -119
- package/src/providers/configured-openai-providers.ts +4 -4
- package/src/providers/default-registry.ts +5 -4
- 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/openai-model-discovery.ts +5 -0
- package/src/providers/discovery/openrouter-free-roster.ts +15 -17
- 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 +27 -20
- package/src/providers/integrations/cline/cline.ts +537 -539
- package/src/providers/integrations/codex/codex-headers.ts +25 -39
- package/src/providers/integrations/codex/codex-oauth.ts +1 -1
- package/src/providers/integrations/codex/codex.ts +2 -29
- 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 -0
- package/src/providers/integrations/cursor/cursor-request.ts +616 -471
- package/src/providers/integrations/cursor/cursor-session-manager.ts +319 -281
- package/src/providers/integrations/cursor/cursor.ts +1333 -960
- package/src/providers/integrations/cursor/protocol/messages.ts +25 -0
- package/src/providers/integrations/factory/factory-models.ts +3 -5
- package/src/providers/integrations/factory/factory.ts +8 -1
- package/src/providers/integrations/gemini.ts +6 -1
- package/src/providers/integrations/grok/grok-install-id.ts +2 -3
- package/src/providers/integrations/grok/grok-quota.ts +279 -177
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +73 -0
- package/src/providers/integrations/grok/grok-ratelimit.ts +218 -0
- 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 +19 -20
- 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-quota.ts +192 -0
- 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-quota.ts +384 -0
- 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 +75 -27
- 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-contracts.ts +7 -0
- package/src/providers/provider-metadata.ts +10 -8
- package/src/providers/provider-registry.ts +6 -7
- package/src/providers/provider-usage.ts +1 -1
- package/src/providers/quota/quota-support.ts +8 -0
- 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 +27 -17
- 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/generation.ts +6 -0
- package/src/transport/dispatch/proxy-request.ts +24 -1
- package/src/transport/dispatch/ratelimit-capture.ts +37 -0
- 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 +19 -6
- package/src/transport/dispatch/upstream.ts +9 -0
- 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 +9 -8
- package/src/transport/request/state.ts +21 -8
- package/src/transport/request/tenant-preferences.ts +60 -0
- package/src/transport/routing/admission.ts +4 -0
- package/src/transport/routing/route-catalog.ts +65 -10
- 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-hfCzi-Ux.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-DLGqYEwI.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-DLGqYEwI.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-DEDyKBlC.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CfuYiQ8Z.js +0 -1
- package/dist/dashboard/assets/CombosPage-CfuYiQ8Z.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-bsLuZmYH.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-_UWhwziJ.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-Cjfc5WFS.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-Cjfc5WFS.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-DDVIfZGW.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-CWkTUtpX.js +0 -1
- package/dist/dashboard/assets/ModelPicker-CWkTUtpX.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-B53YYMng.js +0 -1
- package/dist/dashboard/assets/OverviewPage-B53YYMng.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-B0KaAQf0.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-B0KaAQf0.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-Dx31DgIO.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-Dx31DgIO.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BpnR4kXT.js +0 -7
- package/dist/dashboard/assets/ProxyPage-BpnR4kXT.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-BpOQCnun.js +0 -1
- package/dist/dashboard/assets/QuotaPage-BpOQCnun.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-DV1eo2J_.js +0 -1
- package/dist/dashboard/assets/SettingsPage-DV1eo2J_.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-D6pmQ86L.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-DWvKiuSl.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-CmkUrgdj.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-B47uOydr.js +0 -56
- package/dist/dashboard/assets/UsagePage-B47uOydr.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-uNywYlfv.js +0 -1
- package/dist/dashboard/assets/api-keys-uNywYlfv.js.gz +0 -0
- package/dist/dashboard/assets/app-DxivpfYG.css +0 -2
- package/dist/dashboard/assets/app-DxivpfYG.css.gz +0 -0
- package/dist/dashboard/assets/assert-NHwYq95t.js.gz +0 -0
- package/dist/dashboard/assets/badge-6uzDDvqs.js.gz +0 -0
- package/dist/dashboard/assets/banner-4_WNg2WZ.js.gz +0 -0
- package/dist/dashboard/assets/card--AtFedAq.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-B3e7dx3N.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-NreUx6c8.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BtpsJU98.js +0 -1
- package/dist/dashboard/assets/dialog-BtpsJU98.js.gz +0 -0
- package/dist/dashboard/assets/download-A0SW9OCW.js +0 -1
- package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
- package/dist/dashboard/assets/drawer-WwwtzihF.js +0 -1
- package/dist/dashboard/assets/drawer-WwwtzihF.js.gz +0 -0
- package/dist/dashboard/assets/entry-CkryrIea.js +0 -4
- package/dist/dashboard/assets/entry-CkryrIea.js.gz +0 -0
- package/dist/dashboard/assets/entry-TJIye_jT.js +0 -1
- package/dist/dashboard/assets/entry-TJIye_jT.js.gz +0 -0
- package/dist/dashboard/assets/entry-jy9_4-Ke.js +0 -1
- package/dist/dashboard/assets/entry-jy9_4-Ke.js.gz +0 -0
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-D_eM3IgG.js.gz +0 -0
- package/dist/dashboard/assets/index-BydyKaDz.js.gz +0 -0
- package/dist/dashboard/assets/inline-BcNGF8Gr.js.gz +0 -0
- package/dist/dashboard/assets/input-BG41et9G.js.gz +0 -0
- package/dist/dashboard/assets/layout-C8mer_Ak.js +0 -1
- package/dist/dashboard/assets/layout-C8mer_Ak.js.gz +0 -0
- package/dist/dashboard/assets/list-row-Gh_W4OR_.js.gz +0 -0
- package/dist/dashboard/assets/live-BJGYRBnR.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-DeVLDA7I.js +0 -1
- package/dist/dashboard/assets/model-bans-DeVLDA7I.js.gz +0 -0
- package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
- package/dist/dashboard/assets/numbers-Bs4LOOuf.js +0 -2
- package/dist/dashboard/assets/numbers-Bs4LOOuf.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-D7wX2vM5.js.gz +0 -0
- package/dist/dashboard/assets/routing-CcusqXA7.js.gz +0 -0
- package/dist/dashboard/assets/select-BO6h8yNv.js.gz +0 -0
- package/dist/dashboard/assets/settings-mpmXTgUa.js.gz +0 -0
- package/dist/dashboard/assets/sparkles-BRaRUxAU.js +0 -1
- package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
- package/dist/dashboard/assets/stack-DwLmjUFK.js.gz +0 -0
- package/dist/dashboard/assets/state-DYdQmdAl.js.gz +0 -0
- package/dist/dashboard/assets/switch-CidSfbG7.js +0 -1
- package/dist/dashboard/assets/switch-CidSfbG7.js.gz +0 -0
- package/dist/dashboard/assets/terminal-Bd4ee8TA.js +0 -1
- package/dist/dashboard/assets/terminal-Bd4ee8TA.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-w4u4CVue.js.gz +0 -0
- package/scripts/cli/command/admin.ts +0 -65
- package/scripts/cli/command/doctor.ts +0 -257
- package/scripts/cli/command/update.ts +0 -23
- 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-CafWtVXA.js → app-BIt446yE.js} +0 -0
- /package/dist/dashboard/assets/{app-CafWtVXA.js.gz → app-BIt446yE.js.gz} +0 -0
- /package/scripts/cli/{ui/prompt.ts → prompt.ts} +0 -0
|
@@ -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
|
|
@@ -146,6 +146,13 @@ export interface ProviderDispatchContext {
|
|
|
146
146
|
readonly request_headers?: Readonly<Record<string, string>> | undefined;
|
|
147
147
|
/** Stable per-conversation cache affinity passed through dispatch. */
|
|
148
148
|
readonly conversation_affinity?: string | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Per-tenant ceiling for one inline attachment, in bytes. `undefined` means
|
|
151
|
+
* the deployment default. Read by wire encoders that clamp images, which
|
|
152
|
+
* otherwise have no access to tenant preferences — they are pure translation
|
|
153
|
+
* and hold no database handle.
|
|
154
|
+
*/
|
|
155
|
+
readonly image_clamp_max_bytes?: number | undefined;
|
|
149
156
|
/** Opaque identity shared by retries of one logical gateway request. */
|
|
150
157
|
readonly request_identity?: object | undefined;
|
|
151
158
|
/**
|
|
@@ -316,6 +316,12 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
|
|
|
316
316
|
hasAdapterUserAgent: true,
|
|
317
317
|
},
|
|
318
318
|
{ id: "bai", displayName: "B.AI", baseUrl: "https://api.b.ai/v1", credentialUrl: "https://b.ai" },
|
|
319
|
+
{
|
|
320
|
+
id: "larprouter",
|
|
321
|
+
displayName: "LarRouter",
|
|
322
|
+
baseUrl: "https://larprouter.com/v1",
|
|
323
|
+
credentialUrl: "https://larprouter.com",
|
|
324
|
+
},
|
|
319
325
|
{ id: "inferhub", displayName: "InferHub", baseUrl: "https://api.inferhub.dev/v1", defaultSkipProxy: true },
|
|
320
326
|
{ id: "aihubmix", displayName: "AiHubMix", baseUrl: "https://aihubmix.com/v1", credentialUrl: "https://aihubmix.com/token" },
|
|
321
327
|
{ id: "tokenharbor", displayName: "TokenHarbor", baseUrl: "https://tokenharbor.ai/v1", credentialUrl: "https://tokenharbor.ai" },
|
|
@@ -409,18 +415,14 @@ const RAW_BUNDLED_PROVIDER_METADATA = [
|
|
|
409
415
|
/**
|
|
410
416
|
* Web search is a route of its own, never a model capability.
|
|
411
417
|
*
|
|
412
|
-
*
|
|
413
|
-
* proven", and a `providerSupportsWebSearch` helper that consulted it. Both are
|
|
414
|
-
* 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
|
|
415
419
|
* purely by declaring a `serviceKind: "websearch"` catalog row — which is what
|
|
416
420
|
* Exa, Parallel, and Gemini do. Those rows answer `POST /v1/search` and are
|
|
417
421
|
* never reached from a chat turn.
|
|
418
422
|
*
|
|
419
|
-
*
|
|
420
|
-
* deliberately does not derive `web_search`, so no chat request
|
|
421
|
-
* filtered or degraded by it.
|
|
422
|
-
* (Codex, Antigravity) into the fallback candidate list as if they were search
|
|
423
|
-
* 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
|
|
424
426
|
* turn is dispatched once to the route its model selects, and a hosted search
|
|
425
427
|
* declaration is answered by that upstream, not executed by the gateway.
|
|
426
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"
|
|
@@ -54,6 +54,14 @@ export interface QuotaCollectionContext {
|
|
|
54
54
|
readonly auth_state?: Readonly<Record<string, unknown>> | undefined;
|
|
55
55
|
/** Stored credential kind, for surfaces that differ per auth family. */
|
|
56
56
|
readonly credential_kind?: "api_key" | "oauth" | "none" | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* The account the reading belongs to, when the caller knows it.
|
|
59
|
+
*
|
|
60
|
+
* Needed by collectors that can reuse a value captured from real traffic:
|
|
61
|
+
* that reading is keyed by account, so without this the collector cannot
|
|
62
|
+
* find it and spends a request rediscovering what dispatch already learned.
|
|
63
|
+
*/
|
|
64
|
+
readonly accountId?: string | undefined;
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
/** Provider quota callback supplied by the canonical provider registry. */
|
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,
|