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
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// Grok's two quota numbers, and why they disagree.
|
|
2
|
+
//
|
|
3
|
+
// The CLI plane answers every response with a token bucket:
|
|
4
|
+
//
|
|
5
|
+
// x-ratelimit-limit-tokens: 1000000
|
|
6
|
+
// x-ratelimit-remaining-tokens: 996169
|
|
7
|
+
// x-ratelimit-remaining-requests: 20
|
|
8
|
+
//
|
|
9
|
+
// and that bucket is *eventually consistent*. Right after a request it can
|
|
10
|
+
// still read a full `1000000` and only drop later. Worse, the figure it
|
|
11
|
+
// advertises is not the figure that binds: the real free allowance for a model
|
|
12
|
+
// like `grok-4.6` is 600k tokens per rolling 24 hours, and the only place
|
|
13
|
+
// upstream states it is the body of a 429:
|
|
14
|
+
//
|
|
15
|
+
// {"code":"subscription:free-usage-exhausted",
|
|
16
|
+
// "error":"... tokens (actual/limit): 603024/600000 ... Usage resets over a
|
|
17
|
+
// rolling 24-hour window"}
|
|
18
|
+
//
|
|
19
|
+
// So there are two readings with different authority. The header is available
|
|
20
|
+
// on every call and is the coarse indicator; the 429 body is only available
|
|
21
|
+
// once the account is actually being refused, and is the authoritative one.
|
|
22
|
+
//
|
|
23
|
+
// They are therefore kept as separate windows rather than merged: a merged
|
|
24
|
+
// number would look precise and be neither. The header window is listed first
|
|
25
|
+
// because it is what a caller sees day to day, and the authoritative one is
|
|
26
|
+
// appended beneath it.
|
|
27
|
+
|
|
28
|
+
import type { ProviderQuotaWindow } from "../../quota/quota-contracts";
|
|
29
|
+
import { isoDate, number, percentWindow, record, text } from "../../quota/quota-contracts";
|
|
30
|
+
|
|
31
|
+
/** Header names the CLI plane uses for its token bucket. */
|
|
32
|
+
const HEADER_LIMIT_TOKENS = "x-ratelimit-limit-tokens";
|
|
33
|
+
const HEADER_REMAINING_TOKENS = "x-ratelimit-remaining-tokens";
|
|
34
|
+
const HEADER_REMAINING_REQUESTS = "x-ratelimit-remaining-requests";
|
|
35
|
+
const HEADER_RESET_TOKENS = "x-ratelimit-reset-tokens";
|
|
36
|
+
|
|
37
|
+
/** The upstream code that carries the authoritative free-usage allowance. */
|
|
38
|
+
export const GROK_FREE_USAGE_EXHAUSTED = "subscription:free-usage-exhausted";
|
|
39
|
+
|
|
40
|
+
/** Kinds, so the view can tell an indicator from a verdict. */
|
|
41
|
+
export const GROK_HEADER_WINDOW_KIND = "grok:cli-header";
|
|
42
|
+
export const GROK_HEADER_REQUESTS_WINDOW_KIND = "grok:cli-header-requests";
|
|
43
|
+
export const GROK_AUTHORITATIVE_WINDOW_KIND = "grok:free-usage-authoritative";
|
|
44
|
+
|
|
45
|
+
/** The per-minute request cap the CLI plane applies. */
|
|
46
|
+
const REQUEST_WINDOW_LIMIT = 21;
|
|
47
|
+
|
|
48
|
+
/** One reading of the CLI token bucket. */
|
|
49
|
+
export interface GrokRateLimitReading {
|
|
50
|
+
readonly limitTokens: number | null;
|
|
51
|
+
readonly remainingTokens: number | null;
|
|
52
|
+
readonly remainingRequests: number | null;
|
|
53
|
+
readonly resetsAt: string | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** A `Headers`-like reader, narrowed at the boundary rather than asserted. */
|
|
57
|
+
function headerReader(
|
|
58
|
+
headers: { get(name: string): string | null } | Record<string, string>,
|
|
59
|
+
): (name: string) => string | null {
|
|
60
|
+
if (typeof headers.get === "function") {
|
|
61
|
+
const reader = headers as { get(name: string): string | null };
|
|
62
|
+
return (name) => reader.get(name);
|
|
63
|
+
}
|
|
64
|
+
const literal = headers as Record<string, string>;
|
|
65
|
+
return (name) => literal[name] ?? null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Reads the CLI token bucket off a response.
|
|
70
|
+
*
|
|
71
|
+
* `Headers` and a plain object both reach here — the quota probe gets the real
|
|
72
|
+
* thing, a test gets a literal — so both shapes are accepted rather than
|
|
73
|
+
* forcing one caller to adapt.
|
|
74
|
+
*/
|
|
75
|
+
export function readGrokRateLimitHeaders(
|
|
76
|
+
headers: { get(name: string): string | null } | Record<string, string>,
|
|
77
|
+
): GrokRateLimitReading {
|
|
78
|
+
const get = headerReader(headers);
|
|
79
|
+
const resetSeconds = number(get(HEADER_RESET_TOKENS));
|
|
80
|
+
return {
|
|
81
|
+
limitTokens: number(get(HEADER_LIMIT_TOKENS)),
|
|
82
|
+
remainingTokens: number(get(HEADER_REMAINING_TOKENS)),
|
|
83
|
+
remainingRequests: number(get(HEADER_REMAINING_REQUESTS)),
|
|
84
|
+
resetsAt:
|
|
85
|
+
isoDate(get(HEADER_RESET_TOKENS)) ??
|
|
86
|
+
(resetSeconds !== null && resetSeconds > 0
|
|
87
|
+
? new Date(Date.now() + resetSeconds * 1000).toISOString()
|
|
88
|
+
: null),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The header bucket as a quota window.
|
|
94
|
+
*
|
|
95
|
+
* Marked independent: this is the CLI request bucket, a different budget from
|
|
96
|
+
* the free-usage allowance, so it must never be summed into a credit total.
|
|
97
|
+
*/
|
|
98
|
+
export function grokHeaderWindow(reading: GrokRateLimitReading): ProviderQuotaWindow | null {
|
|
99
|
+
if (reading.remainingTokens === null && reading.limitTokens === null) return null;
|
|
100
|
+
const used =
|
|
101
|
+
reading.remainingTokens !== null && reading.limitTokens !== null
|
|
102
|
+
? reading.limitTokens - reading.remainingTokens
|
|
103
|
+
: null;
|
|
104
|
+
// The third argument is the *percentage*, not the count. Passing null left
|
|
105
|
+
// `usedPercent` null, and the bar renders a null percentage as grey — so a
|
|
106
|
+
// window that knew its exact used and limit still drew as unknown.
|
|
107
|
+
const usedPercent =
|
|
108
|
+
reading.limitTokens !== null && reading.limitTokens > 0 && used !== null
|
|
109
|
+
? (used / reading.limitTokens) * 100
|
|
110
|
+
: null;
|
|
111
|
+
return percentWindow(
|
|
112
|
+
GROK_HEADER_WINDOW_KIND,
|
|
113
|
+
"Rate limit token (header)",
|
|
114
|
+
usedPercent,
|
|
115
|
+
reading.resetsAt,
|
|
116
|
+
used,
|
|
117
|
+
reading.limitTokens,
|
|
118
|
+
"independent",
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The request bucket as its own window.
|
|
124
|
+
*
|
|
125
|
+
* Separate from the token bucket on purpose: `x-ratelimit-remaining-requests`
|
|
126
|
+
* is a per-minute cap (21) with no token equivalent, and folding it into the
|
|
127
|
+
* token window produced one number that described neither budget.
|
|
128
|
+
*/
|
|
129
|
+
export function grokHeaderRequestsWindow(
|
|
130
|
+
reading: GrokRateLimitReading,
|
|
131
|
+
): ProviderQuotaWindow | null {
|
|
132
|
+
if (reading.remainingRequests === null) return null;
|
|
133
|
+
const used = REQUEST_WINDOW_LIMIT - reading.remainingRequests;
|
|
134
|
+
const usedPercent = (used / REQUEST_WINDOW_LIMIT) * 100;
|
|
135
|
+
return percentWindow(
|
|
136
|
+
GROK_HEADER_REQUESTS_WINDOW_KIND,
|
|
137
|
+
"Rate limit request (header)",
|
|
138
|
+
usedPercent,
|
|
139
|
+
reading.resetsAt,
|
|
140
|
+
used,
|
|
141
|
+
REQUEST_WINDOW_LIMIT,
|
|
142
|
+
"independent",
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** The authoritative allowance a 429 states, parsed out of its message. */
|
|
147
|
+
export interface GrokFreeUsageVerdict {
|
|
148
|
+
readonly actual: number | null;
|
|
149
|
+
readonly limit: number | null;
|
|
150
|
+
readonly resetsAt: string | null;
|
|
151
|
+
readonly rolling: boolean;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Parses `tokens (actual/limit): 603024/600000` out of a refusal.
|
|
156
|
+
*
|
|
157
|
+
* The numbers are in prose, not in a field, so this is a text match — but the
|
|
158
|
+
* shape is the only place upstream publishes the real allowance, and a refusal
|
|
159
|
+
* that does not carry it yields `null` rather than a guess.
|
|
160
|
+
*/
|
|
161
|
+
export function parseGrokFreeUsageVerdict(body: unknown, message?: string): GrokFreeUsageVerdict | null {
|
|
162
|
+
const root = record(body) ?? {};
|
|
163
|
+
const error = text(root["error"] ?? root["message"]) ?? message ?? "";
|
|
164
|
+
const haystack = `${error} ${text(root["code"]) ?? ""}`;
|
|
165
|
+
const match = /tokens\s*\(actual\/limit\)\s*:?\s*([\d_,]+)\s*\/\s*([\d_,]+)/i.exec(haystack);
|
|
166
|
+
const actual = match?.[1] ? number(match[1].replaceAll(/[_,]/g, "")) : null;
|
|
167
|
+
const limit = match?.[2] ? number(match[2].replaceAll(/[_,]/g, "")) : null;
|
|
168
|
+
if (actual === null && limit === null) {
|
|
169
|
+
// A refusal without the figures still tells us the code; it just cannot
|
|
170
|
+
// tell us the allowance.
|
|
171
|
+
if (!haystack.toLowerCase().includes("free-usage") && !haystack.toLowerCase().includes("rolling 24")) return null;
|
|
172
|
+
}
|
|
173
|
+
const rolling = /rolling\s*24[\s-]*hour/i.test(haystack);
|
|
174
|
+
const resetMatch = /resets?\s+(?:over|in|at)\s+([^.;]{0,60})/i.exec(haystack);
|
|
175
|
+
return {
|
|
176
|
+
actual,
|
|
177
|
+
limit,
|
|
178
|
+
resetsAt: resetMatch ? isoDate(resetMatch[1]) ?? null : null,
|
|
179
|
+
rolling,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The authoritative allowance as a quota window.
|
|
185
|
+
*
|
|
186
|
+
* `remaining` is what decides whether the account can serve, so it is derived
|
|
187
|
+
* rather than left null: an account that has spent 603024 of 600000 has none
|
|
188
|
+
* left, and reporting "unknown" there would leave a refused account looking
|
|
189
|
+
* merely unmeasured.
|
|
190
|
+
*/
|
|
191
|
+
export function grokAuthoritativeWindow(verdict: GrokFreeUsageVerdict): ProviderQuotaWindow | null {
|
|
192
|
+
if (verdict.limit === null && verdict.actual === null) return null;
|
|
193
|
+
return percentWindow(
|
|
194
|
+
GROK_AUTHORITATIVE_WINDOW_KIND,
|
|
195
|
+
"Free usage allowance (authoritative)",
|
|
196
|
+
null,
|
|
197
|
+
verdict.resetsAt,
|
|
198
|
+
verdict.actual,
|
|
199
|
+
verdict.limit,
|
|
200
|
+
// Independent: the free allowance is per model per rolling day, not part of
|
|
201
|
+
// a pooled credit balance.
|
|
202
|
+
"independent",
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** One probe's two readings: the coarse header and the authoritative refusal. */
|
|
207
|
+
export interface GrokRateLimitProbe {
|
|
208
|
+
/** The CLI token bucket from the response headers. */
|
|
209
|
+
readonly header: ProviderQuotaWindow | null;
|
|
210
|
+
/** The per-minute request bucket, which has no token equivalent. */
|
|
211
|
+
readonly requests: ProviderQuotaWindow | null;
|
|
212
|
+
/** The free-usage allowance from a 429 body, or `null` when not refused. */
|
|
213
|
+
readonly authoritative: ProviderQuotaWindow | null;
|
|
214
|
+
/** Whether upstream refused the probe at all. */
|
|
215
|
+
readonly refusal: boolean;
|
|
216
|
+
/** The refusal code, for the console note. */
|
|
217
|
+
readonly note: string | null;
|
|
218
|
+
}
|
|
@@ -373,11 +373,10 @@ function normalizeTools(payload: Record<string, unknown>): void {
|
|
|
373
373
|
normalized.push(tool);
|
|
374
374
|
continue;
|
|
375
375
|
}
|
|
376
|
-
// Tools arrive factory-normalized (flat `{type:"function",name,parameters}
|
|
377
|
-
// canonical tools are flat, so
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
// fallback, custom-tool synthesis.
|
|
376
|
+
// Tools arrive factory-normalized (flat `{type:"function",name,parameters}`
|
|
377
|
+
// — canonical tools are flat, so there is no nested `function.*` payload to
|
|
378
|
+
// resolve). Only grok wire strictness stays here: trimmed names,
|
|
379
|
+
// empty-name drop, parameters fallback, custom-tool synthesis.
|
|
381
380
|
const name = typeof tool.name === "string" ? tool.name : "";
|
|
382
381
|
if (!name.trim()) continue;
|
|
383
382
|
const parameters =
|
|
@@ -413,8 +412,8 @@ function normalizeTools(payload: Record<string, unknown>): void {
|
|
|
413
412
|
if (type === "function" || type === "custom") {
|
|
414
413
|
// Unlike `tools`, `tool_choice` genuinely arrives nested: the chat
|
|
415
414
|
// encoder writes `{type:"function", function:{name}}` and
|
|
416
|
-
// `{type:"custom", custom:{name}}`, so these reads are
|
|
417
|
-
//
|
|
415
|
+
// `{type:"custom", custom:{name}}`, so these nested reads are required
|
|
416
|
+
// even though the tools loop above has no nested path.
|
|
418
417
|
const fn = value.function;
|
|
419
418
|
const nested = fn && typeof fn === "object" && !Array.isArray(fn) ? fn as Record<string, unknown> : undefined;
|
|
420
419
|
const custom = value.custom;
|
|
@@ -28,17 +28,15 @@ const HERMES_PROVIDER_ID = "hermes" as const;
|
|
|
28
28
|
* (`agent/portal_tags.py` in `NousResearch/hermes-agent`). Neither is required
|
|
29
29
|
* for dispatch — a request carrying only `user=` answers 200 — but they are
|
|
30
30
|
* sent because they are the client's real attribution and cost nothing. The
|
|
31
|
-
* client version
|
|
32
|
-
* Hermes does not publish a semver, so
|
|
33
|
-
*
|
|
31
|
+
* client version is read from `getHermesVersion()` and sent in the shape the
|
|
32
|
+
* released tags use (`v<version>`): Hermes does not publish a semver, so its
|
|
33
|
+
* versions are date-based release tags.
|
|
34
34
|
*/
|
|
35
35
|
/**
|
|
36
36
|
* Builds the portal tags for one dispatch.
|
|
37
37
|
*
|
|
38
|
-
* `client=` carries the version in the shape the released
|
|
39
|
-
* (`v<version>`)
|
|
40
|
-
* constant named a date tag (`v2026.9.24`) that was neither a release nor the
|
|
41
|
-
* version the project publishes. `getHermesVersion()` tracks the real release.
|
|
38
|
+
* `client=` carries the resolved version in the shape the released tags use
|
|
39
|
+
* (`v<version>`); `getHermesVersion()` tracks the real release.
|
|
42
40
|
*/
|
|
43
41
|
function hermesPortalTags(): readonly string[] {
|
|
44
42
|
return [
|
|
@@ -66,25 +64,23 @@ import type { ModelDefinition } from "../provider-model-definition";
|
|
|
66
64
|
*
|
|
67
65
|
* `loadModelDiscovery` supersedes this list whenever `/v1/models` answers, so
|
|
68
66
|
* these numbers are only read by a fetch that failed. They are the upstream's
|
|
69
|
-
* own `context_length` and `top_provider.max_completion_tokens
|
|
70
|
-
*
|
|
71
|
-
* one of them.
|
|
67
|
+
* own `context_length` and `top_provider.max_completion_tokens`, stated per row
|
|
68
|
+
* because they differ per row.
|
|
72
69
|
*
|
|
73
|
-
* Two ids
|
|
74
|
-
*
|
|
75
|
-
* `upstage/solar-pro4
|
|
76
|
-
* `upstage/solar-mini4:free` exist).
|
|
70
|
+
* Two ids upstream no longer carries are absent: `tencent/hy3:free` (missing
|
|
71
|
+
* from the catalog entirely) and `upstage/solar-pro4:free` (only the billed
|
|
72
|
+
* `upstage/solar-pro4` and the free `upstage/solar-mini4:free` exist).
|
|
77
73
|
*/
|
|
78
74
|
export const HERMES_MODELS: readonly ModelDefinition[] = [
|
|
79
75
|
// The live `/models` free rows, with the limits the catalog states. Verified
|
|
80
76
|
// against the API: every id here answers 200.
|
|
81
77
|
//
|
|
82
|
-
// `meituan/longcat-2.0:free` is
|
|
83
|
-
// dispatching it answers 404 "This model is no longer free", so
|
|
78
|
+
// `meituan/longcat-2.0:free` is excluded: the catalog still lists the id, but
|
|
79
|
+
// dispatching it answers 404 "This model is no longer free", so listing it
|
|
84
80
|
// would be a card that can only ever fail. `meituan/longcat-2.5-preview:free`
|
|
85
|
-
//
|
|
81
|
+
// is listed instead and answers 200.
|
|
86
82
|
//
|
|
87
|
-
// `stepfun/step-5-preview:free` is
|
|
83
|
+
// `stepfun/step-5-preview:free` is excluded: it is absent from the live catalog
|
|
88
84
|
// entirely and dispatching it answers 404 "This model's free period has
|
|
89
85
|
// ended" — a retired row, not a capacity blip, so it cannot be left in.
|
|
90
86
|
//
|
|
@@ -31,7 +31,7 @@ const MAX_DISCOVERED_MODELS = 500;
|
|
|
31
31
|
const KIRO_EFFORTS = ["low", "medium", "high", "xhigh"] as const;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* Ids the seed catalog deliberately
|
|
34
|
+
* Ids the seed catalog deliberately excludes.
|
|
35
35
|
*
|
|
36
36
|
* Discovery adds every id the upstream lists, so without this a retired row
|
|
37
37
|
* comes back the moment an account fetches its models. The seed is the owner
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// Two upstream behaviours drive the header and endpoint logic:
|
|
9
9
|
//
|
|
10
10
|
// * There is exactly one generation surface, `q.{region}.amazonaws.com`. The
|
|
11
|
-
//
|
|
11
|
+
// `codewhisperer.*` host and the vendor's own path-style gateway are
|
|
12
12
|
// not what the real client talks to, and reaching for them is actively
|
|
13
13
|
// harmful: an account that has just been refused would immediately probe two
|
|
14
14
|
// other service entries with the same token, which is the shape of credential
|
|
@@ -6,12 +6,12 @@ const MISTRAL_PROVIDER_ID = "mistral" as const;
|
|
|
6
6
|
/**
|
|
7
7
|
* Mistral's own current generalist tiers.
|
|
8
8
|
*
|
|
9
|
-
* The provider is registered as a generic OpenAI-compatible API-key provider,
|
|
10
|
-
*
|
|
11
|
-
* discovery run
|
|
12
|
-
* Mistral keeps pointed at its current generalist models —
|
|
13
|
-
* (Large 4) and `mistral-medium-latest` (Medium 3.5),
|
|
14
|
-
* overview.
|
|
9
|
+
* The provider is registered as a generic OpenAI-compatible API-key provider,
|
|
10
|
+
* which carries no catalog of its own: without this list, every model it serves
|
|
11
|
+
* stays absent until a discovery run happens to fetch them. These are the two
|
|
12
|
+
* `latest` aliases Mistral keeps pointed at its current generalist models —
|
|
13
|
+
* `mistral-large-latest` (Large 4) and `mistral-medium-latest` (Medium 3.5),
|
|
14
|
+
* per the Mistral model overview.
|
|
15
15
|
*
|
|
16
16
|
* Limits and pricing come from the base catalog via `providerId`: `defineModel`
|
|
17
17
|
* resolves `mistral:<id>` and falls back to the majority row, so no number is
|
|
@@ -23,11 +23,11 @@ const SESSION_COUNTER_MAX = 63;
|
|
|
23
23
|
* `ses_` + 12-char hex (bitwise inverted millisecond timestamp * 4096 + seq) + 14-char base62.
|
|
24
24
|
*
|
|
25
25
|
* The counter is capped rather than left to grow. Sixty-four dispatches inside
|
|
26
|
-
* one millisecond
|
|
27
|
-
*
|
|
26
|
+
* one millisecond emit ids the gate refuses, so a burst — exactly what a proxy
|
|
27
|
+
* pool produces — would 403 on its own headers while every other field was
|
|
28
28
|
* correct. On overflow the timestamp advances by one millisecond instead: the
|
|
29
29
|
* id stays inside the window, and the only cost is that ids minted in the same
|
|
30
|
-
* real millisecond
|
|
30
|
+
* real millisecond do not sort as the client's would.
|
|
31
31
|
*/
|
|
32
32
|
export function generateOpenCodeSessionId(now = Date.now()): string {
|
|
33
33
|
if (now !== lastTimestamp) {
|
|
@@ -79,7 +79,7 @@ const UNAVAILABLE_FREE_ZEN_IDS: readonly string[] = [
|
|
|
79
79
|
* `CARTETHYIA_OPENCODE_UNAVAILABLE_FREE` lets an operator correct that
|
|
80
80
|
* immediately: a comma-separated list that *replaces* the bundled one, or the
|
|
81
81
|
* single token `none` to trust the listing completely. The bundled ids remain
|
|
82
|
-
* the default so an unconfigured install
|
|
82
|
+
* the default so an unconfigured install keeps these refusals.
|
|
83
83
|
*/
|
|
84
84
|
function unavailableFreeZenIds(): readonly string[] {
|
|
85
85
|
const override = resolveOpenCodeUnavailableFree();
|
|
@@ -116,8 +116,12 @@ export function isSystemoneZenModel(modelId: string): boolean {
|
|
|
116
116
|
* fail a probe.
|
|
117
117
|
*/
|
|
118
118
|
export function isFreeTierZenModel(modelId: string): boolean {
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
// Dispatch ids arrive provider-prefixed (`opencode/big-pickle`) while the
|
|
120
|
+
// catalog and `KNOWN_FREE_ZEN_IDS` hold the bare id, so match on the bare
|
|
121
|
+
// id rather than the prefixed one.
|
|
122
|
+
const bare = modelId.slice(modelId.indexOf("/") + 1);
|
|
123
|
+
if (unavailableFreeZenIds().includes(bare)) return false;
|
|
124
|
+
return bare.endsWith("-free") || KNOWN_FREE_ZEN_IDS.includes(bare);
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
/**
|
|
@@ -159,11 +163,11 @@ function opencodeDesktopHeaders(
|
|
|
159
163
|
// The free-tier gate refuses non-streaming dispatches with 403
|
|
160
164
|
// FreeTierError, so free models always advertise SSE regardless of the
|
|
161
165
|
// client's own Accept; billed models keep the JSON default. The value is
|
|
162
|
-
// what OpenCode 2.x's AI SDK sends
|
|
163
|
-
// `text/event-stream`
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
166
|
+
// what OpenCode 2.x's AI SDK sends — a broader Accept than the narrower
|
|
167
|
+
// `text/event-stream` the gate is known to accept, so this is alignment
|
|
168
|
+
// with the real client rather than a fix for a live failure. It costs
|
|
169
|
+
// nothing: `stream: true` is forced on the body either way, so the upstream
|
|
170
|
+
// answers SSE regardless.
|
|
167
171
|
...(freeModel ? { accept: FREE_TIER_ACCEPT } : {}),
|
|
168
172
|
};
|
|
169
173
|
}
|
|
@@ -493,29 +497,24 @@ export function systemoneLimits(): Pick<ModelDefinition, "contextLimit" | "outpu
|
|
|
493
497
|
|
|
494
498
|
export const OPENCODE_FREE_MODELS: readonly ModelDefinition[] = [
|
|
495
499
|
...sharedZenChat,
|
|
496
|
-
//
|
|
497
|
-
//
|
|
498
|
-
//
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
defineModel({ id: "nemotron-3-ultra-free", providerId: "opencode", wireFamily: "chat", endpoint: `${ZEN_PATH_PREFIX}/chat/completions`, reasoning: true, free: true }),
|
|
503
|
-
defineModel({ id: "nemotron-3.5-lightning-free", providerId: "opencode", wireFamily: "chat", endpoint: `${ZEN_PATH_PREFIX}/chat/completions`, reasoning: true, free: true }),
|
|
504
|
-
// Absent from the snapshot: keep declared limits rather than the generic default.
|
|
505
|
-
defineModel({ id: "longcat-2.5-preview-free", providerId: "opencode", wireFamily: "chat", endpoint: `${ZEN_PATH_PREFIX}/chat/completions`, ctx: 1_000_000, out: 131_072, reasoning: true, free: true }),
|
|
500
|
+
// `nemotron-3-ultra-free`, `nemotron-3.5-lightning-free` and
|
|
501
|
+
// `longcat-2.5-preview-free` are excluded: the live Zen roster does not list
|
|
502
|
+
// them. A row the provider's own roster dropped can disappear from the wire
|
|
503
|
+
// without notice, which makes it a stale row — one that routes to a 404 at
|
|
504
|
+
// dispatch time rather than failing at catalog load. `big-pickle` and the
|
|
505
|
+
// rest of the shared Zen listing remain.
|
|
506
506
|
systemoneZen("jev-1.13-free", true),
|
|
507
507
|
];
|
|
508
508
|
|
|
509
509
|
export const OPENCODE_ZEN_MODELS: readonly ModelDefinition[] = [
|
|
510
510
|
...sharedZenChat,
|
|
511
|
-
defineModel({ id: "nemotron-3-ultra-free", providerId: "opencode", wireFamily: "chat", endpoint: `${ZEN_PATH_PREFIX}/chat/completions`, reasoning: true }),
|
|
512
511
|
defineModel({ id: "muse-spark-1.2", providerId: "opencode", wireFamily: "responses", endpoint: `${ZEN_PATH_PREFIX}/responses`, vision: true, reasoning: true, reasoningEfforts: MUSE_SPARK_REASONING_EFFORTS }),
|
|
513
512
|
defineModel({ id: "muse-spark-1.3", providerId: "opencode", wireFamily: "responses", endpoint: `${ZEN_PATH_PREFIX}/responses`, vision: true, reasoning: true, reasoningEfforts: MUSE_SPARK_REASONING_EFFORTS }),
|
|
514
513
|
systemoneZen("jev-1.13", false),
|
|
515
514
|
];
|
|
516
515
|
|
|
517
516
|
export const OPENCODE_GO_MODELS: readonly ModelDefinition[] = [
|
|
518
|
-
// `muse-spark-1.2` is
|
|
517
|
+
// `muse-spark-1.2` is not served upstream; the catalog files
|
|
519
518
|
// `muse-spark-1.2-contributor` at 1048576/131072, which is what this row
|
|
520
519
|
// serves.
|
|
521
520
|
defineModel({ id: "muse-spark-1.2-contributor", providerId: "opencode-go", wireFamily: "responses", endpoint: `${GO_PATH_PREFIX}/responses`, ctx: 1048576, out: 131072, vision: true, reasoning: true }),
|