cartethyia 2.5.9 → 2.6.0
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 +15 -42
- package/README.md +11 -10
- package/dist/dashboard/assets/{BannedPage-Brvuj_Eb.js → BannedPage-l6XMnfr9.js} +1 -1
- package/dist/dashboard/assets/BannedPage-l6XMnfr9.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-CqfXtI3y.js → CliToolDetailPage-DwOzAW45.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DwOzAW45.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-GQeS91bg.js → CliToolsPage-BT3Up3QA.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BT3Up3QA.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BDRsTXBB.js → CombosPage-6kYIUpzR.js} +1 -1
- package/dist/dashboard/assets/CombosPage-6kYIUpzR.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-zP8AFHX0.js → ConsoleLogPage-zRnj1mlR.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-zRnj1mlR.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-BmfrNZ14.js → CustomizationPage-C7m-H1Rz.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-C7m-H1Rz.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-C8MR_BdB.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-C8MR_BdB.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-DoreIgm8.js → LoginPage-CbphLvjg.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CbphLvjg.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-C7pDb41R.js → ModelPicker-DVny4S5_.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DVny4S5_.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-DABu2Wgt.js +1 -0
- package/dist/dashboard/assets/OverviewPage-DABu2Wgt.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-C15x9q13.js +3 -0
- package/dist/dashboard/assets/ProviderDetailPage-C15x9q13.js.gz +0 -0
- package/dist/dashboard/assets/{ProvidersPage-BnoPgA7w.js → ProvidersPage-Dfb2896L.js} +1 -1
- package/dist/dashboard/assets/ProvidersPage-Dfb2896L.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-Bq_TGgdb.js → ProxyPage-BaCIdAUt.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BaCIdAUt.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-BsdoCIw1.js +1 -0
- package/dist/dashboard/assets/QuotaPage-BsdoCIw1.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-KVJFh3Ip.js +1 -0
- package/dist/dashboard/assets/SettingsPage-KVJFh3Ip.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-Day3mCOn.js → SetupPage-D4g6vOGc.js} +1 -1
- package/dist/dashboard/assets/SetupPage-D4g6vOGc.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-DQxllnB5.js → SortableList-C93i14BD.js} +1 -1
- package/dist/dashboard/assets/SortableList-C93i14BD.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-uMExoWu1.js → StudioPage-SgQpymjm.js} +1 -1
- package/dist/dashboard/assets/{StudioPage-uMExoWu1.js.gz → StudioPage-SgQpymjm.js.gz} +0 -0
- package/dist/dashboard/assets/{UsagePage-DXa1oR-4.js → UsagePage-BFME-eba.js} +2 -2
- package/dist/dashboard/assets/UsagePage-BFME-eba.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-DQYLQxpW.js → api-keys-C23S9sgp.js} +1 -1
- package/dist/dashboard/assets/api-keys-C23S9sgp.js.gz +0 -0
- package/dist/dashboard/assets/{app-BIt446yE.js → app-2KhtHCv9.js} +1 -1
- package/dist/dashboard/assets/{app-BIt446yE.js.gz → app-2KhtHCv9.js.gz} +0 -0
- package/dist/dashboard/assets/app-CEeaMHOy.css +2 -0
- package/dist/dashboard/assets/app-CEeaMHOy.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C9FD_JwJ.js → assert-DU6qrMA_.js} +1 -1
- package/dist/dashboard/assets/assert-DU6qrMA_.js.gz +0 -0
- package/dist/dashboard/assets/{badge-CR72dasT.js → badge-CKsF123d.js} +1 -1
- package/dist/dashboard/assets/badge-CKsF123d.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CI9_eSfO.js → banner-8j7uChA9.js} +1 -1
- package/dist/dashboard/assets/banner-8j7uChA9.js.gz +0 -0
- package/dist/dashboard/assets/{card-DS7CQEsO.js → card-CdsSlWA3.js} +1 -1
- package/dist/dashboard/assets/card-CdsSlWA3.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-CNqzrfdb.js → cli-tools-BaFUuFFF.js} +1 -1
- package/dist/dashboard/assets/cli-tools-BaFUuFFF.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-611pSsaX.js → clipboard-button-uL5aYLfW.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-uL5aYLfW.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-k37exjNt.js → dialog-C07hr5_G.js} +1 -1
- package/dist/dashboard/assets/dialog-C07hr5_G.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CX7N8ucR.js → drawer-BPO1TcKH.js} +1 -1
- package/dist/dashboard/assets/drawer-BPO1TcKH.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CTP8AyiS.js → entry-Bz_CtDfC.js} +1 -1
- package/dist/dashboard/assets/entry-Bz_CtDfC.js.gz +0 -0
- package/dist/dashboard/assets/entry-CwPRKk0d.js +4 -0
- package/dist/dashboard/assets/entry-CwPRKk0d.js.gz +0 -0
- package/dist/dashboard/assets/entry-GJRbmrpA.js +1 -0
- package/dist/dashboard/assets/entry-GJRbmrpA.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-sltk1qUi.js → github-badge-DmQreSDd.js} +1 -1
- package/dist/dashboard/assets/github-badge-DmQreSDd.js.gz +0 -0
- package/dist/dashboard/assets/{index-z3zDOSMM.js → index-Bblu6erR.js} +2 -2
- package/dist/dashboard/assets/index-Bblu6erR.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BhY2sSnO.js → inline-C9dCYaBZ.js} +1 -1
- package/dist/dashboard/assets/inline-C9dCYaBZ.js.gz +0 -0
- package/dist/dashboard/assets/{input-V1umFiBk.js → input-CjCnXweJ.js} +1 -1
- package/dist/dashboard/assets/input-CjCnXweJ.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BBOYycyS.js → layout-V6y8DAkl.js} +1 -1
- package/dist/dashboard/assets/layout-V6y8DAkl.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-1zzZYM0B.js → list-row-CM1AaG_y.js} +1 -1
- package/dist/dashboard/assets/list-row-CM1AaG_y.js.gz +0 -0
- package/dist/dashboard/assets/{live-BivGfuUs.js → live-ta6GMb-8.js} +1 -1
- package/dist/dashboard/assets/live-ta6GMb-8.js.gz +0 -0
- package/dist/dashboard/assets/{model-bans-CmffjLuG.js → model-bans-BmYTmbAk.js} +1 -1
- package/dist/dashboard/assets/model-bans-BmYTmbAk.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-46P0oWMe.js → mutation-g_fduiNw.js} +1 -1
- package/dist/dashboard/assets/mutation-g_fduiNw.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-DkfMR5Qs.js → numbers-BOevJzdz.js} +1 -1
- package/dist/dashboard/assets/numbers-BOevJzdz.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-BFhGpwR1.js → query-keys-UETqfytp.js} +1 -1
- package/dist/dashboard/assets/query-keys-UETqfytp.js.gz +0 -0
- package/dist/dashboard/assets/{routing-CAb4F37R.js → routing-BPUo-W8d.js} +1 -1
- package/dist/dashboard/assets/routing-BPUo-W8d.js.gz +0 -0
- package/dist/dashboard/assets/{select-C6MMiaio.js → select-C980c4cz.js} +1 -1
- package/dist/dashboard/assets/select-C980c4cz.js.gz +0 -0
- package/dist/dashboard/assets/{settings-DNX9sydi.js → settings--3hxSyry.js} +1 -1
- package/dist/dashboard/assets/settings--3hxSyry.js.gz +0 -0
- package/dist/dashboard/assets/{stack-BHTfXdz_.js → stack-_gfTdLVB.js} +1 -1
- package/dist/dashboard/assets/stack-_gfTdLVB.js.gz +0 -0
- package/dist/dashboard/assets/{state-mPDRlQkl.js → state-2c5V4zo7.js} +1 -1
- package/dist/dashboard/assets/state-2c5V4zo7.js.gz +0 -0
- package/dist/dashboard/assets/{switch-DOmJxg7H.js → switch-Dkke7Naf.js} +1 -1
- package/dist/dashboard/assets/switch-Dkke7Naf.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dem0lXQj.js → useMutation-EDFRkn1i.js} +1 -1
- package/dist/dashboard/assets/useMutation-EDFRkn1i.js.gz +0 -0
- package/dist/dashboard/index.html +1 -1
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +51 -51
- package/migrations/README.md +52 -52
- package/migrations/full-postgres/0020_add_telemetry_event_analytics.sql +77 -0
- package/migrations/full-postgres/0021_add_api_key_concurrency_tolerance.sql +13 -0
- package/migrations/full-postgres/0022_add_inferhub_config_key.sql +17 -0
- package/migrations/full-postgres/0023_drop_api_key_concurrency_tolerance.sql +13 -0
- package/migrations/lite-sqlite3/0020_add_telemetry_event_analytics.sql +69 -0
- package/migrations/lite-sqlite3/0021_add_api_key_concurrency_tolerance.sql +13 -0
- package/migrations/lite-sqlite3/0022_add_inferhub_config_key.sql +17 -0
- package/migrations/lite-sqlite3/0023_drop_api_key_concurrency_tolerance.sql +13 -0
- package/package.json +96 -97
- package/scripts/cli/admin.ts +126 -125
- package/scripts/cli/autostart.ts +237 -237
- package/scripts/cli/background.ts +120 -110
- package/scripts/cli/bin/carte.cjs +8 -8
- package/scripts/cli/bin/cartethyia.cjs +167 -167
- package/scripts/cli/console-menu.ts +308 -275
- package/scripts/cli/controller.ts +145 -0
- package/scripts/cli/doctor.ts +1 -1
- package/scripts/cli/env.ts +99 -99
- package/scripts/cli/gateway.ts +264 -261
- package/scripts/{health.ts → cli/health.ts} +4 -4
- package/scripts/cli/instance.ts +234 -224
- package/scripts/cli/main.ts +188 -164
- package/scripts/cli/platform.ts +64 -64
- package/scripts/cli/prompt.ts +275 -107
- package/scripts/cli/services.ts +88 -88
- package/scripts/cli/setup.ts +445 -445
- package/scripts/cli/start.ts +85 -82
- package/scripts/cli/startup-signal.ts +23 -23
- package/scripts/cli/telemetry.ts +70 -0
- package/scripts/cli/tray/index.ts +263 -263
- package/scripts/cli/tray/windows.ps1 +107 -107
- package/scripts/cli/tray.ts +192 -208
- package/scripts/cli/update.ts +39 -39
- package/scripts/cli/version.ts +67 -67
- package/scripts/cli/wordmark.ts +58 -58
- package/src/boot/app.ts +16 -1
- package/src/boot/dependencies.ts +128 -25
- package/src/config/package-paths.ts +24 -0
- package/src/config/resources.ts +137 -0
- package/src/config/runtime.ts +133 -76
- package/src/config/spec.ts +30 -29
- package/src/config/telemetry.ts +0 -25
- package/src/console/api-keys/bucket-spend.ts +14 -17
- package/src/console/api-keys/contracts.ts +410 -410
- package/src/console/api-keys/routes.ts +12 -0
- package/src/console/audit/store.ts +2 -3
- package/src/console/auth/setup-service.ts +8 -1
- package/src/console/backup/routes.ts +7 -0
- package/src/console/backup/service.ts +463 -463
- package/src/console/backup/store.ts +16 -11
- package/src/console/backup/validate.ts +1 -4
- package/src/console/cli-tools/fs-ops.ts +18 -2
- package/src/console/data-management/contracts.ts +1 -8
- package/src/console/data-management/operations.ts +61 -48
- package/src/console/data-management/routes.ts +4 -2
- package/src/console/domain-registration.ts +25 -3
- package/src/console/inferhub/client.ts +139 -0
- package/src/console/inferhub/key-store.ts +129 -0
- package/src/console/inferhub/normalize.ts +347 -0
- package/src/console/inferhub/routes.ts +411 -0
- package/src/console/inferhub/store.ts +109 -0
- package/src/console/inferhub/types.ts +183 -0
- package/src/console/observability/contracts.ts +2 -41
- package/src/console/observability/store.ts +176 -371
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/store.ts +23 -36
- package/src/console/quota/account-quota-shared.ts +52 -52
- package/src/console/quota/account-quota-tenant.ts +16 -24
- package/src/console/quota/refresh.ts +441 -441
- package/src/console/remote-support/service.ts +270 -114
- package/src/console/routing/pools/import-parse.ts +206 -206
- package/src/console/routing/pools/operations.ts +543 -543
- package/src/console/routing/pools/probe-verdict.ts +132 -132
- package/src/console/routing/pools/routes.ts +181 -181
- package/src/console/routing/pools/store.ts +1 -1
- package/src/console/settings/contracts.ts +42 -40
- package/src/console/settings/store.ts +25 -25
- package/src/console/share/share-stats.ts +22 -4
- package/src/console/share/share-usage.ts +30 -4
- package/src/console/shared/cursor.ts +15 -0
- package/src/console/updates/repository-updates.ts +40 -39
- package/src/console/updates/routes.ts +12 -0
- package/src/main.ts +13 -5
- package/src/network/pool/resolver.ts +1104 -1104
- package/src/observability/client-name.ts +22 -0
- package/src/observability/event-log.ts +5 -29
- package/src/observability/event-query.ts +690 -0
- package/src/observability/log-ring.ts +26 -2
- package/src/observability/log-sanitize.ts +118 -0
- package/src/observability/logger.ts +17 -13
- package/src/observability/metrics.ts +35 -0
- package/src/observability/payload-capture.ts +114 -41
- package/src/observability/payload-store.ts +249 -24
- package/src/observability/raw-event-writer.ts +118 -0
- package/src/observability/runtime-metrics.ts +71 -1
- package/src/observability/telemetry-buffer.ts +100 -17
- package/src/observability/telemetry-reconciliation.ts +417 -0
- package/src/persistence/boot.ts +20 -9
- package/src/persistence/db-pg.ts +13 -0
- package/src/persistence/db-sqlite.ts +569 -497
- package/src/persistence/dialect.ts +3 -2
- package/src/persistence/migrate.ts +181 -181
- package/src/persistence/schema.ts +1496 -1406
- package/src/persistence/shared-cache.ts +5 -1
- package/src/persistence/stores/api-key-store.ts +581 -581
- package/src/persistence/stores/telemetry-store.ts +124 -63
- package/src/protocol/reasoning-text.ts +30 -0
- package/src/protocol/registry.ts +2 -0
- package/src/protocol/response/chat.ts +33 -7
- package/src/protocol/response/codex.ts +14 -2
- package/src/protocol/response/messages.ts +5 -2
- package/src/providers/authentication/oauth-flow-store.ts +3 -10
- package/src/providers/bundled-discovery-providers.ts +122 -122
- package/src/providers/default-registry.ts +14 -0
- package/src/providers/discovery/catalog/catalog-blob.ts +18 -18
- package/src/providers/discovery/models-dev-catalog.ts +354 -354
- package/src/providers/discovery/probe-phases.ts +43 -7
- package/src/providers/discovery/probing-service.ts +70 -32
- package/src/providers/integrations/antigravity/antigravity.ts +9 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +85 -17
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +934 -934
- package/src/providers/integrations/buddy/buddy-checkin.ts +5 -9
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +3 -7
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +3 -1
- package/src/providers/integrations/buddy/capabilities.ts +4 -0
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +57 -49
- package/src/providers/integrations/buddy/codebuddy/provider.ts +180 -180
- package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -206
- package/src/providers/integrations/buddy/workbuddy/quota.ts +161 -161
- package/src/providers/integrations/claude/claude-quota.ts +2 -2
- package/src/providers/integrations/claude/claude-user-profiles.ts +3 -2
- package/src/providers/integrations/claude/claude.ts +3 -4
- package/src/providers/integrations/cline/cline.ts +94 -8
- package/src/providers/integrations/codex/codex.ts +61 -37
- package/src/providers/integrations/cursor/cursor-catalog.ts +368 -368
- package/src/providers/integrations/cursor/cursor-http2.ts +300 -300
- package/src/providers/integrations/cursor/cursor-identity.ts +2 -4
- package/src/providers/integrations/cursor/cursor-request.ts +11 -0
- package/src/providers/integrations/cursor/cursor.ts +29 -17
- package/src/providers/integrations/cursor/protocol/framing.ts +129 -129
- package/src/providers/integrations/cursor/protocol/messages.ts +2380 -2380
- package/src/providers/integrations/cursor/protocol/struct.ts +305 -305
- package/src/providers/integrations/cursor/protocol/tool-canonical.ts +275 -0
- package/src/providers/integrations/github/github.ts +3 -1
- package/src/providers/integrations/grok/grok-quota.ts +279 -279
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +73 -73
- package/src/providers/integrations/grok/grok-ratelimit.ts +218 -218
- package/src/providers/integrations/hermes.ts +7 -1
- package/src/providers/integrations/inferhub.ts +201 -73
- package/src/providers/integrations/kilo/kilo.ts +152 -152
- package/src/providers/integrations/kiro/kiro-machine-id.ts +2 -4
- package/src/providers/integrations/opencode/provider.ts +2 -0
- package/src/providers/integrations/openrouter/provider.ts +129 -129
- package/src/providers/integrations/qoder/qoder-quota.ts +193 -192
- package/src/providers/integrations/qoder/qoder-realm.ts +106 -106
- package/src/providers/integrations/trae/trae-headers.ts +17 -48
- package/src/providers/integrations/trae/trae-oauth.ts +4 -26
- package/src/providers/integrations/trae/trae-quota.ts +389 -384
- package/src/providers/integrations/trae/trae-realm.ts +15 -2
- package/src/providers/integrations/trae/trae.ts +22 -24
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +100 -24
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/operations/account-health-service.ts +605 -279
- package/src/providers/provider-metadata.ts +12 -1
- package/src/providers/provider-model-definition.ts +373 -373
- package/src/providers/provider-probe.ts +3 -0
- package/src/providers/quota/quota-contracts.ts +3 -7
- package/src/providers/search/search-provider.ts +2 -6
- package/src/security/admission/contracts.ts +10 -0
- package/src/security/admission/in-memory-store.ts +89 -14
- package/src/security/admission/lua.ts +191 -182
- package/src/security/admission/redis-store.ts +30 -0
- package/src/security/admission/service.ts +18 -0
- package/src/security/api-key-auth-cache.ts +96 -0
- package/src/security/api-key-auth.ts +11 -100
- package/src/security/client-router-fingerprint.ts +3 -7
- package/src/security/ip-boundary.ts +7 -3
- package/src/shared/coerce.ts +67 -0
- package/src/shared/hash.ts +6 -0
- package/src/shared/time.ts +7 -0
- package/src/transport/dispatch/attempt-finalize.ts +26 -138
- package/src/transport/dispatch/attempt-loop.ts +103 -81
- package/src/transport/dispatch/capture-policy.ts +78 -0
- package/src/transport/dispatch/proxy-request.ts +4 -2
- package/src/transport/dispatch/streaming/encoder.ts +111 -5
- package/src/transport/dispatch/streaming/stream.ts +19 -2
- package/src/transport/dispatch/streaming/thinking-loop.ts +300 -0
- package/src/transport/failure-policy.ts +27 -0
- package/src/transport/guards/abuse-guard.ts +2 -2
- package/src/transport/guards/auth-guard.ts +17 -0
- package/src/transport/guards/body-policy.ts +3 -2
- package/src/transport/guards/concurrency-guard.ts +89 -13
- package/src/transport/guards/early-rejection-capture.ts +43 -3
- package/src/transport/guards/error-lifecycle.ts +10 -2
- package/src/transport/guards/guard-errors.ts +23 -0
- package/src/transport/guards/headroom-guard.ts +41 -7
- package/src/transport/guards/pipeline.ts +24 -0
- package/src/transport/guards/request-context.ts +2 -1
- package/src/transport/routing/admission.ts +51 -9
- package/src/transport/routing/bounded-lru.ts +49 -0
- package/src/transport/routing/candidate-index.ts +88 -0
- package/src/transport/routing/reservations.ts +121 -7
- package/src/transport/routing/round-robin.ts +10 -22
- package/src/transport/routing/route-catalog.ts +26 -13
- package/src/transport/routing/route-model.ts +22 -2
- package/src/transport/routing/router.ts +53 -31
- package/src/transport/surface/chat/encode.ts +2 -3
- package/src/transport/surface/chat/parse.ts +2 -1
- package/src/transport/surface/dialects.ts +11 -3
- package/src/transport/surface/messages/encode.ts +2 -1
- package/src/transport/surface/messages/parse.ts +3 -1
- package/src/transport/surface/messages/stream.ts +2 -6
- package/src/workers/maintenance-lease.ts +200 -0
- package/src/workers/scheduler.ts +101 -1
- package/dist/dashboard/assets/BannedPage-Brvuj_Eb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CqfXtI3y.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-GQeS91bg.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BDRsTXBB.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-zP8AFHX0.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BmfrNZ14.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-Dn3M6WZc.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-Dn3M6WZc.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-DoreIgm8.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-C7pDb41R.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CvvD1Ugk.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CvvD1Ugk.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-Clbn1gsW.js +0 -3
- package/dist/dashboard/assets/ProviderDetailPage-Clbn1gsW.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BnoPgA7w.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-Bq_TGgdb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-D9DHXvom.js +0 -1
- package/dist/dashboard/assets/QuotaPage-D9DHXvom.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-7xV8WkWL.js +0 -1
- package/dist/dashboard/assets/SettingsPage-7xV8WkWL.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-Day3mCOn.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-DQxllnB5.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DXa1oR-4.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-DQYLQxpW.js.gz +0 -0
- package/dist/dashboard/assets/app-CX_Z8cMs.css +0 -2
- package/dist/dashboard/assets/app-CX_Z8cMs.css.gz +0 -0
- package/dist/dashboard/assets/assert-C9FD_JwJ.js.gz +0 -0
- package/dist/dashboard/assets/badge-CR72dasT.js.gz +0 -0
- package/dist/dashboard/assets/banner-CI9_eSfO.js.gz +0 -0
- package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-611pSsaX.js.gz +0 -0
- package/dist/dashboard/assets/dialog-k37exjNt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CX7N8ucR.js.gz +0 -0
- package/dist/dashboard/assets/entry-B9Xvtnfj.js +0 -1
- package/dist/dashboard/assets/entry-B9Xvtnfj.js.gz +0 -0
- package/dist/dashboard/assets/entry-ByMGkR3C.js +0 -4
- package/dist/dashboard/assets/entry-ByMGkR3C.js.gz +0 -0
- package/dist/dashboard/assets/entry-CTP8AyiS.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
- package/dist/dashboard/assets/index-z3zDOSMM.js.gz +0 -0
- package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
- package/dist/dashboard/assets/input-V1umFiBk.js.gz +0 -0
- package/dist/dashboard/assets/layout-BBOYycyS.js.gz +0 -0
- package/dist/dashboard/assets/list-row-1zzZYM0B.js.gz +0 -0
- package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
- package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
- package/dist/dashboard/assets/mutation-46P0oWMe.js.gz +0 -0
- package/dist/dashboard/assets/numbers-DkfMR5Qs.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
- package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
- package/dist/dashboard/assets/select-C6MMiaio.js.gz +0 -0
- package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
- package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
- package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
- package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dem0lXQj.js.gz +0 -0
- package/scripts/build/aot.ts +0 -143
- package/scripts/build/build.ts +0 -24
- package/scripts/build/compile.ts +0 -88
- package/scripts/build/restart.ts +0 -120
- package/scripts/build/start.ts +0 -25
- package/src/observability/event-compaction.ts +0 -317
- package/src/observability/event-day-index.ts +0 -440
|
@@ -1,161 +1,161 @@
|
|
|
1
|
-
import type { FetchLike, ProviderQuotaResult } from "../../../quota/quota-contracts";
|
|
2
|
-
import type { QuotaCollectionContext } from "../../../quota/quota-support";
|
|
3
|
-
import { providerBaseUrl } from "../../../provider-metadata";
|
|
4
|
-
import {
|
|
5
|
-
buildWorkBuddyUserAgent,
|
|
6
|
-
getWorkBuddyClientVersion,
|
|
7
|
-
getWorkBuddyCnClientVersion,
|
|
8
|
-
getWorkBuddyCliVersion,
|
|
9
|
-
} from "../../../operations/client-versions";
|
|
10
|
-
import { WORKBUDDY_DOMAIN } from "./shared";
|
|
11
|
-
import { fetchTencentBillingQuota } from "../buddy-quota-shared";
|
|
12
|
-
import { fetchBuddyRequestUsage, type BuddyUsageResult } from "../buddy-usage-shared";
|
|
13
|
-
import { buddyAccountUid } from "../buddy-oauth-shared";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* WorkBuddy international billing quota.
|
|
17
|
-
*
|
|
18
|
-
* Endpoint: POST https://www.workbuddy.ai/v2/billing/meter/get-user-resource
|
|
19
|
-
* Request: Authorization: Bearer <accessToken||apiKey>, desktop-client headers,
|
|
20
|
-
* X-User-Id for the account UID, and the reference filter envelope
|
|
21
|
-
* (ProductCode p_tcaca, statuses [0, 3], 101-year package window).
|
|
22
|
-
* Response: { code: 0, data: { Response: { Data: { Accounts: [...] } } } }
|
|
23
|
-
*
|
|
24
|
-
* Same Tencent billing envelope as CodeBuddy CN, so the parsing is the shared
|
|
25
|
-
* one in `buddy-quota-shared.ts`; only the endpoint and identity headers are
|
|
26
|
-
* WorkBuddy-specific.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* The CN billing realm's host.
|
|
31
|
-
*
|
|
32
|
-
* The reference bills the CN realm here rather than on the CN chat host
|
|
33
|
-
* (`www.workbuddy.cn`): billing is a separate service, and the chat host does
|
|
34
|
-
* not serve the meter path.
|
|
35
|
-
*/
|
|
36
|
-
const WORKBUDDY_CN_BILLING_BASE_URL = "https://www.codebuddy.cn";
|
|
37
|
-
|
|
38
|
-
export const WORKBUDDY_USAGE_URL =
|
|
39
|
-
`${providerBaseUrl("workbuddy")}/v2/billing/meter/get-user-resource`;
|
|
40
|
-
|
|
41
|
-
async function billingHeaders(
|
|
42
|
-
domain: string,
|
|
43
|
-
clientVersion: string,
|
|
44
|
-
enterpriseId?: string,
|
|
45
|
-
): Promise<Record<string, string>> {
|
|
46
|
-
return {
|
|
47
|
-
"User-Agent": buildWorkBuddyUserAgent(clientVersion, getWorkBuddyCliVersion()),
|
|
48
|
-
"X-Product": "SaaS",
|
|
49
|
-
"X-Domain": domain,
|
|
50
|
-
"X-Requested-With": "XMLHttpRequest",
|
|
51
|
-
"X-CodeBuddy-Request": "1",
|
|
52
|
-
"Accept-Language": "en-US",
|
|
53
|
-
...(enterpriseId === undefined || enterpriseId.length === 0
|
|
54
|
-
? {}
|
|
55
|
-
: { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Fetches WorkBuddy quota via the Tencent billing endpoint.
|
|
61
|
-
*
|
|
62
|
-
* Auth: `Authorization: Bearer <credential>` (api_key and oauth both use
|
|
63
|
-
* Bearer; the caller passes the resolved secret).
|
|
64
|
-
*/
|
|
65
|
-
export async function fetchWorkBuddyQuota(
|
|
66
|
-
credential: string,
|
|
67
|
-
fetcher: FetchLike,
|
|
68
|
-
context?: QuotaCollectionContext,
|
|
69
|
-
): Promise<ProviderQuotaResult> {
|
|
70
|
-
return fetchWorkBuddyQuotaFor({
|
|
71
|
-
providerId: "workbuddy",
|
|
72
|
-
display: "WorkBuddy",
|
|
73
|
-
domain: WORKBUDDY_DOMAIN,
|
|
74
|
-
credential,
|
|
75
|
-
fetcher,
|
|
76
|
-
...(context === undefined ? {} : { context }),
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export async function fetchWorkBuddyCnQuota(
|
|
81
|
-
credential: string,
|
|
82
|
-
fetcher: FetchLike,
|
|
83
|
-
context?: QuotaCollectionContext,
|
|
84
|
-
): Promise<ProviderQuotaResult> {
|
|
85
|
-
return fetchWorkBuddyQuotaFor({
|
|
86
|
-
providerId: "workbuddycn",
|
|
87
|
-
display: "WorkBuddy CN",
|
|
88
|
-
domain: "www.workbuddy.cn",
|
|
89
|
-
credential,
|
|
90
|
-
fetcher,
|
|
91
|
-
...(context === undefined ? {} : { context }),
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async function fetchWorkBuddyQuotaFor(args: {
|
|
96
|
-
readonly providerId: "workbuddy" | "workbuddycn";
|
|
97
|
-
readonly display: string;
|
|
98
|
-
readonly domain: string;
|
|
99
|
-
readonly credential: string;
|
|
100
|
-
readonly fetcher: FetchLike;
|
|
101
|
-
readonly context?: QuotaCollectionContext;
|
|
102
|
-
}): Promise<ProviderQuotaResult> {
|
|
103
|
-
const { providerId, display, domain, credential, fetcher, context } = args;
|
|
104
|
-
const authState = typeof context?.auth_state === "object" && context?.auth_state !== null
|
|
105
|
-
? (context.auth_state as Record<string, unknown>)
|
|
106
|
-
: undefined;
|
|
107
|
-
const enterpriseId = typeof authState?.enterpriseId === "string" ? authState.enterpriseId : undefined;
|
|
108
|
-
const clientVersion = providerId === "workbuddycn"
|
|
109
|
-
? getWorkBuddyCnClientVersion()
|
|
110
|
-
: getWorkBuddyClientVersion();
|
|
111
|
-
// The reference bills the CN realm on `www.codebuddy.cn`, not the chat host:
|
|
112
|
-
// the billing realm is a different service from the one that serves chat,
|
|
113
|
-
// and the CN chat host answers the meter path with an HTML error page.
|
|
114
|
-
const billingBase = providerId === "workbuddycn" ? WORKBUDDY_CN_BILLING_BASE_URL : providerBaseUrl(providerId);
|
|
115
|
-
return fetchTencentBillingQuota({
|
|
116
|
-
source: providerId,
|
|
117
|
-
display,
|
|
118
|
-
url: `${billingBase}/v2/billing/meter/get-user-resource`,
|
|
119
|
-
headers: await billingHeaders(domain, clientVersion, enterpriseId),
|
|
120
|
-
credential,
|
|
121
|
-
fetcher,
|
|
122
|
-
defaultPlan: display,
|
|
123
|
-
uid: buddyAccountUid(credential),
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Real credit deductions for one WorkBuddy account.
|
|
129
|
-
*
|
|
130
|
-
* Mirrors {@link fetchWorkBuddyQuotaFor} in every respect but the endpoint —
|
|
131
|
-
* same billing host, same client-version identity headers, same account UID —
|
|
132
|
-
* because the usage-detail surface is the billing meter's other read.
|
|
133
|
-
*/
|
|
134
|
-
export async function fetchWorkBuddyRequestUsage(
|
|
135
|
-
credential: string,
|
|
136
|
-
fetcher: FetchLike,
|
|
137
|
-
args: {
|
|
138
|
-
readonly providerId?: "workbuddy" | "workbuddycn";
|
|
139
|
-
readonly days?: number;
|
|
140
|
-
readonly context?: QuotaCollectionContext;
|
|
141
|
-
} = {},
|
|
142
|
-
): Promise<BuddyUsageResult> {
|
|
143
|
-
const providerId = args.providerId ?? "workbuddy";
|
|
144
|
-
const domain = providerId === "workbuddycn" ? "www.workbuddy.cn" : WORKBUDDY_DOMAIN;
|
|
145
|
-
const authState = typeof args.context?.auth_state === "object" && args.context?.auth_state !== null
|
|
146
|
-
? (args.context.auth_state as Record<string, unknown>)
|
|
147
|
-
: undefined;
|
|
148
|
-
const enterpriseId = typeof authState?.enterpriseId === "string" ? authState.enterpriseId : undefined;
|
|
149
|
-
const clientVersion = providerId === "workbuddycn"
|
|
150
|
-
? getWorkBuddyCnClientVersion()
|
|
151
|
-
: getWorkBuddyClientVersion();
|
|
152
|
-
return fetchBuddyRequestUsage({
|
|
153
|
-
url: `${providerBaseUrl(providerId)}/billing/meter/get-user-request-usage`,
|
|
154
|
-
headers: await billingHeaders(domain, clientVersion, enterpriseId),
|
|
155
|
-
credential,
|
|
156
|
-
fetcher,
|
|
157
|
-
days: args.days ?? 30,
|
|
158
|
-
uid: buddyAccountUid(credential),
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
1
|
+
import type { FetchLike, ProviderQuotaResult } from "../../../quota/quota-contracts";
|
|
2
|
+
import type { QuotaCollectionContext } from "../../../quota/quota-support";
|
|
3
|
+
import { providerBaseUrl } from "../../../provider-metadata";
|
|
4
|
+
import {
|
|
5
|
+
buildWorkBuddyUserAgent,
|
|
6
|
+
getWorkBuddyClientVersion,
|
|
7
|
+
getWorkBuddyCnClientVersion,
|
|
8
|
+
getWorkBuddyCliVersion,
|
|
9
|
+
} from "../../../operations/client-versions";
|
|
10
|
+
import { WORKBUDDY_DOMAIN } from "./shared";
|
|
11
|
+
import { fetchTencentBillingQuota } from "../buddy-quota-shared";
|
|
12
|
+
import { fetchBuddyRequestUsage, type BuddyUsageResult } from "../buddy-usage-shared";
|
|
13
|
+
import { buddyAccountUid } from "../buddy-oauth-shared";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* WorkBuddy international billing quota.
|
|
17
|
+
*
|
|
18
|
+
* Endpoint: POST https://www.workbuddy.ai/v2/billing/meter/get-user-resource
|
|
19
|
+
* Request: Authorization: Bearer <accessToken||apiKey>, desktop-client headers,
|
|
20
|
+
* X-User-Id for the account UID, and the reference filter envelope
|
|
21
|
+
* (ProductCode p_tcaca, statuses [0, 3], 101-year package window).
|
|
22
|
+
* Response: { code: 0, data: { Response: { Data: { Accounts: [...] } } } }
|
|
23
|
+
*
|
|
24
|
+
* Same Tencent billing envelope as CodeBuddy CN, so the parsing is the shared
|
|
25
|
+
* one in `buddy-quota-shared.ts`; only the endpoint and identity headers are
|
|
26
|
+
* WorkBuddy-specific.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The CN billing realm's host.
|
|
31
|
+
*
|
|
32
|
+
* The reference bills the CN realm here rather than on the CN chat host
|
|
33
|
+
* (`www.workbuddy.cn`): billing is a separate service, and the chat host does
|
|
34
|
+
* not serve the meter path.
|
|
35
|
+
*/
|
|
36
|
+
const WORKBUDDY_CN_BILLING_BASE_URL = "https://www.codebuddy.cn";
|
|
37
|
+
|
|
38
|
+
export const WORKBUDDY_USAGE_URL =
|
|
39
|
+
`${providerBaseUrl("workbuddy")}/v2/billing/meter/get-user-resource`;
|
|
40
|
+
|
|
41
|
+
async function billingHeaders(
|
|
42
|
+
domain: string,
|
|
43
|
+
clientVersion: string,
|
|
44
|
+
enterpriseId?: string,
|
|
45
|
+
): Promise<Record<string, string>> {
|
|
46
|
+
return {
|
|
47
|
+
"User-Agent": buildWorkBuddyUserAgent(clientVersion, getWorkBuddyCliVersion()),
|
|
48
|
+
"X-Product": "SaaS",
|
|
49
|
+
"X-Domain": domain,
|
|
50
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
51
|
+
"X-CodeBuddy-Request": "1",
|
|
52
|
+
"Accept-Language": "en-US",
|
|
53
|
+
...(enterpriseId === undefined || enterpriseId.length === 0
|
|
54
|
+
? {}
|
|
55
|
+
: { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Fetches WorkBuddy quota via the Tencent billing endpoint.
|
|
61
|
+
*
|
|
62
|
+
* Auth: `Authorization: Bearer <credential>` (api_key and oauth both use
|
|
63
|
+
* Bearer; the caller passes the resolved secret).
|
|
64
|
+
*/
|
|
65
|
+
export async function fetchWorkBuddyQuota(
|
|
66
|
+
credential: string,
|
|
67
|
+
fetcher: FetchLike,
|
|
68
|
+
context?: QuotaCollectionContext,
|
|
69
|
+
): Promise<ProviderQuotaResult> {
|
|
70
|
+
return fetchWorkBuddyQuotaFor({
|
|
71
|
+
providerId: "workbuddy",
|
|
72
|
+
display: "WorkBuddy",
|
|
73
|
+
domain: WORKBUDDY_DOMAIN,
|
|
74
|
+
credential,
|
|
75
|
+
fetcher,
|
|
76
|
+
...(context === undefined ? {} : { context }),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function fetchWorkBuddyCnQuota(
|
|
81
|
+
credential: string,
|
|
82
|
+
fetcher: FetchLike,
|
|
83
|
+
context?: QuotaCollectionContext,
|
|
84
|
+
): Promise<ProviderQuotaResult> {
|
|
85
|
+
return fetchWorkBuddyQuotaFor({
|
|
86
|
+
providerId: "workbuddycn",
|
|
87
|
+
display: "WorkBuddy CN",
|
|
88
|
+
domain: "www.workbuddy.cn",
|
|
89
|
+
credential,
|
|
90
|
+
fetcher,
|
|
91
|
+
...(context === undefined ? {} : { context }),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function fetchWorkBuddyQuotaFor(args: {
|
|
96
|
+
readonly providerId: "workbuddy" | "workbuddycn";
|
|
97
|
+
readonly display: string;
|
|
98
|
+
readonly domain: string;
|
|
99
|
+
readonly credential: string;
|
|
100
|
+
readonly fetcher: FetchLike;
|
|
101
|
+
readonly context?: QuotaCollectionContext;
|
|
102
|
+
}): Promise<ProviderQuotaResult> {
|
|
103
|
+
const { providerId, display, domain, credential, fetcher, context } = args;
|
|
104
|
+
const authState = typeof context?.auth_state === "object" && context?.auth_state !== null
|
|
105
|
+
? (context.auth_state as Record<string, unknown>)
|
|
106
|
+
: undefined;
|
|
107
|
+
const enterpriseId = typeof authState?.enterpriseId === "string" ? authState.enterpriseId : undefined;
|
|
108
|
+
const clientVersion = providerId === "workbuddycn"
|
|
109
|
+
? getWorkBuddyCnClientVersion()
|
|
110
|
+
: getWorkBuddyClientVersion();
|
|
111
|
+
// The reference bills the CN realm on `www.codebuddy.cn`, not the chat host:
|
|
112
|
+
// the billing realm is a different service from the one that serves chat,
|
|
113
|
+
// and the CN chat host answers the meter path with an HTML error page.
|
|
114
|
+
const billingBase = providerId === "workbuddycn" ? WORKBUDDY_CN_BILLING_BASE_URL : providerBaseUrl(providerId);
|
|
115
|
+
return fetchTencentBillingQuota({
|
|
116
|
+
source: providerId,
|
|
117
|
+
display,
|
|
118
|
+
url: `${billingBase}/v2/billing/meter/get-user-resource`,
|
|
119
|
+
headers: await billingHeaders(domain, clientVersion, enterpriseId),
|
|
120
|
+
credential,
|
|
121
|
+
fetcher,
|
|
122
|
+
defaultPlan: display,
|
|
123
|
+
uid: buddyAccountUid(credential),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Real credit deductions for one WorkBuddy account.
|
|
129
|
+
*
|
|
130
|
+
* Mirrors {@link fetchWorkBuddyQuotaFor} in every respect but the endpoint —
|
|
131
|
+
* same billing host, same client-version identity headers, same account UID —
|
|
132
|
+
* because the usage-detail surface is the billing meter's other read.
|
|
133
|
+
*/
|
|
134
|
+
export async function fetchWorkBuddyRequestUsage(
|
|
135
|
+
credential: string,
|
|
136
|
+
fetcher: FetchLike,
|
|
137
|
+
args: {
|
|
138
|
+
readonly providerId?: "workbuddy" | "workbuddycn";
|
|
139
|
+
readonly days?: number;
|
|
140
|
+
readonly context?: QuotaCollectionContext;
|
|
141
|
+
} = {},
|
|
142
|
+
): Promise<BuddyUsageResult> {
|
|
143
|
+
const providerId = args.providerId ?? "workbuddy";
|
|
144
|
+
const domain = providerId === "workbuddycn" ? "www.workbuddy.cn" : WORKBUDDY_DOMAIN;
|
|
145
|
+
const authState = typeof args.context?.auth_state === "object" && args.context?.auth_state !== null
|
|
146
|
+
? (args.context.auth_state as Record<string, unknown>)
|
|
147
|
+
: undefined;
|
|
148
|
+
const enterpriseId = typeof authState?.enterpriseId === "string" ? authState.enterpriseId : undefined;
|
|
149
|
+
const clientVersion = providerId === "workbuddycn"
|
|
150
|
+
? getWorkBuddyCnClientVersion()
|
|
151
|
+
: getWorkBuddyClientVersion();
|
|
152
|
+
return fetchBuddyRequestUsage({
|
|
153
|
+
url: `${providerBaseUrl(providerId)}/billing/meter/get-user-request-usage`,
|
|
154
|
+
headers: await billingHeaders(domain, clientVersion, enterpriseId),
|
|
155
|
+
credential,
|
|
156
|
+
fetcher,
|
|
157
|
+
days: args.days ?? 30,
|
|
158
|
+
uid: buddyAccountUid(credential),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sha256Hex } from "../../../shared/hash";
|
|
2
2
|
import { TtlCache } from "../../../persistence/ttl-cache";
|
|
3
3
|
import type { FetchLike, ProviderQuotaResult, ProviderQuotaWindow } from "../../quota/quota-contracts";
|
|
4
4
|
import { authCredential, getJson, percentWindow, record, text, number } from "../../quota/quota-contracts";
|
|
@@ -102,7 +102,7 @@ export async function fetchClaudeQuota(
|
|
|
102
102
|
credential: string,
|
|
103
103
|
fetcher: FetchLike,
|
|
104
104
|
): Promise<ProviderQuotaResult> {
|
|
105
|
-
const key =
|
|
105
|
+
const key = sha256Hex(credential);
|
|
106
106
|
const cached = quotaCache.get(key);
|
|
107
107
|
if (cached !== undefined) return cached;
|
|
108
108
|
if (quotaCooldown.get(key) !== undefined) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { sha256Hex } from "../../../shared/hash";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Claude User Profiles REST client.
|
|
3
5
|
*
|
|
@@ -32,7 +34,6 @@
|
|
|
32
34
|
* (`claude-quota.ts:137-142`); **any future dispatch-time caller must catch and
|
|
33
35
|
* continue**, because a profile lookup is metadata, not routing.
|
|
34
36
|
*/
|
|
35
|
-
import { createHash } from "node:crypto";
|
|
36
37
|
import { TtlCache } from "../../../persistence/ttl-cache";
|
|
37
38
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
38
39
|
import type { FetchLike } from "../../quota/quota-contracts";
|
|
@@ -166,7 +167,7 @@ async function requestUserProfiles(
|
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
function credentialKey(credential: string): string {
|
|
169
|
-
return
|
|
170
|
+
return sha256Hex(credential);
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
/** Query string built exactly as the donor builds it (`:152-157`). */
|
|
@@ -484,14 +484,13 @@ export class ClaudeAdapter implements ProviderAdapter {
|
|
|
484
484
|
type: "text",
|
|
485
485
|
text: createClaudeBillingText(firstUserText(request), retryCliVersion),
|
|
486
486
|
};
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
? (parsedBody["system"] as unknown[])
|
|
487
|
+
const existingSystem = Array.isArray(payload["system"])
|
|
488
|
+
? (payload["system"] as unknown[])
|
|
490
489
|
: [];
|
|
491
490
|
const retryBody = isClaudeCodeOAuth
|
|
492
491
|
? patchClaudeCchBody(
|
|
493
492
|
JSON.stringify({
|
|
494
|
-
...
|
|
493
|
+
...payload,
|
|
495
494
|
system: [
|
|
496
495
|
retryBilling,
|
|
497
496
|
...existingSystem.filter(
|
|
@@ -8,7 +8,6 @@ import { completeRequiredSchema, isRecord } from "../../../protocol/codecs";
|
|
|
8
8
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
9
9
|
import { getCachedModelDiscovery } from "../../operations/model-discovery-cache";
|
|
10
10
|
import { defineModel } from "../../provider-model-definition";
|
|
11
|
-
import { openrouterFreeRoster } from "../../discovery/openrouter-free-roster";
|
|
12
11
|
import { clinePlatform, clinePlatformVersion } from "../../operations/cli-platform";
|
|
13
12
|
import {
|
|
14
13
|
getClineCliVersion,
|
|
@@ -502,25 +501,112 @@ export async function fetchClineFreeModelIds(
|
|
|
502
501
|
}
|
|
503
502
|
|
|
504
503
|
/**
|
|
505
|
-
* Static seed for Cline
|
|
504
|
+
* Static seed for Cline: the zero-cost tier and the Cline Pass roster.
|
|
506
505
|
*
|
|
507
506
|
* Every id here is materialized into the `models` table at boot with
|
|
508
507
|
* `source: "builtin"`, and `seedBundledModels` deletes any builtin row this
|
|
509
508
|
* list no longer declares. That makes the list the *owner* of these rows: an id
|
|
510
509
|
* Cline retires from its roster keeps its catalog card — and its route — until
|
|
511
510
|
* it is removed here, because nothing else prunes a builtin row. The seed is
|
|
512
|
-
* therefore kept to ids Cline currently serves
|
|
513
|
-
*
|
|
511
|
+
* therefore kept to ids Cline currently serves; a stale entry is a card that
|
|
512
|
+
* can only ever fail a probe.
|
|
514
513
|
*
|
|
515
514
|
* Cline's live roster (`/ai/cline/recommended-models`, read by
|
|
516
515
|
* `fetchClineRecommendedModels`) is the authority for what is routable right
|
|
517
516
|
* now, and "Fetch models" reconciles against it. This list is the offline seed
|
|
518
517
|
* that makes a fresh install usable before the first fetch.
|
|
518
|
+
*
|
|
519
|
+
* Both sections came from a live probe of that endpoint with a real key, not
|
|
520
|
+
* from the OpenRouter listing Cline is backed by — the two disagree, and the
|
|
521
|
+
* endpoint's own buckets are what the account can route. It is its own list
|
|
522
|
+
* rather than {@link openrouterFreeRoster}, which Kilo and OpenRouter still
|
|
523
|
+
* use: one list for three providers is right for a catalog fact and wrong for
|
|
524
|
+
* an account fact.
|
|
525
|
+
*
|
|
526
|
+
* This is a floor, and live discovery still finds every id the account can
|
|
527
|
+
* route — including any absent here. A manual fetch is unaffected by what this
|
|
528
|
+
* list declares.
|
|
529
|
+
*/
|
|
530
|
+
interface ClineSeedRow {
|
|
531
|
+
readonly id: string;
|
|
532
|
+
readonly ctx: number;
|
|
533
|
+
readonly out: number;
|
|
534
|
+
readonly vision?: boolean;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function clineRow(
|
|
538
|
+
rows: readonly ClineSeedRow[],
|
|
539
|
+
extra: { free?: boolean; proOnly?: boolean },
|
|
540
|
+
): readonly ModelDefinition[] {
|
|
541
|
+
return rows.map((row) =>
|
|
542
|
+
defineModel({
|
|
543
|
+
id: row.id,
|
|
544
|
+
providerId: CLINE_PROVIDER_ID,
|
|
545
|
+
wireFamily: "chat",
|
|
546
|
+
endpoint: CLINE_CHAT_PATH,
|
|
547
|
+
ctx: row.ctx,
|
|
548
|
+
out: row.out,
|
|
549
|
+
vision: row.vision ?? false,
|
|
550
|
+
reasoning: true,
|
|
551
|
+
toolCall: true,
|
|
552
|
+
...(extra.free === true ? { free: true, freeTier: true } : {}),
|
|
553
|
+
...(extra.proOnly === true ? { proOnly: true } : {}),
|
|
554
|
+
}),
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* The zero-cost tier, exactly as this account's `free` bucket publishes it.
|
|
560
|
+
*
|
|
561
|
+
* Probed against `/ai/cline/recommended-models` with a live key, not inferred
|
|
562
|
+
* from the OpenRouter listing. That matters because the two disagree: the
|
|
563
|
+
* `/models` listing names 17 `:free` ids, while the account's own `free` bucket
|
|
564
|
+
* names 5 and shares none of them. The listing is the upstream catalog; the
|
|
565
|
+
* bucket is what this account can actually route, and only the second is a
|
|
566
|
+
* fact worth seeding.
|
|
567
|
+
*
|
|
568
|
+
* Two ids carry the `cline-free/` prefix. That prefix is Cline's own namespace,
|
|
569
|
+
* not a tier marker — membership of the bucket is what makes a row free.
|
|
519
570
|
*/
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
571
|
+
const CLINE_FREE_ROWS: readonly ClineSeedRow[] = [
|
|
572
|
+
{ id: "reflection/beam-free", ctx: 128_000, out: 32_000 },
|
|
573
|
+
{ id: "cline-free/nemotron-3.5-super-vl", ctx: 1_000_000, out: 131_072, vision: true },
|
|
574
|
+
{ id: "nvidia/nemotron-3.5-lightning-free", ctx: 1_000_000, out: 65_536 },
|
|
575
|
+
{ id: "poolside/laguna-s-2.1-free", ctx: 262_144, out: 32_768 },
|
|
576
|
+
{ id: "cline-free/solar-mini4", ctx: 524_288, out: 131_072 },
|
|
577
|
+
];
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* The Cline Pass subscription roster, as the account's `clinePass` bucket
|
|
581
|
+
* publishes it.
|
|
582
|
+
*
|
|
583
|
+
* Seeded with `proOnly`, matching how the buddy roster marks a row a free plan
|
|
584
|
+
* is refused: dispatching one without a subscription 401s, so the card should
|
|
585
|
+
* say so rather than fail at request time. Discovery reads `clineAccountHasPass`
|
|
586
|
+
* first and only asks for these rows when the account has one.
|
|
587
|
+
*/
|
|
588
|
+
const CLINE_PASS_ROWS: readonly ClineSeedRow[] = [
|
|
589
|
+
{ id: "cline-pass/kimi-k3.1-pro", ctx: 1_000_000, out: 32_000 },
|
|
590
|
+
{ id: "cline-pass/minimax-m3.1-flash", ctx: 1_000_000, out: 128_000 },
|
|
591
|
+
{ id: "cline-pass/deepseek-v4.1-flash-1017", ctx: 1_000_000, out: 128_000 },
|
|
592
|
+
{ id: "cline-pass/deepseek-v4.1-flash", ctx: 1_000_000, out: 128_000 },
|
|
593
|
+
{ id: "cline-pass/mimo-v2.6-flash", ctx: 1_000_000, out: 128_000 },
|
|
594
|
+
{ id: "cline-pass/mimo-v2.6-pro", ctx: 1_000_000, out: 128_000 },
|
|
595
|
+
{ id: "cline-pass/glm-5.3", ctx: 1_000_000, out: 64_000 },
|
|
596
|
+
{ id: "cline-pass/deepseek-v4-pro", ctx: 1_000_000, out: 128_000 },
|
|
597
|
+
{ id: "cline-pass/qwen3.8-max", ctx: 1_000_000, out: 65_536 },
|
|
598
|
+
{ id: "cline-pass/muse-spark-1.3-contributor", ctx: 1_000_000, out: 65_536 },
|
|
599
|
+
{ id: "cline-pass/kimi-k3", ctx: 1_000_000, out: 32_000 },
|
|
600
|
+
{ id: "cline-pass/glm-5.3-flash", ctx: 1_000_000, out: 32_000 },
|
|
601
|
+
{ id: "cline-pass/qwen3.7-plus", ctx: 1_000_000, out: 65_536 },
|
|
602
|
+
{ id: "cline-pass/qwen3.7-max", ctx: 1_000_000, out: 65_536 },
|
|
603
|
+
{ id: "cline-pass/minimax-m3", ctx: 512_000, out: 64_000 },
|
|
604
|
+
];
|
|
605
|
+
|
|
606
|
+
export const CLINE_MODELS: readonly ModelDefinition[] = [
|
|
607
|
+
...clineRow(CLINE_FREE_ROWS, { free: true }),
|
|
608
|
+
...clineRow(CLINE_PASS_ROWS, { proOnly: true }),
|
|
609
|
+
];
|
|
524
610
|
|
|
525
611
|
|
|
526
612
|
export function createClineAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
|
|
@@ -369,16 +369,21 @@ function authHeadersForCodex(
|
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
/**
|
|
372
|
-
*
|
|
372
|
+
* Paths of the Codex model registry, in the order they are tried.
|
|
373
373
|
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
374
|
+
* The donor tries `/codex/models` first and `/models` second
|
|
375
|
+
* (`packages/catalog/src/discovery/codex.ts:9`), both relative to the
|
|
376
|
+
* `https://chatgpt.com/backend-api` root (`packages/catalog/src/wire/codex.ts:5`)
|
|
377
|
+
* — so the first candidate is the same URL this file always used.
|
|
378
|
+
*
|
|
379
|
+
* The fallback used to be omitted on the ground that it exists upstream only
|
|
380
|
+
* for relay base URLs this adapter does not support. It is restored because
|
|
381
|
+
* fetching models failed outright with no listing endpoint reported: a single
|
|
382
|
+
* candidate means one upstream shape change removes discovery entirely, while
|
|
383
|
+
* trying both costs one extra request only when the first misses.
|
|
380
384
|
*/
|
|
381
|
-
const
|
|
385
|
+
const CODEX_MODELS_PATHS = ["/backend-api/codex/models", "/backend-api/models"] as const;
|
|
386
|
+
const CODEX_MODELS_PATH = CODEX_MODELS_PATHS[0];
|
|
382
387
|
|
|
383
388
|
/**
|
|
384
389
|
* Shapes a client version may take for the `client_version` query parameter.
|
|
@@ -410,7 +415,7 @@ const CODEX_CLIENT_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
|
|
|
410
415
|
*/
|
|
411
416
|
export function buildCodexModelsUrl(
|
|
412
417
|
baseUrl: string,
|
|
413
|
-
path = CODEX_MODELS_PATH,
|
|
418
|
+
path: string = CODEX_MODELS_PATH,
|
|
414
419
|
clientVersion = getCodexVersion(),
|
|
415
420
|
): string {
|
|
416
421
|
const root = baseUrl.replace(/\/+$/, "");
|
|
@@ -471,39 +476,58 @@ export async function discoverCodexModels(input: {
|
|
|
471
476
|
? {}
|
|
472
477
|
: { "x-openai-internal-codex-residency": residency }),
|
|
473
478
|
};
|
|
479
|
+
const fetcher = input.fetcher ?? globalThis.fetch;
|
|
480
|
+
const root = input.baseUrl ?? DEFAULT_CHATGPT_BASE_URL;
|
|
481
|
+
let entries: readonly unknown[] | undefined;
|
|
474
482
|
try {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
);
|
|
483
|
+
// Each candidate is tried in order and the first usable roster wins. The
|
|
484
|
+
// loop is what the donor does (`packages/catalog/src/discovery/codex.ts:138`);
|
|
485
|
+
// a non-200 or an unparseable body just advances to the next path, and
|
|
486
|
+
// exhausting them is the same "no roster" outcome as before.
|
|
487
|
+
for (const path of CODEX_MODELS_PATHS) {
|
|
488
|
+
let response: Response;
|
|
489
|
+
try {
|
|
490
|
+
response = await fetcher(buildCodexModelsUrl(root, path, version), {
|
|
491
|
+
method: "GET",
|
|
492
|
+
headers,
|
|
493
|
+
...(input.signal === undefined ? {} : { signal: input.signal }),
|
|
494
|
+
});
|
|
495
|
+
} catch {
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
if (!response.ok) continue;
|
|
499
|
+
let payload: unknown;
|
|
500
|
+
try {
|
|
501
|
+
payload = (await response.json()) as unknown;
|
|
502
|
+
} catch {
|
|
503
|
+
continue;
|
|
504
|
+
}
|
|
505
|
+
const found = boundedUpstreamArray(isRecord(payload) ? payload["models"] : undefined);
|
|
506
|
+
if (found === undefined) continue;
|
|
507
|
+
entries = found;
|
|
508
|
+
break;
|
|
502
509
|
}
|
|
503
|
-
return [...byId.values()].sort((a, b) => a.modelId.localeCompare(b.modelId));
|
|
504
510
|
} catch {
|
|
505
511
|
return null;
|
|
506
512
|
}
|
|
513
|
+
if (entries === undefined) return null;
|
|
514
|
+
const byId = new Map<string, ModelDefinition>();
|
|
515
|
+
for (const entry of entries) {
|
|
516
|
+
if (!isRecord(entry)) continue;
|
|
517
|
+
const id = sanitizeUpstreamLabel(entry["slug"] ?? entry["id"]);
|
|
518
|
+
if (id === undefined) continue;
|
|
519
|
+
const contextLimit = boundedUpstreamNumber(entry["context_window"], { min: 1, max: 1_000_000_000 });
|
|
520
|
+
const outputLimit = boundedUpstreamNumber(entry["max_output_tokens"], { min: 1, max: 1_000_000_000 });
|
|
521
|
+
byId.set(
|
|
522
|
+
id,
|
|
523
|
+
codexResponsesModel(
|
|
524
|
+
id,
|
|
525
|
+
contextLimit ?? DEFAULT_CODEX_DISCOVERY_CONTEXT_LIMIT,
|
|
526
|
+
outputLimit ?? DEFAULT_CODEX_DISCOVERY_OUTPUT_LIMIT,
|
|
527
|
+
),
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
return [...byId.values()].sort((a, b) => a.modelId.localeCompare(b.modelId));
|
|
507
531
|
}
|
|
508
532
|
|
|
509
533
|
/** Reads just enough of an untyped body to tell SSE from JSON, then replays it. */
|