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
|
@@ -5,24 +5,6 @@
|
|
|
5
5
|
// end-of-stream trailer. Compression and trailer semantics stay at the call
|
|
6
6
|
// sites; this module owns only the envelope arithmetic.
|
|
7
7
|
|
|
8
|
-
/** Payload is gzip-compressed. */
|
|
9
|
-
export const CONNECT_COMPRESSED_FLAG = 0x01;
|
|
10
|
-
/** Frame carries the end-of-stream trailer rather than a message. */
|
|
11
|
-
export const CONNECT_END_STREAM_FLAG = 0x02;
|
|
12
|
-
|
|
13
|
-
/** One decoded Connect envelope. */
|
|
14
|
-
interface ConnectFrame {
|
|
15
|
-
readonly flags: number;
|
|
16
|
-
readonly payload: Uint8Array;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface ConsumeConnectFramesOptions {
|
|
20
|
-
/** Reject frames whose declared payload exceeds this many bytes. */
|
|
21
|
-
readonly maxPayloadBytes?: number;
|
|
22
|
-
/** Builds the error thrown for an oversized frame; defaults to a plain `Error`. */
|
|
23
|
-
readonly oversizeError?: (declaredLength: number) => Error;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
8
|
/** Initial allocation for a frame buffer that has not received a chunk yet. */
|
|
27
9
|
const FRAME_BUFFER_MIN_BYTES = 4096;
|
|
28
10
|
/** Ceiling on the spare capacity kept above the live length when growing. */
|
|
@@ -84,39 +66,3 @@ export class FrameBuffer {
|
|
|
84
66
|
this.start = 0;
|
|
85
67
|
}
|
|
86
68
|
}
|
|
87
|
-
|
|
88
|
-
/** Wraps `payload` in a 5-byte Connect envelope. */
|
|
89
|
-
export function frameConnectMessage(payload: Uint8Array, flags = 0) {
|
|
90
|
-
const frame = Buffer.alloc(5 + payload.length);
|
|
91
|
-
frame.writeUInt8(flags, 0);
|
|
92
|
-
frame.writeUInt32BE(payload.length, 1);
|
|
93
|
-
frame.set(payload, 5);
|
|
94
|
-
return frame;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Splits every complete Connect frame out of `buffer`, in order. Returns the
|
|
99
|
-
* trailing bytes that do not yet form a complete frame so a streaming caller
|
|
100
|
-
* can prepend them to the next chunk and call again.
|
|
101
|
-
*/
|
|
102
|
-
export function consumeConnectFrames(
|
|
103
|
-
buffer: Buffer,
|
|
104
|
-
options: ConsumeConnectFramesOptions = {},
|
|
105
|
-
): { frames: ConnectFrame[]; rest: Buffer } {
|
|
106
|
-
const frames: ConnectFrame[] = [];
|
|
107
|
-
let pending = buffer;
|
|
108
|
-
while (pending.length >= 5) {
|
|
109
|
-
const flags = pending[0] ?? 0;
|
|
110
|
-
const length = pending.readUInt32BE(1);
|
|
111
|
-
if (options.maxPayloadBytes !== undefined && length > options.maxPayloadBytes) {
|
|
112
|
-
throw (
|
|
113
|
-
options.oversizeError?.(length) ??
|
|
114
|
-
new Error(`Connect frame length ${length} exceeds cap`)
|
|
115
|
-
);
|
|
116
|
-
}
|
|
117
|
-
if (pending.length < 5 + length) break;
|
|
118
|
-
frames.push({ flags, payload: pending.subarray(5, 5 + length) });
|
|
119
|
-
pending = pending.subarray(5 + length);
|
|
120
|
-
}
|
|
121
|
-
return { frames, rest: pending };
|
|
122
|
-
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 32-bit FNV-1a hash.
|
|
3
|
+
*
|
|
4
|
+
* Single source for the two former inline copies (claude `hashBody`,
|
|
5
|
+
* cursor `cursorAccountTag`). Fast, deterministic, sufficient for cache
|
|
6
|
+
* identity / short display tags — not a cryptographic hash.
|
|
7
|
+
*/
|
|
8
|
+
export function fnv1a32(input: string): number {
|
|
9
|
+
let hash = 0x811c9dc5;
|
|
10
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
11
|
+
hash ^= input.charCodeAt(index);
|
|
12
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
13
|
+
}
|
|
14
|
+
return hash >>> 0;
|
|
15
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Shared session-cache estimation factory.
|
|
2
|
+
//
|
|
3
|
+
// The Kiro and Trae adapters both need to ESTIMATE prompt-cache hits locally
|
|
4
|
+
// because their upstream surfaces never report them. Their logic is
|
|
5
|
+
// byte-identical modulo the provider header comment, so it lives here once —
|
|
6
|
+
// but the state must stay per-provider: a factory call creates a private Map
|
|
7
|
+
// per integration, so cross-provider session-id collisions can never
|
|
8
|
+
// contaminate each other's estimates. Call each provider's wrapper
|
|
9
|
+
// (kiro-cache.ts / trae-cache.ts); do not import this module directly.
|
|
10
|
+
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import type { CanonicalMessage, UsageRecord } from "../../../protocol/canonical-model";
|
|
13
|
+
|
|
14
|
+
/** Bounded in-memory tracker: one entry per session, oldest evicted first. */
|
|
15
|
+
export const SESSION_CACHE_MAX_SESSIONS = 512;
|
|
16
|
+
|
|
17
|
+
interface SessionCacheEntry {
|
|
18
|
+
/** hash(full messages) -> reported input tokens for that exact list. */
|
|
19
|
+
readonly seen: Map<string, number>;
|
|
20
|
+
/** Insertion order for bounded eviction. */
|
|
21
|
+
readonly order: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SessionCache {
|
|
25
|
+
estimate(
|
|
26
|
+
record: UsageRecord,
|
|
27
|
+
sessionId: string | undefined,
|
|
28
|
+
messages: readonly CanonicalMessage[] | undefined,
|
|
29
|
+
): UsageRecord;
|
|
30
|
+
resetForTesting(): void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function hashOf(messages: readonly CanonicalMessage[]): string {
|
|
34
|
+
return createHash("sha256").update(JSON.stringify(messages)).digest("hex");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Creates an isolated session-cache estimator: its own private session Map,
|
|
39
|
+
* bounded at SESSION_CACHE_MAX_SESSIONS with per-entry oldest-first eviction.
|
|
40
|
+
*/
|
|
41
|
+
export function createSessionCache(): SessionCache {
|
|
42
|
+
const sessions = new Map<string, SessionCacheEntry>();
|
|
43
|
+
|
|
44
|
+
function sessionFor(sessionId: string): SessionCacheEntry {
|
|
45
|
+
let entry = sessions.get(sessionId);
|
|
46
|
+
if (!entry) {
|
|
47
|
+
entry = { seen: new Map(), order: [] };
|
|
48
|
+
sessions.set(sessionId, entry);
|
|
49
|
+
}
|
|
50
|
+
return entry;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function remember(sessionId: string, fullHash: string, inputTokens: number): void {
|
|
54
|
+
const entry = sessionFor(sessionId);
|
|
55
|
+
if (!entry.seen.has(fullHash)) {
|
|
56
|
+
entry.order.push(fullHash);
|
|
57
|
+
if (entry.order.length > SESSION_CACHE_MAX_SESSIONS) {
|
|
58
|
+
const oldest = entry.order.shift();
|
|
59
|
+
if (oldest !== undefined) entry.seen.delete(oldest);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
entry.seen.set(fullHash, inputTokens);
|
|
63
|
+
if (sessions.size > SESSION_CACHE_MAX_SESSIONS) {
|
|
64
|
+
const oldestSession = sessions.keys().next().value;
|
|
65
|
+
if (oldestSession !== undefined) sessions.delete(oldestSession);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
estimate(record, sessionId, messages) {
|
|
71
|
+
if (!sessionId || !messages || messages.length === 0) return record;
|
|
72
|
+
const upstreamReported =
|
|
73
|
+
typeof record.cached_input_tokens === "number" && record.cached_input_tokens > 0;
|
|
74
|
+
if (upstreamReported) return record;
|
|
75
|
+
|
|
76
|
+
const fullHash = hashOf(messages);
|
|
77
|
+
const entry = sessions.get(sessionId);
|
|
78
|
+
|
|
79
|
+
if (entry) {
|
|
80
|
+
// Longest prefix that matches a previously sent complete request.
|
|
81
|
+
for (let len = messages.length; len >= 1; len -= 1) {
|
|
82
|
+
const prefix = messages.slice(0, len);
|
|
83
|
+
const tokens = entry.seen.get(hashOf(prefix));
|
|
84
|
+
if (tokens === undefined) continue;
|
|
85
|
+
if (len === messages.length) {
|
|
86
|
+
// Byte-identical request: the whole input came from cache.
|
|
87
|
+
return {
|
|
88
|
+
...record,
|
|
89
|
+
cached_input_tokens: record.input_tokens,
|
|
90
|
+
uncached_input_tokens: 0,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const cached = Math.min(tokens, record.input_tokens);
|
|
94
|
+
return {
|
|
95
|
+
...record,
|
|
96
|
+
cached_input_tokens: cached,
|
|
97
|
+
uncached_input_tokens: Math.max(0, record.input_tokens - cached),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
remember(sessionId, fullHash, record.input_tokens);
|
|
103
|
+
return record;
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
resetForTesting() {
|
|
107
|
+
sessions.clear();
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Estimates how much of this request's input was served from cache.
|
|
114
|
+
*
|
|
115
|
+
* The longest prefix of `messages` that was ever sent as a complete request in
|
|
116
|
+
* this session is considered cached, and its recorded token count is the
|
|
117
|
+
* cached portion — if that prefix is the whole request, everything was cached.
|
|
118
|
+
* This models how upstream prompt caching actually behaves (byte-identical
|
|
119
|
+
* prefix reuse) without trusting a counter the upstream never reports.
|
|
120
|
+
*
|
|
121
|
+
* Returns the record unchanged when there is nothing to estimate (no session,
|
|
122
|
+
* no history, or upstream already reported a real hit).
|
|
123
|
+
*/
|
|
124
|
+
export function estimateSessionCache(
|
|
125
|
+
cache: SessionCache,
|
|
126
|
+
record: UsageRecord,
|
|
127
|
+
sessionId: string | undefined,
|
|
128
|
+
messages: readonly CanonicalMessage[] | undefined,
|
|
129
|
+
): UsageRecord {
|
|
130
|
+
return cache.estimate(record, sessionId, messages);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Drops all tracked sessions in this cache. Test-only. */
|
|
134
|
+
export function resetSessionCacheForTesting(cache: SessionCache): void {
|
|
135
|
+
cache.resetForTesting();
|
|
136
|
+
}
|
|
@@ -71,11 +71,11 @@ export const TOKENHARBOR_FALLBACK_MODELS: readonly ModelDefinition[] = [
|
|
|
71
71
|
function tokenharborPrePayload(payload: Record<string, unknown>): void {
|
|
72
72
|
const model = payload["model"];
|
|
73
73
|
if (typeof model !== "string" || model.length === 0) {
|
|
74
|
-
throw new GatewayError("invalid_request", 400, "TokenHarbor model is required");
|
|
74
|
+
throw new GatewayError("invalid_request", 400, "TokenHarbor model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
75
75
|
}
|
|
76
76
|
// Strip accidental query-string smuggling (mirrors the factory's own guard)
|
|
77
77
|
if (model.includes("?")) {
|
|
78
|
-
throw new GatewayError("invalid_request", 400, "TokenHarbor model must not contain query string");
|
|
78
|
+
throw new GatewayError("invalid_request", 400, "TokenHarbor model must not contain query string (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -7,104 +7,24 @@
|
|
|
7
7
|
// conversation we ESTIMATE the hit locally. This only fills the gap when
|
|
8
8
|
// upstream reports nothing (0 or unavailable); a genuine upstream report (>0)
|
|
9
9
|
// is trusted and left untouched.
|
|
10
|
+
//
|
|
11
|
+
// The state lives in a factory-created instance, so Trae's sessions are fully
|
|
12
|
+
// isolated from Kiro's (and any other consumer of the shared factory).
|
|
10
13
|
|
|
11
|
-
import { createHash } from "node:crypto";
|
|
12
14
|
import type { CanonicalMessage, UsageRecord } from "../../../protocol/canonical-model";
|
|
15
|
+
import { createSessionCache, estimateSessionCache, resetSessionCacheForTesting } from "../shared/session-cache";
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
const MAX_SESSIONS = 512;
|
|
16
|
-
|
|
17
|
-
interface TraeSessionCacheEntry {
|
|
18
|
-
/** hash(full messages) -> reported input tokens for that exact list. */
|
|
19
|
-
readonly seen: Map<string, number>;
|
|
20
|
-
/** Insertion order for bounded eviction. */
|
|
21
|
-
readonly order: string[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const sessions = new Map<string, TraeSessionCacheEntry>();
|
|
17
|
+
const cache = createSessionCache();
|
|
25
18
|
|
|
26
|
-
function hashOf(messages: readonly CanonicalMessage[]): string {
|
|
27
|
-
return createHash("sha256").update(JSON.stringify(messages)).digest("hex");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function sessionFor(sessionId: string): TraeSessionCacheEntry {
|
|
31
|
-
let entry = sessions.get(sessionId);
|
|
32
|
-
if (!entry) {
|
|
33
|
-
entry = { seen: new Map(), order: [] };
|
|
34
|
-
sessions.set(sessionId, entry);
|
|
35
|
-
}
|
|
36
|
-
return entry;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function remember(sessionId: string, fullHash: string, inputTokens: number): void {
|
|
40
|
-
const entry = sessionFor(sessionId);
|
|
41
|
-
if (!entry.seen.has(fullHash)) {
|
|
42
|
-
entry.order.push(fullHash);
|
|
43
|
-
if (entry.order.length > MAX_SESSIONS) {
|
|
44
|
-
const oldest = entry.order.shift();
|
|
45
|
-
if (oldest !== undefined) entry.seen.delete(oldest);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
entry.seen.set(fullHash, inputTokens);
|
|
49
|
-
if (sessions.size > MAX_SESSIONS) {
|
|
50
|
-
const oldestSession = sessions.keys().next().value;
|
|
51
|
-
if (oldestSession !== undefined) sessions.delete(oldestSession);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Estimates how much of this request's input was served from cache.
|
|
57
|
-
*
|
|
58
|
-
* The longest prefix of `messages` that was ever sent as a complete request in
|
|
59
|
-
* this session is considered cached, and its recorded token count is the
|
|
60
|
-
* cached portion — if that prefix is the whole request, everything was cached.
|
|
61
|
-
* This models how upstream prompt caching actually behaves (byte-identical
|
|
62
|
-
* prefix reuse) without trusting a counter the upstream never reports.
|
|
63
|
-
*
|
|
64
|
-
* Returns the record unchanged when there is nothing to estimate (no session,
|
|
65
|
-
* no history, or upstream already reported a real hit).
|
|
66
|
-
*/
|
|
67
19
|
export function estimateTraeSessionCache(
|
|
68
20
|
record: UsageRecord,
|
|
69
21
|
sessionId: string | undefined,
|
|
70
22
|
messages: readonly CanonicalMessage[] | undefined,
|
|
71
23
|
): UsageRecord {
|
|
72
|
-
|
|
73
|
-
const upstreamReported =
|
|
74
|
-
typeof record.cached_input_tokens === "number" && record.cached_input_tokens > 0;
|
|
75
|
-
if (upstreamReported) return record;
|
|
76
|
-
|
|
77
|
-
const fullHash = hashOf(messages);
|
|
78
|
-
const entry = sessions.get(sessionId);
|
|
79
|
-
|
|
80
|
-
if (entry) {
|
|
81
|
-
// Longest prefix that matches a previously sent complete request.
|
|
82
|
-
for (let len = messages.length; len >= 1; len -= 1) {
|
|
83
|
-
const prefix = messages.slice(0, len);
|
|
84
|
-
const tokens = entry.seen.get(hashOf(prefix));
|
|
85
|
-
if (tokens === undefined) continue;
|
|
86
|
-
if (len === messages.length) {
|
|
87
|
-
// Byte-identical request: the whole input came from cache.
|
|
88
|
-
return {
|
|
89
|
-
...record,
|
|
90
|
-
cached_input_tokens: record.input_tokens,
|
|
91
|
-
uncached_input_tokens: 0,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
const cached = Math.min(tokens, record.input_tokens);
|
|
95
|
-
return {
|
|
96
|
-
...record,
|
|
97
|
-
cached_input_tokens: cached,
|
|
98
|
-
uncached_input_tokens: Math.max(0, record.input_tokens - cached),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
remember(sessionId, fullHash, record.input_tokens);
|
|
104
|
-
return record;
|
|
24
|
+
return estimateSessionCache(cache, record, sessionId, messages);
|
|
105
25
|
}
|
|
106
26
|
|
|
107
27
|
/** Drops all tracked sessions. Test-only. */
|
|
108
28
|
export function resetTraeSessionCacheForTesting(): void {
|
|
109
|
-
|
|
29
|
+
resetSessionCacheForTesting(cache);
|
|
110
30
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// intl stays on its static roster and says so via `modelListSupported`.
|
|
13
13
|
|
|
14
14
|
import { defineModel, type ModelDefinition } from "../../provider-model-definition";
|
|
15
|
-
import { TRAE_AGENT_CHAT_PATH, TRAE_CHAT_PATH
|
|
15
|
+
import { TRAE_AGENT_CHAT_PATH, TRAE_CHAT_PATH } from "./trae-realm";
|
|
16
16
|
|
|
17
17
|
/** One roster row, as upstream describes it. */
|
|
18
18
|
export interface TraeModelRow {
|
|
@@ -135,11 +135,6 @@ function traeModels(rows: readonly TraeModelRow[], providerId: string): readonly
|
|
|
135
135
|
export const TRAE_CN_MODELS: readonly ModelDefinition[] = traeModels(TRAE_CN_ROWS, "traecn");
|
|
136
136
|
export const TRAE_INTL_MODELS: readonly ModelDefinition[] = traeModels(TRAE_INTL_ROWS, "trae");
|
|
137
137
|
|
|
138
|
-
/** Roster for a realm. */
|
|
139
|
-
export function traeStaticModels(realm: TraeRealm): readonly ModelDefinition[] {
|
|
140
|
-
return realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
138
|
/**
|
|
144
139
|
* Reads the largest context window out of one upstream model object.
|
|
145
140
|
*
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
// `iter_events` in `trae_client.py`).
|
|
14
14
|
|
|
15
15
|
import type { CanonicalRequest, ContentPart } from "../../../protocol/canonical-model";
|
|
16
|
+
import { resolveWireMaxTokens } from "../../../protocol/translation/quirks";
|
|
16
17
|
import {
|
|
17
18
|
TRAE_AGENT_CHAT_PATH,
|
|
18
19
|
TRAE_AGENT_FUNCTION,
|
|
19
20
|
TRAE_CHAT_PATH,
|
|
20
|
-
TRAE_MODEL_LIST_PATH,
|
|
21
21
|
TRAE_REALMS,
|
|
22
22
|
type TraeRealm,
|
|
23
23
|
} from "./trae-realm";
|
|
@@ -161,6 +161,7 @@ export function buildTraeChatBody(
|
|
|
161
161
|
request: CanonicalRequest,
|
|
162
162
|
realm: TraeRealm,
|
|
163
163
|
sessionId?: string,
|
|
164
|
+
maxOutputTokens?: number,
|
|
164
165
|
): TraeChatBody {
|
|
165
166
|
if (modelId.length === 0) throw new Error("trae model name is required");
|
|
166
167
|
|
|
@@ -257,13 +258,26 @@ export function buildTraeChatBody(
|
|
|
257
258
|
},
|
|
258
259
|
}));
|
|
259
260
|
}
|
|
261
|
+
const requestedMaxTokens =
|
|
262
|
+
typeof controls.max_tokens === "number" && Number.isFinite(controls.max_tokens)
|
|
263
|
+
? controls.max_tokens
|
|
264
|
+
: undefined;
|
|
260
265
|
const options: Record<string, unknown> = {
|
|
261
266
|
temperature: controls.temperature,
|
|
262
267
|
top_p: controls.top_p,
|
|
263
|
-
max_tokens: controls.max_tokens,
|
|
264
268
|
stop: controls.stop,
|
|
265
|
-
|
|
266
269
|
};
|
|
270
|
+
// Route a numeric `max_tokens` through the shared chat-wire bound so it is
|
|
271
|
+
// floored to the wire minimum and clamped to the model's roster output limit
|
|
272
|
+
// — it must never balloon unboundedly (the roster's `out` is the ceiling).
|
|
273
|
+
// Non-numeric values keep the previous verbatim passthrough, and an absent
|
|
274
|
+
// value still omits the field (the chat bound must not invent a default here).
|
|
275
|
+
options["max_tokens"] =
|
|
276
|
+
requestedMaxTokens === undefined
|
|
277
|
+
? controls.max_tokens
|
|
278
|
+
: resolveWireMaxTokens("chat", { max_tokens: requestedMaxTokens }, {
|
|
279
|
+
...(maxOutputTokens === undefined ? {} : { maxOutputTokens }),
|
|
280
|
+
});
|
|
267
281
|
for (const key of PASSTHROUGH_OPTIONS) {
|
|
268
282
|
const value = options[key];
|
|
269
283
|
if (value !== undefined && value !== null) body[key] = value;
|
|
@@ -272,13 +286,8 @@ export function buildTraeChatBody(
|
|
|
272
286
|
}
|
|
273
287
|
|
|
274
288
|
/** Body for the live model list. Upstream requires a body even to list. */
|
|
275
|
-
export function buildTraeModelListBody(): Record<string, unknown> {
|
|
276
|
-
return { type: "chat" };
|
|
277
|
-
}
|
|
278
|
-
|
|
279
289
|
export const TRAE_CHAT_ENDPOINT = TRAE_CHAT_PATH;
|
|
280
290
|
export const TRAE_AGENT_ENDPOINT = TRAE_AGENT_CHAT_PATH;
|
|
281
|
-
export const TRAE_MODEL_LIST_ENDPOINT = TRAE_MODEL_LIST_PATH;
|
|
282
291
|
|
|
283
292
|
/**
|
|
284
293
|
* Rewrites a chat-surface body into the agent surface's shape.
|
|
@@ -88,7 +88,6 @@ export const TRAE_AUTH_CODE_EXCHANGE_PATHS: readonly string[] = [
|
|
|
88
88
|
"/trae/api/v3/oauth/ExchangeToken",
|
|
89
89
|
"/cloudide/api/v3/public/oauth/ExchangeToken",
|
|
90
90
|
];
|
|
91
|
-
export const TRAE_TEMP_TOKEN_PATH = "/cloudide/api/v3/trae/GenerateTempToken";
|
|
92
91
|
export const TRAE_GET_USER_INFO_PATH = "/cloudide/api/v3/trae/GetUserInfo";
|
|
93
92
|
|
|
94
93
|
/** Browser-login path on the host `GetLoginGuidance` names. */
|
|
@@ -123,13 +122,7 @@ export const TRAE_LOGIN_GUIDANCE_URLS: readonly string[] = [
|
|
|
123
122
|
|
|
124
123
|
/** Usage / entitlement paths, relative to the realm's `pay` host. */
|
|
125
124
|
export const TRAE_SESSION_USAGE_PATH = "/api/v1/commercial/get_session_usage";
|
|
126
|
-
export const TRAE_ACTIVITY_PATH = "/api/v1/commercial/get_user_activity";
|
|
127
125
|
export const TRAE_ENT_USAGE_PATH = "/trae/api/v1/pay/ide_user_ent_usage";
|
|
128
|
-
export const TRAE_PAY_STATUS_PATH = "/trae/api/v1/pay/ide_user_pay_status";
|
|
129
|
-
|
|
130
|
-
/** Growth paths, relative to the realm's `ug` host. CN-only upstream. */
|
|
131
|
-
export const TRAE_CHECKIN_STATUS_PATH = "/trae/api/v2/ug/checkin_credits/status";
|
|
132
|
-
export const TRAE_CHECKIN_CLAIM_PATH = "/trae/api/v2/ug/checkin_credits/claim";
|
|
133
126
|
|
|
134
127
|
/**
|
|
135
128
|
* Realm → deployment.
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import { GatewayError } from "../../../protocol/gateway-error";
|
|
8
8
|
import type { CanonicalEvent, CanonicalMessage, CanonicalRequest, CanonicalStopReason } from "../../../protocol/canonical-model";
|
|
9
9
|
import type { UsageRecord } from "../../../protocol/canonical-model";
|
|
10
|
-
import { usageFromProvider } from "../../provider-usage";
|
|
10
|
+
import { applyCacheMode, usageFromProvider } from "../../provider-usage";
|
|
11
11
|
import {
|
|
12
12
|
readCredentialSecret,
|
|
13
|
+
assertWireFamily,
|
|
13
14
|
type ProviderAdapter,
|
|
14
15
|
type ProviderDispatchContext,
|
|
15
16
|
type ProviderDispatchTarget,
|
|
@@ -67,7 +68,7 @@ const STOP_REASONS: Readonly<Record<string, CanonicalStopReason>> = {
|
|
|
67
68
|
function traeAuth(secret: string, accountId: string | undefined): TraeAuth {
|
|
68
69
|
const token = extractToken(secret);
|
|
69
70
|
if (token === undefined) {
|
|
70
|
-
throw new GatewayError("authentication_failed", 401, "Trae credential has no access token", {}, "upstream");
|
|
71
|
+
throw new GatewayError("authentication_failed", 401, "Trae credential has no access token (request {requestId}). Wrong key, right door — check the credential 🔑", {}, "upstream");
|
|
71
72
|
}
|
|
72
73
|
return { token, uid: accountId ?? "" };
|
|
73
74
|
}
|
|
@@ -102,7 +103,11 @@ function extractToken(secret: string): string | undefined {
|
|
|
102
103
|
* `quota_exceeded` 429, not a platform fault.
|
|
103
104
|
* - Everything else is a platform fault (`platform_unavailable`).
|
|
104
105
|
*/
|
|
105
|
-
function throwTraeUpstreamError(
|
|
106
|
+
function throwTraeUpstreamError(
|
|
107
|
+
codeRaw: unknown,
|
|
108
|
+
messageRaw: unknown,
|
|
109
|
+
providerId?: string,
|
|
110
|
+
): never {
|
|
106
111
|
const code =
|
|
107
112
|
typeof codeRaw === "number" || typeof codeRaw === "string" ? String(codeRaw) : undefined;
|
|
108
113
|
const message =
|
|
@@ -116,8 +121,13 @@ function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
|
|
|
116
121
|
throw new GatewayError(
|
|
117
122
|
"authentication_failed",
|
|
118
123
|
401,
|
|
119
|
-
`Trae could not authenticate the account (upstream code 1001): ${message}
|
|
120
|
-
{
|
|
124
|
+
`Trae could not authenticate the account (upstream code 1001): ${message} (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
125
|
+
{
|
|
126
|
+
providerCode: "1001",
|
|
127
|
+
providerStatus: 1001,
|
|
128
|
+
credentialEvidence: true,
|
|
129
|
+
...(providerId ? { providerId } : {}),
|
|
130
|
+
},
|
|
121
131
|
"upstream",
|
|
122
132
|
);
|
|
123
133
|
}
|
|
@@ -127,13 +137,39 @@ function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
|
|
|
127
137
|
throw new GatewayError(
|
|
128
138
|
"quota_exceeded",
|
|
129
139
|
429,
|
|
130
|
-
`Trae quota exceeded (upstream code ${code ?? "unknown"}): ${message}
|
|
131
|
-
{
|
|
140
|
+
`Trae quota exceeded (upstream code ${code ?? "unknown"}): ${message} (request {requestId}). You've maxed this window — pace yourself ⏳`,
|
|
141
|
+
{
|
|
142
|
+
providerCode: code ?? "4008",
|
|
143
|
+
providerStatus: code === "4008" ? 4008 : 429,
|
|
144
|
+
...(providerId ? { providerId } : {}),
|
|
145
|
+
},
|
|
132
146
|
"upstream",
|
|
133
147
|
);
|
|
134
148
|
}
|
|
135
149
|
|
|
136
|
-
|
|
150
|
+
// Trae answers `4013 "AI service is not available in the current region now."`
|
|
151
|
+
// when the upstream does not serve the account's region. That is a durable
|
|
152
|
+
// verdict, not a transient transport fault: the account reproduces it on
|
|
153
|
+
// every request until the region opens, so it must cool hard rather than be
|
|
154
|
+
// re-dialled every thirty seconds. The classifier scopes this to the account
|
|
155
|
+
// (`trae-region-unavailable`) — never the proxy pool.
|
|
156
|
+
if (code === "4013" || lower.includes("not available in the current region")) {
|
|
157
|
+
throw new GatewayError(
|
|
158
|
+
"platform_unavailable",
|
|
159
|
+
502,
|
|
160
|
+
message,
|
|
161
|
+
{ providerCode: "4013", ...(providerId ? { providerId } : {}) },
|
|
162
|
+
"upstream",
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
throw new GatewayError(
|
|
167
|
+
"platform_unavailable",
|
|
168
|
+
502,
|
|
169
|
+
message,
|
|
170
|
+
{ ...(providerId ? { providerId } : {}) },
|
|
171
|
+
"upstream",
|
|
172
|
+
);
|
|
137
173
|
}
|
|
138
174
|
|
|
139
175
|
class TraeAdapter implements ProviderAdapter {
|
|
@@ -152,11 +188,7 @@ class TraeAdapter implements ProviderAdapter {
|
|
|
152
188
|
context: ProviderDispatchContext,
|
|
153
189
|
): AsyncIterable<CanonicalEvent> {
|
|
154
190
|
if (candidate.wire_family !== "chat") {
|
|
155
|
-
|
|
156
|
-
"capability_unsupported",
|
|
157
|
-
400,
|
|
158
|
-
`trae supports chat only, got ${candidate.wire_family}`,
|
|
159
|
-
);
|
|
191
|
+
assertWireFamily(candidate, "chat", "trae");
|
|
160
192
|
}
|
|
161
193
|
const secret = readCredentialSecret(context.credential, "Trae credential is required");
|
|
162
194
|
const modelId = candidate.model_id || request.model;
|
|
@@ -175,7 +207,13 @@ class TraeAdapter implements ProviderAdapter {
|
|
|
175
207
|
* hash) and thread it through.
|
|
176
208
|
*/
|
|
177
209
|
const sessionId = request.session_id ?? resolvePromptCacheKey(request, context);
|
|
178
|
-
const body = buildTraeChatBody(
|
|
210
|
+
const body = buildTraeChatBody(
|
|
211
|
+
modelId,
|
|
212
|
+
request,
|
|
213
|
+
this.realm,
|
|
214
|
+
sessionId,
|
|
215
|
+
candidate.output_limit ?? undefined,
|
|
216
|
+
);
|
|
179
217
|
// The cache estimator is scoped per (session, model): upstream cache keys
|
|
180
218
|
// are model-specific, so two models sharing a conversation id must not
|
|
181
219
|
// treat each other's identical prefixes as hits.
|
|
@@ -214,7 +252,7 @@ class TraeAdapter implements ProviderAdapter {
|
|
|
214
252
|
});
|
|
215
253
|
if (!response.ok) throw await mapUpstreamHttpError(response, this.provider_id);
|
|
216
254
|
if (!response.body) {
|
|
217
|
-
throw new GatewayError("platform_unavailable", 502, "Trae returned empty body", {}, "upstream");
|
|
255
|
+
throw new GatewayError("platform_unavailable", 502, "Trae returned empty body (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
218
256
|
}
|
|
219
257
|
// Headers arrived, so the pre-stream deadline has served its purpose;
|
|
220
258
|
// from here the gateway's own stall watchdog governs the body.
|
|
@@ -270,7 +308,7 @@ class TraeAdapter implements ProviderAdapter {
|
|
|
270
308
|
}
|
|
271
309
|
if (frame.event === "error") {
|
|
272
310
|
const data = frame.data as { message?: unknown; code?: unknown };
|
|
273
|
-
throwTraeUpstreamError(data.code, data.message);
|
|
311
|
+
throwTraeUpstreamError(data.code, data.message, this.provider_id);
|
|
274
312
|
}
|
|
275
313
|
if (typeof frame.data !== "object" || frame.data === null) continue;
|
|
276
314
|
const record = frame.data as Record<string, unknown>;
|
|
@@ -283,7 +321,7 @@ class TraeAdapter implements ProviderAdapter {
|
|
|
283
321
|
const nested = record["error"] as Record<string, unknown> | undefined;
|
|
284
322
|
const code = record["code"] ?? nested?.["code"];
|
|
285
323
|
const message = record["message"] ?? nested?.["message"];
|
|
286
|
-
throwTraeUpstreamError(code, message);
|
|
324
|
+
throwTraeUpstreamError(code, message, this.provider_id);
|
|
287
325
|
}
|
|
288
326
|
/**
|
|
289
327
|
* Two frame layouts reach here and both are live.
|
|
@@ -441,8 +479,10 @@ class TraeAdapter implements ProviderAdapter {
|
|
|
441
479
|
const record = usageFromProvider(usage);
|
|
442
480
|
if (record === undefined) return undefined;
|
|
443
481
|
// Trae's agent surface never reports prompt-cache hits; for repeated
|
|
444
|
-
// prefixes we estimate them locally (see trae-cache.ts).
|
|
445
|
-
|
|
482
|
+
// prefixes we estimate them locally (see trae-cache.ts). Then the
|
|
483
|
+
// operator's cache mode decides whether a hit makes the whole input count
|
|
484
|
+
// as cached.
|
|
485
|
+
return applyCacheMode(estimateTraeSessionCache(record, sessionId, messages));
|
|
446
486
|
}
|
|
447
487
|
|
|
448
488
|
}
|
|
@@ -44,10 +44,10 @@ const XAI_AUTH_SERVER = {
|
|
|
44
44
|
} as const;
|
|
45
45
|
|
|
46
46
|
export { XAI_AUTH_SERVER };
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const XAI_CLIENT_ID = XAI_AUTH_SERVER.clientId;
|
|
48
|
+
const XAI_DEVICE_URL = XAI_AUTH_SERVER.deviceUrl;
|
|
49
|
+
const XAI_TOKEN_URL = XAI_AUTH_SERVER.tokenUrl;
|
|
50
|
+
const XAI_USERINFO_URL = XAI_AUTH_SERVER.userinfoUrl;
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* Scopes the subscription token needs.
|
|
@@ -56,7 +56,7 @@ export const XAI_USERINFO_URL = XAI_AUTH_SERVER.userinfoUrl;
|
|
|
56
56
|
* what admits the token to `api.x.ai`. The rest are the OIDC identity scopes the
|
|
57
57
|
* userinfo label is read from.
|
|
58
58
|
*/
|
|
59
|
-
|
|
59
|
+
const XAI_SCOPE = [
|
|
60
60
|
"openid",
|
|
61
61
|
"profile",
|
|
62
62
|
"email",
|
|
@@ -78,7 +78,7 @@ function unwrapEnvelope(body: unknown, operation: string): unknown {
|
|
|
78
78
|
// codebase is 401. A 400 told the client to fix its body when the real
|
|
79
79
|
// action is to fix the credential — and HTTP itself reserves 401 for
|
|
80
80
|
// exactly this, so a standard client reads the class from the status.
|
|
81
|
-
throw new GatewayError("authentication_failed", 401, `Z.AI ${message}
|
|
81
|
+
throw new GatewayError("authentication_failed", 401, `Z.AI ${message} (request {requestId}). Wrong key, right door — check the credential 🔑`, { providerId: "zcode" });
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
return root.data ?? body;
|