cartethyia 2.7.3 → 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-2TJD37Hb.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-xefJNRmJ.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.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-BKj_r0rp.js +1 -0
- 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-C4w7vea-.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BtPcAfot.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-5SnUSy3j.js +9 -0
- 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-BQS0Rx_u.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-TP7voAQ0.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-C0YYuZJ4.js → assert-C0K-c4eo.js} +1 -1
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DMrMPmth.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-Be5Uzamx.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-muFRphDu.js → cli-tools-CQXVMn4P.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DOfrVmsi.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-C9omdjQt.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bm8WKaGY.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-q5HwZ8nN.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-BTScrQpe.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-cPrX5vn6.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/{layout-C_7A6H55.js.gz → layout-CajrYUnD.js.gz} +0 -0
- package/dist/dashboard/assets/{list-row-CzFvogbj.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/minimize-2-BTmMTK4o.js +1 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-JJGQm8TD.js → mutation-Rr0TIvcj.js} +1 -1
- package/dist/dashboard/assets/mutation-Rr0TIvcj.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/{query-keys-CLaNz8Xz.js → query-keys-BloKtaXJ.js} +1 -1
- package/dist/dashboard/assets/query-keys-BloKtaXJ.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-BEH32QOC.js → routing-in0f_IfK.js} +1 -1
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-B3iTetHN.js → select-BLULNqTp.js} +2 -2
- 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-KrOrm7JZ.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-DLS7IDMy.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.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 +59 -57
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
- package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
- package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
- package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
- 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/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
- package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
- package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
- package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -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 -5
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +67 -10
- 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 +8 -4
- 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 +92 -31
- package/src/console/api-keys/routes.ts +131 -6
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +5 -5
- 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 +40 -34
- 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 +11 -9
- package/src/console/backup/export-endpoint.ts +11 -12
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +32 -36
- 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 +4 -4
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +36 -4
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +18 -4
- 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 +5 -1
- package/src/console/observability/live.ts +34 -21
- package/src/console/observability/logs.ts +4 -4
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +36 -20
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +82 -22
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +110 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +30 -6
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1662 -1292
- package/src/console/providers/detail/routes.ts +4 -4
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +95 -16
- 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 +285 -67
- package/src/console/quota/account-test-egress.ts +4 -4
- 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/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +13 -10
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/operations.ts +14 -7
- package/src/console/routing/pools/probe-verdict.ts +8 -3
- package/src/console/routing/pools/relay-deploy.ts +12 -12
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/routes.ts +3 -3
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +112 -44
- package/src/console/share/share-stats.ts +109 -39
- 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 +42 -6
- 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 +256 -98
- 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 +76 -5
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +55 -51
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +22 -2
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +24 -75
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +286 -214
- 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/telemetry-status.ts +1 -1
- 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 +10 -5
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +19 -7
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +177 -45
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +109 -4
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/stores/telemetry-store.ts +1 -1
- 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 +12 -16
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/image-generation.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 +27 -12
- package/src/protocol/response/codex.ts +2 -2
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +6 -6
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +3 -3
- package/src/protocol/sse-decoder.ts +64 -4
- 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 +8 -8
- 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/protocol/upstream/send-claude-messages.ts +3 -3
- package/src/providers/adapters/base-adapter.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +44 -5
- 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/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/configured-provider.ts +1 -1
- 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 +50 -15
- package/src/providers/discovery/probing-service.ts +18 -20
- package/src/providers/integrations/agentrouter/agentrouter.ts +14 -5
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- 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 +15 -26
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +2 -2
- 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-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +108 -1
- package/src/providers/integrations/buddy/buddy-media.ts +16 -16
- 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 +5 -16
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -10
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/claude-credentials.ts +1 -1
- package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
- package/src/providers/integrations/claude/claude.ts +3 -10
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +76 -116
- package/src/providers/integrations/commandcode/quota.ts +132 -48
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -14
- 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 +53 -20
- 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 +13 -13
- package/src/providers/integrations/gemini.ts +11 -11
- 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 +47 -20
- 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 +88 -42
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- 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 +91 -78
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +132 -17
- package/src/providers/integrations/qoder/qoder-checkin.ts +26 -8
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +9 -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 +22 -28
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +33 -38
- package/src/providers/integrations/qoder/qoder-virtual.ts +14 -2
- package/src/providers/integrations/qoder/qoder.ts +521 -63
- 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/tokenharbor.ts +2 -2
- 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 +59 -19
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- 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 +22 -6
- package/src/providers/operations/provider-credential-service.ts +35 -6
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +65 -10
- package/src/providers/provider-credential-resolver.ts +1 -1
- 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-registry.ts +4 -4
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +28 -10
- package/src/providers/quota/refresh.ts +29 -6
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +6 -8
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +8 -8
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +20 -8
- 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/coerce.ts +19 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +5 -4
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +28 -25
- package/src/transport/dispatch/generation.ts +33 -53
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +10 -8
- package/src/transport/dispatch/responses-compact.ts +35 -56
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +11 -10
- 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 +27 -55
- package/src/transport/dispatch/token-count.ts +49 -46
- package/src/transport/dispatch/websearch.ts +24 -50
- package/src/transport/drain-endpoint.ts +3 -3
- package/src/transport/failure-policy.ts +19 -6
- package/src/transport/guards/auth-guard.ts +6 -11
- package/src/transport/guards/body-policy.ts +7 -7
- package/src/transport/guards/error-lifecycle.ts +18 -3
- package/src/transport/guards/guard-errors.ts +7 -3
- package/src/transport/guards/headroom-guard.ts +2 -2
- package/src/transport/guards/pipeline.ts +7 -7
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +15 -20
- package/src/transport/request/preparer.ts +306 -27
- 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 +5 -20
- 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 +113 -19
- package/src/transport/routing/route-model.ts +131 -38
- package/src/transport/routing/router.ts +154 -39
- package/src/transport/shutdown-notice.ts +21 -9
- 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 +3 -3
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/encode.ts +1 -1
- 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-2TJD37Hb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js +0 -1
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.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-0OsXRGXe.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +0 -9
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js +0 -1
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-BAL5npBC.js +0 -1
- package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js +0 -56
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js +0 -1
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
- package/dist/dashboard/assets/app-B2vyPoII.css +0 -2
- package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
- package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
- package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
- package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
- package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
- package/dist/dashboard/assets/entry-DS90gUks.js +0 -1
- package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
- package/dist/dashboard/assets/entry-j40LJotO.js +0 -4
- package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
- package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
- package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
- package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
- package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
- package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
- package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
- package/dist/dashboard/assets/live-KaG15HLQ.js +0 -1
- package/dist/dashboard/assets/live-KaG15HLQ.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/mutation-JJGQm8TD.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BNDZnsUE.js +0 -2
- package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CLaNz8Xz.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
- package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js +0 -1
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
- package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
- package/dist/dashboard/assets/state-DLS7IDMy.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-42ItvbAs.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dmnfh1Ue.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-wvwCi4Eh.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.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
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
|
|
3
|
-
const MASK = 0xffffffffffffffffn;
|
|
4
|
-
const PRIME1 = 0x9e3779b185ebca87n;
|
|
5
|
-
const PRIME2 = 0xc2b2ae3d27d4eb4fn;
|
|
6
|
-
const PRIME3 = 0x165667b19e3779f9n;
|
|
7
|
-
const PRIME4 = 0x85ebca77c2b2ae63n;
|
|
8
|
-
const PRIME5 = 0x27d4eb2f165667c5n;
|
|
9
|
-
const CCH_SEED = 0x4d659218e32a3268n;
|
|
10
|
-
const PLACEHOLDER = "cch=00000";
|
|
11
|
-
const encoder = new TextEncoder();
|
|
12
|
-
|
|
13
|
-
function round(acc: bigint, input: bigint): bigint {
|
|
14
|
-
let value = (acc + input * PRIME2) & MASK;
|
|
15
|
-
value = ((value << 31n) | (value >> 33n)) & MASK;
|
|
16
|
-
return (value * PRIME1) & MASK;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function mergeRound(acc: bigint, value: bigint): bigint {
|
|
20
|
-
let result = acc ^ round(0n, value);
|
|
21
|
-
return (result * PRIME1 + PRIME4) & MASK;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function read32(bytes: Uint8Array, offset: number): bigint {
|
|
25
|
-
return (
|
|
26
|
-
BigInt(bytes[offset] ?? 0) |
|
|
27
|
-
(BigInt(bytes[offset + 1] ?? 0) << 8n) |
|
|
28
|
-
(BigInt(bytes[offset + 2] ?? 0) << 16n) |
|
|
29
|
-
(BigInt(bytes[offset + 3] ?? 0) << 24n)
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function read64(bytes: Uint8Array, offset: number): bigint {
|
|
34
|
-
let value = 0n;
|
|
35
|
-
for (let index = 0; index < 8; index += 1)
|
|
36
|
-
value |= BigInt(bytes[offset + index] ?? 0) << BigInt(index * 8);
|
|
37
|
-
return value;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function xxHash64(bytes: Uint8Array, seed: bigint): bigint {
|
|
41
|
-
let offset = 0;
|
|
42
|
-
let hash: bigint;
|
|
43
|
-
if (bytes.length >= 32) {
|
|
44
|
-
let v1 = (seed + PRIME1 + PRIME2) & MASK;
|
|
45
|
-
let v2 = (seed + PRIME2) & MASK;
|
|
46
|
-
let v3 = seed & MASK;
|
|
47
|
-
let v4 = (seed - PRIME1) & MASK;
|
|
48
|
-
while (offset <= bytes.length - 32) {
|
|
49
|
-
v1 = round(v1, read64(bytes, offset));
|
|
50
|
-
v2 = round(v2, read64(bytes, offset + 8));
|
|
51
|
-
v3 = round(v3, read64(bytes, offset + 16));
|
|
52
|
-
v4 = round(v4, read64(bytes, offset + 24));
|
|
53
|
-
offset += 32;
|
|
54
|
-
}
|
|
55
|
-
hash =
|
|
56
|
-
(((v1 << 1n) | (v1 >> 63n)) +
|
|
57
|
-
((v2 << 7n) | (v2 >> 57n)) +
|
|
58
|
-
((v3 << 12n) | (v3 >> 52n)) +
|
|
59
|
-
((v4 << 18n) | (v4 >> 46n))) &
|
|
60
|
-
MASK;
|
|
61
|
-
hash = mergeRound(hash, v1);
|
|
62
|
-
hash = mergeRound(hash, v2);
|
|
63
|
-
hash = mergeRound(hash, v3);
|
|
64
|
-
hash = mergeRound(hash, v4);
|
|
65
|
-
} else hash = (seed + PRIME5) & MASK;
|
|
66
|
-
hash = (hash + BigInt(bytes.length)) & MASK;
|
|
67
|
-
while (offset <= bytes.length - 8) {
|
|
68
|
-
const value = round(0n, read64(bytes, offset));
|
|
69
|
-
hash ^= value;
|
|
70
|
-
hash = (((hash << 27n) | (hash >> 37n)) * PRIME1 + PRIME4) & MASK;
|
|
71
|
-
offset += 8;
|
|
72
|
-
}
|
|
73
|
-
if (offset <= bytes.length - 4) {
|
|
74
|
-
hash ^= (read32(bytes, offset) * PRIME1) & MASK;
|
|
75
|
-
hash = (((hash << 23n) | (hash >> 41n)) * PRIME2 + PRIME3) & MASK;
|
|
76
|
-
offset += 4;
|
|
77
|
-
}
|
|
78
|
-
while (offset < bytes.length) {
|
|
79
|
-
hash ^= (BigInt(bytes[offset] ?? 0) * PRIME5) & MASK;
|
|
80
|
-
hash = (((hash << 11n) | (hash >> 53n)) * PRIME1) & MASK;
|
|
81
|
-
offset += 1;
|
|
82
|
-
}
|
|
83
|
-
hash ^= hash >> 33n;
|
|
84
|
-
hash = (hash * PRIME2) & MASK;
|
|
85
|
-
hash ^= hash >> 29n;
|
|
86
|
-
hash = (hash * PRIME3) & MASK;
|
|
87
|
-
return (hash ^ (hash >> 32n)) & MASK;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** Computes Claude Code's five-hex-digit CCH from the exact outgoing body bytes. */
|
|
91
|
-
export function computeClaudeCch(body: Uint8Array): string {
|
|
92
|
-
return (xxHash64(body, CCH_SEED) & 0xfffffn).toString(16).padStart(5, "0");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/** Replaces the anchored Claude billing placeholder in a mutable body before sending. */
|
|
96
|
-
export function patchClaudeCch(body: Uint8Array): boolean {
|
|
97
|
-
const marker = encoder.encode('"system":[{"type":"text","text":"x-anthropic-billing-header:');
|
|
98
|
-
const placeholder = encoder.encode(PLACEHOLDER);
|
|
99
|
-
let markerIndex = -1;
|
|
100
|
-
outer: for (let index = 0; index <= body.length - marker.length; index += 1) {
|
|
101
|
-
for (let j = 0; j < marker.length; j += 1) if (body[index + j] !== marker[j]) continue outer;
|
|
102
|
-
markerIndex = index;
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
if (markerIndex < 0) return false;
|
|
106
|
-
const start = markerIndex + marker.length;
|
|
107
|
-
const end = Math.min(body.length - placeholder.length, start + 150);
|
|
108
|
-
for (let index = start; index <= end; index += 1) {
|
|
109
|
-
let found = true;
|
|
110
|
-
for (let j = 0; j < placeholder.length; j += 1)
|
|
111
|
-
if (body[index + j] !== placeholder[j]) {
|
|
112
|
-
found = false;
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
if (!found) continue;
|
|
116
|
-
const cch = encoder.encode(computeClaudeCch(body));
|
|
117
|
-
body.set(cch, index + 4);
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Harness identity instruction, sent on OAuth dispatch. */
|
|
124
|
-
export const CLAUDE_CODE_SYSTEM_INSTRUCTION =
|
|
125
|
-
"You are Claude Code, Anthropic's official CLI for Claude.";
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Builds the billing header text with the captured version suffix:
|
|
129
|
-
* `cc_version={ver}.{sha256("59cf53e54c78" + chars + ver)[0:3]}` where
|
|
130
|
-
* chars are the 5th/8th/21st chars of the first user text (or "0" when
|
|
131
|
-
* absent). `cc_entrypoint=cli` matches the harness UA `(external, cli)`;
|
|
132
|
-
* an older snapshot used `claude-desktop`, which is unverified from local
|
|
133
|
-
* evidence, so cli is kept with this note.
|
|
134
|
-
*/
|
|
135
|
-
export function createClaudeBillingText(userText: string, version: string): string {
|
|
136
|
-
const chars = [4, 7, 20].map((index) => userText[index] ?? "0").join("");
|
|
137
|
-
const suffix = createHash("sha256")
|
|
138
|
-
.update(`59cf53e54c78${chars}${version}`)
|
|
139
|
-
.digest("hex")
|
|
140
|
-
.slice(0, 3);
|
|
141
|
-
return `x-anthropic-billing-header: cc_version=${version}.${suffix}; cc_entrypoint=cli; cch=00000;`;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/** Patches a string request body and returns its encoded bytes, or undefined when no billing block exists. */
|
|
145
|
-
export function patchClaudeCchBody(body: string): Uint8Array | undefined {
|
|
146
|
-
const bytes = encoder.encode(body);
|
|
147
|
-
return patchClaudeCch(bytes) ? bytes : undefined;
|
|
148
|
-
}
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
const MASK = 0xffffffffffffffffn;
|
|
4
|
+
const PRIME1 = 0x9e3779b185ebca87n;
|
|
5
|
+
const PRIME2 = 0xc2b2ae3d27d4eb4fn;
|
|
6
|
+
const PRIME3 = 0x165667b19e3779f9n;
|
|
7
|
+
const PRIME4 = 0x85ebca77c2b2ae63n;
|
|
8
|
+
const PRIME5 = 0x27d4eb2f165667c5n;
|
|
9
|
+
const CCH_SEED = 0x4d659218e32a3268n;
|
|
10
|
+
const PLACEHOLDER = "cch=00000";
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
|
|
13
|
+
function round(acc: bigint, input: bigint): bigint {
|
|
14
|
+
let value = (acc + input * PRIME2) & MASK;
|
|
15
|
+
value = ((value << 31n) | (value >> 33n)) & MASK;
|
|
16
|
+
return (value * PRIME1) & MASK;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function mergeRound(acc: bigint, value: bigint): bigint {
|
|
20
|
+
let result = acc ^ round(0n, value);
|
|
21
|
+
return (result * PRIME1 + PRIME4) & MASK;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function read32(bytes: Uint8Array, offset: number): bigint {
|
|
25
|
+
return (
|
|
26
|
+
BigInt(bytes[offset] ?? 0) |
|
|
27
|
+
(BigInt(bytes[offset + 1] ?? 0) << 8n) |
|
|
28
|
+
(BigInt(bytes[offset + 2] ?? 0) << 16n) |
|
|
29
|
+
(BigInt(bytes[offset + 3] ?? 0) << 24n)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function read64(bytes: Uint8Array, offset: number): bigint {
|
|
34
|
+
let value = 0n;
|
|
35
|
+
for (let index = 0; index < 8; index += 1)
|
|
36
|
+
value |= BigInt(bytes[offset + index] ?? 0) << BigInt(index * 8);
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function xxHash64(bytes: Uint8Array, seed: bigint): bigint {
|
|
41
|
+
let offset = 0;
|
|
42
|
+
let hash: bigint;
|
|
43
|
+
if (bytes.length >= 32) {
|
|
44
|
+
let v1 = (seed + PRIME1 + PRIME2) & MASK;
|
|
45
|
+
let v2 = (seed + PRIME2) & MASK;
|
|
46
|
+
let v3 = seed & MASK;
|
|
47
|
+
let v4 = (seed - PRIME1) & MASK;
|
|
48
|
+
while (offset <= bytes.length - 32) {
|
|
49
|
+
v1 = round(v1, read64(bytes, offset));
|
|
50
|
+
v2 = round(v2, read64(bytes, offset + 8));
|
|
51
|
+
v3 = round(v3, read64(bytes, offset + 16));
|
|
52
|
+
v4 = round(v4, read64(bytes, offset + 24));
|
|
53
|
+
offset += 32;
|
|
54
|
+
}
|
|
55
|
+
hash =
|
|
56
|
+
(((v1 << 1n) | (v1 >> 63n)) +
|
|
57
|
+
((v2 << 7n) | (v2 >> 57n)) +
|
|
58
|
+
((v3 << 12n) | (v3 >> 52n)) +
|
|
59
|
+
((v4 << 18n) | (v4 >> 46n))) &
|
|
60
|
+
MASK;
|
|
61
|
+
hash = mergeRound(hash, v1);
|
|
62
|
+
hash = mergeRound(hash, v2);
|
|
63
|
+
hash = mergeRound(hash, v3);
|
|
64
|
+
hash = mergeRound(hash, v4);
|
|
65
|
+
} else hash = (seed + PRIME5) & MASK;
|
|
66
|
+
hash = (hash + BigInt(bytes.length)) & MASK;
|
|
67
|
+
while (offset <= bytes.length - 8) {
|
|
68
|
+
const value = round(0n, read64(bytes, offset));
|
|
69
|
+
hash ^= value;
|
|
70
|
+
hash = (((hash << 27n) | (hash >> 37n)) * PRIME1 + PRIME4) & MASK;
|
|
71
|
+
offset += 8;
|
|
72
|
+
}
|
|
73
|
+
if (offset <= bytes.length - 4) {
|
|
74
|
+
hash ^= (read32(bytes, offset) * PRIME1) & MASK;
|
|
75
|
+
hash = (((hash << 23n) | (hash >> 41n)) * PRIME2 + PRIME3) & MASK;
|
|
76
|
+
offset += 4;
|
|
77
|
+
}
|
|
78
|
+
while (offset < bytes.length) {
|
|
79
|
+
hash ^= (BigInt(bytes[offset] ?? 0) * PRIME5) & MASK;
|
|
80
|
+
hash = (((hash << 11n) | (hash >> 53n)) * PRIME1) & MASK;
|
|
81
|
+
offset += 1;
|
|
82
|
+
}
|
|
83
|
+
hash ^= hash >> 33n;
|
|
84
|
+
hash = (hash * PRIME2) & MASK;
|
|
85
|
+
hash ^= hash >> 29n;
|
|
86
|
+
hash = (hash * PRIME3) & MASK;
|
|
87
|
+
return (hash ^ (hash >> 32n)) & MASK;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Computes Claude Code's five-hex-digit CCH from the exact outgoing body bytes. */
|
|
91
|
+
export function computeClaudeCch(body: Uint8Array): string {
|
|
92
|
+
return (xxHash64(body, CCH_SEED) & 0xfffffn).toString(16).padStart(5, "0");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Replaces the anchored Claude billing placeholder in a mutable body before sending. */
|
|
96
|
+
export function patchClaudeCch(body: Uint8Array): boolean {
|
|
97
|
+
const marker = encoder.encode('"system":[{"type":"text","text":"x-anthropic-billing-header:');
|
|
98
|
+
const placeholder = encoder.encode(PLACEHOLDER);
|
|
99
|
+
let markerIndex = -1;
|
|
100
|
+
outer: for (let index = 0; index <= body.length - marker.length; index += 1) {
|
|
101
|
+
for (let j = 0; j < marker.length; j += 1) if (body[index + j] !== marker[j]) continue outer;
|
|
102
|
+
markerIndex = index;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
if (markerIndex < 0) return false;
|
|
106
|
+
const start = markerIndex + marker.length;
|
|
107
|
+
const end = Math.min(body.length - placeholder.length, start + 150);
|
|
108
|
+
for (let index = start; index <= end; index += 1) {
|
|
109
|
+
let found = true;
|
|
110
|
+
for (let j = 0; j < placeholder.length; j += 1)
|
|
111
|
+
if (body[index + j] !== placeholder[j]) {
|
|
112
|
+
found = false;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
if (!found) continue;
|
|
116
|
+
const cch = encoder.encode(computeClaudeCch(body));
|
|
117
|
+
body.set(cch, index + 4);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Harness identity instruction, sent on OAuth dispatch. */
|
|
124
|
+
export const CLAUDE_CODE_SYSTEM_INSTRUCTION =
|
|
125
|
+
"You are Claude Code, Anthropic's official CLI for Claude.";
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Builds the billing header text with the captured version suffix:
|
|
129
|
+
* `cc_version={ver}.{sha256("59cf53e54c78" + chars + ver)[0:3]}` where
|
|
130
|
+
* chars are the 5th/8th/21st chars of the first user text (or "0" when
|
|
131
|
+
* absent). `cc_entrypoint=cli` matches the harness UA `(external, cli)`;
|
|
132
|
+
* an older snapshot used `claude-desktop`, which is unverified from local
|
|
133
|
+
* evidence, so cli is kept with this note.
|
|
134
|
+
*/
|
|
135
|
+
export function createClaudeBillingText(userText: string, version: string): string {
|
|
136
|
+
const chars = [4, 7, 20].map((index) => userText[index] ?? "0").join("");
|
|
137
|
+
const suffix = createHash("sha256")
|
|
138
|
+
.update(`59cf53e54c78${chars}${version}`)
|
|
139
|
+
.digest("hex")
|
|
140
|
+
.slice(0, 3);
|
|
141
|
+
return `x-anthropic-billing-header: cc_version=${version}.${suffix}; cc_entrypoint=cli; cch=00000;`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Patches a string request body and returns its encoded bytes, or undefined when no billing block exists. */
|
|
145
|
+
export function patchClaudeCchBody(body: string): Uint8Array | undefined {
|
|
146
|
+
const bytes = encoder.encode(body);
|
|
147
|
+
return patchClaudeCch(bytes) ? bytes : undefined;
|
|
148
|
+
}
|
|
@@ -10,7 +10,7 @@ function invalidHeader(
|
|
|
10
10
|
message: string,
|
|
11
11
|
details: Readonly<Record<string, unknown>> = {},
|
|
12
12
|
): GatewayError {
|
|
13
|
-
return new GatewayError("invalid_request", 400, message
|
|
13
|
+
return new GatewayError("invalid_request", 400, `${message} (request {requestId}). Check the shape of what you sent — then resend 🪞`, details);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function decodeSecret(secret: Uint8Array | undefined): string | undefined {
|
|
@@ -96,5 +96,5 @@ export function planSlowLaneRetry(
|
|
|
96
96
|
|
|
97
97
|
/** Typed error for a caller-aborted wait, so it is never read as a failure. */
|
|
98
98
|
export function slowLaneAborted(): GatewayError {
|
|
99
|
-
return new GatewayError("transport_closed", 499, "
|
|
99
|
+
return new GatewayError("transport_closed", 499, "The request was cancelled during the slow-lane capacity wait (request {requestId}). Send it again whenever ready 🙃");
|
|
100
100
|
}
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
refusalCreditToken,
|
|
62
62
|
sharedFallbackCreditCache,
|
|
63
63
|
} from "./fallback-credit";
|
|
64
|
+
import { assertCredentialKind, assertWireFamily } from "../../provider-contracts";
|
|
64
65
|
import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext } from "../../provider-contracts";
|
|
65
66
|
import { defineModel } from "../../provider-model-definition";
|
|
66
67
|
import type { ModelDefinition } from "../../provider-model-definition";
|
|
@@ -185,21 +186,13 @@ export class ClaudeAdapter implements ProviderAdapter {
|
|
|
185
186
|
context: ProviderDispatchContext,
|
|
186
187
|
): AsyncIterable<CanonicalEvent> {
|
|
187
188
|
if (candidate.wire_family !== "messages") {
|
|
188
|
-
|
|
189
|
-
"capability_unsupported",
|
|
190
|
-
400,
|
|
191
|
-
"claude supports messages only",
|
|
192
|
-
);
|
|
189
|
+
assertWireFamily(candidate, "messages", "claude");
|
|
193
190
|
}
|
|
194
191
|
if (
|
|
195
192
|
context.credential.credential_kind !== "oauth" &&
|
|
196
193
|
context.credential.credential_kind !== "scoped_access_token"
|
|
197
194
|
) {
|
|
198
|
-
|
|
199
|
-
"invalid_request",
|
|
200
|
-
400,
|
|
201
|
-
`claude: the assistant OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
202
|
-
);
|
|
195
|
+
assertCredentialKind(context.credential, ["oauth", "scoped_access_token"], "claude");
|
|
203
196
|
}
|
|
204
197
|
const customHeaders = filterClaudeCustomHeaders({
|
|
205
198
|
...this.customHeaders,
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
import { GatewayError } from "../../../protocol/gateway-error";
|
|
30
|
+
import { fnv1a32 } from "../shared/hash";
|
|
30
31
|
|
|
31
32
|
const CREDIT_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
32
33
|
const MAX_CACHE_SIZE = 64;
|
|
@@ -122,15 +123,10 @@ export class FallbackCreditCache {
|
|
|
122
123
|
|
|
123
124
|
/**
|
|
124
125
|
* Compute a simple hash of the request body for cache keying.
|
|
125
|
-
*
|
|
126
|
+
* FNV-1a — fast, deterministic, sufficient for cache identity.
|
|
126
127
|
*/
|
|
127
128
|
export function hashBody(body: string): string {
|
|
128
|
-
|
|
129
|
-
for (let i = 0; i < body.length; i++) {
|
|
130
|
-
hash ^= body.charCodeAt(i);
|
|
131
|
-
hash = Math.imul(hash, 0x01000193);
|
|
132
|
-
}
|
|
133
|
-
return (hash >>> 0).toString(36);
|
|
129
|
+
return fnv1a32(body).toString(36);
|
|
134
130
|
}
|
|
135
131
|
|
|
136
132
|
// Shared process-wide cache instance
|
|
@@ -28,7 +28,7 @@ const CLINE_MODELS_CATALOG_PATH = "/ai/cline/models" as const;
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
function workosToken(token: string): string {
|
|
32
32
|
return token.startsWith("workos:") ? token : `workos:${token}`;
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -150,7 +150,7 @@ function clinePrePayload(
|
|
|
150
150
|
const cur = typeof payload["max_tokens"] === "number" ? (payload["max_tokens"] as number) : 0;
|
|
151
151
|
payload["max_tokens"] = Math.max(cur, 256);
|
|
152
152
|
// keep GatewayError reachable
|
|
153
|
-
if (!model) throw new GatewayError("invalid_request", 400, "Cline model is required");
|
|
153
|
+
if (!model) throw new GatewayError("invalid_request", 400, "Cline model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* protocol at the `/anthropic` path suffix, including `thinking_delta`
|
|
17
17
|
* blocks, so the Messages leg is built directly.
|
|
18
18
|
*/
|
|
19
|
+
import { assertWireFamily } from "../../provider-contracts";
|
|
19
20
|
import type {
|
|
20
21
|
ProviderAdapter,
|
|
21
22
|
ProviderDispatchContext,
|
|
@@ -57,7 +58,7 @@ function cloudflareEnvelope(context: ProviderDispatchContext): {
|
|
|
57
58
|
} {
|
|
58
59
|
const secret = context.credential.secret;
|
|
59
60
|
if (secret === undefined || secret.length === 0) {
|
|
60
|
-
throw new GatewayError("invalid_request", 400, "cloudflareai: credential is missing a secret value");
|
|
61
|
+
throw new GatewayError("invalid_request", 400, "cloudflareai: credential is missing a secret value (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
61
62
|
}
|
|
62
63
|
let envelope: ReturnType<typeof decodeCloudflareAiGatewayCredential>;
|
|
63
64
|
try {
|
|
@@ -66,7 +67,7 @@ function cloudflareEnvelope(context: ProviderDispatchContext): {
|
|
|
66
67
|
throw new GatewayError(
|
|
67
68
|
"invalid_request",
|
|
68
69
|
400,
|
|
69
|
-
`cloudflareai: ${error instanceof Error ? error.message : "stored credential is not a Cloudflare envelope"}
|
|
70
|
+
`cloudflareai: ${error instanceof Error ? error.message : "stored credential is not a Cloudflare envelope"} (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
70
71
|
);
|
|
71
72
|
}
|
|
72
73
|
return { token: envelope.token, baseUrl: cloudflareBaseUrl(envelope.accountId, envelope.gatewayId) };
|
|
@@ -93,11 +94,7 @@ class CloudflareAiGatewayAdapter implements ProviderAdapter {
|
|
|
93
94
|
context: ProviderDispatchContext,
|
|
94
95
|
): AsyncIterable<CanonicalEvent> {
|
|
95
96
|
if (candidate.wire_family !== "messages") {
|
|
96
|
-
|
|
97
|
-
"capability_unsupported",
|
|
98
|
-
400,
|
|
99
|
-
`cloudflareai supports messages only, got ${candidate.wire_family}`,
|
|
100
|
-
);
|
|
97
|
+
assertWireFamily(candidate, "messages", "cloudflareai");
|
|
101
98
|
}
|
|
102
99
|
const { token, baseUrl } = cloudflareEnvelope(context);
|
|
103
100
|
const outbound = buildClaudeMessagesRequest({
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
import type { FetchLike } from "../../authentication/oauth-client";
|
|
2
|
-
|
|
3
|
-
export const CODEX_DEVICE_USERCODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
|
|
4
|
-
export const CODEX_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Lifetime of one device authorization, in seconds.
|
|
8
|
-
*
|
|
9
|
-
* The Codex device endpoint states no expiry, so the flow bounds itself: this
|
|
10
|
-
* is both what `startDeviceAuth` reports to the dashboard (its own countdown)
|
|
11
|
-
* and what the poll checks before spending a request on a dead authorization.
|
|
12
|
-
*/
|
|
13
|
-
export const CODEX_DEVICE_TTL_SECONDS = 900;
|
|
14
|
-
|
|
15
|
-
interface CodexDeviceStart {
|
|
16
|
-
readonly deviceAuthId: string;
|
|
17
|
-
readonly userCode: string;
|
|
18
|
-
readonly intervalSeconds: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface CodexDeviceAuthorization {
|
|
22
|
-
readonly authorizationCode: string;
|
|
23
|
-
readonly codeVerifier: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Validates persisted provider-private device state read back from the flow store. */
|
|
27
|
-
export function parseCodexDeviceStart(value: Record<string, unknown>): CodexDeviceStart | undefined {
|
|
28
|
-
const { deviceAuthId, userCode, intervalSeconds } = value;
|
|
29
|
-
if (typeof deviceAuthId !== "string" || typeof userCode !== "string") return undefined;
|
|
30
|
-
if (typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds)) return undefined;
|
|
31
|
-
return { deviceAuthId, userCode, intervalSeconds: Math.max(0, intervalSeconds) };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface DeviceUserCodeResponse {
|
|
35
|
-
device_auth_id?: unknown;
|
|
36
|
-
user_code?: unknown;
|
|
37
|
-
interval?: unknown;
|
|
38
|
-
}
|
|
39
|
-
interface DeviceTokenResponse {
|
|
40
|
-
authorization_code?: unknown;
|
|
41
|
-
code_verifier?: unknown;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function jsonHeaders(): HeadersInit {
|
|
45
|
-
return { "content-type": "application/json", accept: "application/json" };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function startCodexDeviceAuth(
|
|
49
|
-
clientId: string,
|
|
50
|
-
fetchFn: FetchLike = globalThis.fetch,
|
|
51
|
-
): Promise<CodexDeviceStart> {
|
|
52
|
-
const response = await fetchFn(CODEX_DEVICE_USERCODE_URL, {
|
|
53
|
-
method: "POST",
|
|
54
|
-
headers: jsonHeaders(),
|
|
55
|
-
body: JSON.stringify({ client_id: clientId }),
|
|
56
|
-
});
|
|
57
|
-
if (!response.ok) throw new Error(`Codex device authorization failed (${response.status})`);
|
|
58
|
-
const body = (await response.json()) as DeviceUserCodeResponse;
|
|
59
|
-
if (typeof body.device_auth_id !== "string" || typeof body.user_code !== "string")
|
|
60
|
-
throw new Error("Codex device authorization returned an invalid response");
|
|
61
|
-
const interval =
|
|
62
|
-
typeof body.interval === "number" && Number.isFinite(body.interval)
|
|
63
|
-
? Math.max(0, body.interval)
|
|
64
|
-
: 5;
|
|
65
|
-
return { deviceAuthId: body.device_auth_id, userCode: body.user_code, intervalSeconds: interval };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* One device-token poll attempt.
|
|
70
|
-
*
|
|
71
|
-
* Returns `undefined` while the user has not approved yet (the endpoint answers
|
|
72
|
-
* 403/404) and the parsed PKCE pair once it has. Deliberately a single request:
|
|
73
|
-
* the dashboard owns the polling cadence, so the console route returns
|
|
74
|
-
* `pending` between attempts instead of holding one HTTP request open for the
|
|
75
|
-
* whole authorization window. A blocking loop here occupied a console worker
|
|
76
|
-
* for up to the full TTL and made the dialog's own interval meaningless.
|
|
77
|
-
*/
|
|
78
|
-
export async function pollCodexDeviceAuth(
|
|
79
|
-
device: CodexDeviceStart,
|
|
80
|
-
fetchFn: FetchLike = globalThis.fetch,
|
|
81
|
-
): Promise<CodexDeviceAuthorization | undefined> {
|
|
82
|
-
let response: Response;
|
|
83
|
-
try {
|
|
84
|
-
response = await fetchFn(CODEX_DEVICE_TOKEN_URL, {
|
|
85
|
-
method: "POST",
|
|
86
|
-
headers: jsonHeaders(),
|
|
87
|
-
body: JSON.stringify({ device_auth_id: device.deviceAuthId, user_code: device.userCode }),
|
|
88
|
-
});
|
|
89
|
-
} catch (error) {
|
|
90
|
-
// A network failure is not "not approved yet": surface it so the caller
|
|
91
|
-
// can return a failed verdict instead of polling to expiry.
|
|
92
|
-
throw new Error(`Codex device polling failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
-
}
|
|
94
|
-
// 403/404 are the endpoint's "not approved yet" answers, not failures.
|
|
95
|
-
if (response.status === 403 || response.status === 404) return undefined;
|
|
96
|
-
if (!response.ok) throw new Error(`Codex device polling failed (${response.status})`);
|
|
97
|
-
const body = (await response.json()) as DeviceTokenResponse;
|
|
98
|
-
if (typeof body.authorization_code === "string" && typeof body.code_verifier === "string")
|
|
99
|
-
return { authorizationCode: body.authorization_code, codeVerifier: body.code_verifier };
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
1
|
+
import type { FetchLike } from "../../authentication/oauth-client";
|
|
2
|
+
|
|
3
|
+
export const CODEX_DEVICE_USERCODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
|
|
4
|
+
export const CODEX_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Lifetime of one device authorization, in seconds.
|
|
8
|
+
*
|
|
9
|
+
* The Codex device endpoint states no expiry, so the flow bounds itself: this
|
|
10
|
+
* is both what `startDeviceAuth` reports to the dashboard (its own countdown)
|
|
11
|
+
* and what the poll checks before spending a request on a dead authorization.
|
|
12
|
+
*/
|
|
13
|
+
export const CODEX_DEVICE_TTL_SECONDS = 900;
|
|
14
|
+
|
|
15
|
+
interface CodexDeviceStart {
|
|
16
|
+
readonly deviceAuthId: string;
|
|
17
|
+
readonly userCode: string;
|
|
18
|
+
readonly intervalSeconds: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface CodexDeviceAuthorization {
|
|
22
|
+
readonly authorizationCode: string;
|
|
23
|
+
readonly codeVerifier: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Validates persisted provider-private device state read back from the flow store. */
|
|
27
|
+
export function parseCodexDeviceStart(value: Record<string, unknown>): CodexDeviceStart | undefined {
|
|
28
|
+
const { deviceAuthId, userCode, intervalSeconds } = value;
|
|
29
|
+
if (typeof deviceAuthId !== "string" || typeof userCode !== "string") return undefined;
|
|
30
|
+
if (typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds)) return undefined;
|
|
31
|
+
return { deviceAuthId, userCode, intervalSeconds: Math.max(0, intervalSeconds) };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface DeviceUserCodeResponse {
|
|
35
|
+
device_auth_id?: unknown;
|
|
36
|
+
user_code?: unknown;
|
|
37
|
+
interval?: unknown;
|
|
38
|
+
}
|
|
39
|
+
interface DeviceTokenResponse {
|
|
40
|
+
authorization_code?: unknown;
|
|
41
|
+
code_verifier?: unknown;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function jsonHeaders(): HeadersInit {
|
|
45
|
+
return { "content-type": "application/json", accept: "application/json" };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function startCodexDeviceAuth(
|
|
49
|
+
clientId: string,
|
|
50
|
+
fetchFn: FetchLike = globalThis.fetch,
|
|
51
|
+
): Promise<CodexDeviceStart> {
|
|
52
|
+
const response = await fetchFn(CODEX_DEVICE_USERCODE_URL, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: jsonHeaders(),
|
|
55
|
+
body: JSON.stringify({ client_id: clientId }),
|
|
56
|
+
});
|
|
57
|
+
if (!response.ok) throw new Error(`Codex device authorization failed (${response.status})`);
|
|
58
|
+
const body = (await response.json()) as DeviceUserCodeResponse;
|
|
59
|
+
if (typeof body.device_auth_id !== "string" || typeof body.user_code !== "string")
|
|
60
|
+
throw new Error("Codex device authorization returned an invalid response");
|
|
61
|
+
const interval =
|
|
62
|
+
typeof body.interval === "number" && Number.isFinite(body.interval)
|
|
63
|
+
? Math.max(0, body.interval)
|
|
64
|
+
: 5;
|
|
65
|
+
return { deviceAuthId: body.device_auth_id, userCode: body.user_code, intervalSeconds: interval };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* One device-token poll attempt.
|
|
70
|
+
*
|
|
71
|
+
* Returns `undefined` while the user has not approved yet (the endpoint answers
|
|
72
|
+
* 403/404) and the parsed PKCE pair once it has. Deliberately a single request:
|
|
73
|
+
* the dashboard owns the polling cadence, so the console route returns
|
|
74
|
+
* `pending` between attempts instead of holding one HTTP request open for the
|
|
75
|
+
* whole authorization window. A blocking loop here occupied a console worker
|
|
76
|
+
* for up to the full TTL and made the dialog's own interval meaningless.
|
|
77
|
+
*/
|
|
78
|
+
export async function pollCodexDeviceAuth(
|
|
79
|
+
device: CodexDeviceStart,
|
|
80
|
+
fetchFn: FetchLike = globalThis.fetch,
|
|
81
|
+
): Promise<CodexDeviceAuthorization | undefined> {
|
|
82
|
+
let response: Response;
|
|
83
|
+
try {
|
|
84
|
+
response = await fetchFn(CODEX_DEVICE_TOKEN_URL, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: jsonHeaders(),
|
|
87
|
+
body: JSON.stringify({ device_auth_id: device.deviceAuthId, user_code: device.userCode }),
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
// A network failure is not "not approved yet": surface it so the caller
|
|
91
|
+
// can return a failed verdict instead of polling to expiry.
|
|
92
|
+
throw new Error(`Codex device polling failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
// 403/404 are the endpoint's "not approved yet" answers, not failures.
|
|
95
|
+
if (response.status === 403 || response.status === 404) return undefined;
|
|
96
|
+
if (!response.ok) throw new Error(`Codex device polling failed (${response.status})`);
|
|
97
|
+
const body = (await response.json()) as DeviceTokenResponse;
|
|
98
|
+
if (typeof body.authorization_code === "string" && typeof body.code_verifier === "string")
|
|
99
|
+
return { authorizationCode: body.authorization_code, codeVerifier: body.code_verifier };
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
@@ -167,7 +167,7 @@ export async function mapCodexErrorResponse(res: Response): Promise<never> {
|
|
|
167
167
|
throw new GatewayError(
|
|
168
168
|
classification.code,
|
|
169
169
|
classification.status,
|
|
170
|
-
friendlyMessage ?? sanitized
|
|
170
|
+
`${friendlyMessage ?? sanitized} (request {requestId}). The upstream came back empty-handed — retry 🌙`,
|
|
171
171
|
details,
|
|
172
172
|
classification.origin,
|
|
173
173
|
);
|