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
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Canonical → Claude Messages request builder.
|
|
3
3
|
*/
|
|
4
4
|
import { allParts, type CanonicalRequest, type ContentPart } from "../canonical-model";
|
|
5
|
+
import type { DialectPolicy } from "../translation/dialect/types";
|
|
5
6
|
import { buildAnthropicThinkingPayload } from "../../protocol/reasoning";
|
|
6
7
|
import { anthropicCacheControl } from "../../protocol/translation/cache-controls";
|
|
7
8
|
import {
|
|
@@ -28,14 +29,17 @@ import {
|
|
|
28
29
|
} from "../codecs";
|
|
29
30
|
import { log } from "../../observability/logger";
|
|
30
31
|
import { base64DecodedByteLength, clampImage } from "../image-clamp";
|
|
31
|
-
import {
|
|
32
|
+
import { LEVEL_TO_BUDGET } from "../../protocol/translation/thinking";
|
|
33
|
+
import type { ThinkingConfig } from "../../protocol/translation/dialect/thinking-ladder";
|
|
34
|
+
import { clampThinkingLevelForModel } from "../../protocol/translation/dialect/model-thinking";
|
|
35
|
+
import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
|
|
32
36
|
import { claudeResponseToEvents, parseClaudeSseStream } from "../response/messages";
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
39
|
* Gateway default when the caller sent no max_tokens (Anthropic requires
|
|
36
40
|
* the field). Explicit and warned at the call site — never silent.
|
|
37
41
|
*/
|
|
38
|
-
|
|
42
|
+
const ANTHROPIC_DEFAULT_MAX_TOKENS = WIRE_TOKEN_BOUNDS["messages"]?.defaultMaxTokens ?? 4_096;
|
|
39
43
|
|
|
40
44
|
/** Anthropic Messages' documented base64-image media-type allowlist. */
|
|
41
45
|
const ANTHROPIC_IMAGE_MEDIA_TYPES = new Set([
|
|
@@ -556,7 +560,13 @@ export function claudeFallbacksChain(
|
|
|
556
560
|
|
|
557
561
|
export function canonicalToClaudeMessagesPayload(
|
|
558
562
|
request: CanonicalRequest,
|
|
559
|
-
options: {
|
|
563
|
+
options: {
|
|
564
|
+
isOAuth?: boolean;
|
|
565
|
+
maxBytesOverride?: number;
|
|
566
|
+
dialectPolicy?: DialectPolicy;
|
|
567
|
+
thinking?: ThinkingConfig;
|
|
568
|
+
maxOutputTokens?: number;
|
|
569
|
+
} = {},
|
|
560
570
|
): ClaudeWireObject {
|
|
561
571
|
const seen = new Map<string, number>();
|
|
562
572
|
const idMap = new Map<string, string>();
|
|
@@ -653,7 +663,11 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
653
663
|
const normalizedControls = normalizeWireMaxTokens(request.generation_controls);
|
|
654
664
|
const requestedMax = normalizedControls.max_tokens;
|
|
655
665
|
const hasTools = (request.tools?.length ?? 0) > 0;
|
|
656
|
-
let maxTokens = resolveWireMaxTokens("messages", { max_tokens: requestedMax }, {
|
|
666
|
+
let maxTokens = resolveWireMaxTokens("messages", { max_tokens: requestedMax }, {
|
|
667
|
+
hasTools,
|
|
668
|
+
isOAuth,
|
|
669
|
+
...(options.maxOutputTokens === undefined ? {} : { maxOutputTokens: options.maxOutputTokens }),
|
|
670
|
+
}) ?? ANTHROPIC_DEFAULT_MAX_TOKENS;
|
|
657
671
|
if (requestedMax === undefined) {
|
|
658
672
|
log.warn("claude: max_tokens absent, defaulting", {
|
|
659
673
|
max_tokens: maxTokens,
|
|
@@ -665,21 +679,32 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
665
679
|
});
|
|
666
680
|
}
|
|
667
681
|
const thinkingEnabled = isThinkingEnabled(request);
|
|
682
|
+
// Real ceilings (P2-12): an impossible thinking budget surfaces as a typed
|
|
683
|
+
// local 400 instead of an over-ceiling max_tokens that 400s opaquely upstream.
|
|
684
|
+
// Non-OAuth caps at the model's catalog output limit (when known) so the
|
|
685
|
+
// thinking guard can fire instead of shipping an over-catalog-limit
|
|
686
|
+
// `max_tokens`; OAuth keeps its own ceiling per the table.
|
|
687
|
+
const maxAllowed = isOAuth
|
|
688
|
+
? WIRE_TOKEN_BOUNDS["messages"]?.oauthCeiling ?? Number.MAX_SAFE_INTEGER
|
|
689
|
+
: options.maxOutputTokens ?? Number.MAX_SAFE_INTEGER;
|
|
668
690
|
if (thinkingEnabled && request.reasoning?.budget_tokens !== undefined) {
|
|
669
691
|
maxTokens = ensureMaxTokensForThinking(
|
|
670
692
|
maxTokens,
|
|
671
693
|
request.reasoning.budget_tokens,
|
|
672
|
-
|
|
694
|
+
maxAllowed,
|
|
673
695
|
);
|
|
674
696
|
}
|
|
675
697
|
// Whether this model speaks adaptive thinking (`type: "adaptive"` +
|
|
676
698
|
// `output_config.effort`) or budget thinking (`type: "enabled"` +
|
|
677
699
|
// `budget_tokens`). The two generations reject each other's shape, so the
|
|
678
|
-
// choice is made from the
|
|
679
|
-
// a chat/responses caller states only an effort, and a
|
|
680
|
-
// answers the adaptive shape with "adaptive thinking is not
|
|
681
|
-
// model" (verified live: opus-4-5/sonnet-4-5/haiku-4-5).
|
|
682
|
-
|
|
700
|
+
// choice is made from the resolved thinking config, not from the caller's
|
|
701
|
+
// canonical intent — a chat/responses caller states only an effort, and a
|
|
702
|
+
// budget-era model answers the adaptive shape with "adaptive thinking is not
|
|
703
|
+
// supported on this model" (verified live: opus-4-5/sonnet-4-5/haiku-4-5).
|
|
704
|
+
// When no config is supplied (direct-route callers), fall back to resolving
|
|
705
|
+
// it from the model/wire — the resolved `mode` IS the generation answer.
|
|
706
|
+
const resolvedThinking = options.thinking ?? resolveThinkingForModel(request.model, "", "messages");
|
|
707
|
+
const adaptiveThinking = resolvedThinking.mode === "anthropic-adaptive";
|
|
683
708
|
let effectiveBudgetTokens = request.reasoning?.budget_tokens;
|
|
684
709
|
// Derive a budget from the level whenever a budget-era model is asked to
|
|
685
710
|
// reason by effort alone. The gate is NOT `isThinkingEnabled`: a chat/responses
|
|
@@ -699,7 +724,13 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
699
724
|
if (!adaptiveThinking && effectiveBudgetTokens !== undefined) {
|
|
700
725
|
// The upstream requires the budget to stay below `max_tokens`; raise
|
|
701
726
|
// max_tokens to leave room for the answer rather than let it 400.
|
|
702
|
-
maxTokens = ensureMaxTokensForThinking(maxTokens, effectiveBudgetTokens,
|
|
727
|
+
maxTokens = ensureMaxTokensForThinking(maxTokens, effectiveBudgetTokens, maxAllowed);
|
|
728
|
+
}
|
|
729
|
+
// Final clamp to the model's catalog output limit: thinking may have raised
|
|
730
|
+
// `max_tokens` (e.g. under an OAuth ceiling wider than the catalog limit), so
|
|
731
|
+
// the value that ships must never exceed what the model can actually emit.
|
|
732
|
+
if (options.maxOutputTokens !== undefined && maxTokens > options.maxOutputTokens) {
|
|
733
|
+
maxTokens = options.maxOutputTokens;
|
|
703
734
|
}
|
|
704
735
|
const payload: ClaudeWireObject = {
|
|
705
736
|
model: request.model,
|
|
@@ -748,7 +779,8 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
748
779
|
}
|
|
749
780
|
const parallelToolCallsDisabled =
|
|
750
781
|
request.generation_controls.parallel_tool_calls === false;
|
|
751
|
-
|
|
782
|
+
const supportsToolChoice = options.dialectPolicy?.supportsToolChoice ?? true;
|
|
783
|
+
if (supportsToolChoice && (rawToolChoice !== undefined || parallelToolCallsDisabled)) {
|
|
752
784
|
const baseChoice = rawToolChoice as Record<string, unknown> | undefined;
|
|
753
785
|
const choice: Record<string, unknown> = baseChoice
|
|
754
786
|
? { ...baseChoice }
|
|
@@ -835,9 +867,9 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
835
867
|
// is NOT a wire field — display rides on `thinking.display` above.
|
|
836
868
|
// Clamp to the model's published ladder exactly like the chat/Responses
|
|
837
869
|
// codecs: an out-of-ladder tier is an upstream 4xx.
|
|
838
|
-
const effort =
|
|
870
|
+
const effort = clampThinkingLevelForModel(
|
|
871
|
+
resolvedThinking,
|
|
839
872
|
request.reasoning.effort,
|
|
840
|
-
resolveSupportedReasoningEfforts(request.model, "messages"),
|
|
841
873
|
);
|
|
842
874
|
const taskBudget = request.reasoning.task_budget;
|
|
843
875
|
// `output_config.effort` rides every generation: budget-era models accept it
|
|
@@ -7,10 +7,10 @@ import { markLatestBreakpoint } from "../../protocol/translation/cache-controls"
|
|
|
7
7
|
import { pickWireSupportedControls } from "../../protocol/translation/capabilities";
|
|
8
8
|
import { normalizeGenerationControls } from "../../protocol/translation/normalize";
|
|
9
9
|
import { resolveWireMaxTokens } from "../../protocol/translation/quirks";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "../../protocol/translation/thinking";
|
|
10
|
+
import type { DialectPolicy } from "../../protocol/translation/dialect/types";
|
|
11
|
+
import type { ThinkingConfig } from "../../protocol/translation/dialect/thinking-ladder";
|
|
12
|
+
import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
|
|
13
|
+
import { clampThinkingLevelForModel } from "../../protocol/translation/dialect/model-thinking";
|
|
14
14
|
import { isClaudeBillingHeaderText, resolveImageSource, resolveOutputVerbosity } from "../codecs";
|
|
15
15
|
import { resolvePromptCacheKey } from "../../providers/operations/session-resolution";
|
|
16
16
|
import { reasoningEffortFromIntent } from "../../protocol/reasoning";
|
|
@@ -27,7 +27,7 @@ const RESPONSES_CACHEABLE_BLOCK_TYPES: ReadonlySet<string> = new Set([
|
|
|
27
27
|
]);
|
|
28
28
|
|
|
29
29
|
/** Marks the latest stable input block with an explicit prompt-cache breakpoint. */
|
|
30
|
-
|
|
30
|
+
function markLatestResponsesCacheBreakpoint(input: Array<Record<string, unknown>>): void {
|
|
31
31
|
markLatestBreakpoint(input, {
|
|
32
32
|
isInputItem: (item) =>
|
|
33
33
|
item["type"] === "message" && (item["role"] === "user" || item["role"] === "developer"),
|
|
@@ -63,9 +63,13 @@ export function canonicalToResponsesPayload(
|
|
|
63
63
|
options: {
|
|
64
64
|
readonly supportsPromptCaching?: boolean;
|
|
65
65
|
readonly promptCacheKey?: string;
|
|
66
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
67
|
+
readonly thinking?: ThinkingConfig;
|
|
68
|
+
readonly maxOutputTokens?: number;
|
|
66
69
|
} = {},
|
|
67
70
|
): Record<string, unknown> {
|
|
68
71
|
const supportsPromptCaching = options.supportsPromptCaching ?? true;
|
|
72
|
+
const resolvedThinking = options.thinking ?? resolveThinkingForModel(request.model, "", "responses");
|
|
69
73
|
const input: Array<Record<string, unknown>> = [];
|
|
70
74
|
// `pending_safety_checks` have no canonical content-part representation, so
|
|
71
75
|
// `parseResponsesRequest` retains them per-item in the scoped item-metadata
|
|
@@ -317,10 +321,7 @@ export function canonicalToResponsesPayload(
|
|
|
317
321
|
// this wire. Codex already derives its tier this way.
|
|
318
322
|
const requestedEffort = reasoningEffortFromIntent(request.reasoning);
|
|
319
323
|
if (requestedEffort !== undefined) {
|
|
320
|
-
const effort =
|
|
321
|
-
requestedEffort,
|
|
322
|
-
resolveSupportedReasoningEfforts(request.model, "responses"),
|
|
323
|
-
);
|
|
324
|
+
const effort = clampThinkingLevelForModel(resolvedThinking, requestedEffort);
|
|
324
325
|
if (effort !== undefined) reasoning.effort = effort;
|
|
325
326
|
}
|
|
326
327
|
if (request.reasoning.mode !== undefined) reasoning.mode = request.reasoning.mode;
|
|
@@ -328,6 +329,12 @@ export function canonicalToResponsesPayload(
|
|
|
328
329
|
if (request.reasoning.summary_mode !== undefined)
|
|
329
330
|
reasoning.summary = request.reasoning.summary_mode;
|
|
330
331
|
else if (request.reasoning.summary !== undefined) reasoning.summary = request.reasoning.summary;
|
|
332
|
+
else if (requestedEffort !== undefined) reasoning.summary = "detailed";
|
|
333
|
+
// When the caller asked for reasoning effort but expressed no summary
|
|
334
|
+
// preference, request a detailed summary. Upstreams (GitHub Copilot's
|
|
335
|
+
// gpt-6-luna etc.) only stream `reasoning_summary_text` when the request
|
|
336
|
+
// asks for it — without this the reasoning is present on the wire yet
|
|
337
|
+
// never reaches the client.
|
|
331
338
|
if (Object.keys(reasoning).length > 0) payload.reasoning = reasoning;
|
|
332
339
|
}
|
|
333
340
|
const picked = pickWireSupportedControls(normalizeGenerationControls(request.generation_controls), "responses");
|
|
@@ -338,7 +345,9 @@ export function canonicalToResponsesPayload(
|
|
|
338
345
|
// Resolved unconditionally so the wire's `defaultMaxTokens` applies: an
|
|
339
346
|
// omitted limit must reach the upstream as a real number, not as an absent
|
|
340
347
|
// field (see the worked "wkwk" case in the WIRE_TOKEN_BOUNDS comment).
|
|
341
|
-
const bounded = resolveWireMaxTokens("responses", { max_tokens: requested }
|
|
348
|
+
const bounded = resolveWireMaxTokens("responses", { max_tokens: requested }, {
|
|
349
|
+
...(options.maxOutputTokens === undefined ? {} : { maxOutputTokens: options.maxOutputTokens }),
|
|
350
|
+
});
|
|
342
351
|
if (bounded !== undefined) picked["max_output_tokens"] = bounded;
|
|
343
352
|
Object.assign(payload, picked);
|
|
344
353
|
// Responses top-level params carried as `extension:responses.<field>` and
|
|
@@ -9,13 +9,15 @@ import { gatewayErrorFromStreamError } from "../stream-error-frames";
|
|
|
9
9
|
import { mergeResponsesUsage } from "./responses";
|
|
10
10
|
import { usageFromProvider, readReasoningText } from "../../providers/provider-usage";
|
|
11
11
|
import { createToolEmitLedger } from "../tool-identity";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { ThinkSplitter, stripThinkingTags } from "../think-split";
|
|
13
|
+
import { DsmlStreamParser, parseDsmlToolCalls } from "../dsml";
|
|
14
14
|
import {
|
|
15
15
|
OmpToolCallMarkupParser,
|
|
16
16
|
parseOmpToolCallMarkup,
|
|
17
17
|
type OmpTextToolCall,
|
|
18
18
|
} from "./omp-tool-call-markup";
|
|
19
|
+
import type { DialectPolicy } from "../translation/dialect/types";
|
|
20
|
+
import { QwenToolCallScanner } from "../translation/dialect/qwen";
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
export function mapChatStopReason(
|
|
@@ -83,11 +85,16 @@ export function parseChatResponseToEvents(
|
|
|
83
85
|
const contentWithoutMarkup = recoveredMarkup?.text ?? content;
|
|
84
86
|
const recovered =
|
|
85
87
|
typeof contentWithoutMarkup === "string"
|
|
86
|
-
? parseDsmlToolCalls(contentWithoutMarkup, declaredToolNames)
|
|
88
|
+
? parseDsmlToolCalls(contentWithoutMarkup, { allowedNames: declaredToolNames })
|
|
87
89
|
: undefined;
|
|
88
|
-
const visible =
|
|
90
|
+
const visible =
|
|
91
|
+
recovered === undefined
|
|
92
|
+
? contentWithoutMarkup
|
|
93
|
+
: "text" in recovered
|
|
94
|
+
? recovered.text
|
|
95
|
+
: recovered.clean;
|
|
89
96
|
if (typeof visible === "string" && visible.includes("<think")) {
|
|
90
|
-
const think = new
|
|
97
|
+
const think = new ThinkSplitter();
|
|
91
98
|
const split = think.push(visible);
|
|
92
99
|
const rest = think.flush();
|
|
93
100
|
const reasoning = `${split.reasoning}${rest.reasoning}`;
|
|
@@ -237,10 +244,12 @@ export async function* decodeChatSseStream(
|
|
|
237
244
|
body: ReadableStream<Uint8Array>,
|
|
238
245
|
request: CanonicalRequest,
|
|
239
246
|
signal?: AbortSignal,
|
|
247
|
+
options?: { readonly dialectPolicy?: DialectPolicy },
|
|
240
248
|
): AsyncIterable<CanonicalEvent> {
|
|
241
249
|
let seq = 1;
|
|
242
250
|
let finishReason: unknown;
|
|
243
251
|
let rawUsage: Record<string, unknown> | undefined;
|
|
252
|
+
const inbandDialect = options?.dialectPolicy?.inband;
|
|
244
253
|
// Last seen tool-call id (and name) per wire index. OpenAI streams the id
|
|
245
254
|
// (and name) only on the first fragment of each call; later fragments carry
|
|
246
255
|
// just `function.arguments`. Without this memory every continuation fragment
|
|
@@ -257,11 +266,11 @@ export async function* decodeChatSseStream(
|
|
|
257
266
|
const recoveredMarkupCalls: OmpTextToolCall[] = [];
|
|
258
267
|
// Single emission ledger: one entry per logical call.
|
|
259
268
|
const ledger = createToolEmitLedger();
|
|
260
|
-
const think = new
|
|
269
|
+
const think = new ThinkSplitter();
|
|
261
270
|
// Separate splitter for the reasoning channel: `reasoning_content` is its own
|
|
262
271
|
// stream, and interleaving it into the answer splitter would let a tag in one
|
|
263
272
|
// channel swallow the other's text.
|
|
264
|
-
const reasoningThink = new
|
|
273
|
+
const reasoningThink = new ThinkSplitter();
|
|
265
274
|
const declaredToolNames = declaredToolNamesForRequest(request);
|
|
266
275
|
const callableToolNames = callableToolNamesForRequest(request);
|
|
267
276
|
const contentMarkup =
|
|
@@ -269,7 +278,13 @@ export async function* decodeChatSseStream(
|
|
|
269
278
|
const reasoningMarkup =
|
|
270
279
|
(request.tools?.length ?? 0) > 0 ? new OmpToolCallMarkupParser(declaredToolNames) : undefined;
|
|
271
280
|
const dsmlMarkup =
|
|
272
|
-
(request.tools?.length ?? 0) > 0
|
|
281
|
+
(request.tools?.length ?? 0) > 0 && inbandDialect !== "qwen"
|
|
282
|
+
? new DsmlStreamParser({ allowedNames: declaredToolNames })
|
|
283
|
+
: undefined;
|
|
284
|
+
const qwenMarkup =
|
|
285
|
+
(request.tools?.length ?? 0) > 0 && inbandDialect === "qwen"
|
|
286
|
+
? new QwenToolCallScanner(declaredToolNames)
|
|
287
|
+
: undefined;
|
|
273
288
|
yield {
|
|
274
289
|
type: "response_start",
|
|
275
290
|
sequence_number: seq++,
|
|
@@ -315,7 +330,7 @@ export async function* decodeChatSseStream(
|
|
|
315
330
|
const raw = delta["content"] as string;
|
|
316
331
|
const markup = contentMarkup?.push(raw);
|
|
317
332
|
if (markup !== undefined) recoveredMarkupCalls.push(...markup.calls);
|
|
318
|
-
const recovered = dsmlMarkup?.push(markup?.text ?? raw);
|
|
333
|
+
const recovered = (qwenMarkup ?? dsmlMarkup)?.push(markup?.text ?? raw);
|
|
319
334
|
const visible = recovered?.text ?? markup?.text ?? raw;
|
|
320
335
|
const split = think.push(visible);
|
|
321
336
|
if (split.reasoning.length > 0) {
|
|
@@ -472,8 +487,8 @@ export async function* decodeChatSseStream(
|
|
|
472
487
|
"platform_unavailable",
|
|
473
488
|
502,
|
|
474
489
|
error instanceof Error
|
|
475
|
-
? `Malformed SSE event: ${error.message}
|
|
476
|
-
:
|
|
490
|
+
? `Malformed SSE event: ${error.message} (request {requestId}). The upstream sent something we can't read — retry 🌙`
|
|
491
|
+
: `Malformed SSE event (request {requestId}). The upstream sent something we can't read — retry 🌙`,
|
|
477
492
|
{},
|
|
478
493
|
"upstream",
|
|
479
494
|
);
|
|
@@ -500,7 +515,7 @@ export async function* decodeChatSseStream(
|
|
|
500
515
|
}
|
|
501
516
|
}
|
|
502
517
|
}
|
|
503
|
-
const dsmlMarkupTail = dsmlMarkup?.flush();
|
|
518
|
+
const dsmlMarkupTail = (qwenMarkup ?? dsmlMarkup)?.flush();
|
|
504
519
|
if (dsmlMarkupTail !== undefined) {
|
|
505
520
|
if (dsmlMarkupTail.text.length > 0) {
|
|
506
521
|
const split = think.push(dsmlMarkupTail.text);
|
|
@@ -15,7 +15,7 @@ import { usageFromProvider, readResponsesReasoningDelta } from '../../providers/
|
|
|
15
15
|
import { canonicalTerminal, decodeCodexToolCallId, isRecord, readOutputIndex } from '../codecs';
|
|
16
16
|
import { gatewayErrorFromStreamError } from '../stream-error-frames';
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
function mapCodexStopReason(
|
|
19
19
|
status: unknown,
|
|
20
20
|
hasToolCall: boolean,
|
|
21
21
|
endTurn?: unknown,
|
|
@@ -364,7 +364,7 @@ export class CodexStreamFrameProcessor {
|
|
|
364
364
|
throw new GatewayError(
|
|
365
365
|
"tool_call_loop_detected",
|
|
366
366
|
502,
|
|
367
|
-
"Codex whitespace-loop guard tripped: tool call emitted only whitespace argument deltas past the safety threshold",
|
|
367
|
+
"Codex whitespace-loop guard tripped (request {requestId}): tool call emitted only whitespace argument deltas past the safety threshold. Caught in a loop — breaking the cycle 🔁",
|
|
368
368
|
{ call_key: key, event_count: next.count, char_count: next.chars },
|
|
369
369
|
);
|
|
370
370
|
}
|
|
@@ -124,7 +124,7 @@ export function decodeGeminiStreamEvent(
|
|
|
124
124
|
throw new GatewayError(
|
|
125
125
|
"platform_unavailable",
|
|
126
126
|
502,
|
|
127
|
-
error instanceof Error ? `Malformed SSE event: ${error.message}
|
|
127
|
+
error instanceof Error ? `Malformed SSE event: ${error.message} (request {requestId}). The upstream sent something we can't read — retry 🌙` : `Malformed SSE event (request {requestId}). The upstream sent something we can't read — retry 🌙`,
|
|
128
128
|
{},
|
|
129
129
|
"upstream",
|
|
130
130
|
);
|
|
@@ -51,7 +51,7 @@ export function parseClaudeContent(value: unknown, isOAuth = false): ContentPart
|
|
|
51
51
|
throw new GatewayError(
|
|
52
52
|
"platform_unavailable",
|
|
53
53
|
502,
|
|
54
|
-
"Claude response tool_use is missing id or name",
|
|
54
|
+
"Claude response tool_use is missing id or name (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
55
55
|
{},
|
|
56
56
|
"upstream",
|
|
57
57
|
);
|
|
@@ -69,7 +69,7 @@ export function parseClaudeContent(value: unknown, isOAuth = false): ContentPart
|
|
|
69
69
|
throw new GatewayError(
|
|
70
70
|
"platform_unavailable",
|
|
71
71
|
502,
|
|
72
|
-
"Claude response tool_result is missing tool_use_id",
|
|
72
|
+
"Claude response tool_result is missing tool_use_id (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
73
73
|
{},
|
|
74
74
|
"upstream",
|
|
75
75
|
);
|
|
@@ -185,7 +185,7 @@ export function withClaudeFallbackSignal(
|
|
|
185
185
|
return { ...(stopDetails ?? {}), [CANONICAL_SERVED_BY_FALLBACK_KEY]: true };
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
|
|
188
|
+
function eventContent(
|
|
189
189
|
content: readonly ContentPart[],
|
|
190
190
|
sequence: number,
|
|
191
191
|
): { events: CanonicalEvent[]; sequence: number } {
|
|
@@ -467,7 +467,7 @@ export async function* parseClaudeSseStream(
|
|
|
467
467
|
throw new GatewayError(
|
|
468
468
|
"platform_unavailable",
|
|
469
469
|
502,
|
|
470
|
-
"Malformed Claude SSE event",
|
|
470
|
+
"Malformed Claude SSE event (request {requestId}). The upstream sent something we can't read — retry 🌙",
|
|
471
471
|
{},
|
|
472
472
|
"upstream",
|
|
473
473
|
);
|
|
@@ -476,7 +476,7 @@ export async function* parseClaudeSseStream(
|
|
|
476
476
|
throw new GatewayError(
|
|
477
477
|
"platform_unavailable",
|
|
478
478
|
502,
|
|
479
|
-
"Invalid Claude SSE event",
|
|
479
|
+
"Invalid Claude SSE event (request {requestId}). The upstream sent something we can't read — retry 🌙",
|
|
480
480
|
{},
|
|
481
481
|
"upstream",
|
|
482
482
|
);
|
|
@@ -492,7 +492,7 @@ export async function* parseClaudeSseStream(
|
|
|
492
492
|
throw new GatewayError(
|
|
493
493
|
"platform_unavailable",
|
|
494
494
|
502,
|
|
495
|
-
"Claude stream ended before message_stop",
|
|
495
|
+
"Claude stream ended before message_stop (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
496
496
|
{},
|
|
497
497
|
"upstream",
|
|
498
498
|
);
|
|
@@ -14,7 +14,7 @@ export interface OmpTextToolCall {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/** Text remaining after complete tool envelopes are removed. */
|
|
17
|
-
|
|
17
|
+
interface OmpTextToolCallResult {
|
|
18
18
|
readonly text: string;
|
|
19
19
|
readonly calls: readonly OmpTextToolCall[];
|
|
20
20
|
}
|
|
@@ -10,7 +10,7 @@ import { gatewayErrorFromStreamError } from "../stream-error-frames";
|
|
|
10
10
|
import { usageFromProvider, readResponsesReasoningDelta } from "../../providers/provider-usage";
|
|
11
11
|
import { createToolEmitLedger } from "../tool-identity";
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
function mapResponsesStopReason(
|
|
14
14
|
status: unknown,
|
|
15
15
|
hasToolCall: boolean,
|
|
16
16
|
): "stop" | "length" | "tool_use" | "error" | undefined {
|
|
@@ -336,8 +336,8 @@ export async function* decodeResponsesSseStream(
|
|
|
336
336
|
"platform_unavailable",
|
|
337
337
|
502,
|
|
338
338
|
error instanceof Error
|
|
339
|
-
? `Malformed SSE event: ${error.message}
|
|
340
|
-
:
|
|
339
|
+
? `Malformed SSE event: ${error.message} (request {requestId}). The upstream sent something we can't read — retry 🌙`
|
|
340
|
+
: `Malformed SSE event (request {requestId}). The upstream sent something we can't read — retry 🌙`,
|
|
341
341
|
{},
|
|
342
342
|
"upstream",
|
|
343
343
|
);
|
|
@@ -31,7 +31,7 @@ export interface SseEvent {
|
|
|
31
31
|
readonly data: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
interface SseDecodeOptions {
|
|
35
35
|
/**
|
|
36
36
|
* Max UTF-16 length of a single line; default equals `maxEventBytes`.
|
|
37
37
|
*
|
|
@@ -51,20 +51,57 @@ export interface SseDecodeOptions {
|
|
|
51
51
|
|
|
52
52
|
const DEFAULT_MAX_EVENT_BYTES = 4 * 1024 * 1024;
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* True when the accumulated data is a complete JSON value.
|
|
56
|
+
*
|
|
57
|
+
* Uses a bracket-depth scan that skips string contents (including escapes), so
|
|
58
|
+
* an inline `\n` or `\n\n` inside a string does not count as a structural
|
|
59
|
+
* terminator. A non-JSON payload (`[DONE]`, plain text) has depth 0 and reads
|
|
60
|
+
* as complete, so blank-line boundaries stay working for ordinary streams.
|
|
61
|
+
*/
|
|
62
|
+
function isCompleteJsonValue(data: string): boolean {
|
|
63
|
+
if (data.length === 0) return true;
|
|
64
|
+
let depth = 0;
|
|
65
|
+
let inString = false;
|
|
66
|
+
let escaped = false;
|
|
67
|
+
for (let i = 0; i < data.length; i += 1) {
|
|
68
|
+
const ch = data[i]!;
|
|
69
|
+
if (inString) {
|
|
70
|
+
if (escaped) {
|
|
71
|
+
escaped = false;
|
|
72
|
+
} else if (ch === "\\") {
|
|
73
|
+
escaped = true;
|
|
74
|
+
} else if (ch === '"') {
|
|
75
|
+
inString = false;
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (ch === '"') {
|
|
80
|
+
inString = true;
|
|
81
|
+
} else if (ch === "{" || ch === "[") {
|
|
82
|
+
depth += 1;
|
|
83
|
+
} else if (ch === "}" || ch === "]") {
|
|
84
|
+
depth -= 1;
|
|
85
|
+
if (depth < 0) return true; // trailing close: not a partial JSON prefix
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return depth <= 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
54
91
|
// A corrupt SSE stream is an upstream protocol failure, not a client mistake:
|
|
55
92
|
// labelling it `invalid_request` told the client its request was wrong and
|
|
56
93
|
// invited a retry of the identical request against a broken upstream. The
|
|
57
94
|
// `upstream` origin keeps the public envelope from prefixing it
|
|
58
95
|
// a gateway-branded message, which blamed the gateway for the provider's bytes.
|
|
59
96
|
function oversized(what: string): GatewayError {
|
|
60
|
-
return new GatewayError("platform_unavailable", 502, `SSE ${what} exceeds size bound
|
|
97
|
+
return new GatewayError("platform_unavailable", 502, `SSE ${what} exceeds size bound (request {requestId}). The upstream sent more than we can hold — retry 🌙`, {}, "upstream");
|
|
61
98
|
}
|
|
62
99
|
|
|
63
100
|
export async function* decodeSseEvents(
|
|
64
101
|
body: ReadableStream<Uint8Array> | null,
|
|
65
102
|
opts: SseDecodeOptions = {},
|
|
66
103
|
): AsyncIterable<SseEvent> {
|
|
67
|
-
if (body === null) throw new GatewayError("platform_unavailable", 502, "SSE response has no body", {}, "upstream");
|
|
104
|
+
if (body === null) throw new GatewayError("platform_unavailable", 502, "SSE response has no body (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
68
105
|
const maxEventBytes = opts.maxEventBytes ?? DEFAULT_MAX_EVENT_BYTES;
|
|
69
106
|
const maxLineBytes = opts.maxLineBytes ?? maxEventBytes;
|
|
70
107
|
const signal = opts.signal;
|
|
@@ -156,6 +193,18 @@ export async function* decodeSseEvents(
|
|
|
156
193
|
}
|
|
157
194
|
if (line.startsWith("id:") || line.startsWith("retry:")) return;
|
|
158
195
|
if (line.trim() === "") {
|
|
196
|
+
// A blank line is an SSE event boundary — but only when the payload
|
|
197
|
+
// accumulated so far is already a complete value. Some upstreams
|
|
198
|
+
// (Qoder IDE /model/v1) emit JSON that contains literal blank lines
|
|
199
|
+
// inside a string (`raw_usage` carries keys like
|
|
200
|
+
// `"data_policy_preferre\n\nnd_count"`). Treating that blank line as a
|
|
201
|
+
// boundary splits the JSON, leaves a dangling continuation, and throws
|
|
202
|
+
// "Malformed SSE line". When the open data is not yet a complete JSON
|
|
203
|
+
// value, append the blank line as a continuation instead.
|
|
204
|
+
if (dataLines.length > 0 && !isCompleteJsonValue(dataLines.join("\n"))) {
|
|
205
|
+
dataLines.push("");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
159
208
|
yield* dispatchEvent();
|
|
160
209
|
return;
|
|
161
210
|
}
|
|
@@ -163,7 +212,18 @@ export async function* decodeSseEvents(
|
|
|
163
212
|
// not 502 the request: only `event:`/`data:` carry payload, the rest is
|
|
164
213
|
// heartbeat/metadata. Unknown colon-prefixed fields are ignored.
|
|
165
214
|
if (/^[a-zA-Z0-9_-]+:/.test(line)) return;
|
|
166
|
-
|
|
215
|
+
// Some vendors (Qoder IDE /model/v1) emit a single `data:` event whose JSON
|
|
216
|
+
// payload contains literal newlines, so the event arrives as several lines:
|
|
217
|
+
// the first has the `data:` prefix, the rest are bare continuations. Treat
|
|
218
|
+
// a bare line as a continuation of the open `data:` event rather than a
|
|
219
|
+
// malformed stream. A bare line with no open data is still an error.
|
|
220
|
+
if (dataLines.length > 0) {
|
|
221
|
+
dataLines.push(line);
|
|
222
|
+
eventBytes += line.length;
|
|
223
|
+
if (eventBytes > maxEventBytes) throw oversized("event");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
throw new GatewayError("platform_unavailable", 502, "Malformed SSE line (request {requestId}). The upstream sent something we can't read — retry 🌙", {}, "upstream");
|
|
167
227
|
}
|
|
168
228
|
|
|
169
229
|
try {
|
|
@@ -35,14 +35,14 @@ const WIRE_STOP_REASONS = {
|
|
|
35
35
|
},
|
|
36
36
|
} satisfies Record<string, Record<CanonicalStopReason, string>>;
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
type StopReasonWireFamily = keyof typeof WIRE_STOP_REASONS;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Maps a canonical stop reason onto `wire`'s vocabulary, falling back when the
|
|
42
42
|
* terminal carried none: Chat has no null finish_reason and defaults to `stop`,
|
|
43
43
|
* while Messages omits `stop_reason` entirely.
|
|
44
44
|
*/
|
|
45
|
-
|
|
45
|
+
function canonicalStopReasonToWire(
|
|
46
46
|
wire: StopReasonWireFamily,
|
|
47
47
|
reason: CanonicalStopReason | undefined,
|
|
48
48
|
fallback: string,
|