cartethyia 2.7.4 → 2.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/README.md +17 -5
- package/dist/dashboard/assets/{BannedPage-ChG5svFb.js → BannedPage-Cj15GsMp.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-BIcWQun7.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Bf2VelDe.js → CliToolsPage-BIccZmeL.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-ggeMSjte.js → CustomizationPage-BKj_r0rp.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-U6AKaJcF.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-DnQPSIA8.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-5SnUSy3j.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-f0DE1h0-.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-BfAb5-o_.js} +3 -3
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0K-c4eo.js +1 -0
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DympBNq4.js → banner-BllT4LcF.js} +1 -1
- package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CtkX66Wd.js} +1 -1
- package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js +1 -0
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-8fiE6tec.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-BrTEZ8zu.js} +1 -1
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/{entry-BSAsYsmV.js → entry-EBHJ3DrE.js} +1 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-CPK47xQx.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-DBNPOfhV.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/layout-CajrYUnD.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Bx2I7XUe.js} +1 -1
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js +1 -0
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BLULNqTp.js} +1 -1
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-CkfdYWel.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-SYm237HG.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-m8WGNPrz.js} +1 -1
- package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +56 -55
- package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
- package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
- package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
- package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
- package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
- package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
- package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
- package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
- package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
- package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
- package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
- package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
- package/package.json +4 -6
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +58 -2
- package/src/boot/dependencies.ts +786 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +1 -1
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +13 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +26 -6
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +71 -62
- package/src/console/api-keys/routes.ts +48 -12
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +1 -1
- package/src/console/auth/audit-recorder.ts +1 -1
- package/src/console/auth/lockout.ts +7 -3
- package/src/console/auth/row-coercion.ts +57 -12
- package/src/console/auth/session-resolver.ts +1 -1
- package/src/console/auth/session-service.ts +8 -2
- package/src/console/auth/session.ts +37 -31
- package/src/console/auth/setup-service.ts +4 -3
- package/src/console/auth/user-store.ts +1 -1
- package/src/console/backup/9router-map.ts +0 -3
- package/src/console/backup/contracts.ts +9 -9
- package/src/console/backup/export-endpoint.ts +5 -6
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +29 -33
- package/src/console/backup/service.ts +468 -468
- package/src/console/backup/store.ts +47 -29
- package/src/console/backup/validate.ts +11 -1
- package/src/console/cli-tools/contracts.ts +7 -7
- package/src/console/cli-tools/injectors/cline.ts +110 -110
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/copilot.ts +108 -108
- package/src/console/cli-tools/injectors/driver.ts +247 -247
- package/src/console/cli-tools/injectors/jcode.ts +115 -115
- package/src/console/cli-tools/injectors/openclaw.ts +161 -161
- package/src/console/cli-tools/injectors/opencode.ts +153 -153
- package/src/console/cli-tools/routes.ts +1 -1
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router.ts +32 -0
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/domain-registration.ts +16 -2
- package/src/console/inferhub/client.ts +0 -7
- package/src/console/inferhub/key-store.ts +1 -1
- package/src/console/inferhub/normalize.ts +2 -2
- package/src/console/inferhub/routes.ts +1 -1
- package/src/console/inferhub/types.ts +1 -1
- package/src/console/observability/contracts.ts +1 -1
- package/src/console/observability/live.ts +31 -18
- package/src/console/observability/logs.ts +1 -1
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +20 -4
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +39 -0
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +95 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +27 -3
- package/src/console/providers/catalog/store.ts +147 -8
- package/src/console/providers/detail/routes.ts +1 -1
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +92 -13
- package/src/console/quota/account-quota-global.ts +41 -3
- package/src/console/quota/account-quota-shared.ts +10 -3
- package/src/console/quota/account-quota-tenant.ts +259 -66
- package/src/console/quota/daily-growth-job.ts +308 -0
- package/src/console/quota/native-identity.ts +2 -2
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/routes.ts +1 -1
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/contracts.ts +1 -1
- package/src/console/routing/pools/contracts.ts +2 -2
- package/src/console/routing/pools/import-parse.ts +3 -3
- package/src/console/routing/pools/relay-deploy.ts +3 -3
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +100 -32
- package/src/console/share/share-stats.ts +4 -4
- package/src/console/share/share-usage.ts +1 -1
- package/src/console/shared/errors.ts +2 -2
- package/src/console/shared/object.ts +18 -0
- package/src/console/shared/read-through-cache.ts +4 -4
- package/src/console/shared/transaction.ts +14 -0
- package/src/console/system-prompt/contracts.ts +89 -12
- package/src/console/system-prompt/routes.ts +98 -45
- package/src/console/updates/apply-update.ts +244 -0
- package/src/console/updates/routes.ts +252 -97
- package/src/main.ts +11 -5
- package/src/network/http2-bidi.ts +1 -1
- package/src/network/ip-utils.ts +298 -0
- package/src/network/outbound-fetch.ts +1 -1
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +16 -12
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-health-machine.ts +1 -1
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +20 -71
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +59 -291
- package/src/observability/log-sanitize.ts +1 -1
- package/src/observability/metrics.ts +4 -4
- package/src/observability/payload-capture.ts +6 -5
- package/src/observability/payload-store.ts +1 -1
- package/src/observability/runtime-metrics.ts +1 -1
- package/src/observability/telemetry-buffer.ts +12 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/token-speed.ts +1 -1
- package/src/persistence/connection-url.ts +1 -1
- package/src/persistence/db-handle.ts +1 -1
- package/src/persistence/db-pg.ts +2 -2
- package/src/persistence/db-sqlite.ts +3 -3
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +1 -1
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +113 -40
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +10 -1
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/system-prompt-store.ts +63 -18
- package/src/persistence/tenant-preferences.ts +1 -1
- package/src/persistence/ttl-cache.ts +3 -3
- package/src/persistence/usage-flush.ts +7 -2
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/codecs.ts +6 -10
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/reasoning-text.ts +1 -1
- package/src/protocol/reasoning.ts +7 -52
- package/src/protocol/registry.ts +50 -15
- package/src/protocol/request/chat.ts +46 -19
- package/src/protocol/request/codex.ts +1 -1
- package/src/protocol/request/messages.ts +46 -14
- package/src/protocol/request/responses.ts +19 -10
- package/src/protocol/response/chat.ts +25 -10
- package/src/protocol/response/codex.ts +1 -1
- package/src/protocol/response/messages.ts +1 -1
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +1 -1
- package/src/protocol/sse-decoder.ts +50 -1
- package/src/protocol/stop-reason.ts +2 -2
- package/src/protocol/think-split.ts +347 -0
- package/src/protocol/translation/attachment-integrity.ts +3 -3
- package/src/protocol/translation/cache-controls.ts +8 -20
- package/src/protocol/translation/capabilities.ts +6 -6
- package/src/protocol/translation/dialect/deepseek.ts +10 -0
- package/src/protocol/translation/dialect/inband.ts +39 -0
- package/src/protocol/translation/dialect/model-thinking.ts +89 -0
- package/src/protocol/translation/dialect/qwen.ts +114 -0
- package/src/protocol/translation/dialect/resolver.ts +83 -0
- package/src/protocol/translation/dialect/rules.ts +93 -0
- package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
- package/src/protocol/translation/dialect/types.ts +58 -0
- package/src/protocol/translation/quirks.ts +18 -4
- package/src/protocol/translation/thinking.ts +12 -252
- package/src/protocol/translation/tool-id.ts +3 -3
- package/src/protocol/translation/tool-repair.ts +1 -1
- package/src/protocol/upstream/post-json.ts +6 -1
- package/src/providers/adapters/compatible-adapter.ts +42 -3
- package/src/providers/authentication/jwt-validator.ts +0 -5
- package/src/providers/authentication/oauth-client.ts +254 -253
- package/src/providers/authentication/oauth-flow-store.ts +42 -7
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/default-registry.ts +23 -35
- package/src/providers/discovery/catalog/catalog-format.ts +13 -2
- package/src/providers/discovery/discovery-types.ts +0 -1
- package/src/providers/discovery/openai-model-discovery.ts +2 -2
- package/src/providers/discovery/probe-phases.ts +48 -13
- package/src/providers/discovery/probing-service.ts +6 -8
- package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
- package/src/providers/integrations/antigravity/antigravity.ts +2 -2
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
- package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
- package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- package/src/providers/integrations/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +1 -1
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/commandcode/commandcode.ts +75 -115
- package/src/providers/integrations/commandcode/quota.ts +131 -51
- package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
- package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
- package/src/providers/integrations/cursor/cursor-request.ts +0 -87
- package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
- package/src/providers/integrations/cursor/cursor.ts +38 -5
- package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
- package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
- package/src/providers/integrations/factory/factory.ts +9 -9
- package/src/providers/integrations/github/github-discovery.ts +55 -10
- package/src/providers/integrations/github/github-oauth.ts +6 -5
- package/src/providers/integrations/github/github.ts +41 -14
- package/src/providers/integrations/grok/grok-oauth.ts +261 -261
- package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
- package/src/providers/integrations/grok/grok-quota.ts +16 -7
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
- package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
- package/src/providers/integrations/grok/grok.ts +86 -36
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
- package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
- package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
- package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
- package/src/providers/integrations/kiro/kiro-request.ts +8 -11
- package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
- package/src/providers/integrations/kiro/kiro.ts +81 -68
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/qoder/qoder-catalog.ts +85 -8
- package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
- package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
- package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
- package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
- package/src/providers/integrations/qoder/qoder.ts +354 -62
- package/src/providers/integrations/shared/connect.ts +0 -54
- package/src/providers/integrations/shared/hash.ts +15 -0
- package/src/providers/integrations/shared/session-cache.ts +136 -0
- package/src/providers/integrations/trae/trae-cache.ts +7 -87
- package/src/providers/integrations/trae/trae-catalog.ts +1 -6
- package/src/providers/integrations/trae/trae-protocol.ts +17 -8
- package/src/providers/integrations/trae/trae-realm.ts +0 -7
- package/src/providers/integrations/trae/trae.ts +53 -10
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
- package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
- package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
- package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
- package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
- package/src/providers/operations/account-error-classification.ts +131 -116
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/cli-platform.ts +31 -5
- package/src/providers/operations/client-version-resolver.ts +4 -6
- package/src/providers/operations/client-versions.ts +10 -7
- package/src/providers/operations/provider-catalog-seeder.ts +2 -0
- package/src/providers/operations/provider-catalog-service.ts +18 -2
- package/src/providers/operations/provider-credential-service.ts +19 -2
- package/src/providers/provider-contracts.ts +18 -7
- package/src/providers/provider-metadata.ts +17 -2
- package/src/providers/provider-model-definition.ts +22 -1
- package/src/providers/provider-probe.ts +4 -2
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +4 -0
- package/src/providers/quota/refresh.ts +27 -4
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +1 -3
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +4 -4
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +16 -4
- package/src/security/client-router-fingerprint.ts +4 -4
- package/src/security/credential-codec.ts +3 -3
- package/src/security/csrf.ts +2 -2
- package/src/security/ip-boundary.ts +16 -189
- package/src/security/model-access-rule.ts +1 -1
- package/src/security/outbound-headers.ts +18 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +1 -1
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +23 -20
- package/src/transport/dispatch/generation.ts +25 -45
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +3 -1
- package/src/transport/dispatch/responses-compact.ts +25 -46
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +2 -2
- package/src/transport/dispatch/streaming/stream.ts +7 -3
- package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
- package/src/transport/dispatch/systemone.ts +20 -48
- package/src/transport/dispatch/token-count.ts +41 -38
- package/src/transport/dispatch/websearch.ts +19 -45
- package/src/transport/drain-endpoint.ts +1 -1
- package/src/transport/failure-policy.ts +6 -0
- package/src/transport/guards/auth-guard.ts +0 -6
- package/src/transport/guards/body-policy.ts +3 -3
- package/src/transport/guards/headroom-guard.ts +1 -1
- package/src/transport/guards/pipeline.ts +1 -1
- package/src/transport/guards/request-context.ts +12 -17
- package/src/transport/request/preparer.ts +286 -7
- package/src/transport/request/rtk/compress-request.ts +3 -3
- package/src/transport/request/rtk/rtk-constants.ts +2 -2
- package/src/transport/request/rtk/rtk-filters.ts +8 -8
- package/src/transport/request/state.ts +1 -13
- package/src/transport/request/system-prompt-injection.ts +74 -11
- package/src/transport/request/tenant-preferences.ts +22 -0
- package/src/transport/routing/candidate-index.ts +2 -2
- package/src/transport/routing/round-robin.ts +1 -1
- package/src/transport/routing/route-catalog.ts +17 -18
- package/src/transport/routing/route-model.ts +126 -33
- package/src/transport/routing/router.ts +152 -37
- package/src/transport/shutdown-notice.ts +2 -2
- package/src/transport/surface/adapters.ts +3 -3
- package/src/transport/surface/chat/encode.ts +7 -7
- package/src/transport/surface/chat/parse.ts +7 -7
- package/src/transport/surface/completion.ts +2 -2
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/parse.ts +3 -3
- package/src/transport/surface/responses/adapter.ts +1 -1
- package/src/transport/surface/responses/errors.ts +0 -9
- package/src/transport/vision-handoff-cache.ts +58 -0
- package/src/transport/vision-handoff.ts +376 -0
- package/src/workers/account-identity-sweep.ts +2 -2
- package/src/workers/buddy-growth-tasks.ts +392 -346
- package/src/workers/daily-checkin.ts +102 -49
- package/src/workers/maintenance-lease.ts +2 -35
- package/src/workers/oauth-refresh-sweep.ts +8 -1
- package/src/workers/quota-refresh-sweep.ts +120 -82
- package/src/workers/scheduler.ts +67 -4
- package/src/workers/sweep-runner.ts +24 -5
- package/src/workers/zcode-gift-claim.ts +108 -0
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
- package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
- package/dist/dashboard/assets/app-a159k0ub.css +0 -2
- package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
- package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
- package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
- package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
- package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
- package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
- package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
- package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
- package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
- package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
- package/src/network/response-headers.ts +0 -39
- package/src/protocol/response/dsml.ts +0 -38
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
- /package/dist/dashboard/assets/{app-BayTTy01.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-BayTTy01.js.gz → app-Bgd3zANQ.js.gz} +0 -0
- /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { ProviderAdapter, ProviderDispatchTarget } from "../../providers/provider-contracts";
|
|
2
2
|
import { GatewayError } from "../../protocol/gateway-error";
|
|
3
|
-
import { resolveCredentialForAccount } from "../../providers/operations/provider-credential-service";
|
|
4
3
|
import { metrics } from "../../observability/metrics";
|
|
5
|
-
import {
|
|
6
|
-
import { completeAttempt, estimatedUsage, nativeCompletionBase } from "./attempt-finalize";
|
|
7
|
-
import { repriceUsage, usageFromProvider } from "../../providers/provider-usage";
|
|
4
|
+
import { estimatedUsage, nativeCompletionBase, completeAttempt } from "./attempt-finalize";
|
|
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 System One route (`POST /v1/systemone`) and the dependency surface
|
|
@@ -20,7 +24,7 @@ import { runAttemptLoop } from "./attempt-loop";
|
|
|
20
24
|
*/
|
|
21
25
|
import type { GatewayHandlerDeps } from "./handler-deps";
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
type SystemoneHandlerDeps = GatewayHandlerDeps;
|
|
24
28
|
|
|
25
29
|
/** Adapter that can serve a System One decision request. */
|
|
26
30
|
type SystemoneAdapter = ProviderAdapter & {
|
|
@@ -31,10 +35,10 @@ export function createSystemoneHandler(deps: SystemoneHandlerDeps) {
|
|
|
31
35
|
return async ({ request }: { request: Request }): Promise<Response> => {
|
|
32
36
|
const state = deps.stateStore.require(request);
|
|
33
37
|
const authorization = state.authorization;
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
const decision = requireRecordBody(
|
|
39
|
+
state,
|
|
40
|
+
"systemone request body must be a JSON object (request {requestId}). Check the shape of what you sent — then resend 🪞",
|
|
41
|
+
);
|
|
38
42
|
if (typeof decision.model !== "string" || decision.model.trim().length === 0)
|
|
39
43
|
throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
40
44
|
// A thinking suffix (`model(high)`) is stripped for the same reason the
|
|
@@ -42,9 +46,7 @@ export function createSystemoneHandler(deps: SystemoneHandlerDeps) {
|
|
|
42
46
|
// allowlist and the route plan, and `(high)` is not part of any registered
|
|
43
47
|
// id. The level itself is dropped — a decision request carries no reasoning
|
|
44
48
|
// effort to shape, and the body is passed upstream verbatim.
|
|
45
|
-
const {
|
|
46
|
-
const decisionBody: Record<string, unknown> =
|
|
47
|
-
bareModel === decision.model ? decision : { ...decision, model: bareModel };
|
|
49
|
+
const { bareModel, body: decisionBody } = stripThinkingSuffix(decision.model, decision);
|
|
48
50
|
// Trust boundary only: the decision model's own question shapes are
|
|
49
51
|
// upstream's to validate. `state` and a `questions` object are what make a
|
|
50
52
|
// System One request a System One request at all.
|
|
@@ -60,7 +62,7 @@ export function createSystemoneHandler(deps: SystemoneHandlerDeps) {
|
|
|
60
62
|
const prepared = await deps.proxyPreparer.prepareNativeService({
|
|
61
63
|
model: bareModel,
|
|
62
64
|
serviceKind: "systemone",
|
|
63
|
-
authorization
|
|
65
|
+
authorization: authorization!,
|
|
64
66
|
...(state.abortController.signal ? { signal: state.abortController.signal } : {}),
|
|
65
67
|
...(state.clientUserAgent === undefined ? {} : { clientUserAgent: state.clientUserAgent }),
|
|
66
68
|
});
|
|
@@ -85,19 +87,7 @@ export function createSystemoneHandler(deps: SystemoneHandlerDeps) {
|
|
|
85
87
|
"no eligible System One route (request {requestId}). The bouncer stepped out — come back shortly 🚪",
|
|
86
88
|
),
|
|
87
89
|
prepare: async (candidate) => {
|
|
88
|
-
const credential = candidate
|
|
89
|
-
? await resolveCredentialForAccount(
|
|
90
|
-
deps.db,
|
|
91
|
-
candidate.provider_id,
|
|
92
|
-
candidate.provider_account_id,
|
|
93
|
-
deps.oauthRefreshService && deps.resolveOAuthRefresher
|
|
94
|
-
? { refreshService: deps.oauthRefreshService, resolveRefresher: deps.resolveOAuthRefresher }
|
|
95
|
-
: undefined,
|
|
96
|
-
)
|
|
97
|
-
: {
|
|
98
|
-
provider_id: candidate.provider_id as ProviderAdapter["provider_id"],
|
|
99
|
-
credential_kind: "none" as const,
|
|
100
|
-
};
|
|
90
|
+
const credential = await resolveAttemptCredential(deps, candidate);
|
|
101
91
|
const adapter = (await deps.resolveProviderAdapter?.(candidate.provider_id)) as SystemoneAdapter | undefined;
|
|
102
92
|
if (!adapter || typeof adapter.systemone !== "function")
|
|
103
93
|
throw new GatewayError(
|
|
@@ -131,14 +121,7 @@ export function createSystemoneHandler(deps: SystemoneHandlerDeps) {
|
|
|
131
121
|
deadline: state.deadlineMs,
|
|
132
122
|
abort_signal: state.abortController.signal,
|
|
133
123
|
...(candidate.user_agent === undefined ? {} : { user_agent: candidate.user_agent }),
|
|
134
|
-
...(deps.
|
|
135
|
-
? {
|
|
136
|
-
outbound_fetch: deps.networkBindingFactory.fetch(
|
|
137
|
-
leases.proxySlot?.poolId,
|
|
138
|
-
authorization.tenantId,
|
|
139
|
-
),
|
|
140
|
-
}
|
|
141
|
-
: {}),
|
|
124
|
+
...networkFetchContext(deps, leases.proxySlot?.poolId, authorization!.tenantId),
|
|
142
125
|
});
|
|
143
126
|
if (!response.ok) {
|
|
144
127
|
// Surface the upstream decision error verbatim: it is the operator's
|
|
@@ -154,20 +137,9 @@ export function createSystemoneHandler(deps: SystemoneHandlerDeps) {
|
|
|
154
137
|
// Prefer the usage the decision endpoint reported; fall back to the
|
|
155
138
|
// fixed native estimate. `response.clone()` leaves the body readable
|
|
156
139
|
// for the client.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
reportedUsage = usageFromProvider(
|
|
161
|
-
typeof parsed === "object" && parsed !== null
|
|
162
|
-
? (parsed as Record<string, unknown>)["usage"]
|
|
163
|
-
: undefined,
|
|
164
|
-
);
|
|
165
|
-
} catch {
|
|
166
|
-
reportedUsage = undefined;
|
|
167
|
-
}
|
|
168
|
-
const usage = repriceUsage(
|
|
169
|
-
reportedUsage ??
|
|
170
|
-
estimatedUsage(prepared.estimatedInputTokens, prepared.estimatedOutputTokens),
|
|
140
|
+
const usage = await usageFromUpstreamClone(
|
|
141
|
+
response,
|
|
142
|
+
estimatedUsage(prepared.estimatedInputTokens, prepared.estimatedOutputTokens),
|
|
171
143
|
candidate.provider_id,
|
|
172
144
|
candidate.model_id,
|
|
173
145
|
);
|
|
@@ -36,31 +36,33 @@
|
|
|
36
36
|
import type { ProviderAdapter, ProviderDispatchTarget } from "../../providers/provider-contracts";
|
|
37
37
|
import { GatewayError } from "../../protocol/gateway-error";
|
|
38
38
|
import { isRecord } from "../../protocol/codecs";
|
|
39
|
-
import { resolveCredentialForAccount } from "../../providers/operations/provider-credential-service";
|
|
40
39
|
import { metrics } from "../../observability/metrics";
|
|
40
|
+
import type { TelemetryBatchBuffer } from "../../observability/telemetry-buffer";
|
|
41
41
|
import type { ProxyRequestState } from "../request/state";
|
|
42
42
|
import type { PreparedNativeRequest } from "../request/preparer";
|
|
43
43
|
import { completeAttempt, estimatedUsage, nativeCompletionBase } from "./attempt-finalize";
|
|
44
|
+
import { finalizeRequestTelemetry } from "../guards/error-lifecycle";
|
|
44
45
|
import { runAttemptLoop } from "./attempt-loop";
|
|
46
|
+
import { hasScope, networkFetchContext, requireRecordBody, resolveAttemptCredential } from "./native-shared";
|
|
45
47
|
|
|
46
48
|
import type { GatewayHandlerDeps } from "./handler-deps";
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
type TokenCountHandlerDeps = GatewayHandlerDeps;
|
|
49
51
|
|
|
50
52
|
/** Builds the `POST /v1/messages/count_tokens` handler. */
|
|
51
53
|
export function createTokenCountHandler(deps: TokenCountHandlerDeps) {
|
|
52
54
|
return async ({ request }: { request: Request }): Promise<Response> => {
|
|
53
55
|
const state = deps.stateStore.require(request);
|
|
54
56
|
const authorization = state.authorization;
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
const countBody = requireRecordBody(
|
|
58
|
+
state,
|
|
59
|
+
"The count_tokens body must be a JSON object (request {requestId}), the same shape POST /v1/messages accepts. Check the shape of what you sent — then resend 🪞",
|
|
60
|
+
);
|
|
61
|
+
// `requireRecordBody` already refused a missing authorization; this guard
|
|
62
|
+
// exists only to narrow the type for the code below.
|
|
63
|
+
if (!authorization) {
|
|
64
|
+
throw new GatewayError("invalid_request", 400, "authentication required (request {requestId})");
|
|
62
65
|
}
|
|
63
|
-
const countBody = body as Record<string, unknown>;
|
|
64
66
|
|
|
65
67
|
// `model` names the route and `messages` is what gets counted; both are the
|
|
66
68
|
// upstream's own required fields, so the gateway does not restate its own
|
|
@@ -71,7 +73,7 @@ export function createTokenCountHandler(deps: TokenCountHandlerDeps) {
|
|
|
71
73
|
if (!Array.isArray(countBody.messages)) {
|
|
72
74
|
throw new GatewayError("invalid_request", 400, "messages must be an array (request {requestId}) — there is nothing to count without it. Check the shape of what you sent — then resend 🪞");
|
|
73
75
|
}
|
|
74
|
-
if (!authorization
|
|
76
|
+
if (!hasScope(authorization?.snapshot.scopes, "routing:invoke")) {
|
|
75
77
|
throw new GatewayError(
|
|
76
78
|
"policy_rejected",
|
|
77
79
|
403,
|
|
@@ -93,7 +95,7 @@ export function createTokenCountHandler(deps: TokenCountHandlerDeps) {
|
|
|
93
95
|
// real 429/503 — a fabricated count would tell the client its context
|
|
94
96
|
// fits when nothing is there to serve the turn that follows.
|
|
95
97
|
if (!(error instanceof GatewayError) || error.code !== "capability_unsupported") throw error;
|
|
96
|
-
return estimatedCountResponse(state, countBody);
|
|
98
|
+
return estimatedCountResponse(state, countBody, deps.telemetryBuffer, deps.db);
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
return runAttemptLoop<Response, ProviderAdapter>({
|
|
@@ -116,19 +118,7 @@ export function createTokenCountHandler(deps: TokenCountHandlerDeps) {
|
|
|
116
118
|
"no eligible route can count tokens for this model (request {requestId}). The bouncer stepped out — come back shortly 🚪",
|
|
117
119
|
),
|
|
118
120
|
prepare: async (candidate) => {
|
|
119
|
-
const credential = candidate
|
|
120
|
-
? await resolveCredentialForAccount(
|
|
121
|
-
deps.db,
|
|
122
|
-
candidate.provider_id,
|
|
123
|
-
candidate.provider_account_id,
|
|
124
|
-
deps.oauthRefreshService && deps.resolveOAuthRefresher
|
|
125
|
-
? { refreshService: deps.oauthRefreshService, resolveRefresher: deps.resolveOAuthRefresher }
|
|
126
|
-
: undefined,
|
|
127
|
-
)
|
|
128
|
-
: {
|
|
129
|
-
provider_id: candidate.provider_id as ProviderAdapter["provider_id"],
|
|
130
|
-
credential_kind: "none" as const,
|
|
131
|
-
};
|
|
121
|
+
const credential = await resolveAttemptCredential(deps, candidate);
|
|
132
122
|
const adapter = await deps.resolveProviderAdapter?.(candidate.provider_id);
|
|
133
123
|
if (!adapter) {
|
|
134
124
|
throw new GatewayError("capability_unsupported", 400, "token counting is unavailable for this provider (request {requestId}). Know your tools — this one just isn't in the box 🧰");
|
|
@@ -167,14 +157,7 @@ export function createTokenCountHandler(deps: TokenCountHandlerDeps) {
|
|
|
167
157
|
deadline: state.deadlineMs,
|
|
168
158
|
abort_signal: state.abortController.signal,
|
|
169
159
|
...(candidate.user_agent === undefined ? {} : { user_agent: candidate.user_agent }),
|
|
170
|
-
...(deps.
|
|
171
|
-
? {
|
|
172
|
-
outbound_fetch: deps.networkBindingFactory.fetch(
|
|
173
|
-
leases.proxySlot?.poolId,
|
|
174
|
-
authorization.tenantId,
|
|
175
|
-
),
|
|
176
|
-
}
|
|
177
|
-
: {}),
|
|
160
|
+
...networkFetchContext(deps, leases.proxySlot?.poolId, authorization.tenantId),
|
|
178
161
|
});
|
|
179
162
|
|
|
180
163
|
// A count is free and generates nothing, so nothing is reserved or
|
|
@@ -221,20 +204,40 @@ export function createTokenCountHandler(deps: TokenCountHandlerDeps) {
|
|
|
221
204
|
*
|
|
222
205
|
* No attempt is finalized: nothing was leased, nothing was sent upstream, and
|
|
223
206
|
* no provider produced this number, so recording it against an account would
|
|
224
|
-
* invent usage the account never served. The request still
|
|
225
|
-
*
|
|
226
|
-
*
|
|
207
|
+
* invent usage the account never served. The request is still finalized through
|
|
208
|
+
* `finalizeRequestTelemetry` (the early-rejection pattern) — without it the
|
|
209
|
+
* latency histogram, the `request_complete` console event, and the durable
|
|
210
|
+
* telemetry row all miss this request — and `state.completed` prevents the
|
|
211
|
+
* `afterResponse` fallback from finalizing it a second time.
|
|
227
212
|
*/
|
|
228
213
|
function estimatedCountResponse(
|
|
229
214
|
state: ProxyRequestState,
|
|
230
215
|
countBody: Record<string, unknown>,
|
|
216
|
+
telemetryBuffer: TelemetryBatchBuffer | undefined,
|
|
217
|
+
db: GatewayHandlerDeps["db"],
|
|
231
218
|
): Response {
|
|
232
219
|
const inputTokens = estimateMessagesInputTokens(countBody);
|
|
233
220
|
const payload = JSON.stringify({ input_tokens: inputTokens });
|
|
234
|
-
|
|
221
|
+
// The request still gets an outcome — without one the `afterResponse` hook
|
|
222
|
+
// would finalize it as a failure, and a count that answered 200 would show up
|
|
223
|
+
// in Console Log as an error. `usage` is a zero-priced estimate: nothing was
|
|
224
|
+
// leased and no provider produced this number, so recording a cost against an
|
|
225
|
+
// account would invent usage the account never served (`estimated_cost: null`).
|
|
226
|
+
state.outcome = {
|
|
227
|
+
status: "completed",
|
|
228
|
+
httpStatus: 200,
|
|
229
|
+
usage: estimatedUsage(inputTokens, 0),
|
|
230
|
+
};
|
|
235
231
|
state.completed = true;
|
|
236
232
|
state.clientResponseText = payload;
|
|
237
233
|
metrics.proxy_requests_total.inc(1, { status: "completed" });
|
|
234
|
+
// Finalize telemetry inline (the early-rejection pattern) instead of routing
|
|
235
|
+
// through `completeAttempt`: there was no lease and no provider — but the
|
|
236
|
+
// latency histogram, the `request_complete` console event, and the durable
|
|
237
|
+
// row must still happen, exactly once. `completed = true` also disables the
|
|
238
|
+
// `afterResponse` fallback, which is what used to make this request vanish
|
|
239
|
+
// from telemetry entirely.
|
|
240
|
+
if (telemetryBuffer) finalizeRequestTelemetry(state, telemetryBuffer, db);
|
|
238
241
|
return new Response(payload, {
|
|
239
242
|
headers: {
|
|
240
243
|
"content-type": "application/json",
|
|
@@ -255,7 +258,7 @@ function estimatedCountResponse(
|
|
|
255
258
|
* `/v1/messages?beta=true/count_tokens` — the counting segment lands inside the
|
|
256
259
|
* query, so the upstream sees the chat path with junk after it and never counts.
|
|
257
260
|
*/
|
|
258
|
-
|
|
261
|
+
function joinCountTokensPath(endpoint: string): string {
|
|
259
262
|
const queryAt = endpoint.indexOf("?");
|
|
260
263
|
const path = queryAt === -1 ? endpoint : endpoint.slice(0, queryAt);
|
|
261
264
|
const query = queryAt === -1 ? "" : endpoint.slice(queryAt);
|
|
@@ -16,51 +16,44 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { ProviderAdapter, ProviderDispatchTarget } from "../../providers/provider-contracts";
|
|
18
18
|
import { GatewayError } from "../../protocol/gateway-error";
|
|
19
|
-
import { resolveCredentialForAccount } from "../../providers/operations/provider-credential-service";
|
|
20
19
|
import { metrics } from "../../observability/metrics";
|
|
21
|
-
import { parseThinkingSuffix } from "../../protocol/translation/thinking";
|
|
22
20
|
import { completeAttempt, estimatedUsage, nativeCompletionBase } from "./attempt-finalize";
|
|
23
21
|
import { runAttemptLoop } from "./attempt-loop";
|
|
22
|
+
import {
|
|
23
|
+
hasScope,
|
|
24
|
+
jsonResponse,
|
|
25
|
+
networkFetchContext,
|
|
26
|
+
requireRecordBody,
|
|
27
|
+
resolveAttemptCredential,
|
|
28
|
+
stripThinkingSuffix,
|
|
29
|
+
} from "./native-shared";
|
|
24
30
|
|
|
25
31
|
import type { GatewayHandlerDeps } from "./handler-deps";
|
|
26
32
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
type WebsearchHandlerDeps = GatewayHandlerDeps;
|
|
30
34
|
|
|
31
35
|
/** Adapter that can serve a web-search request. */
|
|
32
36
|
type WebsearchAdapter = ProviderAdapter & {
|
|
33
37
|
websearch: NonNullable<ProviderAdapter["websearch"]>;
|
|
34
38
|
};
|
|
35
39
|
|
|
36
|
-
function jsonResponse(payload: unknown, status: number, requestId: string): Response {
|
|
37
|
-
return new Response(JSON.stringify(payload), {
|
|
38
|
-
status,
|
|
39
|
-
headers: {
|
|
40
|
-
"content-type": "application/json",
|
|
41
|
-
"cache-control": "no-store",
|
|
42
|
-
"x-request-id": requestId,
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
40
|
export function createWebsearchHandler(deps: WebsearchHandlerDeps) {
|
|
48
41
|
return async ({ request }: { request: Request }): Promise<Response> => {
|
|
49
42
|
const state = deps.stateStore.require(request);
|
|
50
43
|
const authorization = state.authorization;
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
const search = requireRecordBody(state, "The search body must be a JSON object (request {requestId}). Send one with at least a model and a query. Check the shape of what you sent — then resend 🪞");
|
|
45
|
+
// `requireRecordBody` already refused a missing authorization; this guard
|
|
46
|
+
// exists only to narrow the type for the code below.
|
|
47
|
+
if (!authorization) {
|
|
48
|
+
throw new GatewayError("invalid_request", 400, "authentication required (request {requestId})");
|
|
49
|
+
}
|
|
55
50
|
if (typeof search.model !== "string" || search.model.trim().length === 0)
|
|
56
51
|
throw new GatewayError("invalid_request", 400, "A model is required (request {requestId}): it names the search provider to use. Check the shape of what you sent — then resend 🪞");
|
|
57
52
|
// The search "model" names the provider (or an alias/combo of one). A
|
|
58
53
|
// thinking suffix is stripped for the same reason the canonical preparer
|
|
59
54
|
// strips it: it is not part of any registered id.
|
|
60
|
-
const {
|
|
61
|
-
|
|
62
|
-
bareModel === search.model ? search : { ...search, model: bareModel };
|
|
63
|
-
if (!authorization.snapshot.scopes?.includes("search:invoke" as never)) {
|
|
55
|
+
const { bareModel, body: searchBody } = stripThinkingSuffix(search.model, search);
|
|
56
|
+
if (!hasScope(authorization?.snapshot.scopes, "search:invoke")) {
|
|
64
57
|
throw new GatewayError("policy_rejected", 403, "search not allowed for this key (request {requestId}) — enable search:invoke on the API key. Not allowed by policy — no hard feelings 🫂");
|
|
65
58
|
}
|
|
66
59
|
// Trust boundary only: the query must be a non-empty string. The adapter
|
|
@@ -91,19 +84,7 @@ export function createWebsearchHandler(deps: WebsearchHandlerDeps) {
|
|
|
91
84
|
strictPoolSelection: false,
|
|
92
85
|
exhaustedError: new GatewayError("route_unavailable", 503, "no eligible search route (request {requestId}). The bouncer stepped out — come back shortly 🚪"),
|
|
93
86
|
prepare: async (candidate) => {
|
|
94
|
-
const credential = candidate
|
|
95
|
-
? await resolveCredentialForAccount(
|
|
96
|
-
deps.db,
|
|
97
|
-
candidate.provider_id,
|
|
98
|
-
candidate.provider_account_id,
|
|
99
|
-
deps.oauthRefreshService && deps.resolveOAuthRefresher
|
|
100
|
-
? { refreshService: deps.oauthRefreshService, resolveRefresher: deps.resolveOAuthRefresher }
|
|
101
|
-
: undefined,
|
|
102
|
-
)
|
|
103
|
-
: {
|
|
104
|
-
provider_id: candidate.provider_id as ProviderAdapter["provider_id"],
|
|
105
|
-
credential_kind: "none" as const,
|
|
106
|
-
};
|
|
87
|
+
const credential = await resolveAttemptCredential(deps, candidate);
|
|
107
88
|
const adapter = (await deps.resolveProviderAdapter?.(candidate.provider_id)) as WebsearchAdapter | undefined;
|
|
108
89
|
if (!adapter || typeof adapter.websearch !== "function")
|
|
109
90
|
throw new GatewayError(
|
|
@@ -132,14 +113,7 @@ export function createWebsearchHandler(deps: WebsearchHandlerDeps) {
|
|
|
132
113
|
deadline: state.deadlineMs,
|
|
133
114
|
abort_signal: state.abortController.signal,
|
|
134
115
|
...(candidate.user_agent === undefined ? {} : { user_agent: candidate.user_agent }),
|
|
135
|
-
...(deps.
|
|
136
|
-
? {
|
|
137
|
-
outbound_fetch: deps.networkBindingFactory.fetch(
|
|
138
|
-
leases.proxySlot?.poolId,
|
|
139
|
-
authorization.tenantId,
|
|
140
|
-
),
|
|
141
|
-
}
|
|
142
|
-
: {}),
|
|
116
|
+
...networkFetchContext(deps, leases.proxySlot?.poolId, authorization.tenantId),
|
|
143
117
|
});
|
|
144
118
|
const payload = {
|
|
145
119
|
provider: candidate.provider_id,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { timingSafeEqual } from "node:crypto";
|
|
21
21
|
import { GatewayError } from "../protocol/gateway-error";
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface DrainEndpointDeps {
|
|
24
24
|
/** Shared secret; the route is registered only when this is set. */
|
|
25
25
|
readonly token: string;
|
|
26
26
|
/** Begins the graceful drain (the process's own shutdown path). */
|
|
@@ -656,6 +656,12 @@ const QUOTA_ERROR_IDENTIFIERS: ReadonlySet<string> = new Set([
|
|
|
656
656
|
// it is a spend/limit verdict, never an auth one, so it must classify as
|
|
657
657
|
// quota (a cooldown) instead of `auth_invalidated`.
|
|
658
658
|
"110",
|
|
659
|
+
// Qoder also reports quota exhaustion as `{"code":116,"error":"quota
|
|
660
|
+
// exceeded"}` (seen on the IDE model-server surface with a 499/stream
|
|
661
|
+
// close). The 499 special-case below already treats qoder 499 as quota;
|
|
662
|
+
// naming the code here makes any status that carries it classify as quota
|
|
663
|
+
// instead of `invalid_request`/`authentication_failed`.
|
|
664
|
+
"116",
|
|
659
665
|
// InferHub publishes its own vocabulary in `error.code`. The two 403s below
|
|
660
666
|
// are deliberate absences: `account_blocked` means the account was blocked
|
|
661
667
|
// (an auth/entitlement verdict, not a spend limit) and
|
|
@@ -20,12 +20,6 @@ import { createAccessDecision } from "../../security/access-control";
|
|
|
20
20
|
export function createApiKeyAuthenticationMiddleware(deps: {
|
|
21
21
|
readonly db: CartethyiaDatabase;
|
|
22
22
|
readonly stateStore: ProxyRequestStateStore;
|
|
23
|
-
/**
|
|
24
|
-
* Model-abuse ban gate. A banned IP or key is refused here, before the
|
|
25
|
-
* canonical parse and route preparation, and before `state.authorization` is
|
|
26
|
-
* assigned — so a banned caller's attempts produce no telemetry row and no
|
|
27
|
-
* console error, which is exactly the noise this layer exists to stop.
|
|
28
|
-
*/
|
|
29
23
|
/**
|
|
30
24
|
* Tenant invoke kill switch. Checked after the key resolves, because the
|
|
31
25
|
* tenant is a property of the key: the same gateway serves several tenants
|
|
@@ -4,7 +4,7 @@ import { GatewayError } from "../../protocol/gateway-error";
|
|
|
4
4
|
import { assertBoundedJsonDepth } from "../../protocol/codecs";
|
|
5
5
|
import type { ProxyRequestStateStore } from "../request/state";
|
|
6
6
|
import { fastPathname } from "../pathname";
|
|
7
|
-
import { NATIVE_SERVICE_PATHS, TOKEN_COUNT_PATH } from "../contracts";
|
|
7
|
+
import { NATIVE_SERVICE_PATHS, RESPONSES_COMPACT_PATH, TOKEN_COUNT_PATH } from "../contracts";
|
|
8
8
|
import { bodyTooLargeError } from "./guard-errors";
|
|
9
9
|
|
|
10
10
|
/** Whether this request is a gateway (`/v1/*`) request. */
|
|
@@ -33,7 +33,7 @@ const PROXY_JSON_ROUTES = [
|
|
|
33
33
|
"/v1/chat/completions",
|
|
34
34
|
"/v1/responses",
|
|
35
35
|
"/v1/completions",
|
|
36
|
-
|
|
36
|
+
RESPONSES_COMPACT_PATH,
|
|
37
37
|
"/v1/messages",
|
|
38
38
|
// Reads a JSON body through the ingress policy but skips the canonical chat
|
|
39
39
|
// stage — see `isOpaqueBodyRoute`. Listed here because this table must mirror
|
|
@@ -62,7 +62,7 @@ export function isJsonProxyRoutePath(path: string): boolean {
|
|
|
62
62
|
return isJsonProxyRoute(path);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
interface IngressPolicyOptions {
|
|
66
66
|
readonly maxBodyBytes?: number;
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -31,7 +31,7 @@ const SHED_MARKER_TTL_SECONDS = 5;
|
|
|
31
31
|
const SHED_MARKER_KEY = "gateway:shed:v1";
|
|
32
32
|
const SHED_RETRY_MS = 1_000;
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
interface HeadroomGuardDeps {
|
|
35
35
|
readonly store: ProxyRequestStateStore;
|
|
36
36
|
/**
|
|
37
37
|
* The last sampled memory state, published once per sample by
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
} from "../../observability/payload-capture";
|
|
36
36
|
|
|
37
37
|
/** Shared state/context carried by every ordered transport stage. */
|
|
38
|
-
|
|
38
|
+
interface TransportPipelineContext {
|
|
39
39
|
readonly db: CartethyiaDatabase;
|
|
40
40
|
readonly stateStore: ProxyRequestStateStore;
|
|
41
41
|
readonly surfaceRegistry: SurfaceAdapterRegistry;
|
|
@@ -24,7 +24,7 @@ interface RequestApp {
|
|
|
24
24
|
): RequestApp;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
interface RequestContextDeps {
|
|
28
28
|
readonly stateStore: ProxyRequestStateStore;
|
|
29
29
|
readonly clock?: () => number;
|
|
30
30
|
/** Explicit deadline override; defaults to `CARTETHYIA_UPSTREAM_TIMEOUT_MS` (120s). */
|
|
@@ -148,8 +148,7 @@ export function createCanonicalRequestMiddleware(deps: {
|
|
|
148
148
|
// the JSON routes table, so the body-policy predicate covers it.
|
|
149
149
|
// Native routes (compact, System One) read a body but are never parsed
|
|
150
150
|
// into a canonical request — their bodies are opaque by contract.
|
|
151
|
-
if (!isJsonProxyRoutePath(path) ||
|
|
152
|
-
return;
|
|
151
|
+
if (!isJsonProxyRoutePath(path) || isOpaqueBodyRoute(path)) return;
|
|
153
152
|
// Model discovery and other GET/multimodal routes must not go through canonical parsing.
|
|
154
153
|
const state = deps.stateStore.require(request);
|
|
155
154
|
// Single-read invariant: the ingress policy middleware already decoded the
|
|
@@ -221,25 +220,21 @@ export function createProxyRoutePreparationMiddleware(deps: {
|
|
|
221
220
|
if (!path.startsWith("/v1/")) return;
|
|
222
221
|
if (request.method === "GET" || request.method === "HEAD") return;
|
|
223
222
|
const isJsonRoute = isJsonProxyRoutePath(path);
|
|
224
|
-
if (!isJsonRoute ||
|
|
223
|
+
if (!isJsonRoute || isOpaqueBodyRoute(path)) return;
|
|
225
224
|
const state = deps.stateStore.require(request);
|
|
226
225
|
if (!state.authorization || !state.canonicalRequest)
|
|
227
226
|
throw new GatewayError("route_unavailable", 503, "The request was not authenticated and parsed, so this route cannot be served (request {requestId}). Resend the request. The bouncer stepped out — resend shortly 🚪");
|
|
228
227
|
// The key rides along so a strike is charged to the caller that made it.
|
|
229
228
|
// Without it, one recipient of a shared link could escalate a ban onto
|
|
230
|
-
|
|
231
|
-
state.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
});
|
|
240
|
-
} catch (error) {
|
|
241
|
-
throw error;
|
|
242
|
-
}
|
|
229
|
+
state.preparedRequest = await deps.preparer.prepare({
|
|
230
|
+
canonicalRequest: state.canonicalRequest,
|
|
231
|
+
authorization: state.authorization,
|
|
232
|
+
deadlineMs: state.deadlineMs,
|
|
233
|
+
signal: state.abortController.signal,
|
|
234
|
+
...(state.clientUserAgent === undefined
|
|
235
|
+
? {}
|
|
236
|
+
: { clientUserAgent: state.clientUserAgent }),
|
|
237
|
+
});
|
|
243
238
|
})
|
|
244
239
|
.as("plugin");
|
|
245
240
|
}
|