cartethyia 2.7.4 → 2.7.6
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 +5 -0
- package/README.md +18 -6
- package/dist/dashboard/assets/BannedPage-B1N603cM.js +1 -0
- package/dist/dashboard/assets/BannedPage-B1N603cM.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js +3 -0
- package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js +1 -0
- package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-D762MIkp.js +1 -0
- package/dist/dashboard/assets/CombosPage-D762MIkp.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js +899 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js +1 -0
- package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-C6WlpU5E.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js +1 -0
- package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-DxjvUzSD.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-DxjvUzSD.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-OaHScjpX.js +1 -0
- package/dist/dashboard/assets/QuotaPage-OaHScjpX.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-44BZrxFC.js +1 -0
- package/dist/dashboard/assets/SetupPage-44BZrxFC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-DRPavCdU.js} +4 -4
- package/dist/dashboard/assets/StudioPage-DRPavCdU.js.gz +0 -0
- package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js +1 -0
- package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-B7M7LvMM.js +56 -0
- package/dist/dashboard/assets/UsagePage-B7M7LvMM.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-KvX83mRe.js +1 -0
- package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
- package/dist/dashboard/assets/app-DRnQLhsc.js +9 -0
- package/dist/dashboard/assets/app-DRnQLhsc.js.gz +0 -0
- package/dist/dashboard/assets/app-mweRcsKp.css +2 -0
- package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
- package/dist/dashboard/assets/assert-CidQVoNo.js +1 -0
- package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-BaX2GTrn.js} +1 -1
- package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DympBNq4.js → banner-DFH4Bkte.js} +1 -1
- package/dist/dashboard/assets/banner-DFH4Bkte.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-CxDw0lK6.js} +1 -1
- package/dist/dashboard/assets/card-CxDw0lK6.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/circle-question-mark-Cz4un8sH.js +1 -0
- package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +1 -0
- package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-DfS1ntiq.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BK-NRr5u.js +1 -0
- package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-QqPul6sC.js} +1 -1
- package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
- package/dist/dashboard/assets/entry-BMlYJVFj.js +1 -0
- package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
- package/dist/dashboard/assets/entry-D6WvojeD.js +4 -0
- package/dist/dashboard/assets/entry-D6WvojeD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Dmx7gBiN.js +1 -0
- package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-u7JPB5BX.js} +1 -1
- package/dist/dashboard/assets/formatters-u7JPB5BX.js.gz +0 -0
- package/dist/dashboard/assets/house-h9AZlJuT.js +1 -0
- package/dist/dashboard/assets/house-h9AZlJuT.js.gz +0 -0
- package/dist/dashboard/assets/{index-DBNPOfhV.js → index-Ko4dLRnV.js} +2 -2
- package/dist/dashboard/assets/index-Ko4dLRnV.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-CHJQwxLa.js} +1 -1
- package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
- package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BlmlizVV.js} +1 -1
- package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
- package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-Bz93I-yE.js} +1 -1
- package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Ml16KCfu.js} +1 -1
- package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
- package/dist/dashboard/assets/live-7_QpnYGu.js +1 -0
- package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-Rr0TIvcj.js → mutation-GU7XdEjz.js} +1 -1
- package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
- package/dist/dashboard/assets/network-CuMDaTzT.js +1 -0
- package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CoqpaDMx.js +2 -0
- package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
- package/dist/dashboard/assets/pagination-B5aOoweZ.js +1 -0
- package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
- package/dist/dashboard/assets/providers/zai.webp +0 -0
- package/dist/dashboard/assets/providers/zcode.webp +0 -0
- package/dist/dashboard/assets/{query-keys-BloKtaXJ.js → query-keys-YSoQOUh6.js} +1 -1
- package/dist/dashboard/assets/{query-keys-BloKtaXJ.js.gz → query-keys-YSoQOUh6.js.gz} +0 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js +1 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
- package/dist/dashboard/assets/routing-fnCsxgNO.js +1 -0
- package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
- package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BHqpd-bg.js} +2 -2
- package/dist/dashboard/assets/select-BHqpd-bg.js.gz +0 -0
- package/dist/dashboard/assets/settings-BxslsErn.js +1 -0
- package/dist/dashboard/assets/settings-BxslsErn.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-j7cXjgYX.js} +1 -1
- package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
- package/dist/dashboard/assets/{state-CkfdYWel.js → state-DHmEnLa2.js} +1 -1
- package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
- package/dist/dashboard/assets/{switch-SYm237HG.js → switch-DmZcyTIC.js} +1 -1
- package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-CbCP4w1o.js} +1 -1
- package/dist/dashboard/assets/useMutation-CbCP4w1o.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 +60 -59
- 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/full-postgres/0042_add_telemetry_degenerate_stop.sql +14 -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/migrations/lite-sqlite3/0042_add_telemetry_degenerate_stop.sql +12 -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 +794 -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 +19 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +33 -6
- package/src/config/usage.ts +27 -0
- 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 +56 -24
- 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 +43 -299
- package/src/console/cli-tools/fs-ops.ts +29 -0
- package/src/console/cli-tools/injectors/claude.ts +3 -3
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/driver.ts +150 -247
- package/src/console/cli-tools/injectors/kilo.ts +146 -21
- package/src/console/cli-tools/injectors/opencode.ts +176 -153
- package/src/console/cli-tools/routes.ts +7 -1
- package/src/console/cli-tools/service.ts +8 -7
- 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 +7 -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 +23 -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 +11 -13
- 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 +9 -2
- package/src/observability/event-query.ts +61 -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 +19 -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 +121 -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 +29 -2
- 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 +8 -125
- 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 +71 -4
- 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 +35 -37
- 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 +88 -28
- package/src/providers/integrations/antigravity/antigravity-quota.ts +18 -6
- package/src/providers/integrations/antigravity/antigravity.ts +22 -13
- 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 +35 -3
- 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 +70 -12
- package/src/providers/integrations/github/github-oauth.ts +184 -14
- package/src/providers/integrations/github/github.ts +134 -26
- 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 +80 -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 +94 -11
- 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 +422 -71
- 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 +51 -8
- 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 +198 -133
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/byok-wire-profile.ts +19 -15
- 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 +50 -19
- 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 +13 -6
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +17 -3
- 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 +70 -22
- package/src/transport/dispatch/attempt-loop.ts +22 -0
- 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 +21 -1
- package/src/transport/guards/auth-guard.ts +0 -6
- package/src/transport/guards/body-policy.ts +3 -3
- package/src/transport/guards/error-lifecycle.ts +4 -0
- 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 +7 -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 +159 -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/reasoning-summary.ts +9 -14
- 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 +431 -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 +0 -1
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +0 -1
- 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 +0 -1
- 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 +0 -1
- 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 +0 -1
- 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/ToolIcon-K1ckcDKg.js +0 -1
- package/dist/dashboard/assets/ToolIcon-K1ckcDKg.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-BayTTy01.js +0 -9
- package/dist/dashboard/assets/app-BayTTy01.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 +0 -1
- 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 +0 -1
- 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 +0 -1
- 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/mutation-Rr0TIvcj.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/providers/zai-coding-plan.svg +0 -6
- package/dist/dashboard/assets/providers/zai-coding-plan.svg.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/console/cli-tools/injectors/cline.ts +0 -110
- package/src/console/cli-tools/injectors/copilot.ts +0 -108
- package/src/console/cli-tools/injectors/cowork.ts +0 -64
- package/src/console/cli-tools/injectors/deepseek-tui.ts +0 -85
- package/src/console/cli-tools/injectors/droid.ts +0 -96
- package/src/console/cli-tools/injectors/grok-build.ts +0 -70
- package/src/console/cli-tools/injectors/hermes.ts +0 -101
- package/src/console/cli-tools/injectors/jcode.ts +0 -115
- package/src/console/cli-tools/injectors/openclaw.ts +0 -161
- 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/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
package/src/protocol/registry.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CanonicalEvent, CanonicalRequest, WireFamily } from "./canonical-model";
|
|
2
|
+
import type { DialectPolicy } from "./translation/dialect/types";
|
|
3
|
+
import type { ThinkingConfig } from "./translation/dialect/thinking-ladder";
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
interface CodecContext {
|
|
4
6
|
readonly isOAuth?: boolean;
|
|
5
7
|
readonly sessionId?: string;
|
|
6
8
|
readonly supportsPromptCaching?: boolean;
|
|
@@ -13,6 +15,16 @@ export interface CodecContext {
|
|
|
13
15
|
* deployment default; only wire encoders that clamp images read it.
|
|
14
16
|
*/
|
|
15
17
|
readonly maxBytesOverride?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Resolved wire dialect (see `translation/dialect`). Absent = the codec's
|
|
20
|
+
* own default behavior (today's exact bytes).
|
|
21
|
+
*/
|
|
22
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
23
|
+
/**
|
|
24
|
+
* Resolved thinking config (see `translation/dialect/thinking-ladder`).
|
|
25
|
+
* Absent = the codec's own default behavior (today's exact clamp/ladder).
|
|
26
|
+
*/
|
|
27
|
+
readonly thinking?: ThinkingConfig;
|
|
16
28
|
}
|
|
17
29
|
|
|
18
30
|
/**
|
|
@@ -27,7 +39,13 @@ type CodecModule =
|
|
|
27
39
|
readonly family: "messages";
|
|
28
40
|
readonly encodeWireRequest: (
|
|
29
41
|
request: CanonicalRequest,
|
|
30
|
-
options?: {
|
|
42
|
+
options?: {
|
|
43
|
+
readonly isOAuth?: boolean;
|
|
44
|
+
readonly maxBytesOverride?: number;
|
|
45
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
46
|
+
readonly thinking?: ThinkingConfig;
|
|
47
|
+
readonly maxOutputTokens?: number;
|
|
48
|
+
},
|
|
31
49
|
) => Record<string, unknown>;
|
|
32
50
|
readonly decodeWireResponse: (
|
|
33
51
|
json: Record<string, unknown>,
|
|
@@ -48,6 +66,8 @@ type CodecModule =
|
|
|
48
66
|
readonly supportsPromptCaching?: boolean;
|
|
49
67
|
readonly tokenLimitField?: "max_tokens" | "max_completion_tokens";
|
|
50
68
|
readonly promptCacheKey?: string;
|
|
69
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
70
|
+
readonly thinking?: ThinkingConfig;
|
|
51
71
|
},
|
|
52
72
|
) => Record<string, unknown>;
|
|
53
73
|
readonly decodeWireResponse: (
|
|
@@ -58,6 +78,7 @@ type CodecModule =
|
|
|
58
78
|
body: ReadableStream<Uint8Array>,
|
|
59
79
|
request: CanonicalRequest,
|
|
60
80
|
signal?: AbortSignal,
|
|
81
|
+
options?: { readonly dialectPolicy?: DialectPolicy },
|
|
61
82
|
) => AsyncIterable<CanonicalEvent>;
|
|
62
83
|
}
|
|
63
84
|
| {
|
|
@@ -67,6 +88,9 @@ type CodecModule =
|
|
|
67
88
|
options?: {
|
|
68
89
|
readonly supportsPromptCaching?: boolean;
|
|
69
90
|
readonly promptCacheKey?: string;
|
|
91
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
92
|
+
readonly thinking?: ThinkingConfig;
|
|
93
|
+
readonly maxOutputTokens?: number;
|
|
70
94
|
},
|
|
71
95
|
) => Record<string, unknown>;
|
|
72
96
|
readonly decodeWireResponse: (
|
|
@@ -89,8 +113,10 @@ type CodecModule =
|
|
|
89
113
|
*
|
|
90
114
|
* The dynamic import is awaited by the caller. Wire encoding happens before the
|
|
91
115
|
* upstream request is issued, so the cost is paid once, on the first request,
|
|
92
|
-
*
|
|
93
|
-
*
|
|
116
|
+
* The cost is paid once, on the first request for that family, because wire
|
|
117
|
+
* encoding happens before the upstream request is issued. There is no preload
|
|
118
|
+
* at boot: no family is knowable then, and eagerly loading all three codecs
|
|
119
|
+
* would defeat the ~50 MiB of resident memory this indirection removes.
|
|
94
120
|
*/
|
|
95
121
|
const codecCache = new Map<WireFamily, Promise<CodecModule>>();
|
|
96
122
|
|
|
@@ -103,8 +129,8 @@ const codecCache = new Map<WireFamily, Promise<CodecModule>>();
|
|
|
103
129
|
* a gateway instance only ever serves one family.
|
|
104
130
|
*
|
|
105
131
|
* The cost is paid once, on the first request for that family, because wire
|
|
106
|
-
* encoding happens before the upstream request is issued.
|
|
107
|
-
*
|
|
132
|
+
* encoding happens before the upstream request is issued. No boot-time preload
|
|
133
|
+
* exists — see the note on `codecCache` above.
|
|
108
134
|
*/
|
|
109
135
|
async function loadCodec(wireFamily: WireFamily): Promise<CodecModule> {
|
|
110
136
|
const cached = codecCache.get(wireFamily);
|
|
@@ -127,15 +153,6 @@ async function loadCodec(wireFamily: WireFamily): Promise<CodecModule> {
|
|
|
127
153
|
return promise;
|
|
128
154
|
}
|
|
129
155
|
|
|
130
|
-
/**
|
|
131
|
-
* Warms the codec module for a wire family during boot so the first request
|
|
132
|
-
* does not pay the dynamic-import cost. Safe to call concurrently; the cache
|
|
133
|
-
* deduplicates.
|
|
134
|
-
*/
|
|
135
|
-
export function preloadCodec(wireFamily: WireFamily): Promise<void> {
|
|
136
|
-
return loadCodec(wireFamily).then(() => undefined);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
156
|
export async function encodeWireRequest(
|
|
140
157
|
wireFamily: WireFamily,
|
|
141
158
|
request: CanonicalRequest,
|
|
@@ -148,6 +165,11 @@ export async function encodeWireRequest(
|
|
|
148
165
|
...(context?.maxBytesOverride === undefined
|
|
149
166
|
? {}
|
|
150
167
|
: { maxBytesOverride: context.maxBytesOverride }),
|
|
168
|
+
...(context?.maxOutputTokens === undefined
|
|
169
|
+
? {}
|
|
170
|
+
: { maxOutputTokens: context.maxOutputTokens }),
|
|
171
|
+
...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
|
|
172
|
+
...(context?.thinking === undefined ? {} : { thinking: context.thinking }),
|
|
151
173
|
});
|
|
152
174
|
}
|
|
153
175
|
if (codec.family === "chat") {
|
|
@@ -164,6 +186,8 @@ export async function encodeWireRequest(
|
|
|
164
186
|
...(context?.promptCacheKey === undefined
|
|
165
187
|
? {}
|
|
166
188
|
: { promptCacheKey: context.promptCacheKey }),
|
|
189
|
+
...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
|
|
190
|
+
...(context?.thinking === undefined ? {} : { thinking: context.thinking }),
|
|
167
191
|
});
|
|
168
192
|
}
|
|
169
193
|
return codec.encodeWireRequest(request, {
|
|
@@ -173,6 +197,11 @@ export async function encodeWireRequest(
|
|
|
173
197
|
...(context?.promptCacheKey === undefined
|
|
174
198
|
? {}
|
|
175
199
|
: { promptCacheKey: context.promptCacheKey }),
|
|
200
|
+
...(context?.maxOutputTokens === undefined
|
|
201
|
+
? {}
|
|
202
|
+
: { maxOutputTokens: context.maxOutputTokens }),
|
|
203
|
+
...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
|
|
204
|
+
...(context?.thinking === undefined ? {} : { thinking: context.thinking }),
|
|
176
205
|
});
|
|
177
206
|
}
|
|
178
207
|
|
|
@@ -206,6 +235,12 @@ export function decodeWireStream(
|
|
|
206
235
|
yield* codec.decodeWireStream(body, context?.signal, context?.isOAuth ?? false);
|
|
207
236
|
return;
|
|
208
237
|
}
|
|
238
|
+
if (codec.family === "chat") {
|
|
239
|
+
yield* codec.decodeWireStream(body, request, context?.signal, {
|
|
240
|
+
...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
|
|
241
|
+
});
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
209
244
|
yield* codec.decodeWireStream(body, request, context?.signal);
|
|
210
245
|
}
|
|
211
246
|
return decode();
|
|
@@ -8,15 +8,19 @@ import { isWebSearchTool } from "../../protocol/translation/search";
|
|
|
8
8
|
import { pickWireSupportedControls } from "../../protocol/translation/capabilities";
|
|
9
9
|
import { normalizeWireMaxTokens } from "../../protocol/translation/normalize";
|
|
10
10
|
import { resolveWireMaxTokens } from "../../protocol/translation/quirks";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "../../protocol/translation/thinking";
|
|
11
|
+
import { DEFAULT_DIALECT_POLICIES } from "../../protocol/translation/dialect/rules";
|
|
12
|
+
import type { DialectPolicy } from "../../protocol/translation/dialect/types";
|
|
13
|
+
import type { ThinkingConfig } from "../../protocol/translation/dialect/thinking-ladder";
|
|
14
|
+
import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
|
|
15
|
+
import { clampThinkingLevelForModel } from "../../protocol/translation/dialect/model-thinking";
|
|
15
16
|
import { isClaudeBillingHeaderText, resolveImageSource } from "../codecs";
|
|
16
17
|
import { resolvePromptCacheKey } from "../../providers/operations/session-resolution";
|
|
17
18
|
import { reasoningEffortFromIntent } from "../../protocol/reasoning";
|
|
18
19
|
import { parseChatResponseToEvents, decodeChatSseStream } from "../response/chat";
|
|
19
20
|
|
|
21
|
+
/** Fallback when no resolved policy is supplied — today's exact behavior. */
|
|
22
|
+
const DEFAULT_CHAT_DIALECT_POLICY: DialectPolicy = DEFAULT_DIALECT_POLICIES.openai;
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* OpenAI `input_audio.format` accepts only the discrete ids `wav`/`mp3`, never a
|
|
22
26
|
* MIME type. The canonical `audio` part carries a `media_type`; map it here and
|
|
@@ -182,15 +186,31 @@ export function canonicalToChatPayload(
|
|
|
182
186
|
readonly tokenLimitField?: "max_tokens" | "max_completion_tokens";
|
|
183
187
|
readonly maxOutputTokens?: number;
|
|
184
188
|
readonly promptCacheKey?: string;
|
|
189
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
190
|
+
readonly thinking?: ThinkingConfig;
|
|
185
191
|
} = {},
|
|
186
192
|
): Record<string, unknown> {
|
|
193
|
+
const policy = options.dialectPolicy ?? DEFAULT_CHAT_DIALECT_POLICY;
|
|
194
|
+
const resolvedThinking = options.thinking ?? resolveThinkingForModel(request.model, "", "chat");
|
|
187
195
|
const supportsPromptCaching = options.supportsPromptCaching ?? true;
|
|
188
|
-
const tokenLimitField = options.tokenLimitField ??
|
|
196
|
+
const tokenLimitField = options.tokenLimitField ?? policy.maxTokensField;
|
|
197
|
+
const reasoningField = policy.reasoningContentField;
|
|
198
|
+
const carryReasoning = (has: boolean, text: string): Record<string, unknown> =>
|
|
199
|
+
has && reasoningField !== undefined ? { [reasoningField]: text } : {};
|
|
189
200
|
const messages: Array<Record<string, unknown>> = [];
|
|
201
|
+
const systemTexts: string[] = [];
|
|
190
202
|
if (request.system?.length) {
|
|
191
203
|
for (const p of request.system) {
|
|
192
|
-
if (p.kind === "text" && !isClaudeBillingHeaderText(p.text))
|
|
193
|
-
|
|
204
|
+
if (p.kind === "text" && !isClaudeBillingHeaderText(p.text)) systemTexts.push(p.text);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (systemTexts.length > 0) {
|
|
208
|
+
if (policy.supportsMultipleSystemMessages) {
|
|
209
|
+
for (const text of systemTexts) messages.push({ role: "system", content: text });
|
|
210
|
+
} else {
|
|
211
|
+
// Strict chat templates (Qwen Portal / Alibaba / MiniMax) accept a single
|
|
212
|
+
// system message; join the canonical system parts into one.
|
|
213
|
+
messages.push({ role: "system", content: systemTexts.join("\n") });
|
|
194
214
|
}
|
|
195
215
|
}
|
|
196
216
|
if (request.instructions?.length) {
|
|
@@ -217,6 +237,12 @@ export function canonicalToChatPayload(
|
|
|
217
237
|
(c): c is Extract<typeof c, { kind: "text" }> => c.kind === "text",
|
|
218
238
|
);
|
|
219
239
|
const content = textParts.length ? textParts.map((c) => c.text).join("\n") : null;
|
|
240
|
+
// DeepSeek V4 requires the assistant content field to be present on a
|
|
241
|
+
// tool-call turn; a null content would be rejected verbatim.
|
|
242
|
+
const effectiveContent =
|
|
243
|
+
policy.requiresAssistantContentForToolCalls && (content === null || content.length === 0)
|
|
244
|
+
? ""
|
|
245
|
+
: content;
|
|
220
246
|
// Reasoning must survive on a tool-call turn, not just on plain assistant
|
|
221
247
|
// turns. Providers in thinking mode require the previous turn's reasoning
|
|
222
248
|
// to be replayed, and the tool-call turn is exactly where a thinking
|
|
@@ -237,9 +263,9 @@ export function canonicalToChatPayload(
|
|
|
237
263
|
const hasReasoning = m.content.some((c) => c.kind === "reasoning");
|
|
238
264
|
messages.push({
|
|
239
265
|
role: "assistant",
|
|
240
|
-
content,
|
|
266
|
+
content: effectiveContent,
|
|
241
267
|
tool_calls: toolCalls,
|
|
242
|
-
...(hasReasoning
|
|
268
|
+
...carryReasoning(hasReasoning, reasoningContent),
|
|
243
269
|
});
|
|
244
270
|
} else if (m.role === "tool") {
|
|
245
271
|
for (const p of m.content) {
|
|
@@ -332,9 +358,7 @@ export function canonicalToChatPayload(
|
|
|
332
358
|
messages.push({
|
|
333
359
|
role: m.role,
|
|
334
360
|
content: parts,
|
|
335
|
-
...(m.role === "assistant" && hasReasoning
|
|
336
|
-
? { reasoning_content: reasoningContent }
|
|
337
|
-
: {}),
|
|
361
|
+
...carryReasoning(m.role === "assistant" && hasReasoning, reasoningContent),
|
|
338
362
|
});
|
|
339
363
|
} else {
|
|
340
364
|
// A user turn whose toolResult parts were all folded out above has
|
|
@@ -374,7 +398,7 @@ export function canonicalToChatPayload(
|
|
|
374
398
|
messages.push({
|
|
375
399
|
role: "assistant",
|
|
376
400
|
content: "",
|
|
377
|
-
|
|
401
|
+
...carryReasoning(true, reasoningContent),
|
|
378
402
|
});
|
|
379
403
|
continue;
|
|
380
404
|
}
|
|
@@ -401,9 +425,7 @@ export function canonicalToChatPayload(
|
|
|
401
425
|
messages.push({
|
|
402
426
|
role: m.role,
|
|
403
427
|
content,
|
|
404
|
-
...(m.role === "assistant" && hasReasoning
|
|
405
|
-
? { reasoning_content: reasoningContent }
|
|
406
|
-
: {}),
|
|
428
|
+
...carryReasoning(m.role === "assistant" && hasReasoning, reasoningContent),
|
|
407
429
|
});
|
|
408
430
|
}
|
|
409
431
|
}
|
|
@@ -458,7 +480,7 @@ export function canonicalToChatPayload(
|
|
|
458
480
|
};
|
|
459
481
|
});
|
|
460
482
|
}
|
|
461
|
-
if (request.tool_choice) {
|
|
483
|
+
if (request.tool_choice && policy.supportsToolChoice) {
|
|
462
484
|
if (typeof request.tool_choice === "object" && request.tool_choice.type === "allowed_tools") {
|
|
463
485
|
payload["tool_choice"] = {
|
|
464
486
|
type: "allowed_tools",
|
|
@@ -484,11 +506,16 @@ export function canonicalToChatPayload(
|
|
|
484
506
|
// is what the Codex encoder already uses); deriving it here instead of in
|
|
485
507
|
// each codec is what keeps a translated request from silently losing it.
|
|
486
508
|
if (request.reasoning !== undefined) {
|
|
487
|
-
const effort =
|
|
509
|
+
const effort = clampThinkingLevelForModel(
|
|
510
|
+
resolvedThinking,
|
|
488
511
|
reasoningEffortFromIntent(request.reasoning),
|
|
489
|
-
resolveSupportedReasoningEfforts(request.model, "chat"),
|
|
490
512
|
);
|
|
491
513
|
if (effort !== undefined) payload["reasoning_effort"] = effort;
|
|
514
|
+
// Qwen chat templates select thinking with `enable_thinking` (plus optional
|
|
515
|
+
// `thinking_budget`) instead of `reasoning_effort`.
|
|
516
|
+
if (policy.thinkingFormat === "qwen" && effort !== undefined) {
|
|
517
|
+
payload["enable_thinking"] = true;
|
|
518
|
+
}
|
|
492
519
|
}
|
|
493
520
|
// Stream controls the caller asked for are forwarded upstream so a
|
|
494
521
|
// pass-through provider can honor them (the local encoder honors them too).
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
* `provider_options` key that opts one request into the Daybreak
|
|
28
28
|
* `access_programs.cyber` member. See the UNCONFIRMED note at its use site.
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
const CODEX_ACCESS_PROGRAMS_CYBER_OPTION = "codex_access_programs_cyber";
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Removes `access_programs` from an already-built Codex Responses payload.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Canonical → Claude Messages request builder.
|
|
3
3
|
*/
|
|
4
4
|
import { allParts, type CanonicalRequest, type ContentPart } from "../canonical-model";
|
|
5
|
+
import type { DialectPolicy } from "../translation/dialect/types";
|
|
5
6
|
import { buildAnthropicThinkingPayload } from "../../protocol/reasoning";
|
|
6
7
|
import { anthropicCacheControl } from "../../protocol/translation/cache-controls";
|
|
7
8
|
import {
|
|
@@ -28,14 +29,17 @@ import {
|
|
|
28
29
|
} from "../codecs";
|
|
29
30
|
import { log } from "../../observability/logger";
|
|
30
31
|
import { base64DecodedByteLength, clampImage } from "../image-clamp";
|
|
31
|
-
import {
|
|
32
|
+
import { LEVEL_TO_BUDGET } from "../../protocol/translation/thinking";
|
|
33
|
+
import type { ThinkingConfig } from "../../protocol/translation/dialect/thinking-ladder";
|
|
34
|
+
import { clampThinkingLevelForModel } from "../../protocol/translation/dialect/model-thinking";
|
|
35
|
+
import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
|
|
32
36
|
import { claudeResponseToEvents, parseClaudeSseStream } from "../response/messages";
|
|
33
37
|
|
|
34
38
|
/**
|
|
35
39
|
* Gateway default when the caller sent no max_tokens (Anthropic requires
|
|
36
40
|
* the field). Explicit and warned at the call site — never silent.
|
|
37
41
|
*/
|
|
38
|
-
|
|
42
|
+
const ANTHROPIC_DEFAULT_MAX_TOKENS = WIRE_TOKEN_BOUNDS["messages"]?.defaultMaxTokens ?? 4_096;
|
|
39
43
|
|
|
40
44
|
/** Anthropic Messages' documented base64-image media-type allowlist. */
|
|
41
45
|
const ANTHROPIC_IMAGE_MEDIA_TYPES = new Set([
|
|
@@ -556,7 +560,13 @@ export function claudeFallbacksChain(
|
|
|
556
560
|
|
|
557
561
|
export function canonicalToClaudeMessagesPayload(
|
|
558
562
|
request: CanonicalRequest,
|
|
559
|
-
options: {
|
|
563
|
+
options: {
|
|
564
|
+
isOAuth?: boolean;
|
|
565
|
+
maxBytesOverride?: number;
|
|
566
|
+
dialectPolicy?: DialectPolicy;
|
|
567
|
+
thinking?: ThinkingConfig;
|
|
568
|
+
maxOutputTokens?: number;
|
|
569
|
+
} = {},
|
|
560
570
|
): ClaudeWireObject {
|
|
561
571
|
const seen = new Map<string, number>();
|
|
562
572
|
const idMap = new Map<string, string>();
|
|
@@ -653,7 +663,11 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
653
663
|
const normalizedControls = normalizeWireMaxTokens(request.generation_controls);
|
|
654
664
|
const requestedMax = normalizedControls.max_tokens;
|
|
655
665
|
const hasTools = (request.tools?.length ?? 0) > 0;
|
|
656
|
-
let maxTokens = resolveWireMaxTokens("messages", { max_tokens: requestedMax }, {
|
|
666
|
+
let maxTokens = resolveWireMaxTokens("messages", { max_tokens: requestedMax }, {
|
|
667
|
+
hasTools,
|
|
668
|
+
isOAuth,
|
|
669
|
+
...(options.maxOutputTokens === undefined ? {} : { maxOutputTokens: options.maxOutputTokens }),
|
|
670
|
+
}) ?? ANTHROPIC_DEFAULT_MAX_TOKENS;
|
|
657
671
|
if (requestedMax === undefined) {
|
|
658
672
|
log.warn("claude: max_tokens absent, defaulting", {
|
|
659
673
|
max_tokens: maxTokens,
|
|
@@ -665,21 +679,32 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
665
679
|
});
|
|
666
680
|
}
|
|
667
681
|
const thinkingEnabled = isThinkingEnabled(request);
|
|
682
|
+
// Real ceilings (P2-12): an impossible thinking budget surfaces as a typed
|
|
683
|
+
// local 400 instead of an over-ceiling max_tokens that 400s opaquely upstream.
|
|
684
|
+
// Non-OAuth caps at the model's catalog output limit (when known) so the
|
|
685
|
+
// thinking guard can fire instead of shipping an over-catalog-limit
|
|
686
|
+
// `max_tokens`; OAuth keeps its own ceiling per the table.
|
|
687
|
+
const maxAllowed = isOAuth
|
|
688
|
+
? WIRE_TOKEN_BOUNDS["messages"]?.oauthCeiling ?? Number.MAX_SAFE_INTEGER
|
|
689
|
+
: options.maxOutputTokens ?? Number.MAX_SAFE_INTEGER;
|
|
668
690
|
if (thinkingEnabled && request.reasoning?.budget_tokens !== undefined) {
|
|
669
691
|
maxTokens = ensureMaxTokensForThinking(
|
|
670
692
|
maxTokens,
|
|
671
693
|
request.reasoning.budget_tokens,
|
|
672
|
-
|
|
694
|
+
maxAllowed,
|
|
673
695
|
);
|
|
674
696
|
}
|
|
675
697
|
// Whether this model speaks adaptive thinking (`type: "adaptive"` +
|
|
676
698
|
// `output_config.effort`) or budget thinking (`type: "enabled"` +
|
|
677
699
|
// `budget_tokens`). The two generations reject each other's shape, so the
|
|
678
|
-
// choice is made from the
|
|
679
|
-
// a chat/responses caller states only an effort, and a
|
|
680
|
-
// answers the adaptive shape with "adaptive thinking is not
|
|
681
|
-
// model" (verified live: opus-4-5/sonnet-4-5/haiku-4-5).
|
|
682
|
-
|
|
700
|
+
// choice is made from the resolved thinking config, not from the caller's
|
|
701
|
+
// canonical intent — a chat/responses caller states only an effort, and a
|
|
702
|
+
// budget-era model answers the adaptive shape with "adaptive thinking is not
|
|
703
|
+
// supported on this model" (verified live: opus-4-5/sonnet-4-5/haiku-4-5).
|
|
704
|
+
// When no config is supplied (direct-route callers), fall back to resolving
|
|
705
|
+
// it from the model/wire — the resolved `mode` IS the generation answer.
|
|
706
|
+
const resolvedThinking = options.thinking ?? resolveThinkingForModel(request.model, "", "messages");
|
|
707
|
+
const adaptiveThinking = resolvedThinking.mode === "anthropic-adaptive";
|
|
683
708
|
let effectiveBudgetTokens = request.reasoning?.budget_tokens;
|
|
684
709
|
// Derive a budget from the level whenever a budget-era model is asked to
|
|
685
710
|
// reason by effort alone. The gate is NOT `isThinkingEnabled`: a chat/responses
|
|
@@ -699,7 +724,13 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
699
724
|
if (!adaptiveThinking && effectiveBudgetTokens !== undefined) {
|
|
700
725
|
// The upstream requires the budget to stay below `max_tokens`; raise
|
|
701
726
|
// max_tokens to leave room for the answer rather than let it 400.
|
|
702
|
-
maxTokens = ensureMaxTokensForThinking(maxTokens, effectiveBudgetTokens,
|
|
727
|
+
maxTokens = ensureMaxTokensForThinking(maxTokens, effectiveBudgetTokens, maxAllowed);
|
|
728
|
+
}
|
|
729
|
+
// Final clamp to the model's catalog output limit: thinking may have raised
|
|
730
|
+
// `max_tokens` (e.g. under an OAuth ceiling wider than the catalog limit), so
|
|
731
|
+
// the value that ships must never exceed what the model can actually emit.
|
|
732
|
+
if (options.maxOutputTokens !== undefined && maxTokens > options.maxOutputTokens) {
|
|
733
|
+
maxTokens = options.maxOutputTokens;
|
|
703
734
|
}
|
|
704
735
|
const payload: ClaudeWireObject = {
|
|
705
736
|
model: request.model,
|
|
@@ -748,7 +779,8 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
748
779
|
}
|
|
749
780
|
const parallelToolCallsDisabled =
|
|
750
781
|
request.generation_controls.parallel_tool_calls === false;
|
|
751
|
-
|
|
782
|
+
const supportsToolChoice = options.dialectPolicy?.supportsToolChoice ?? true;
|
|
783
|
+
if (supportsToolChoice && (rawToolChoice !== undefined || parallelToolCallsDisabled)) {
|
|
752
784
|
const baseChoice = rawToolChoice as Record<string, unknown> | undefined;
|
|
753
785
|
const choice: Record<string, unknown> = baseChoice
|
|
754
786
|
? { ...baseChoice }
|
|
@@ -835,9 +867,9 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
835
867
|
// is NOT a wire field — display rides on `thinking.display` above.
|
|
836
868
|
// Clamp to the model's published ladder exactly like the chat/Responses
|
|
837
869
|
// codecs: an out-of-ladder tier is an upstream 4xx.
|
|
838
|
-
const effort =
|
|
870
|
+
const effort = clampThinkingLevelForModel(
|
|
871
|
+
resolvedThinking,
|
|
839
872
|
request.reasoning.effort,
|
|
840
|
-
resolveSupportedReasoningEfforts(request.model, "messages"),
|
|
841
873
|
);
|
|
842
874
|
const taskBudget = request.reasoning.task_budget;
|
|
843
875
|
// `output_config.effort` rides every generation: budget-era models accept it
|
|
@@ -7,10 +7,10 @@ import { markLatestBreakpoint } from "../../protocol/translation/cache-controls"
|
|
|
7
7
|
import { pickWireSupportedControls } from "../../protocol/translation/capabilities";
|
|
8
8
|
import { normalizeGenerationControls } from "../../protocol/translation/normalize";
|
|
9
9
|
import { resolveWireMaxTokens } from "../../protocol/translation/quirks";
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "../../protocol/translation/thinking";
|
|
10
|
+
import type { DialectPolicy } from "../../protocol/translation/dialect/types";
|
|
11
|
+
import type { ThinkingConfig } from "../../protocol/translation/dialect/thinking-ladder";
|
|
12
|
+
import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
|
|
13
|
+
import { clampThinkingLevelForModel } from "../../protocol/translation/dialect/model-thinking";
|
|
14
14
|
import { isClaudeBillingHeaderText, resolveImageSource, resolveOutputVerbosity } from "../codecs";
|
|
15
15
|
import { resolvePromptCacheKey } from "../../providers/operations/session-resolution";
|
|
16
16
|
import { reasoningEffortFromIntent } from "../../protocol/reasoning";
|
|
@@ -27,7 +27,7 @@ const RESPONSES_CACHEABLE_BLOCK_TYPES: ReadonlySet<string> = new Set([
|
|
|
27
27
|
]);
|
|
28
28
|
|
|
29
29
|
/** Marks the latest stable input block with an explicit prompt-cache breakpoint. */
|
|
30
|
-
|
|
30
|
+
function markLatestResponsesCacheBreakpoint(input: Array<Record<string, unknown>>): void {
|
|
31
31
|
markLatestBreakpoint(input, {
|
|
32
32
|
isInputItem: (item) =>
|
|
33
33
|
item["type"] === "message" && (item["role"] === "user" || item["role"] === "developer"),
|
|
@@ -63,9 +63,13 @@ export function canonicalToResponsesPayload(
|
|
|
63
63
|
options: {
|
|
64
64
|
readonly supportsPromptCaching?: boolean;
|
|
65
65
|
readonly promptCacheKey?: string;
|
|
66
|
+
readonly dialectPolicy?: DialectPolicy;
|
|
67
|
+
readonly thinking?: ThinkingConfig;
|
|
68
|
+
readonly maxOutputTokens?: number;
|
|
66
69
|
} = {},
|
|
67
70
|
): Record<string, unknown> {
|
|
68
71
|
const supportsPromptCaching = options.supportsPromptCaching ?? true;
|
|
72
|
+
const resolvedThinking = options.thinking ?? resolveThinkingForModel(request.model, "", "responses");
|
|
69
73
|
const input: Array<Record<string, unknown>> = [];
|
|
70
74
|
// `pending_safety_checks` have no canonical content-part representation, so
|
|
71
75
|
// `parseResponsesRequest` retains them per-item in the scoped item-metadata
|
|
@@ -317,10 +321,7 @@ export function canonicalToResponsesPayload(
|
|
|
317
321
|
// this wire. Codex already derives its tier this way.
|
|
318
322
|
const requestedEffort = reasoningEffortFromIntent(request.reasoning);
|
|
319
323
|
if (requestedEffort !== undefined) {
|
|
320
|
-
const effort =
|
|
321
|
-
requestedEffort,
|
|
322
|
-
resolveSupportedReasoningEfforts(request.model, "responses"),
|
|
323
|
-
);
|
|
324
|
+
const effort = clampThinkingLevelForModel(resolvedThinking, requestedEffort);
|
|
324
325
|
if (effort !== undefined) reasoning.effort = effort;
|
|
325
326
|
}
|
|
326
327
|
if (request.reasoning.mode !== undefined) reasoning.mode = request.reasoning.mode;
|
|
@@ -328,6 +329,12 @@ export function canonicalToResponsesPayload(
|
|
|
328
329
|
if (request.reasoning.summary_mode !== undefined)
|
|
329
330
|
reasoning.summary = request.reasoning.summary_mode;
|
|
330
331
|
else if (request.reasoning.summary !== undefined) reasoning.summary = request.reasoning.summary;
|
|
332
|
+
else if (requestedEffort !== undefined) reasoning.summary = "detailed";
|
|
333
|
+
// When the caller asked for reasoning effort but expressed no summary
|
|
334
|
+
// preference, request a detailed summary. Upstreams (GitHub Copilot's
|
|
335
|
+
// gpt-6-luna etc.) only stream `reasoning_summary_text` when the request
|
|
336
|
+
// asks for it — without this the reasoning is present on the wire yet
|
|
337
|
+
// never reaches the client.
|
|
331
338
|
if (Object.keys(reasoning).length > 0) payload.reasoning = reasoning;
|
|
332
339
|
}
|
|
333
340
|
const picked = pickWireSupportedControls(normalizeGenerationControls(request.generation_controls), "responses");
|
|
@@ -338,7 +345,9 @@ export function canonicalToResponsesPayload(
|
|
|
338
345
|
// Resolved unconditionally so the wire's `defaultMaxTokens` applies: an
|
|
339
346
|
// omitted limit must reach the upstream as a real number, not as an absent
|
|
340
347
|
// field (see the worked "wkwk" case in the WIRE_TOKEN_BOUNDS comment).
|
|
341
|
-
const bounded = resolveWireMaxTokens("responses", { max_tokens: requested }
|
|
348
|
+
const bounded = resolveWireMaxTokens("responses", { max_tokens: requested }, {
|
|
349
|
+
...(options.maxOutputTokens === undefined ? {} : { maxOutputTokens: options.maxOutputTokens }),
|
|
350
|
+
});
|
|
342
351
|
if (bounded !== undefined) picked["max_output_tokens"] = bounded;
|
|
343
352
|
Object.assign(payload, picked);
|
|
344
353
|
// Responses top-level params carried as `extension:responses.<field>` and
|
|
@@ -9,13 +9,15 @@ import { gatewayErrorFromStreamError } from "../stream-error-frames";
|
|
|
9
9
|
import { mergeResponsesUsage } from "./responses";
|
|
10
10
|
import { usageFromProvider, readReasoningText } from "../../providers/provider-usage";
|
|
11
11
|
import { createToolEmitLedger } from "../tool-identity";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
12
|
+
import { ThinkSplitter, stripThinkingTags } from "../think-split";
|
|
13
|
+
import { DsmlStreamParser, parseDsmlToolCalls } from "../dsml";
|
|
14
14
|
import {
|
|
15
15
|
OmpToolCallMarkupParser,
|
|
16
16
|
parseOmpToolCallMarkup,
|
|
17
17
|
type OmpTextToolCall,
|
|
18
18
|
} from "./omp-tool-call-markup";
|
|
19
|
+
import type { DialectPolicy } from "../translation/dialect/types";
|
|
20
|
+
import { QwenToolCallScanner } from "../translation/dialect/qwen";
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
export function mapChatStopReason(
|
|
@@ -83,11 +85,16 @@ export function parseChatResponseToEvents(
|
|
|
83
85
|
const contentWithoutMarkup = recoveredMarkup?.text ?? content;
|
|
84
86
|
const recovered =
|
|
85
87
|
typeof contentWithoutMarkup === "string"
|
|
86
|
-
? parseDsmlToolCalls(contentWithoutMarkup, declaredToolNames)
|
|
88
|
+
? parseDsmlToolCalls(contentWithoutMarkup, { allowedNames: declaredToolNames })
|
|
87
89
|
: undefined;
|
|
88
|
-
const visible =
|
|
90
|
+
const visible =
|
|
91
|
+
recovered === undefined
|
|
92
|
+
? contentWithoutMarkup
|
|
93
|
+
: "text" in recovered
|
|
94
|
+
? recovered.text
|
|
95
|
+
: recovered.clean;
|
|
89
96
|
if (typeof visible === "string" && visible.includes("<think")) {
|
|
90
|
-
const think = new
|
|
97
|
+
const think = new ThinkSplitter();
|
|
91
98
|
const split = think.push(visible);
|
|
92
99
|
const rest = think.flush();
|
|
93
100
|
const reasoning = `${split.reasoning}${rest.reasoning}`;
|
|
@@ -237,10 +244,12 @@ export async function* decodeChatSseStream(
|
|
|
237
244
|
body: ReadableStream<Uint8Array>,
|
|
238
245
|
request: CanonicalRequest,
|
|
239
246
|
signal?: AbortSignal,
|
|
247
|
+
options?: { readonly dialectPolicy?: DialectPolicy },
|
|
240
248
|
): AsyncIterable<CanonicalEvent> {
|
|
241
249
|
let seq = 1;
|
|
242
250
|
let finishReason: unknown;
|
|
243
251
|
let rawUsage: Record<string, unknown> | undefined;
|
|
252
|
+
const inbandDialect = options?.dialectPolicy?.inband;
|
|
244
253
|
// Last seen tool-call id (and name) per wire index. OpenAI streams the id
|
|
245
254
|
// (and name) only on the first fragment of each call; later fragments carry
|
|
246
255
|
// just `function.arguments`. Without this memory every continuation fragment
|
|
@@ -257,11 +266,11 @@ export async function* decodeChatSseStream(
|
|
|
257
266
|
const recoveredMarkupCalls: OmpTextToolCall[] = [];
|
|
258
267
|
// Single emission ledger: one entry per logical call.
|
|
259
268
|
const ledger = createToolEmitLedger();
|
|
260
|
-
const think = new
|
|
269
|
+
const think = new ThinkSplitter();
|
|
261
270
|
// Separate splitter for the reasoning channel: `reasoning_content` is its own
|
|
262
271
|
// stream, and interleaving it into the answer splitter would let a tag in one
|
|
263
272
|
// channel swallow the other's text.
|
|
264
|
-
const reasoningThink = new
|
|
273
|
+
const reasoningThink = new ThinkSplitter();
|
|
265
274
|
const declaredToolNames = declaredToolNamesForRequest(request);
|
|
266
275
|
const callableToolNames = callableToolNamesForRequest(request);
|
|
267
276
|
const contentMarkup =
|
|
@@ -269,7 +278,13 @@ export async function* decodeChatSseStream(
|
|
|
269
278
|
const reasoningMarkup =
|
|
270
279
|
(request.tools?.length ?? 0) > 0 ? new OmpToolCallMarkupParser(declaredToolNames) : undefined;
|
|
271
280
|
const dsmlMarkup =
|
|
272
|
-
(request.tools?.length ?? 0) > 0
|
|
281
|
+
(request.tools?.length ?? 0) > 0 && inbandDialect !== "qwen"
|
|
282
|
+
? new DsmlStreamParser({ allowedNames: declaredToolNames })
|
|
283
|
+
: undefined;
|
|
284
|
+
const qwenMarkup =
|
|
285
|
+
(request.tools?.length ?? 0) > 0 && inbandDialect === "qwen"
|
|
286
|
+
? new QwenToolCallScanner(declaredToolNames)
|
|
287
|
+
: undefined;
|
|
273
288
|
yield {
|
|
274
289
|
type: "response_start",
|
|
275
290
|
sequence_number: seq++,
|
|
@@ -315,7 +330,7 @@ export async function* decodeChatSseStream(
|
|
|
315
330
|
const raw = delta["content"] as string;
|
|
316
331
|
const markup = contentMarkup?.push(raw);
|
|
317
332
|
if (markup !== undefined) recoveredMarkupCalls.push(...markup.calls);
|
|
318
|
-
const recovered = dsmlMarkup?.push(markup?.text ?? raw);
|
|
333
|
+
const recovered = (qwenMarkup ?? dsmlMarkup)?.push(markup?.text ?? raw);
|
|
319
334
|
const visible = recovered?.text ?? markup?.text ?? raw;
|
|
320
335
|
const split = think.push(visible);
|
|
321
336
|
if (split.reasoning.length > 0) {
|
|
@@ -500,7 +515,7 @@ export async function* decodeChatSseStream(
|
|
|
500
515
|
}
|
|
501
516
|
}
|
|
502
517
|
}
|
|
503
|
-
const dsmlMarkupTail = dsmlMarkup?.flush();
|
|
518
|
+
const dsmlMarkupTail = (qwenMarkup ?? dsmlMarkup)?.flush();
|
|
504
519
|
if (dsmlMarkupTail !== undefined) {
|
|
505
520
|
if (dsmlMarkupTail.text.length > 0) {
|
|
506
521
|
const split = think.push(dsmlMarkupTail.text);
|
|
@@ -15,7 +15,7 @@ import { usageFromProvider, readResponsesReasoningDelta } from '../../providers/
|
|
|
15
15
|
import { canonicalTerminal, decodeCodexToolCallId, isRecord, readOutputIndex } from '../codecs';
|
|
16
16
|
import { gatewayErrorFromStreamError } from '../stream-error-frames';
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
function mapCodexStopReason(
|
|
19
19
|
status: unknown,
|
|
20
20
|
hasToolCall: boolean,
|
|
21
21
|
endTurn?: unknown,
|
|
@@ -185,7 +185,7 @@ export function withClaudeFallbackSignal(
|
|
|
185
185
|
return { ...(stopDetails ?? {}), [CANONICAL_SERVED_BY_FALLBACK_KEY]: true };
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
|
|
188
|
+
function eventContent(
|
|
189
189
|
content: readonly ContentPart[],
|
|
190
190
|
sequence: number,
|
|
191
191
|
): { events: CanonicalEvent[]; sequence: number } {
|
|
@@ -14,7 +14,7 @@ export interface OmpTextToolCall {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/** Text remaining after complete tool envelopes are removed. */
|
|
17
|
-
|
|
17
|
+
interface OmpTextToolCallResult {
|
|
18
18
|
readonly text: string;
|
|
19
19
|
readonly calls: readonly OmpTextToolCall[];
|
|
20
20
|
}
|
|
@@ -10,7 +10,7 @@ import { gatewayErrorFromStreamError } from "../stream-error-frames";
|
|
|
10
10
|
import { usageFromProvider, readResponsesReasoningDelta } from "../../providers/provider-usage";
|
|
11
11
|
import { createToolEmitLedger } from "../tool-identity";
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
function mapResponsesStopReason(
|
|
14
14
|
status: unknown,
|
|
15
15
|
hasToolCall: boolean,
|
|
16
16
|
): "stop" | "length" | "tool_use" | "error" | undefined {
|