cartethyia 2.7.3 → 2.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/README.md +17 -5
- package/dist/dashboard/assets/{BannedPage-2TJD37Hb.js → BannedPage-Cj15GsMp.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-xefJNRmJ.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.js → CliToolsPage-BIccZmeL.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-C4w7vea-.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BtPcAfot.js → ModelPicker-DnQPSIA8.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js +9 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-BQS0Rx_u.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-TP7voAQ0.js → StudioPage-BfAb5-o_.js} +3 -3
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C0YYuZJ4.js → assert-C0K-c4eo.js} +1 -1
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DMrMPmth.js → banner-BllT4LcF.js} +1 -1
- package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/{card-Be5Uzamx.js → card-CtkX66Wd.js} +1 -1
- package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-muFRphDu.js → cli-tools-CQXVMn4P.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DOfrVmsi.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-C9omdjQt.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bm8WKaGY.js → drawer-BrTEZ8zu.js} +1 -1
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/{entry-q5HwZ8nN.js → entry-EBHJ3DrE.js} +1 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-BTScrQpe.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-cPrX5vn6.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/{layout-C_7A6H55.js.gz → layout-CajrYUnD.js.gz} +0 -0
- package/dist/dashboard/assets/{list-row-CzFvogbj.js → list-row-Bx2I7XUe.js} +1 -1
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +1 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-JJGQm8TD.js → mutation-Rr0TIvcj.js} +1 -1
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CLaNz8Xz.js → query-keys-BloKtaXJ.js} +1 -1
- package/dist/dashboard/assets/query-keys-BloKtaXJ.js.gz +0 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/{routing-BEH32QOC.js → routing-in0f_IfK.js} +1 -1
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-B3iTetHN.js → select-BLULNqTp.js} +2 -2
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
- package/dist/dashboard/assets/{stack-KrOrm7JZ.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-DLS7IDMy.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.js → useMutation-m8WGNPrz.js} +1 -1
- package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +59 -57
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
- package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
- package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
- package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
- package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
- package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
- package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
- package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
- package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
- package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
- package/migrations/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +9 -10
- package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
- package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
- package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
- package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -0
- package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
- package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
- package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
- package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
- package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
- package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
- package/package.json +4 -5
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +67 -10
- package/src/boot/dependencies.ts +786 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +8 -4
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +13 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +26 -6
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +92 -31
- package/src/console/api-keys/routes.ts +131 -6
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +5 -5
- package/src/console/auth/audit-recorder.ts +1 -1
- package/src/console/auth/lockout.ts +7 -3
- package/src/console/auth/row-coercion.ts +57 -12
- package/src/console/auth/session-resolver.ts +1 -1
- package/src/console/auth/session-service.ts +8 -2
- package/src/console/auth/session.ts +40 -34
- package/src/console/auth/setup-service.ts +4 -3
- package/src/console/auth/user-store.ts +1 -1
- package/src/console/backup/9router-map.ts +0 -3
- package/src/console/backup/contracts.ts +11 -9
- package/src/console/backup/export-endpoint.ts +11 -12
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +32 -36
- package/src/console/backup/service.ts +468 -468
- package/src/console/backup/store.ts +47 -29
- package/src/console/backup/validate.ts +11 -1
- package/src/console/cli-tools/contracts.ts +7 -7
- package/src/console/cli-tools/injectors/cline.ts +110 -110
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/copilot.ts +108 -108
- package/src/console/cli-tools/injectors/driver.ts +247 -247
- package/src/console/cli-tools/injectors/jcode.ts +115 -115
- package/src/console/cli-tools/injectors/openclaw.ts +161 -161
- package/src/console/cli-tools/injectors/opencode.ts +153 -153
- package/src/console/cli-tools/routes.ts +4 -4
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +36 -4
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +18 -4
- package/src/console/inferhub/client.ts +0 -7
- package/src/console/inferhub/key-store.ts +1 -1
- package/src/console/inferhub/normalize.ts +2 -2
- package/src/console/inferhub/routes.ts +1 -1
- package/src/console/inferhub/types.ts +1 -1
- package/src/console/observability/contracts.ts +5 -1
- package/src/console/observability/live.ts +34 -21
- package/src/console/observability/logs.ts +4 -4
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +36 -20
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +82 -22
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +110 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +30 -6
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1662 -1292
- package/src/console/providers/detail/routes.ts +4 -4
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +95 -16
- package/src/console/quota/account-quota-global.ts +41 -3
- package/src/console/quota/account-quota-shared.ts +10 -3
- package/src/console/quota/account-quota-tenant.ts +285 -67
- package/src/console/quota/account-test-egress.ts +4 -4
- package/src/console/quota/daily-growth-job.ts +308 -0
- package/src/console/quota/native-identity.ts +2 -2
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/routes.ts +1 -1
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/contracts.ts +1 -1
- package/src/console/routing/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +13 -10
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/operations.ts +14 -7
- package/src/console/routing/pools/probe-verdict.ts +8 -3
- package/src/console/routing/pools/relay-deploy.ts +12 -12
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/routes.ts +3 -3
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +112 -44
- package/src/console/share/share-stats.ts +109 -39
- package/src/console/share/share-usage.ts +1 -1
- package/src/console/shared/errors.ts +2 -2
- package/src/console/shared/object.ts +18 -0
- package/src/console/shared/read-through-cache.ts +42 -6
- package/src/console/shared/transaction.ts +14 -0
- package/src/console/system-prompt/contracts.ts +89 -12
- package/src/console/system-prompt/routes.ts +98 -45
- package/src/console/updates/apply-update.ts +244 -0
- package/src/console/updates/routes.ts +256 -98
- package/src/main.ts +11 -5
- package/src/network/http2-bidi.ts +1 -1
- package/src/network/ip-utils.ts +298 -0
- package/src/network/outbound-fetch.ts +76 -5
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +55 -51
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +22 -2
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +24 -75
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +286 -214
- package/src/observability/log-sanitize.ts +1 -1
- package/src/observability/metrics.ts +4 -4
- package/src/observability/payload-capture.ts +6 -5
- package/src/observability/payload-store.ts +1 -1
- package/src/observability/runtime-metrics.ts +1 -1
- package/src/observability/telemetry-buffer.ts +12 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/telemetry-status.ts +1 -1
- package/src/observability/token-speed.ts +1 -1
- package/src/persistence/connection-url.ts +1 -1
- package/src/persistence/db-handle.ts +1 -1
- package/src/persistence/db-pg.ts +2 -2
- package/src/persistence/db-sqlite.ts +10 -5
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +19 -7
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +177 -45
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +109 -4
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/stores/telemetry-store.ts +1 -1
- package/src/persistence/system-prompt-store.ts +63 -18
- package/src/persistence/tenant-preferences.ts +1 -1
- package/src/persistence/ttl-cache.ts +3 -3
- package/src/persistence/usage-flush.ts +7 -2
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/codecs.ts +12 -16
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/image-generation.ts +2 -2
- package/src/protocol/reasoning-text.ts +1 -1
- package/src/protocol/reasoning.ts +7 -52
- package/src/protocol/registry.ts +50 -15
- package/src/protocol/request/chat.ts +46 -19
- package/src/protocol/request/codex.ts +1 -1
- package/src/protocol/request/messages.ts +46 -14
- package/src/protocol/request/responses.ts +19 -10
- package/src/protocol/response/chat.ts +27 -12
- package/src/protocol/response/codex.ts +2 -2
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +6 -6
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +3 -3
- package/src/protocol/sse-decoder.ts +64 -4
- package/src/protocol/stop-reason.ts +2 -2
- package/src/protocol/think-split.ts +347 -0
- package/src/protocol/translation/attachment-integrity.ts +3 -3
- package/src/protocol/translation/cache-controls.ts +8 -20
- package/src/protocol/translation/capabilities.ts +8 -8
- package/src/protocol/translation/dialect/deepseek.ts +10 -0
- package/src/protocol/translation/dialect/inband.ts +39 -0
- package/src/protocol/translation/dialect/model-thinking.ts +89 -0
- package/src/protocol/translation/dialect/qwen.ts +114 -0
- package/src/protocol/translation/dialect/resolver.ts +83 -0
- package/src/protocol/translation/dialect/rules.ts +93 -0
- package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
- package/src/protocol/translation/dialect/types.ts +58 -0
- package/src/protocol/translation/quirks.ts +18 -4
- package/src/protocol/translation/thinking.ts +12 -252
- package/src/protocol/translation/tool-id.ts +3 -3
- package/src/protocol/translation/tool-repair.ts +1 -1
- package/src/protocol/upstream/post-json.ts +6 -1
- package/src/protocol/upstream/send-claude-messages.ts +3 -3
- package/src/providers/adapters/base-adapter.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +44 -5
- package/src/providers/authentication/jwt-validator.ts +0 -5
- package/src/providers/authentication/oauth-client.ts +254 -253
- package/src/providers/authentication/oauth-flow-store.ts +42 -7
- package/src/providers/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/configured-provider.ts +1 -1
- package/src/providers/default-registry.ts +23 -35
- package/src/providers/discovery/catalog/catalog-format.ts +13 -2
- package/src/providers/discovery/discovery-types.ts +0 -1
- package/src/providers/discovery/openai-model-discovery.ts +2 -2
- package/src/providers/discovery/probe-phases.ts +50 -15
- package/src/providers/discovery/probing-service.ts +18 -20
- package/src/providers/integrations/agentrouter/agentrouter.ts +14 -5
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
- package/src/providers/integrations/antigravity/antigravity.ts +15 -26
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +2 -2
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +108 -1
- package/src/providers/integrations/buddy/buddy-media.ts +16 -16
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
- package/src/providers/integrations/buddy/codebuddy/provider.ts +5 -16
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -10
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/claude-credentials.ts +1 -1
- package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
- package/src/providers/integrations/claude/claude.ts +3 -10
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +76 -116
- package/src/providers/integrations/commandcode/quota.ts +132 -48
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -14
- package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
- package/src/providers/integrations/cursor/cursor-request.ts +0 -87
- package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
- package/src/providers/integrations/cursor/cursor.ts +53 -20
- package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
- package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
- package/src/providers/integrations/factory/factory.ts +13 -13
- package/src/providers/integrations/gemini.ts +11 -11
- package/src/providers/integrations/github/github-discovery.ts +55 -10
- package/src/providers/integrations/github/github-oauth.ts +6 -5
- package/src/providers/integrations/github/github.ts +47 -20
- package/src/providers/integrations/grok/grok-oauth.ts +261 -261
- package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
- package/src/providers/integrations/grok/grok-quota.ts +16 -7
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
- package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
- package/src/providers/integrations/grok/grok.ts +88 -42
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
- package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
- package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
- package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
- package/src/providers/integrations/kiro/kiro-request.ts +8 -11
- package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
- package/src/providers/integrations/kiro/kiro.ts +91 -78
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +132 -17
- package/src/providers/integrations/qoder/qoder-checkin.ts +26 -8
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +9 -8
- package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
- package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
- package/src/providers/integrations/qoder/qoder-realm.ts +22 -28
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +33 -38
- package/src/providers/integrations/qoder/qoder-virtual.ts +14 -2
- package/src/providers/integrations/qoder/qoder.ts +521 -63
- package/src/providers/integrations/shared/connect.ts +0 -54
- package/src/providers/integrations/shared/hash.ts +15 -0
- package/src/providers/integrations/shared/session-cache.ts +136 -0
- package/src/providers/integrations/tokenharbor.ts +2 -2
- package/src/providers/integrations/trae/trae-cache.ts +7 -87
- package/src/providers/integrations/trae/trae-catalog.ts +1 -6
- package/src/providers/integrations/trae/trae-protocol.ts +17 -8
- package/src/providers/integrations/trae/trae-realm.ts +0 -7
- package/src/providers/integrations/trae/trae.ts +59 -19
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
- package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
- package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
- package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
- package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
- package/src/providers/operations/account-error-classification.ts +131 -116
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/cli-platform.ts +31 -5
- package/src/providers/operations/client-version-resolver.ts +4 -6
- package/src/providers/operations/client-versions.ts +10 -7
- package/src/providers/operations/provider-catalog-seeder.ts +2 -0
- package/src/providers/operations/provider-catalog-service.ts +22 -6
- package/src/providers/operations/provider-credential-service.ts +35 -6
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +65 -10
- package/src/providers/provider-credential-resolver.ts +1 -1
- package/src/providers/provider-metadata.ts +17 -2
- package/src/providers/provider-model-definition.ts +22 -1
- package/src/providers/provider-probe.ts +4 -2
- package/src/providers/provider-registry.ts +4 -4
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +28 -10
- package/src/providers/quota/refresh.ts +29 -6
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +6 -8
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +8 -8
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +20 -8
- package/src/security/client-router-fingerprint.ts +4 -4
- package/src/security/credential-codec.ts +3 -3
- package/src/security/csrf.ts +2 -2
- package/src/security/ip-boundary.ts +16 -189
- package/src/security/model-access-rule.ts +1 -1
- package/src/security/outbound-headers.ts +18 -0
- package/src/shared/coerce.ts +19 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +5 -4
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +28 -25
- package/src/transport/dispatch/generation.ts +33 -53
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +10 -8
- package/src/transport/dispatch/responses-compact.ts +35 -56
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +11 -10
- package/src/transport/dispatch/streaming/stream.ts +7 -3
- package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
- package/src/transport/dispatch/systemone.ts +27 -55
- package/src/transport/dispatch/token-count.ts +49 -46
- package/src/transport/dispatch/websearch.ts +24 -50
- package/src/transport/drain-endpoint.ts +3 -3
- package/src/transport/failure-policy.ts +19 -6
- package/src/transport/guards/auth-guard.ts +6 -11
- package/src/transport/guards/body-policy.ts +7 -7
- package/src/transport/guards/error-lifecycle.ts +18 -3
- package/src/transport/guards/guard-errors.ts +7 -3
- package/src/transport/guards/headroom-guard.ts +2 -2
- package/src/transport/guards/pipeline.ts +7 -7
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +15 -20
- package/src/transport/request/preparer.ts +306 -27
- package/src/transport/request/rtk/compress-request.ts +3 -3
- package/src/transport/request/rtk/rtk-constants.ts +2 -2
- package/src/transport/request/rtk/rtk-filters.ts +8 -8
- package/src/transport/request/state.ts +5 -20
- package/src/transport/request/system-prompt-injection.ts +74 -11
- package/src/transport/request/tenant-preferences.ts +22 -0
- package/src/transport/routing/candidate-index.ts +2 -2
- package/src/transport/routing/round-robin.ts +1 -1
- package/src/transport/routing/route-catalog.ts +113 -19
- package/src/transport/routing/route-model.ts +131 -38
- package/src/transport/routing/router.ts +154 -39
- package/src/transport/shutdown-notice.ts +21 -9
- package/src/transport/surface/adapters.ts +3 -3
- package/src/transport/surface/chat/encode.ts +7 -7
- package/src/transport/surface/chat/parse.ts +7 -7
- package/src/transport/surface/completion.ts +3 -3
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/encode.ts +1 -1
- package/src/transport/surface/messages/parse.ts +3 -3
- package/src/transport/surface/responses/adapter.ts +1 -1
- package/src/transport/surface/responses/errors.ts +0 -9
- package/src/transport/vision-handoff-cache.ts +58 -0
- package/src/transport/vision-handoff.ts +376 -0
- package/src/workers/account-identity-sweep.ts +2 -2
- package/src/workers/buddy-growth-tasks.ts +392 -346
- package/src/workers/daily-checkin.ts +102 -49
- package/src/workers/maintenance-lease.ts +2 -35
- package/src/workers/oauth-refresh-sweep.ts +8 -1
- package/src/workers/quota-refresh-sweep.ts +120 -82
- package/src/workers/scheduler.ts +67 -4
- package/src/workers/sweep-runner.ts +24 -5
- package/src/workers/zcode-gift-claim.ts +108 -0
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-2TJD37Hb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js +0 -1
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +0 -9
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js +0 -1
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-BAL5npBC.js +0 -1
- package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js +0 -56
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js +0 -1
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
- package/dist/dashboard/assets/app-B2vyPoII.css +0 -2
- package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
- package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
- package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
- package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
- package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
- package/dist/dashboard/assets/entry-DS90gUks.js +0 -1
- package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
- package/dist/dashboard/assets/entry-j40LJotO.js +0 -4
- package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
- package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
- package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
- package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
- package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
- package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
- package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
- package/dist/dashboard/assets/live-KaG15HLQ.js +0 -1
- package/dist/dashboard/assets/live-KaG15HLQ.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/mutation-JJGQm8TD.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BNDZnsUE.js +0 -2
- package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CLaNz8Xz.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
- package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js +0 -1
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
- package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
- package/dist/dashboard/assets/state-DLS7IDMy.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/switch-42ItvbAs.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dmnfh1Ue.js.gz +0 -0
- package/src/network/response-headers.ts +0 -39
- package/src/protocol/response/dsml.ts +0 -38
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js.gz → app-Bgd3zANQ.js.gz} +0 -0
- /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { GatewayError } from "../../protocol/gateway-error";
|
|
2
|
-
import { resolveCredentialForAccount } from "../../providers/operations/provider-credential-service";
|
|
3
2
|
import { metrics } from "../../observability/metrics";
|
|
4
|
-
import { parseThinkingSuffix } from "../../protocol/translation/thinking";
|
|
5
3
|
import type { CodexCompactAdapter } from "../../providers/integrations/codex/codex";
|
|
6
4
|
import { completeAttempt, estimatedUsage, nativeCompletionBase } from "./attempt-finalize";
|
|
7
|
-
import { repriceUsage, usageFromProvider } from "../../providers/provider-usage";
|
|
8
5
|
import { runAttemptLoop } from "./attempt-loop";
|
|
6
|
+
import {
|
|
7
|
+
networkFetchContext,
|
|
8
|
+
requireRecordBody,
|
|
9
|
+
resolveAttemptCredential,
|
|
10
|
+
stripThinkingSuffix,
|
|
11
|
+
usageFromUpstreamClone,
|
|
12
|
+
} from "./native-shared";
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* The native Codex compaction route (`POST /v1/responses/compact`) and the
|
|
@@ -13,7 +17,7 @@ import { runAttemptLoop } from "./attempt-loop";
|
|
|
13
17
|
*/
|
|
14
18
|
import type { GatewayHandlerDeps } from "./handler-deps";
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
type ResponsesCompactHandlerDeps = GatewayHandlerDeps;
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
23
|
* Handles `POST /v1/responses/compact`: the native Codex compaction proxy. The
|
|
@@ -25,12 +29,12 @@ export function createResponsesCompactHandler(deps: ResponsesCompactHandlerDeps)
|
|
|
25
29
|
return async ({ request }: { request: Request }): Promise<Response> => {
|
|
26
30
|
const state = deps.stateStore.require(request);
|
|
27
31
|
const authorization = state.authorization;
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
const compact = requireRecordBody(
|
|
33
|
+
state,
|
|
34
|
+
"compact request body must be a JSON object (request {requestId}). Check the shape of what you sent — then resend 🪞",
|
|
35
|
+
);
|
|
32
36
|
if (typeof compact.model !== "string" || compact.model.trim().length === 0)
|
|
33
|
-
throw new GatewayError("invalid_request", 400, "model is required");
|
|
37
|
+
throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
34
38
|
// A thinking suffix (`model(high)`) is stripped here for the same reason the
|
|
35
39
|
// canonical preparer strips it: this route matches the model name against
|
|
36
40
|
// the allowlist and the route plan, and `(high)` is not part of any
|
|
@@ -39,25 +43,23 @@ export function createResponsesCompactHandler(deps: ResponsesCompactHandlerDeps)
|
|
|
39
43
|
// reasoning effort to shape, and the body is passed upstream verbatim.
|
|
40
44
|
// Stripping keeps a client that appends the suffix to every request working
|
|
41
45
|
// here instead of failing with a misleading model-not-found.
|
|
42
|
-
const {
|
|
43
|
-
const compactBody: Record<string, unknown> =
|
|
44
|
-
compactModel === compact.model ? compact : { ...compact, model: compactModel };
|
|
46
|
+
const { bareModel: compactModel, body: compactBody } = stripThinkingSuffix(compact.model, compact);
|
|
45
47
|
if (!(typeof compact.input === "string" || Array.isArray(compact.input)))
|
|
46
|
-
throw new GatewayError("invalid_request", 400, "input must be a string or array");
|
|
48
|
+
throw new GatewayError("invalid_request", 400, "input must be a string or array (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
47
49
|
if ("instructions" in compact && typeof compact.instructions !== "string")
|
|
48
|
-
throw new GatewayError("invalid_request", 400, "instructions must be a string");
|
|
50
|
+
throw new GatewayError("invalid_request", 400, "instructions must be a string (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
49
51
|
if (compact.stream === true)
|
|
50
52
|
throw new GatewayError(
|
|
51
53
|
"capability_unsupported",
|
|
52
54
|
400,
|
|
53
|
-
"Responses compact does not support streaming",
|
|
55
|
+
"Responses compact does not support streaming (request {requestId}). Know your tools — this one just isn't in the box 🧰",
|
|
54
56
|
);
|
|
55
57
|
const adapter = (await deps.resolveProviderAdapter?.("codex")) as CodexCompactAdapter | undefined;
|
|
56
58
|
if (!adapter || typeof adapter.compact !== "function")
|
|
57
|
-
throw new GatewayError("admission_unavailable", 503, "Codex compact transport unavailable");
|
|
59
|
+
throw new GatewayError("admission_unavailable", 503, "Codex compact transport unavailable (request {requestId}). The bouncer stepped out — come back shortly 🚪");
|
|
58
60
|
const prepared = await deps.proxyPreparer.prepareNativeCompact({
|
|
59
61
|
model: compactModel,
|
|
60
|
-
authorization
|
|
62
|
+
authorization: authorization!,
|
|
61
63
|
signal: state.abortController.signal,
|
|
62
64
|
...(state.clientUserAgent === undefined ? {} : { clientUserAgent: state.clientUserAgent }),
|
|
63
65
|
});
|
|
@@ -77,30 +79,26 @@ export function createResponsesCompactHandler(deps: ResponsesCompactHandlerDeps)
|
|
|
77
79
|
// Lenient pool semantics: a missing slot tolerates direct egress.
|
|
78
80
|
strictPoolSelection: false,
|
|
79
81
|
exhaustedError: new GatewayError(
|
|
80
|
-
"
|
|
82
|
+
"route_unavailable",
|
|
81
83
|
503,
|
|
82
|
-
"no eligible Codex route",
|
|
84
|
+
"no eligible Codex route (request {requestId}). The bouncer stepped out — come back shortly 🚪",
|
|
83
85
|
),
|
|
84
86
|
prepare: async (candidate) => {
|
|
85
87
|
if (!candidate.provider_account_id)
|
|
86
88
|
throw new GatewayError(
|
|
87
|
-
"
|
|
89
|
+
"route_unavailable",
|
|
88
90
|
503,
|
|
89
|
-
"Codex compact requires an OAuth account",
|
|
91
|
+
"Codex compact requires an OAuth account (request {requestId}). Wrong key, right door — check the credential 🔑",
|
|
90
92
|
);
|
|
91
|
-
const credential = await
|
|
92
|
-
|
|
93
|
-
"codex",
|
|
94
|
-
|
|
95
|
-
deps.oauthRefreshService && deps.resolveOAuthRefresher
|
|
96
|
-
? { refreshService: deps.oauthRefreshService, resolveRefresher: deps.resolveOAuthRefresher }
|
|
97
|
-
: undefined,
|
|
98
|
-
);
|
|
93
|
+
const credential = await resolveAttemptCredential(deps, {
|
|
94
|
+
...candidate,
|
|
95
|
+
provider_id: "codex",
|
|
96
|
+
});
|
|
99
97
|
if (credential.credential_kind !== "oauth")
|
|
100
98
|
throw new GatewayError(
|
|
101
99
|
"capability_unsupported",
|
|
102
100
|
400,
|
|
103
|
-
"Responses compact requires a Codex ChatGPT OAuth account",
|
|
101
|
+
"Responses compact requires a Codex ChatGPT OAuth account (request {requestId}). Wrong key, right door — check the credential 🔑",
|
|
104
102
|
);
|
|
105
103
|
return { credential, adapter };
|
|
106
104
|
},
|
|
@@ -110,36 +108,17 @@ export function createResponsesCompactHandler(deps: ResponsesCompactHandlerDeps)
|
|
|
110
108
|
credential,
|
|
111
109
|
deadline: state.deadlineMs,
|
|
112
110
|
abort_signal: state.abortController.signal,
|
|
113
|
-
...(deps.
|
|
114
|
-
? {
|
|
115
|
-
outbound_fetch: deps.networkBindingFactory.fetch(
|
|
116
|
-
leases.proxySlot?.poolId,
|
|
117
|
-
authorization.tenantId,
|
|
118
|
-
),
|
|
119
|
-
}
|
|
120
|
-
: {}),
|
|
111
|
+
...networkFetchContext(deps, leases.proxySlot?.poolId, authorization!.tenantId),
|
|
121
112
|
});
|
|
122
113
|
// Prefer the usage the compaction endpoint actually reported. The
|
|
123
114
|
// estimate is a fixed 1024+1024 reserve, and compaction is by
|
|
124
115
|
// construction a large-input operation, so charging it unconditionally
|
|
125
|
-
// let real spend run far past the counter. `
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const parsed: unknown = await response.clone().json();
|
|
132
|
-
reportedUsage = usageFromProvider(
|
|
133
|
-
typeof parsed === "object" && parsed !== null
|
|
134
|
-
? (parsed as Record<string, unknown>)["usage"]
|
|
135
|
-
: undefined,
|
|
136
|
-
);
|
|
137
|
-
} catch {
|
|
138
|
-
reportedUsage = undefined;
|
|
139
|
-
}
|
|
140
|
-
const usage = repriceUsage(
|
|
141
|
-
reportedUsage ??
|
|
142
|
-
estimatedUsage(prepared.estimatedInputTokens, prepared.estimatedOutputTokens),
|
|
116
|
+
// let real spend run far past the counter. `usageFromUpstreamClone`
|
|
117
|
+
// falls back to the estimate when the body reported nothing, and
|
|
118
|
+
// `response.clone()` leaves the body readable for the client.
|
|
119
|
+
const usage = await usageFromUpstreamClone(
|
|
120
|
+
response,
|
|
121
|
+
estimatedUsage(prepared.estimatedInputTokens, prepared.estimatedOutputTokens),
|
|
143
122
|
candidate.provider_id,
|
|
144
123
|
candidate.model_id,
|
|
145
124
|
);
|
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
* than inside it so the loop stays a policy *consumer* — one place decides
|
|
9
9
|
* retryability (`../failure-policy.ts`), one place decides refresh and
|
|
10
10
|
* cooldown eligibility (here).
|
|
11
|
+
*
|
|
12
|
+
* The egress-scoped half of the rate-limit decision lives in
|
|
13
|
+
* `../../network/rate-limit-verdict`; this module keeps only the credential-
|
|
14
|
+
* scoped predicates.
|
|
11
15
|
*/
|
|
12
16
|
import { GatewayError } from "../../protocol/gateway-error";
|
|
13
|
-
import { providerRateLimitIsIpScoped } from "../../providers/provider-metadata";
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Returns true only when an upstream failure is evidence that the OAuth
|
|
@@ -32,69 +35,3 @@ export function isOAuthCredentialInvalidated(error: unknown): error is GatewayEr
|
|
|
32
35
|
if (/web[ _-]?search|web[ _-]?fetch|x[ _-]?search|tool invocation|search backend/i.test(message)) return false;
|
|
33
36
|
return error.details.credentialEvidence === true;
|
|
34
37
|
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* A free-tier IP refusal: the upstream has flagged this egress address, not
|
|
38
|
-
* this request.
|
|
39
|
-
*
|
|
40
|
-
* OpenCode answers a blocked address with `403` and its own
|
|
41
|
-
* `FreeTierError`/`ModelDeprecated`-style body. The request was never read, so
|
|
42
|
-
* retrying it — with the same tools, the same headers, or the same credential —
|
|
43
|
-
* cannot succeed from the same address. Only a different egress can.
|
|
44
|
-
*
|
|
45
|
-
* This is deliberately narrower than "any 403": a content-policy rejection or a
|
|
46
|
-
* licence refusal is also a 403 and must not retire a healthy proxy. The
|
|
47
|
-
* provider must also declare `ipScopedRateLimit`, which is the same fact the
|
|
48
|
-
* 429 path already relies on.
|
|
49
|
-
*/
|
|
50
|
-
export function isFreeTierIpBlock(error: unknown, providerId: string): error is GatewayError {
|
|
51
|
-
if (!(error instanceof GatewayError) || error.origin !== "upstream" || error.status !== 403) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
if (!providerRateLimitIsIpScoped(providerId)) return false;
|
|
55
|
-
const providerCode = typeof error.details.providerCode === "string" ? error.details.providerCode : "";
|
|
56
|
-
const raw = String(error.details.raw ?? "");
|
|
57
|
-
return (
|
|
58
|
-
/freetier|free.?tier/i.test(providerCode) ||
|
|
59
|
-
/FreeTierError|free tier can only be used/i.test(`${error.message} ${raw}`)
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* A provider-scoped 429, on a provider whose limits follow the egress address.
|
|
65
|
-
*
|
|
66
|
-
* Only then is the pool the thing that ran out: the upstream counted requests
|
|
67
|
-
* from this address, so the next attempt must leave by a different one and
|
|
68
|
-
* cooling this pool is the fix. `providerRateLimitIsIpScoped` holds that fact
|
|
69
|
-
* per provider (see the metadata field) rather than inferring it from the
|
|
70
|
-
* response — a 429 states which bucket was exhausted only in the provider's own
|
|
71
|
-
* wording, and every account-keyed provider words it the same way.
|
|
72
|
-
*
|
|
73
|
-
* For an account-keyed provider the 429 belongs to the credential that was
|
|
74
|
-
* dialed. The account health machine already records it and routes the next
|
|
75
|
-
* request to a sibling, so cooling the pool as well only removed healthy
|
|
76
|
-
* accounts from service: every account sharing that egress lost its route for
|
|
77
|
-
* the cooldown window because one of them hit its own limit. A bare 429 with no
|
|
78
|
-
* provider scope stays a request-level limit and never cools the pool.
|
|
79
|
-
*
|
|
80
|
-
* `providerId` is the caller's own candidate, not a field read off the error:
|
|
81
|
-
* the in-stream error frames the protocol modules build carry no `providerId`
|
|
82
|
-
* detail, so reading it from `details` would silently disable the IP-scoped
|
|
83
|
-
* rule on exactly the streaming path it exists for.
|
|
84
|
-
*
|
|
85
|
-
* A type guard on `GatewayError`, so a caller that passes this check can hand
|
|
86
|
-
* the same value to `flagPoolCooldown` without a second narrowing step.
|
|
87
|
-
*/
|
|
88
|
-
export function shouldCooldownPool(error: unknown, providerId: string): error is GatewayError {
|
|
89
|
-
if (
|
|
90
|
-
!(
|
|
91
|
-
error instanceof GatewayError &&
|
|
92
|
-
error.origin === "upstream" &&
|
|
93
|
-
error.status === 429 &&
|
|
94
|
-
error.details.rateLimitScope === "provider"
|
|
95
|
-
)
|
|
96
|
-
) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
return providerRateLimitIsIpScoped(providerId);
|
|
100
|
-
}
|
|
@@ -60,7 +60,7 @@ export function createDispatchStreamEncoder(
|
|
|
60
60
|
throw new GatewayError(
|
|
61
61
|
"capability_unsupported",
|
|
62
62
|
400,
|
|
63
|
-
`Unknown surface: ${surface}
|
|
63
|
+
`Unknown surface: ${surface} (request {requestId}). Know your tools — this one just isn't in the box 🧰`,
|
|
64
64
|
{ surface },
|
|
65
65
|
);
|
|
66
66
|
}
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
import type { CanonicalEvent, SourceSurface, UsageRecord } from "../../../protocol/canonical-model";
|
|
13
13
|
import { canonicalTerminal } from "../../../protocol/codecs";
|
|
14
14
|
import { reasoningTextOf } from "../../../protocol/reasoning-text";
|
|
15
|
-
import {
|
|
15
|
+
import { ThinkSplitter } from "../../../protocol/think-split";
|
|
16
16
|
import { createDispatchStreamEncoder, type DispatchStreamEncoder } from "../stream-bridge";
|
|
17
17
|
import { THINKING_LOOP_MARKER, ThinkingLoopDetector } from "./thinking-loop";
|
|
18
18
|
|
|
19
19
|
/** The terminal event shape every stream settles (or fails to settle) on. */
|
|
20
|
-
|
|
20
|
+
type StreamTerminalEvent = Extract<CanonicalEvent, { type: "terminal" }>;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* SSE comment frame: valid framing on every streamed surface, ignored by
|
|
@@ -46,7 +46,7 @@ interface TruncatedEventTranscript {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/** Error-frame input in the shape the dispatch stream encoder accepts. */
|
|
49
|
-
|
|
49
|
+
type StreamErrorFrameInput = Parameters<DispatchStreamEncoder["encodeError"]>[0];
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Per-event state and framing for one stream. Client framing and protocol
|
|
@@ -93,10 +93,11 @@ export class StreamEventPipeline {
|
|
|
93
93
|
*/
|
|
94
94
|
private readonly diagnosticsCaptureMode: "none" | "metadata" | "full";
|
|
95
95
|
private readonly streamEncoder: DispatchStreamEncoder;
|
|
96
|
-
// One splitter per stream
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
|
|
96
|
+
// One splitter per stream, kept purely as a feeder for the loop guard: it
|
|
97
|
+
// reports the content currently inside an open `<think>` span so a runaway
|
|
98
|
+
// chain-of-thought is caught even when the provider wrote it into the text
|
|
99
|
+
// stream. It never re-routes the emitted events — text is forwarded verbatim.
|
|
100
|
+
private readonly thinkSplitter = new ThinkSplitter();
|
|
100
101
|
/**
|
|
101
102
|
* Content-level loop guard. A model that degenerates into a repeated
|
|
102
103
|
* chain-of-thought keeps sending bytes, so the stall timeout — which fires
|
|
@@ -259,26 +260,17 @@ export class StreamEventPipeline {
|
|
|
259
260
|
// `loopDetected`, so this only matters for an event already in flight;
|
|
260
261
|
// dropping it is the alternative to throwing mid-stream.
|
|
261
262
|
if (this.loopDetector.detected) return false;
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
263
|
+
// Text is forwarded verbatim: inline thinking tags are a per-provider
|
|
264
|
+
// decoder concern, not a universal one. Splitting them here for every
|
|
265
|
+
// surface misclassified literal `<think>` in an answer as reasoning — the
|
|
266
|
+
// answer vanished into the thinking pane and the poisoned history stopped
|
|
267
|
+
// follow-up turns. The loop guard still watches reasoning a provider puts
|
|
268
|
+
// inside an open `<think>` span, without reclassifying the answer.
|
|
267
269
|
if (event.type === "content_delta" && event.content.kind === "text") {
|
|
270
|
+
const enqueued = this.enqueueOne(event, controller);
|
|
268
271
|
const split = this.thinkSplitter.push(event.content.text);
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const reasoningEvent: CanonicalEvent = {
|
|
272
|
-
...event,
|
|
273
|
-
content: { kind: "reasoning", payload: null, summary: split.reasoning },
|
|
274
|
-
};
|
|
275
|
-
enqueued = this.enqueueOne(reasoningEvent, controller) || enqueued;
|
|
276
|
-
if (this.guardReasoning(split.reasoning, controller)) return enqueued;
|
|
277
|
-
}
|
|
278
|
-
if (split.text.length > 0) {
|
|
279
|
-
enqueued =
|
|
280
|
-
this.enqueueOne({ ...event, content: { kind: "text", text: split.text } }, controller) ||
|
|
281
|
-
enqueued;
|
|
272
|
+
if (split.pendingReasoning.length > 0) {
|
|
273
|
+
if (this.guardReasoning(split.pendingReasoning, controller)) return true;
|
|
282
274
|
}
|
|
283
275
|
return enqueued;
|
|
284
276
|
}
|
|
@@ -290,31 +282,8 @@ export class StreamEventPipeline {
|
|
|
290
282
|
this.guardReasoning(reasoningTextOf(event.content) ?? "", controller);
|
|
291
283
|
return enqueued;
|
|
292
284
|
}
|
|
293
|
-
// Text held back for a tag that never completed must be released *before*
|
|
294
|
-
// the terminal: a content event after it is rejected by the surface
|
|
295
|
-
// encoders, and the tail of the answer would be lost instead.
|
|
296
285
|
if (event.type === "terminal") {
|
|
297
|
-
|
|
298
|
-
if (rest.reasoning.length > 0) {
|
|
299
|
-
this.enqueueOne(
|
|
300
|
-
{
|
|
301
|
-
type: "content_delta",
|
|
302
|
-
sequence_number: event.sequence_number,
|
|
303
|
-
content: { kind: "reasoning", payload: null, summary: rest.reasoning },
|
|
304
|
-
},
|
|
305
|
-
controller,
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
if (rest.text.length > 0) {
|
|
309
|
-
this.enqueueOne(
|
|
310
|
-
{
|
|
311
|
-
type: "content_delta",
|
|
312
|
-
sequence_number: event.sequence_number,
|
|
313
|
-
content: { kind: "text", text: rest.text },
|
|
314
|
-
},
|
|
315
|
-
controller,
|
|
316
|
-
);
|
|
317
|
-
}
|
|
286
|
+
return this.enqueueOne(event, controller);
|
|
318
287
|
}
|
|
319
288
|
return this.enqueueOne(event, controller);
|
|
320
289
|
}
|
|
@@ -335,29 +304,6 @@ export class StreamEventPipeline {
|
|
|
335
304
|
): boolean {
|
|
336
305
|
const reason = text.length > 0 ? this.loopDetector.push(text) : undefined;
|
|
337
306
|
if (reason === undefined) return false;
|
|
338
|
-
// Flush before the terminal: content after it is rejected by the surface
|
|
339
|
-
// encoders, and the held-back text would be lost.
|
|
340
|
-
const rest = this.thinkSplitter.flush();
|
|
341
|
-
if (rest.reasoning.length > 0) {
|
|
342
|
-
this.enqueueOne(
|
|
343
|
-
{
|
|
344
|
-
type: "content_delta",
|
|
345
|
-
sequence_number: this.lastSequenceNumber + 1,
|
|
346
|
-
content: { kind: "reasoning", payload: null, summary: rest.reasoning },
|
|
347
|
-
},
|
|
348
|
-
controller,
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
if (rest.text.length > 0) {
|
|
352
|
-
this.enqueueOne(
|
|
353
|
-
{
|
|
354
|
-
type: "content_delta",
|
|
355
|
-
sequence_number: this.lastSequenceNumber + 1,
|
|
356
|
-
content: { kind: "text", text: rest.text },
|
|
357
|
-
},
|
|
358
|
-
controller,
|
|
359
|
-
);
|
|
360
|
-
}
|
|
361
307
|
this.enqueueOne(
|
|
362
308
|
canonicalTerminal({
|
|
363
309
|
sequenceNumber: this.lastSequenceNumber + 1,
|
|
@@ -24,7 +24,7 @@ import type { Reservation } from "../../routing/route-model";
|
|
|
24
24
|
import { repriceUsage } from "../../../providers/provider-usage";
|
|
25
25
|
import { metrics } from "../../../observability/metrics";
|
|
26
26
|
import { flagPoolBlocked, flagPoolCooldown } from "../../../network/pool-health";
|
|
27
|
-
import {
|
|
27
|
+
import { classifyEgressFailure } from "../../../network/rate-limit-verdict";
|
|
28
28
|
import { releaseAttemptLeases } from "../leases";
|
|
29
29
|
import type { AttemptLeaseOwnership } from "../leases";
|
|
30
30
|
import { finalizeRequestTelemetry } from "../../guards/error-lifecycle";
|
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
import { KEEPALIVE_COMMENT_BYTES, type StreamEventPipeline } from "./encoder";
|
|
40
40
|
|
|
41
41
|
/** Collaborators the stream tail reads from the dispatch handler. */
|
|
42
|
-
|
|
42
|
+
interface StreamFinalizeDeps {
|
|
43
43
|
readonly db: CartethyiaDatabase;
|
|
44
44
|
readonly poolSelector?: NetworkPoolSelector | undefined;
|
|
45
45
|
readonly telemetryBuffer?: TelemetryBatchBuffer | undefined;
|
|
@@ -56,7 +56,7 @@ export interface StreamCandidateIdentity {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/** What the stream tail needs from the attempt's input. */
|
|
59
|
-
|
|
59
|
+
interface StreamFinalizeInput {
|
|
60
60
|
readonly state: ProxyRequestState;
|
|
61
61
|
readonly deps: StreamFinalizeDeps;
|
|
62
62
|
readonly prepared: PreparedProxyRequest;
|
|
@@ -186,7 +186,7 @@ export class StreamFinalizer {
|
|
|
186
186
|
// origin is the upstream's: labelling it `cartethyia` reported a
|
|
187
187
|
// provider that stopped sending as a gateway defect.
|
|
188
188
|
this.input.state.abortController.abort(
|
|
189
|
-
new GatewayError("deadline_exceeded", 504, "The upstream stopped sending data mid-stream. Retry; if it keeps happening, the account or pool is unstable.", {}, "upstream"),
|
|
189
|
+
new GatewayError("deadline_exceeded", 504, "The upstream stopped sending data mid-stream (request {requestId}). Retry; if it keeps happening, the account or pool is unstable. The connection ghosted us — come back in a moment 👻", {}, "upstream"),
|
|
190
190
|
);
|
|
191
191
|
}, timeoutMs);
|
|
192
192
|
}
|
|
@@ -363,7 +363,7 @@ export class StreamFinalizer {
|
|
|
363
363
|
if (drain) return drain;
|
|
364
364
|
if (reason instanceof GatewayError && reason.code === "deadline_exceeded") return reason;
|
|
365
365
|
if (reason instanceof DOMException && reason.name === "TimeoutError")
|
|
366
|
-
return new GatewayError("deadline_exceeded", 504, "request deadline exceeded", {}, "cartethyia");
|
|
366
|
+
return new GatewayError("deadline_exceeded", 504, "request deadline exceeded (request {requestId}). Some things just take longer 🐢", {}, "cartethyia");
|
|
367
367
|
return undefined;
|
|
368
368
|
}
|
|
369
369
|
|
|
@@ -453,7 +453,7 @@ export class StreamFinalizer {
|
|
|
453
453
|
? new GatewayError(
|
|
454
454
|
"transport_unavailable",
|
|
455
455
|
502,
|
|
456
|
-
"The upstream closed the stream before it reported a final result. Retry; if it keeps happening, the account or pool is unstable.",
|
|
456
|
+
"The upstream closed the stream before it reported a final result (request {requestId}). Retry; if it keeps happening, the account or pool is unstable. The connection ghosted us — come back in a moment 👻",
|
|
457
457
|
{},
|
|
458
458
|
"upstream",
|
|
459
459
|
)
|
|
@@ -531,7 +531,7 @@ export class StreamFinalizer {
|
|
|
531
531
|
? new GatewayError(
|
|
532
532
|
"deadline_exceeded",
|
|
533
533
|
504,
|
|
534
|
-
"request deadline exceeded",
|
|
534
|
+
"request deadline exceeded (request {requestId}). Some things just take longer 🐢",
|
|
535
535
|
{},
|
|
536
536
|
"cartethyia",
|
|
537
537
|
)
|
|
@@ -579,10 +579,11 @@ export class StreamFinalizer {
|
|
|
579
579
|
...(pipeline.clientResponseText.length > 0 ? { clientResponseText: pipeline.clientResponseText } : {}),
|
|
580
580
|
});
|
|
581
581
|
this.streamSettled = true;
|
|
582
|
-
if (candidate.networkPoolId && !cancelled && deps.poolSelector) {
|
|
583
|
-
|
|
582
|
+
if (candidate.networkPoolId && !cancelled && deps.poolSelector && err instanceof GatewayError) {
|
|
583
|
+
const egressVerdict = classifyEgressFailure(err, candidate.providerId);
|
|
584
|
+
if (egressVerdict.kind === "cooldown") {
|
|
584
585
|
flagPoolCooldown(deps.poolSelector, deps.db, candidate.networkPoolId, candidate.providerId, err);
|
|
585
|
-
} else if (
|
|
586
|
+
} else if (egressVerdict.kind === "blocked") {
|
|
586
587
|
flagPoolBlocked(deps.poolSelector, deps.db, candidate.networkPoolId, candidate.providerId, err);
|
|
587
588
|
}
|
|
588
589
|
}
|
|
@@ -64,7 +64,7 @@ import { StreamEventPipeline } from "./encoder";
|
|
|
64
64
|
import { StreamFinalizer, type StreamCandidateIdentity } from "./finalize";
|
|
65
65
|
|
|
66
66
|
/** Collaborators the streaming branch reads from the dispatch handler. */
|
|
67
|
-
|
|
67
|
+
interface StreamingDispatchDeps {
|
|
68
68
|
readonly db: CartethyiaDatabase;
|
|
69
69
|
readonly networkBindingFactory?: ValidatedNetworkBindingFactory | undefined;
|
|
70
70
|
readonly poolSelector?: NetworkPoolSelector | undefined;
|
|
@@ -73,7 +73,7 @@ export interface StreamingDispatchDeps {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/** Everything one streamed attempt needs, all resolved by its caller. */
|
|
76
|
-
|
|
76
|
+
interface StreamingDispatchInput {
|
|
77
77
|
readonly state: ProxyRequestState;
|
|
78
78
|
readonly deps: StreamingDispatchDeps;
|
|
79
79
|
readonly prepared: PreparedProxyRequest;
|
|
@@ -228,7 +228,11 @@ export async function dispatchStreamingAttempt(input: StreamingDispatchInput): P
|
|
|
228
228
|
if (!isWrappedInjectionProvider(candidate.provider_id)) return {};
|
|
229
229
|
const text = resolveTenantSystemPrompt(
|
|
230
230
|
await readTenantSystemPromptsForDispatch(deps.db, prepared.authorization.snapshot.tenant_id),
|
|
231
|
-
{
|
|
231
|
+
{
|
|
232
|
+
providerId: candidate.provider_id,
|
|
233
|
+
modelId: candidate.model_id,
|
|
234
|
+
requestedModel: prepared.plan?.requested_model ?? candidate.model_id,
|
|
235
|
+
},
|
|
232
236
|
)?.text;
|
|
233
237
|
return text === undefined ? {} : { tenantSystemPrompt: text };
|
|
234
238
|
})()),
|
|
@@ -70,7 +70,7 @@ const SEGMENT_MIN_CLUSTER = 4;
|
|
|
70
70
|
* would hide every later prose paragraph from the heuristics. */
|
|
71
71
|
const CODE_LINE = /^(?:[ \t]*```.*|(?: {2,}|\t)(?![ \t]*(?:[-*+]|\d+[.)])[ \t]).*|.*[{}[\](;,>][ \t]*)$/gm;
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
interface ThinkingLoopConfig {
|
|
74
74
|
readonly enabled?: boolean;
|
|
75
75
|
}
|
|
76
76
|
|