cartethyia 2.7.4 → 2.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/README.md +17 -5
- package/dist/dashboard/assets/{BannedPage-ChG5svFb.js → BannedPage-Cj15GsMp.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-BIcWQun7.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Bf2VelDe.js → CliToolsPage-BIccZmeL.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-ggeMSjte.js → CustomizationPage-BKj_r0rp.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-U6AKaJcF.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-DnQPSIA8.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-5SnUSy3j.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-f0DE1h0-.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-BfAb5-o_.js} +3 -3
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0K-c4eo.js +1 -0
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DympBNq4.js → banner-BllT4LcF.js} +1 -1
- package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CtkX66Wd.js} +1 -1
- package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js +1 -0
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-8fiE6tec.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-BrTEZ8zu.js} +1 -1
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/{entry-BSAsYsmV.js → entry-EBHJ3DrE.js} +1 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-CPK47xQx.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-DBNPOfhV.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/layout-CajrYUnD.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Bx2I7XUe.js} +1 -1
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js +1 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BLULNqTp.js} +1 -1
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-CkfdYWel.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-SYm237HG.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-m8WGNPrz.js} +1 -1
- package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +56 -55
- package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
- package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
- package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
- package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
- package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
- package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
- package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
- package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
- package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
- package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
- package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
- package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
- package/package.json +4 -6
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +58 -2
- package/src/boot/dependencies.ts +786 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +1 -1
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +13 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +26 -6
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +71 -62
- package/src/console/api-keys/routes.ts +48 -12
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +1 -1
- package/src/console/auth/audit-recorder.ts +1 -1
- package/src/console/auth/lockout.ts +7 -3
- package/src/console/auth/row-coercion.ts +57 -12
- package/src/console/auth/session-resolver.ts +1 -1
- package/src/console/auth/session-service.ts +8 -2
- package/src/console/auth/session.ts +37 -31
- package/src/console/auth/setup-service.ts +4 -3
- package/src/console/auth/user-store.ts +1 -1
- package/src/console/backup/9router-map.ts +0 -3
- package/src/console/backup/contracts.ts +9 -9
- package/src/console/backup/export-endpoint.ts +5 -6
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +29 -33
- package/src/console/backup/service.ts +468 -468
- package/src/console/backup/store.ts +47 -29
- package/src/console/backup/validate.ts +11 -1
- package/src/console/cli-tools/contracts.ts +7 -7
- package/src/console/cli-tools/injectors/cline.ts +110 -110
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/copilot.ts +108 -108
- package/src/console/cli-tools/injectors/driver.ts +247 -247
- package/src/console/cli-tools/injectors/jcode.ts +115 -115
- package/src/console/cli-tools/injectors/openclaw.ts +161 -161
- package/src/console/cli-tools/injectors/opencode.ts +153 -153
- package/src/console/cli-tools/routes.ts +1 -1
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router.ts +32 -0
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/domain-registration.ts +16 -2
- package/src/console/inferhub/client.ts +0 -7
- package/src/console/inferhub/key-store.ts +1 -1
- package/src/console/inferhub/normalize.ts +2 -2
- package/src/console/inferhub/routes.ts +1 -1
- package/src/console/inferhub/types.ts +1 -1
- package/src/console/observability/contracts.ts +1 -1
- package/src/console/observability/live.ts +31 -18
- package/src/console/observability/logs.ts +1 -1
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +20 -4
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +39 -0
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +95 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +27 -3
- package/src/console/providers/catalog/store.ts +147 -8
- package/src/console/providers/detail/routes.ts +1 -1
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +92 -13
- package/src/console/quota/account-quota-global.ts +41 -3
- package/src/console/quota/account-quota-shared.ts +10 -3
- package/src/console/quota/account-quota-tenant.ts +259 -66
- package/src/console/quota/daily-growth-job.ts +308 -0
- package/src/console/quota/native-identity.ts +2 -2
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/routes.ts +1 -1
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/contracts.ts +1 -1
- package/src/console/routing/pools/contracts.ts +2 -2
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/relay-deploy.ts +3 -3
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +100 -32
- package/src/console/share/share-stats.ts +4 -4
- package/src/console/share/share-usage.ts +1 -1
- package/src/console/shared/errors.ts +2 -2
- package/src/console/shared/object.ts +18 -0
- package/src/console/shared/read-through-cache.ts +4 -4
- package/src/console/shared/transaction.ts +14 -0
- package/src/console/system-prompt/contracts.ts +89 -12
- package/src/console/system-prompt/routes.ts +98 -45
- package/src/console/updates/apply-update.ts +244 -0
- package/src/console/updates/routes.ts +252 -97
- package/src/main.ts +11 -5
- package/src/network/http2-bidi.ts +1 -1
- package/src/network/ip-utils.ts +298 -0
- package/src/network/outbound-fetch.ts +1 -1
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +16 -12
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-health-machine.ts +1 -1
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +20 -71
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +59 -291
- package/src/observability/log-sanitize.ts +1 -1
- package/src/observability/metrics.ts +4 -4
- package/src/observability/payload-capture.ts +6 -5
- package/src/observability/payload-store.ts +1 -1
- package/src/observability/runtime-metrics.ts +1 -1
- package/src/observability/telemetry-buffer.ts +12 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/token-speed.ts +1 -1
- package/src/persistence/connection-url.ts +1 -1
- package/src/persistence/db-handle.ts +1 -1
- package/src/persistence/db-pg.ts +2 -2
- package/src/persistence/db-sqlite.ts +3 -3
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +1 -1
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +113 -40
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +10 -1
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/system-prompt-store.ts +63 -18
- package/src/persistence/tenant-preferences.ts +1 -1
- package/src/persistence/ttl-cache.ts +3 -3
- package/src/persistence/usage-flush.ts +7 -2
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/codecs.ts +6 -10
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/reasoning-text.ts +1 -1
- package/src/protocol/reasoning.ts +7 -52
- package/src/protocol/registry.ts +50 -15
- package/src/protocol/request/chat.ts +46 -19
- package/src/protocol/request/codex.ts +1 -1
- package/src/protocol/request/messages.ts +46 -14
- package/src/protocol/request/responses.ts +19 -10
- package/src/protocol/response/chat.ts +25 -10
- package/src/protocol/response/codex.ts +1 -1
- package/src/protocol/response/messages.ts +1 -1
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +1 -1
- package/src/protocol/sse-decoder.ts +50 -1
- package/src/protocol/stop-reason.ts +2 -2
- package/src/protocol/think-split.ts +347 -0
- package/src/protocol/translation/attachment-integrity.ts +3 -3
- package/src/protocol/translation/cache-controls.ts +8 -20
- package/src/protocol/translation/capabilities.ts +6 -6
- package/src/protocol/translation/dialect/deepseek.ts +10 -0
- package/src/protocol/translation/dialect/inband.ts +39 -0
- package/src/protocol/translation/dialect/model-thinking.ts +89 -0
- package/src/protocol/translation/dialect/qwen.ts +114 -0
- package/src/protocol/translation/dialect/resolver.ts +83 -0
- package/src/protocol/translation/dialect/rules.ts +93 -0
- package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
- package/src/protocol/translation/dialect/types.ts +58 -0
- package/src/protocol/translation/quirks.ts +18 -4
- package/src/protocol/translation/thinking.ts +12 -252
- package/src/protocol/translation/tool-id.ts +3 -3
- package/src/protocol/translation/tool-repair.ts +1 -1
- package/src/protocol/upstream/post-json.ts +6 -1
- package/src/providers/adapters/compatible-adapter.ts +42 -3
- package/src/providers/authentication/jwt-validator.ts +0 -5
- package/src/providers/authentication/oauth-client.ts +254 -253
- package/src/providers/authentication/oauth-flow-store.ts +42 -7
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/default-registry.ts +23 -35
- package/src/providers/discovery/catalog/catalog-format.ts +13 -2
- package/src/providers/discovery/discovery-types.ts +0 -1
- package/src/providers/discovery/openai-model-discovery.ts +2 -2
- package/src/providers/discovery/probe-phases.ts +48 -13
- package/src/providers/discovery/probing-service.ts +6 -8
- package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
- package/src/providers/integrations/antigravity/antigravity.ts +2 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
- package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
- package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +1 -1
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/commandcode/commandcode.ts +75 -115
- package/src/providers/integrations/commandcode/quota.ts +131 -51
- package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
- package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
- package/src/providers/integrations/cursor/cursor-request.ts +0 -87
- package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
- package/src/providers/integrations/cursor/cursor.ts +38 -5
- package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
- package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
- package/src/providers/integrations/factory/factory.ts +9 -9
- package/src/providers/integrations/github/github-discovery.ts +55 -10
- package/src/providers/integrations/github/github-oauth.ts +6 -5
- package/src/providers/integrations/github/github.ts +41 -14
- package/src/providers/integrations/grok/grok-oauth.ts +261 -261
- package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
- package/src/providers/integrations/grok/grok-quota.ts +16 -7
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
- package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
- package/src/providers/integrations/grok/grok.ts +86 -36
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
- package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
- package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
- package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
- package/src/providers/integrations/kiro/kiro-request.ts +8 -11
- package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
- package/src/providers/integrations/kiro/kiro.ts +81 -68
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/qoder/qoder-catalog.ts +85 -8
- package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
- package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
- package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
- package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
- package/src/providers/integrations/qoder/qoder.ts +354 -62
- package/src/providers/integrations/shared/connect.ts +0 -54
- package/src/providers/integrations/shared/hash.ts +15 -0
- package/src/providers/integrations/shared/session-cache.ts +136 -0
- package/src/providers/integrations/trae/trae-cache.ts +7 -87
- package/src/providers/integrations/trae/trae-catalog.ts +1 -6
- package/src/providers/integrations/trae/trae-protocol.ts +17 -8
- package/src/providers/integrations/trae/trae-realm.ts +0 -7
- package/src/providers/integrations/trae/trae.ts +53 -10
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
- package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
- package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
- package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
- package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
- package/src/providers/operations/account-error-classification.ts +131 -116
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/cli-platform.ts +31 -5
- package/src/providers/operations/client-version-resolver.ts +4 -6
- package/src/providers/operations/client-versions.ts +10 -7
- package/src/providers/operations/provider-catalog-seeder.ts +2 -0
- package/src/providers/operations/provider-catalog-service.ts +18 -2
- package/src/providers/operations/provider-credential-service.ts +19 -2
- package/src/providers/provider-contracts.ts +18 -7
- package/src/providers/provider-metadata.ts +17 -2
- package/src/providers/provider-model-definition.ts +22 -1
- package/src/providers/provider-probe.ts +4 -2
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +4 -0
- package/src/providers/quota/refresh.ts +27 -4
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +1 -3
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +4 -4
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +16 -4
- package/src/security/client-router-fingerprint.ts +4 -4
- package/src/security/credential-codec.ts +3 -3
- package/src/security/csrf.ts +2 -2
- package/src/security/ip-boundary.ts +16 -189
- package/src/security/model-access-rule.ts +1 -1
- package/src/security/outbound-headers.ts +18 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +1 -1
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +23 -20
- package/src/transport/dispatch/generation.ts +25 -45
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +3 -1
- package/src/transport/dispatch/responses-compact.ts +25 -46
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +2 -2
- package/src/transport/dispatch/streaming/stream.ts +7 -3
- package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
- package/src/transport/dispatch/systemone.ts +20 -48
- package/src/transport/dispatch/token-count.ts +41 -38
- package/src/transport/dispatch/websearch.ts +19 -45
- package/src/transport/drain-endpoint.ts +1 -1
- package/src/transport/failure-policy.ts +6 -0
- package/src/transport/guards/auth-guard.ts +0 -6
- package/src/transport/guards/body-policy.ts +3 -3
- package/src/transport/guards/headroom-guard.ts +1 -1
- package/src/transport/guards/pipeline.ts +1 -1
- package/src/transport/guards/request-context.ts +12 -17
- package/src/transport/request/preparer.ts +286 -7
- package/src/transport/request/rtk/compress-request.ts +3 -3
- package/src/transport/request/rtk/rtk-constants.ts +2 -2
- package/src/transport/request/rtk/rtk-filters.ts +8 -8
- package/src/transport/request/state.ts +1 -13
- package/src/transport/request/system-prompt-injection.ts +74 -11
- package/src/transport/request/tenant-preferences.ts +22 -0
- package/src/transport/routing/candidate-index.ts +2 -2
- package/src/transport/routing/round-robin.ts +1 -1
- package/src/transport/routing/route-catalog.ts +17 -18
- package/src/transport/routing/route-model.ts +126 -33
- package/src/transport/routing/router.ts +152 -37
- package/src/transport/shutdown-notice.ts +2 -2
- package/src/transport/surface/adapters.ts +3 -3
- package/src/transport/surface/chat/encode.ts +7 -7
- package/src/transport/surface/chat/parse.ts +7 -7
- package/src/transport/surface/completion.ts +2 -2
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/parse.ts +3 -3
- package/src/transport/surface/responses/adapter.ts +1 -1
- package/src/transport/surface/responses/errors.ts +0 -9
- package/src/transport/vision-handoff-cache.ts +58 -0
- package/src/transport/vision-handoff.ts +376 -0
- package/src/workers/account-identity-sweep.ts +2 -2
- package/src/workers/buddy-growth-tasks.ts +392 -346
- package/src/workers/daily-checkin.ts +102 -49
- package/src/workers/maintenance-lease.ts +2 -35
- package/src/workers/oauth-refresh-sweep.ts +8 -1
- package/src/workers/quota-refresh-sweep.ts +120 -82
- package/src/workers/scheduler.ts +67 -4
- package/src/workers/sweep-runner.ts +24 -5
- package/src/workers/zcode-gift-claim.ts +108 -0
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
- package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
- package/dist/dashboard/assets/app-a159k0ub.css +0 -2
- package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
- package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
- package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
- package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
- package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
- package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
- package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
- package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
- package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
- package/src/network/response-headers.ts +0 -39
- package/src/protocol/response/dsml.ts +0 -38
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
- /package/dist/dashboard/assets/{app-BayTTy01.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-BayTTy01.js.gz → app-Bgd3zANQ.js.gz} +0 -0
- /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
|
@@ -6,20 +6,22 @@ import { canContainToolResult, joinTextParts, toolCallParts, toolResultParts } f
|
|
|
6
6
|
import {
|
|
7
7
|
classifyUpstreamError,
|
|
8
8
|
extractUpstreamMessage,
|
|
9
|
+
mapUpstreamHttpError,
|
|
9
10
|
upstreamErrorIdentifier,
|
|
10
11
|
} from "../../../transport/failure-policy";
|
|
11
|
-
import {
|
|
12
|
-
import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason, ContentPart } from "../../../protocol/canonical-model";
|
|
12
|
+
import { postUpstreamJson } from "../../../protocol/upstream/post-json";
|
|
13
|
+
import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason, ContentPart, UsageRecord } from "../../../protocol/canonical-model";
|
|
13
14
|
import { isRecord, readNumber, readString, resolveImageSource, splitDataUrl } from "../../../protocol/codecs";
|
|
14
15
|
import { usageFromProvider } from "../../provider-usage";
|
|
15
16
|
import { readCredentialSecret, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext } from "../../provider-contracts";
|
|
17
|
+
import { abortGatewayError } from "../../operations/upstream-deadline";
|
|
16
18
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
17
19
|
import { defineModel } from "../../provider-model-definition";
|
|
18
20
|
import type { ModelDefinition } from "../../provider-model-definition";
|
|
19
21
|
import {
|
|
20
22
|
getCommandCodeVersion,
|
|
21
23
|
} from "../../operations/client-versions";
|
|
22
|
-
import {
|
|
24
|
+
import { ThinkSplitter } from "../../../protocol/think-split";
|
|
23
25
|
export const COMMANDCODE_PROVIDER_ID = "commandcode" as const;
|
|
24
26
|
export const COMMANDCODE_BASE_URL = providerBaseUrl("commandcode");
|
|
25
27
|
/**
|
|
@@ -37,10 +39,6 @@ export const COMMANDCODE_HOST = "https://api.commandcode.ai" as const;
|
|
|
37
39
|
* generate.
|
|
38
40
|
*/
|
|
39
41
|
export const COMMANDCODE_GENERATE_PATH = "/alpha/generate" as const;
|
|
40
|
-
/** The three routes the Provider API serves, one per wire family. */
|
|
41
|
-
export const COMMANDCODE_CHAT_PATH = "/chat/completions" as const;
|
|
42
|
-
export const COMMANDCODE_RESPONSES_PATH = "/responses" as const;
|
|
43
|
-
export const COMMANDCODE_MESSAGES_PATH = "/messages" as const;
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
44
|
* Command Code's roster, as the Provider API publishes it.
|
|
@@ -426,7 +424,7 @@ export async function headers(sessionId: string, token: string): Promise<Record<
|
|
|
426
424
|
}
|
|
427
425
|
|
|
428
426
|
|
|
429
|
-
type StreamState = { toolIndexById: Map<string, number>; nextToolIndex: number; finishReason: string | undefined; usage: Record<string, unknown> | undefined; think:
|
|
427
|
+
type StreamState = { toolIndexById: Map<string, number>; nextToolIndex: number; finishReason: string | undefined; usage: Record<string, unknown> | undefined; think: ThinkSplitter };
|
|
430
428
|
|
|
431
429
|
export function ccMapFinishReason(reason: string): CanonicalStopReason {
|
|
432
430
|
return reason === "length" ? "length" : reason === "tool_calls" ? "tool_use" : reason === "content_filter" ? "content_filter" : "stop";
|
|
@@ -450,7 +448,7 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
450
448
|
if (!text) return [];
|
|
451
449
|
const split = state.think.push(text);
|
|
452
450
|
const events: CanonicalEvent[] = [];
|
|
453
|
-
if (split.reasoning) events.push({ type: "content_delta", sequence_number: seqBase
|
|
451
|
+
if (split.reasoning) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "reasoning", payload: null, summary: split.reasoning } } as CanonicalEvent);
|
|
454
452
|
if (split.text) events.push({ type: "content_delta", sequence_number: seqBase, content: { kind: "text", text: split.text } } as CanonicalEvent);
|
|
455
453
|
return events;
|
|
456
454
|
}
|
|
@@ -485,9 +483,11 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
485
483
|
if (type === "finish") {
|
|
486
484
|
const reason = state.finishReason ?? readString(event, "finishReason") ?? "stop";
|
|
487
485
|
const canonicalReason = ccMapFinishReason(reason);
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
486
|
+
const rest = state.think.flush();
|
|
487
|
+
const events: CanonicalEvent[] = [];
|
|
488
|
+
if (rest.reasoning) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } });
|
|
489
|
+
if (rest.text) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "text", text: rest.text } });
|
|
490
|
+
let usage: UsageRecord | undefined;
|
|
491
491
|
if (state.usage) {
|
|
492
492
|
const prompt = readNumber(state.usage, "promptTokens") ?? readNumber(state.usage, "inputTokens") ?? 0;
|
|
493
493
|
const completion = readNumber(state.usage, "completionTokens") ?? readNumber(state.usage, "outputTokens") ?? 0;
|
|
@@ -500,9 +500,9 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
500
500
|
cached_tokens: cached,
|
|
501
501
|
cache_creation_input_tokens: readNumber(state.usage, "cacheWriteTokens") ?? undefined,
|
|
502
502
|
} as unknown as Record<string, unknown>);
|
|
503
|
-
|
|
504
|
-
(events[0] as unknown as Record<string, unknown>)["usage"] = usageRecord;
|
|
503
|
+
usage = usageRecord;
|
|
505
504
|
}
|
|
505
|
+
events.push({ type: "terminal", sequence_number: seqBase, state: "complete", stop_reason: canonicalReason, provider_stop_reason: reason, ...(usage === undefined ? {} : { usage }) });
|
|
506
506
|
return events;
|
|
507
507
|
}
|
|
508
508
|
if (type === "error") {
|
|
@@ -546,30 +546,29 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
|
|
|
546
546
|
return [];
|
|
547
547
|
}
|
|
548
548
|
|
|
549
|
-
/** NDJSON
|
|
550
|
-
export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal: AbortSignal): AsyncIterable<CanonicalEvent> {
|
|
549
|
+
/** NDJSON decoding uses the request signal after the opening deadline is released. */
|
|
550
|
+
export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal: AbortSignal, model: string): AsyncIterable<CanonicalEvent> {
|
|
551
551
|
const reader = body.getReader();
|
|
552
552
|
const decoder = new TextDecoder();
|
|
553
|
-
const state: StreamState = { toolIndexById: new Map(), nextToolIndex: 0, finishReason: undefined, usage: undefined, think: new
|
|
553
|
+
const state: StreamState = { toolIndexById: new Map(), nextToolIndex: 0, finishReason: undefined, usage: undefined, think: new ThinkSplitter() };
|
|
554
554
|
let buffer = "";
|
|
555
|
-
let hasTerminal = false;
|
|
556
555
|
let seq = 1;
|
|
557
|
-
// initial response_start
|
|
558
|
-
yield { type: "response_start", sequence_number: seq++, model: "commandcode" } as CanonicalEvent;
|
|
559
556
|
|
|
560
|
-
const readWithAbort = (): Promise<{ done: boolean; value?: Uint8Array }> => {
|
|
561
|
-
if (signal.aborted) throw
|
|
562
|
-
const { promise, resolve, reject } = Promise.withResolvers<{ done: boolean; value?: Uint8Array
|
|
563
|
-
const onAbort = (): void =>
|
|
564
|
-
if (signal.aborted) reject(new GatewayError("transport_closed", 499, "Command Code stream aborted (request {requestId}). Send it again whenever ready 🙃"));
|
|
565
|
-
else reject(new GatewayError("platform_unavailable", 502, "Command Code stream error (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream"));
|
|
566
|
-
};
|
|
557
|
+
const readWithAbort = async (): Promise<{ readonly done: boolean; readonly value?: Uint8Array | undefined }> => {
|
|
558
|
+
if (signal.aborted) throw signal.reason;
|
|
559
|
+
const { promise, resolve, reject } = Promise.withResolvers<{ readonly done: boolean; readonly value?: Uint8Array | undefined }>();
|
|
560
|
+
const onAbort = (): void => reject(signal.reason);
|
|
567
561
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
568
|
-
void reader.read().then(resolve, reject)
|
|
569
|
-
|
|
562
|
+
void reader.read().then(resolve, reject);
|
|
563
|
+
try {
|
|
564
|
+
return await promise;
|
|
565
|
+
} finally {
|
|
566
|
+
signal.removeEventListener("abort", onAbort);
|
|
567
|
+
}
|
|
570
568
|
};
|
|
571
569
|
|
|
572
570
|
try {
|
|
571
|
+
yield { type: "response_start", sequence_number: seq++, model };
|
|
573
572
|
while (true) {
|
|
574
573
|
const { done, value } = await readWithAbort();
|
|
575
574
|
if (done) break;
|
|
@@ -579,20 +578,11 @@ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal:
|
|
|
579
578
|
const line = buffer.slice(0, nl).trim();
|
|
580
579
|
buffer = buffer.slice(nl + 1);
|
|
581
580
|
if (line) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
for (const ev of evs) {
|
|
589
|
-
// Strictly increasing per line, in emission order: the Responses
|
|
590
|
-
// surface throws on any non-monotonic sequence mid-stream, after
|
|
591
|
-
// partial bytes are already flushed. No special-casing for
|
|
592
|
-
// dual-event lines — order is order.
|
|
593
|
-
(ev as unknown as Record<string, unknown>)["sequence_number"] = seq++;
|
|
594
|
-
if (ev.type === "terminal") hasTerminal = true;
|
|
595
|
-
yield ev;
|
|
581
|
+
const events = transformLine(line, state, seq);
|
|
582
|
+
seq += events.length;
|
|
583
|
+
for (const event of events) {
|
|
584
|
+
yield event;
|
|
585
|
+
if (event.type === "terminal") return;
|
|
596
586
|
}
|
|
597
587
|
}
|
|
598
588
|
nl = buffer.indexOf("\n");
|
|
@@ -601,101 +591,71 @@ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal:
|
|
|
601
591
|
buffer += decoder.decode();
|
|
602
592
|
const tail = buffer.trim();
|
|
603
593
|
if (tail) {
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
yield
|
|
594
|
+
const events = transformLine(tail, state, seq);
|
|
595
|
+
seq += events.length;
|
|
596
|
+
for (const event of events) {
|
|
597
|
+
yield event;
|
|
598
|
+
if (event.type === "terminal") return;
|
|
608
599
|
}
|
|
609
600
|
}
|
|
610
601
|
const rest = state.think.flush();
|
|
611
|
-
if (rest.reasoning) yield { type: "content_delta", sequence_number: seq++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } }
|
|
612
|
-
if (rest.text) yield { type: "content_delta", sequence_number: seq++, content: { kind: "text", text: rest.text } }
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
yield { type: "terminal", sequence_number: seq++, state: "failed", stop_reason: ccMapFinishReason(state.finishReason ?? "stop"), provider_stop_reason: state.finishReason ?? "stop" } as CanonicalEvent;
|
|
616
|
-
}
|
|
602
|
+
if (rest.reasoning) yield { type: "content_delta", sequence_number: seq++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } };
|
|
603
|
+
if (rest.text) yield { type: "content_delta", sequence_number: seq++, content: { kind: "text", text: rest.text } };
|
|
604
|
+
// NDJSON ended with no terminal envelope: truncated, never complete.
|
|
605
|
+
yield { type: "terminal", sequence_number: seq++, state: "failed", stop_reason: ccMapFinishReason(state.finishReason ?? "stop"), provider_stop_reason: state.finishReason ?? "stop" };
|
|
617
606
|
} finally {
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
} catch {
|
|
621
|
-
// Best-effort reader unlock during stream cleanup.
|
|
622
|
-
}
|
|
623
|
-
void reader.cancel().catch(() => {});
|
|
607
|
+
void reader.cancel(signal.reason).catch(() => {});
|
|
608
|
+
reader.releaseLock();
|
|
624
609
|
}
|
|
625
610
|
}
|
|
626
611
|
|
|
627
|
-
//
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
// ProviderAdapter — the Provider API serves three wires, so dispatch is the
|
|
632
|
-
// shared OpenAI-compatible adapter rather than one bespoke NDJSON reader.
|
|
633
|
-
//
|
|
634
|
-
// Generation goes to `/alpha/generate` for every model: that is the CLI's own
|
|
635
|
-
// surface and the one the reference client calls, and it does not vary the path
|
|
636
|
-
// by the wire a model row declares. `/provider/v1` is the catalog surface — it
|
|
637
|
-
// answers `GET /models`, which discovery still uses — so a completion posted to
|
|
638
|
-
// `/provider/v1/<wire>` was reaching a surface the CLI never calls to
|
|
639
|
-
// generate. The wire family still decides how the body is shaped; only the
|
|
640
|
-
// endpoint is shared.
|
|
612
|
+
// The CLI generation surface takes a proprietary envelope and returns NDJSON
|
|
613
|
+
// regardless of the catalog row's wire family.
|
|
641
614
|
|
|
642
615
|
interface CommandCodeAdapterOptions {
|
|
643
616
|
readonly fetch?: typeof fetch;
|
|
644
617
|
}
|
|
645
618
|
|
|
646
|
-
function commandCodeIdentityHeaders(_token: string): Record<string, string> {
|
|
647
|
-
return {
|
|
648
|
-
"x-command-code-version": getCommandCodeVersion(),
|
|
649
|
-
"x-cli-environment": "production",
|
|
650
|
-
"x-taste-learning": "true",
|
|
651
|
-
"x-project-slug": "cartethyia",
|
|
652
|
-
"user-agent": "cli",
|
|
653
|
-
// Per-request, as the CLI client sends it. The upstream expects a session
|
|
654
|
-
// id on every generate call and the reference client mints a fresh UUID
|
|
655
|
-
// for each one; sending a constant correlated requests that had nothing
|
|
656
|
-
// to do with each other.
|
|
657
|
-
"x-session-id": randomUUID(),
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
function providerApiAdapter(options: CommandCodeAdapterOptions): ProviderAdapter {
|
|
662
|
-
return createApiKeyAdapter(
|
|
663
|
-
{
|
|
664
|
-
provider_id: COMMANDCODE_PROVIDER_ID,
|
|
665
|
-
// The host, not the `/provider/v1` base: generation is a sibling
|
|
666
|
-
// surface, so every wire resolves under the host and the path below
|
|
667
|
-
// supplies the CLI endpoint. Nesting it under `/provider/v1` produced a
|
|
668
|
-
// URL that is neither surface.
|
|
669
|
-
base_url: COMMANDCODE_HOST,
|
|
670
|
-
endpoint_paths_by_wire_family: {
|
|
671
|
-
// Every wire, not one per family: the reference client sends all
|
|
672
|
-
// generation to `/alpha/generate` regardless of the row's declared
|
|
673
|
-
// wire, so dispatch must not fan out across three paths.
|
|
674
|
-
chat: COMMANDCODE_GENERATE_PATH,
|
|
675
|
-
responses: COMMANDCODE_GENERATE_PATH,
|
|
676
|
-
messages: COMMANDCODE_GENERATE_PATH,
|
|
677
|
-
},
|
|
678
|
-
buildExtraHeaders: async (context: ProviderDispatchContext) =>
|
|
679
|
-
commandCodeIdentityHeaders(await readCredentialSecret(context.credential, "Command Code bearer token is required")),
|
|
680
|
-
},
|
|
681
|
-
options.fetch,
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
619
|
|
|
685
620
|
class CommandCodeAdapter implements ProviderAdapter {
|
|
686
621
|
readonly provider_id = COMMANDCODE_PROVIDER_ID;
|
|
687
|
-
private readonly
|
|
622
|
+
private readonly fetchFn: typeof fetch;
|
|
688
623
|
|
|
689
624
|
constructor(options: CommandCodeAdapterOptions = {}) {
|
|
690
|
-
this.
|
|
625
|
+
this.fetchFn = options.fetch ?? globalThis.fetch;
|
|
691
626
|
}
|
|
692
627
|
|
|
693
|
-
dispatch(
|
|
628
|
+
async *dispatch(
|
|
694
629
|
request: CanonicalRequest,
|
|
695
630
|
candidate: ProviderDispatchTarget,
|
|
696
631
|
context: ProviderDispatchContext,
|
|
697
632
|
): AsyncIterable<CanonicalEvent> {
|
|
698
|
-
|
|
633
|
+
const token = readCredentialSecret(context.credential, "Command Code bearer token is required");
|
|
634
|
+
const sessionId = randomUUID();
|
|
635
|
+
const payload = buildRequest(candidate.model_id, {
|
|
636
|
+
messages: request.messages,
|
|
637
|
+
tools: (request.tools ?? []).map(({ name, description, jsonSchema }) => ({ name, description, jsonSchema })),
|
|
638
|
+
maxOutputTokens: request.generation_controls.max_output_tokens ?? request.generation_controls.max_tokens ?? request.generation_controls.max_completion_tokens ?? null,
|
|
639
|
+
temperature: request.generation_controls.temperature ?? null,
|
|
640
|
+
topP: request.generation_controls.top_p ?? null,
|
|
641
|
+
reasoningEffort: request.reasoning?.effort ?? null,
|
|
642
|
+
}, sessionId, [request.system, request.instructions].map((parts) => joinTextParts(parts ?? [])).filter(Boolean).join("\n"));
|
|
643
|
+
const { res, release } = await postUpstreamJson(
|
|
644
|
+
`${COMMANDCODE_HOST}${COMMANDCODE_GENERATE_PATH}`,
|
|
645
|
+
await headers(sessionId, token),
|
|
646
|
+
payload,
|
|
647
|
+
context,
|
|
648
|
+
context.outbound_fetch ?? this.fetchFn,
|
|
649
|
+
);
|
|
650
|
+
release();
|
|
651
|
+
try {
|
|
652
|
+
if (!res.ok) throw await mapUpstreamHttpError(res, COMMANDCODE_PROVIDER_ID);
|
|
653
|
+
if (!res.body) throw new GatewayError("platform_unavailable", 502, "Command Code returned an empty stream (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
654
|
+
// NDJSON carries no model identity; use the selected model, not the provider id.
|
|
655
|
+
yield* transformNdjson(res.body, context.abort_signal, candidate.model_id);
|
|
656
|
+
} catch (error: unknown) {
|
|
657
|
+
throw abortGatewayError({ signal: context.abort_signal, release }, error) ?? error;
|
|
658
|
+
}
|
|
699
659
|
}
|
|
700
660
|
}
|
|
701
661
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Command Code quota, read from the
|
|
2
|
+
* Command Code quota, read from the billing endpoints its client reads.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* renders still expects windows, so the balance is reported as one independent
|
|
7
|
-
* window — the honest reading, since credits are the only thing consumed.
|
|
4
|
+
* Monthly allowance and purchased/free credits are separate pooled windows:
|
|
5
|
+
* the monthly cap and reset do not limit or expire the additional balance.
|
|
8
6
|
*
|
|
9
7
|
* The endpoints, all on `https://api.commandcode.ai` (not the Provider API
|
|
10
8
|
* origin the model catalog lives on):
|
|
@@ -12,17 +10,42 @@
|
|
|
12
10
|
* `/alpha/whoami` identity, and the `orgId` when one exists
|
|
13
11
|
* `/alpha/billing/credits` the balance and any window limits
|
|
14
12
|
* `/alpha/billing/subscriptions` the plan, when there is one
|
|
15
|
-
* `/alpha/usage/summary` spend in the period, for context
|
|
16
13
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* balance has already got the answer even if the usage summary never came back.
|
|
14
|
+
* Identity resolves the organization before billing is read. Billing reads are
|
|
15
|
+
* independent: retain the balance or subscription when the other is unavailable.
|
|
20
16
|
*/
|
|
21
17
|
import type { FetchLike, ProviderQuotaResult, ProviderQuotaWindow } from "../../quota/quota-contracts";
|
|
22
18
|
|
|
23
19
|
const COMMANDCODE_API_BASE = "https://api.commandcode.ai" as const;
|
|
24
20
|
const REQUEST_TIMEOUT_MS = 15_000;
|
|
25
21
|
|
|
22
|
+
const PLAN_CAPS: Readonly<Record<string, number>> = {
|
|
23
|
+
"individual-go": 10,
|
|
24
|
+
"individual-goat": 70,
|
|
25
|
+
"individual-pro": 30,
|
|
26
|
+
"individual-provider": 15,
|
|
27
|
+
"individual-max": 150,
|
|
28
|
+
"individual-ultra": 300,
|
|
29
|
+
"teams-pro": 40,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const PLAN_CAP_OVERRIDES: Readonly<Record<string, number>> = {
|
|
33
|
+
"individual-pro-v1": 80,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function commandCodePlan(planId: string): { readonly label: string; readonly cap: number | null } {
|
|
37
|
+
const [scope, tier] = planId.toLowerCase().split("-");
|
|
38
|
+
if ((scope !== "individual" && scope !== "teams") || !tier) {
|
|
39
|
+
return { label: planId, cap: PLAN_CAP_OVERRIDES[planId] ?? PLAN_CAPS[planId] ?? null };
|
|
40
|
+
}
|
|
41
|
+
const tierLabel = tier === "goat" ? "GOAT" : `${tier[0]?.toUpperCase() ?? ""}${tier.slice(1)}`;
|
|
42
|
+
const normalizedId = `${scope}-${tier}`;
|
|
43
|
+
return {
|
|
44
|
+
label: `CommandCode ${scope === "teams" ? "Teams " : ""}${tierLabel}`,
|
|
45
|
+
cap: PLAN_CAP_OVERRIDES[planId] ?? PLAN_CAPS[normalizedId] ?? null,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
interface RequestOk {
|
|
27
50
|
readonly ok: true;
|
|
28
51
|
readonly value: unknown;
|
|
@@ -57,31 +80,69 @@ function recordValue(value: unknown): Record<string, unknown> | undefined {
|
|
|
57
80
|
}
|
|
58
81
|
|
|
59
82
|
function numberOrNull(value: unknown): number | null {
|
|
60
|
-
|
|
83
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
84
|
+
if (typeof value === "string" && value.trim() && Number.isFinite(Number(value))) {
|
|
85
|
+
return Number(value);
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isoTimestamp(value: unknown): string | null {
|
|
91
|
+
const numeric = numberOrNull(value);
|
|
92
|
+
if (numeric !== null) {
|
|
93
|
+
if (numeric <= 0) return null;
|
|
94
|
+
const date = new Date(numeric > 1_000_000_000_000 ? numeric : numeric * 1000);
|
|
95
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : null;
|
|
96
|
+
}
|
|
97
|
+
if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) return null;
|
|
98
|
+
return new Date(value).toISOString();
|
|
61
99
|
}
|
|
62
100
|
|
|
63
|
-
|
|
64
|
-
|
|
101
|
+
function withQuery(path: string, params: Readonly<Record<string, string | null>>): string {
|
|
102
|
+
const query = new URLSearchParams(
|
|
103
|
+
Object.entries(params).filter((entry): entry is [string, string] => entry[1] !== null),
|
|
104
|
+
).toString();
|
|
105
|
+
return query ? `${path}?${query}` : path;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Only monthly credits share the subscription allowance and reset. */
|
|
109
|
+
function creditWindows(
|
|
110
|
+
credits: Record<string, unknown>,
|
|
111
|
+
planCap: number | null,
|
|
112
|
+
resetsAt: string | null,
|
|
113
|
+
): readonly ProviderQuotaWindow[] {
|
|
65
114
|
const monthly = numberOrNull(credits["monthlyCredits"]) ?? 0;
|
|
66
115
|
const purchased = numberOrNull(credits["purchasedCredits"]) ?? 0;
|
|
67
116
|
const free = numberOrNull(credits["freeCredits"]) ?? 0;
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
117
|
+
const used = planCap === null ? null : Math.max(0, planCap - monthly);
|
|
118
|
+
const usedPercent = planCap !== null && planCap > 0 && used !== null
|
|
119
|
+
? Math.min(100, Math.max(0, (used / planCap) * 100))
|
|
120
|
+
: null;
|
|
121
|
+
const windows: ProviderQuotaWindow[] = [{
|
|
73
122
|
kind: "credits",
|
|
74
|
-
label: "
|
|
75
|
-
// These are credits in one unit that can be spent interchangeably, so
|
|
76
|
-
// they are pooled like Qoder's plan/granted balances — not independent
|
|
77
|
-
// rate-limit lanes. The account-row pill and the Quota page both sum
|
|
78
|
-
// pooled windows, so this must be `pooled` or the balance never renders.
|
|
123
|
+
label: "Monthly credits",
|
|
79
124
|
accounting: "pooled",
|
|
80
|
-
usedPercent
|
|
81
|
-
remainingPercent: null,
|
|
82
|
-
resetsAt
|
|
83
|
-
|
|
84
|
-
|
|
125
|
+
usedPercent,
|
|
126
|
+
remainingPercent: usedPercent === null ? null : Math.max(0, 100 - usedPercent),
|
|
127
|
+
resetsAt,
|
|
128
|
+
used,
|
|
129
|
+
limit: planCap,
|
|
130
|
+
remaining: monthly,
|
|
131
|
+
}];
|
|
132
|
+
if (purchased + free > 0) {
|
|
133
|
+
windows.push({
|
|
134
|
+
kind: "additional_credits",
|
|
135
|
+
label: "Purchased/free credits",
|
|
136
|
+
accounting: "pooled",
|
|
137
|
+
usedPercent: null,
|
|
138
|
+
remainingPercent: null,
|
|
139
|
+
resetsAt: null,
|
|
140
|
+
used: null,
|
|
141
|
+
limit: null,
|
|
142
|
+
remaining: purchased + free,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return windows;
|
|
85
146
|
}
|
|
86
147
|
|
|
87
148
|
function windowLimits(
|
|
@@ -92,17 +153,25 @@ function windowLimits(
|
|
|
92
153
|
const weekly = recordValue(limits["weekly"]);
|
|
93
154
|
const push = (source: Record<string, unknown> | undefined, kind: string, label: string) => {
|
|
94
155
|
if (source === undefined) return;
|
|
156
|
+
const used = numberOrNull(source["used"]) ?? 0;
|
|
157
|
+
const limit = numberOrNull(source["cap"]);
|
|
158
|
+
if ((limit === null || limit <= 0) && used <= 0) return;
|
|
159
|
+
const usedPercent = limit !== null && limit > 0
|
|
160
|
+
? Math.min(100, Math.max(0, (used / limit) * 100))
|
|
161
|
+
: null;
|
|
95
162
|
out.push({
|
|
96
163
|
kind,
|
|
97
164
|
label,
|
|
98
165
|
accounting: "independent",
|
|
99
|
-
usedPercent
|
|
100
|
-
remainingPercent:
|
|
101
|
-
resetsAt:
|
|
102
|
-
|
|
166
|
+
usedPercent,
|
|
167
|
+
remainingPercent: usedPercent === null ? null : Math.max(0, 100 - usedPercent),
|
|
168
|
+
resetsAt: isoTimestamp(source["resetAt"]),
|
|
169
|
+
used,
|
|
170
|
+
limit,
|
|
171
|
+
remaining: limit === null ? null : Math.max(0, limit - used),
|
|
103
172
|
});
|
|
104
173
|
};
|
|
105
|
-
push(fiveHour, "five_hour", "
|
|
174
|
+
push(fiveHour, "five_hour", "Session (5h)");
|
|
106
175
|
push(weekly, "weekly", "Weekly");
|
|
107
176
|
return out;
|
|
108
177
|
}
|
|
@@ -112,12 +181,8 @@ export async function fetchCommandCodeQuota(
|
|
|
112
181
|
fetcher: FetchLike,
|
|
113
182
|
): Promise<ProviderQuotaResult> {
|
|
114
183
|
const source = "commandcode";
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
readJson("/alpha/billing/credits", credential, fetcher),
|
|
118
|
-
readJson("/alpha/billing/subscriptions", credential, fetcher),
|
|
119
|
-
]);
|
|
120
|
-
if (!whoami.ok && !creditsRaw.ok) {
|
|
184
|
+
const whoami = await readJson(withQuery("/alpha/whoami", { limits: "1" }), credential, fetcher);
|
|
185
|
+
if (!whoami.ok) {
|
|
121
186
|
return {
|
|
122
187
|
source,
|
|
123
188
|
plan: null,
|
|
@@ -128,32 +193,47 @@ export async function fetchCommandCodeQuota(
|
|
|
128
193
|
|
|
129
194
|
const whoamiBody = whoami.ok ? recordValue(whoami.value) : undefined;
|
|
130
195
|
const user = recordValue(whoamiBody?.["user"]);
|
|
196
|
+
const organization = recordValue(whoamiBody?.["org"]);
|
|
197
|
+
const orgId = typeof organization?.["id"] === "string" ? organization["id"] : null;
|
|
131
198
|
const accountLabel =
|
|
132
199
|
(typeof user?.["email"] === "string" && user["email"]) ||
|
|
133
200
|
(typeof user?.["userName"] === "string" && user["userName"]) ||
|
|
201
|
+
(typeof user?.["name"] === "string" && user["name"]) ||
|
|
134
202
|
undefined;
|
|
135
203
|
|
|
204
|
+
const [creditsRaw, subscriptionRaw] = await Promise.all([
|
|
205
|
+
readJson(withQuery("/alpha/billing/credits", { orgId }), credential, fetcher),
|
|
206
|
+
readJson(withQuery("/alpha/billing/subscriptions", { orgId }), credential, fetcher),
|
|
207
|
+
]);
|
|
208
|
+
if (!creditsRaw.ok && !subscriptionRaw.ok) {
|
|
209
|
+
return {
|
|
210
|
+
source,
|
|
211
|
+
plan: null,
|
|
212
|
+
windows: [],
|
|
213
|
+
error: "Command Code did not answer its billing endpoints",
|
|
214
|
+
...(accountLabel === undefined ? {} : { accountLabel }),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const subscriptionBody = subscriptionRaw.ok ? recordValue(subscriptionRaw.value) : undefined;
|
|
219
|
+
const planRecord = recordValue(subscriptionBody?.["data"]);
|
|
220
|
+
const planId = typeof planRecord?.["planId"] === "string" ? planRecord["planId"] : null;
|
|
221
|
+
const parsedPlan = planId === null ? null : commandCodePlan(planId);
|
|
222
|
+
const plan =
|
|
223
|
+
parsedPlan?.label ??
|
|
224
|
+
(typeof planRecord?.["name"] === "string" ? planRecord["name"] : null) ??
|
|
225
|
+
(creditsRaw.ok ? "Credits" : null);
|
|
226
|
+
const periodEnd = isoTimestamp(planRecord?.["currentPeriodEnd"]);
|
|
227
|
+
|
|
136
228
|
const creditsBody = creditsRaw.ok ? recordValue(creditsRaw.value) : undefined;
|
|
137
229
|
const windows: ProviderQuotaWindow[] = [];
|
|
138
230
|
if (creditsBody !== undefined) {
|
|
139
231
|
const credits = recordValue(creditsBody["credits"]);
|
|
140
|
-
if (credits !== undefined)
|
|
141
|
-
const window = creditWindow(credits);
|
|
142
|
-
if (window !== null) windows.push(window);
|
|
143
|
-
}
|
|
232
|
+
if (credits !== undefined) windows.push(...creditWindows(credits, parsedPlan?.cap ?? null, periodEnd));
|
|
144
233
|
const limits = recordValue(creditsBody["windowLimits"]);
|
|
145
234
|
if (limits !== undefined) windows.push(...windowLimits(limits));
|
|
146
235
|
}
|
|
147
236
|
|
|
148
|
-
const subscriptionBody = subscriptionRaw.ok ? recordValue(subscriptionRaw.value) : undefined;
|
|
149
|
-
const planRecord = recordValue(subscriptionBody?.["data"]);
|
|
150
|
-
const plan =
|
|
151
|
-
typeof planRecord?.["name"] === "string"
|
|
152
|
-
? planRecord["name"]
|
|
153
|
-
: creditsRaw.ok
|
|
154
|
-
? "Credits"
|
|
155
|
-
: null;
|
|
156
|
-
|
|
157
237
|
return {
|
|
158
238
|
source,
|
|
159
239
|
plan,
|
|
@@ -295,6 +295,3 @@ function concat(left: Uint8Array, right: Uint8Array): Uint8Array {
|
|
|
295
295
|
out.set(right, left.byteLength);
|
|
296
296
|
return out;
|
|
297
297
|
}
|
|
298
|
-
|
|
299
|
-
/** Heartbeat cadence while a Run is held open waiting for a tool result. */
|
|
300
|
-
export const RUN_HEARTBEAT_INTERVAL_MS = 20_000;
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
} from "../../quota/quota-contracts";
|
|
36
36
|
import type { QuotaCollectionContext } from "../../quota/quota-support";
|
|
37
37
|
import { cursorAccountIdentity } from "./cursor-auth";
|
|
38
|
+
import { fnv1a32 } from "../shared/hash";
|
|
38
39
|
import { CURSOR_API_HOST, CURSOR_WEBSITE_HOST } from "./cursor-shared";
|
|
39
40
|
|
|
40
41
|
/** Timestamp keys naming the end of the current window. */
|
|
@@ -226,12 +227,7 @@ function authStateUserId(context: QuotaCollectionContext | undefined): string |
|
|
|
226
227
|
* subject it replaces.
|
|
227
228
|
*/
|
|
228
229
|
function cursorAccountTag(credential: string): string {
|
|
229
|
-
|
|
230
|
-
for (let index = 0; index < credential.length; index += 1) {
|
|
231
|
-
hash ^= credential.charCodeAt(index);
|
|
232
|
-
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
233
|
-
}
|
|
234
|
-
return `cursor-${hash.toString(36).padStart(7, "0").slice(0, 7)}`;
|
|
230
|
+
return `cursor-${fnv1a32(credential).toString(36).padStart(7, "0").slice(0, 7)}`;
|
|
235
231
|
}
|
|
236
232
|
|
|
237
233
|
export async function fetchCursorQuota(
|