cartethyia 2.8.0 → 2.8.1
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 +3 -3
- package/dist/dashboard/assets/{BannedPage-Cc0vKpMG.js → BannedPage-Dq530awD.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Dq530awD.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-Bqj2aa1T.js → CliToolDetailPage-DZzaS-7S.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZzaS-7S.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-CXsaOAO2.js → CliToolsPage-DaZZ3cqP.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-DaZZ3cqP.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BeLpJ4ma.js → CombosPage-BlC_xdkX.js} +1 -1
- package/dist/dashboard/assets/CombosPage-BlC_xdkX.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-DnV0uZ3m.js → ConsoleLogPage-D-rqeVtG.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-D-rqeVtG.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-CBxAjo63.js → CustomizationPage-7xT5yg2E.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-7xT5yg2E.js.gz +0 -0
- package/dist/dashboard/assets/{HealthEventsModal-B5yEE0k6.js → HealthEventsModal-Clq8E9cW.js} +1 -1
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-BWFLECmz.js → InjectSystemPromptPanel-6Teoq9Se.js} +1 -1
- package/dist/dashboard/assets/InjectSystemPromptPanel-6Teoq9Se.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-CgoPc5B9.js → LoginPage-CZuI0MAR.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CZuI0MAR.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-D9bFQern.js → ModelPicker-C1hNTlkr.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C1hNTlkr.js.gz +0 -0
- package/dist/dashboard/assets/{OverviewPage-B_p4tL8k.js → OverviewPage-0yfhSI1C.js} +1 -1
- package/dist/dashboard/assets/OverviewPage-0yfhSI1C.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js.gz +0 -0
- package/dist/dashboard/assets/{ProviderIcon-D_0PiZtg.js → ProviderIcon-Ddhm1InL.js} +1 -1
- package/dist/dashboard/assets/ProviderIcon-Ddhm1InL.js.gz +0 -0
- package/dist/dashboard/assets/{ProvidersPage-CLI2bJTK.js → ProvidersPage-C3fYuu6i.js} +1 -1
- package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js +9 -0
- package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js.gz +0 -0
- package/dist/dashboard/assets/{QuotaPage-DA-a1iSN.js → QuotaPage-D1RV_2BX.js} +1 -1
- package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-CctTga2C.js → SettingsPage-BzZAvYSX.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-BzZAvYSX.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-febLU4r1.js → SetupPage--s-EfEIL.js} +1 -1
- package/dist/dashboard/assets/SetupPage--s-EfEIL.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-M6fvR5Wz.js → StudioPage-BjXFGSK4.js} +1 -1
- package/dist/dashboard/assets/StudioPage-BjXFGSK4.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-nyeuRqz9.js → UsagePage-CP8F8BN7.js} +1 -1
- package/dist/dashboard/assets/UsagePage-CP8F8BN7.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-BFOlvrJC.js → api-keys-2hc12Uz2.js} +1 -1
- package/dist/dashboard/assets/api-keys-2hc12Uz2.js.gz +0 -0
- package/dist/dashboard/assets/app-DGXbNfAR.css +2 -0
- package/dist/dashboard/assets/app-DGXbNfAR.css.gz +0 -0
- package/dist/dashboard/assets/{assert-CqTLw5e7.js → assert-BMcj1xZE.js} +1 -1
- package/dist/dashboard/assets/assert-BMcj1xZE.js.gz +0 -0
- package/dist/dashboard/assets/{badge-C83EqLB0.js → badge-DkRUuVfz.js} +1 -1
- package/dist/dashboard/assets/badge-DkRUuVfz.js.gz +0 -0
- package/dist/dashboard/assets/{banner-D1xn7pIe.js → banner-CDjW841Q.js} +1 -1
- package/dist/dashboard/assets/banner-CDjW841Q.js.gz +0 -0
- package/dist/dashboard/assets/{card-DU3Lq5Lm.js → card-Bto5UlL9.js} +1 -1
- package/dist/dashboard/assets/card-Bto5UlL9.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-Dw1U_drK.js → cli-tools-DaH6g9hL.js} +1 -1
- package/dist/dashboard/assets/cli-tools-DaH6g9hL.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-CEL5Sg_J.js → clipboard-button-BYKBCzjk.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BYKBCzjk.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-BjFR5UHy.js → dialog-DL0Zftwv.js} +1 -1
- package/dist/dashboard/assets/dialog-DL0Zftwv.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-HvBW0AjI.js → drawer-Dpx_UXaS.js} +1 -1
- package/dist/dashboard/assets/drawer-Dpx_UXaS.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CECVELyy.js → entry-BV7-1NoM.js} +1 -1
- package/dist/dashboard/assets/entry-BV7-1NoM.js.gz +0 -0
- package/dist/dashboard/assets/{entry-DYYofQ7W.js → entry-CGvdNU6r.js} +1 -1
- package/dist/dashboard/assets/entry-CGvdNU6r.js.gz +0 -0
- package/dist/dashboard/assets/{entry-BSu3gFlt.js → entry-DScKYvZj.js} +3 -3
- package/dist/dashboard/assets/entry-DScKYvZj.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-DLW4i8zK.js → formatters-BS3DZlZj.js} +1 -1
- package/dist/dashboard/assets/formatters-BS3DZlZj.js.gz +0 -0
- package/dist/dashboard/assets/{index-1-fCqe64.js → index-SQnvvTWX.js} +2 -2
- package/dist/dashboard/assets/index-SQnvvTWX.js.gz +0 -0
- package/dist/dashboard/assets/{inline-DGvU2oLK.js → inline-Dl-cuLK0.js} +1 -1
- package/dist/dashboard/assets/inline-Dl-cuLK0.js.gz +0 -0
- package/dist/dashboard/assets/{input-iNnO1X2K.js → input-Bfx0EzRc.js} +1 -1
- package/dist/dashboard/assets/input-Bfx0EzRc.js.gz +0 -0
- package/dist/dashboard/assets/{layout-0q8UGypb.js → layout-BxhbQ_JS.js} +1 -1
- package/dist/dashboard/assets/layout-BxhbQ_JS.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-C0w2bQjJ.js → list-row-D49Y4ptn.js} +1 -1
- package/dist/dashboard/assets/list-row-D49Y4ptn.js.gz +0 -0
- package/dist/dashboard/assets/{live-M5aJ_xCa.js → live-CbVTdX9V.js} +1 -1
- package/dist/dashboard/assets/live-CbVTdX9V.js.gz +0 -0
- package/dist/dashboard/assets/{network-BKeQGT3K.js → network-JGvDveof.js} +1 -1
- package/dist/dashboard/assets/network-JGvDveof.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-CivAk3da.js → numbers-Dw6kiew-.js} +1 -1
- package/dist/dashboard/assets/numbers-Dw6kiew-.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-CpzvI5ep.js → pagination-iUoI8GeE.js} +1 -1
- package/dist/dashboard/assets/pagination-iUoI8GeE.js.gz +0 -0
- package/dist/dashboard/assets/providers/sensenova-intl.png +0 -0
- package/dist/dashboard/assets/providers/sensenova.png +0 -0
- package/dist/dashboard/assets/{routing-BFQX2VBc.js → routing-8jZr-3WE.js} +1 -1
- package/dist/dashboard/assets/routing-8jZr-3WE.js.gz +0 -0
- package/dist/dashboard/assets/{select-CXbck0jG.js → select-oO1FxMVb.js} +1 -1
- package/dist/dashboard/assets/select-oO1FxMVb.js.gz +0 -0
- package/dist/dashboard/assets/{settings-C_XvMHh9.js → settings-CLr3kdIx.js} +1 -1
- package/dist/dashboard/assets/settings-CLr3kdIx.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DggRiCxE.js → stack-Y3pDteZr.js} +1 -1
- package/dist/dashboard/assets/stack-Y3pDteZr.js.gz +0 -0
- package/dist/dashboard/assets/{state-ClFzfbYp.js → state-CArX_Iak.js} +1 -1
- package/dist/dashboard/assets/state-CArX_Iak.js.gz +0 -0
- package/dist/dashboard/assets/{switch-CTIFxKqS.js → switch-DwlwmDO-.js} +1 -1
- package/dist/dashboard/assets/switch-DwlwmDO-.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BClG3yWj.js → useMutation-DJ9GYEgf.js} +1 -1
- package/dist/dashboard/assets/useMutation-DJ9GYEgf.js.gz +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +51 -51
- package/migrations/full-postgres/0047_add_provider_device_flow_proxy.sql +17 -0
- package/migrations/lite-sqlite3/0047_add_provider_device_flow_proxy.sql +19 -0
- package/package.json +1 -1
- package/src/boot/app.ts +1 -1
- package/src/boot/dependencies.ts +4 -6
- package/src/config/providers.ts +6 -5
- package/src/config/spec.ts +8 -8
- package/src/console/backup/nine-router.ts +71 -10
- package/src/console/backup/service.ts +8 -1
- package/src/console/console-router.ts +1 -1
- package/src/console/domain-registration.ts +7 -2
- package/src/console/inferhub/client.ts +1 -1
- package/src/console/observability/live.ts +2 -2
- package/src/console/providers/catalog/contracts.ts +9 -3
- package/src/console/providers/catalog/model-operations.ts +2 -3
- package/src/console/providers/catalog/provider-operations.ts +1 -1
- package/src/console/providers/catalog/routes.ts +2 -2
- package/src/console/providers/catalog/store.ts +1914 -1907
- package/src/console/providers/detail/routes.ts +1 -0
- package/src/console/providers/detail/store.ts +4 -0
- package/src/console/providers/oauth/callback-listener.ts +30 -11
- package/src/console/providers/oauth/device-egress.ts +123 -0
- package/src/console/providers/oauth/routes.ts +123 -16
- package/src/console/quota/account-quota-tenant.ts +5 -5
- package/src/console/quota/account-test-egress.ts +2 -2
- package/src/console/quota/daily-growth-job.ts +1 -1
- package/src/console/routing/pools/contracts.ts +1 -1
- package/src/console/routing/pools/operations.ts +1 -1
- package/src/console/routing/pools/probe-verdict.ts +2 -2
- package/src/console/routing/pools/relay-deploy.ts +1 -1
- package/src/console/routing/pools/store.ts +4 -4
- package/src/network/client.ts +67 -0
- package/src/network/egress/bidi-session.ts +322 -0
- package/src/network/egress/dial.ts +201 -0
- package/src/network/egress/factory.ts +191 -0
- package/src/network/{outbound-fetch.ts → egress/fetch.ts} +195 -29
- package/src/network/egress/tls-profile.ts +123 -0
- package/src/network/egress/ws.ts +175 -0
- package/src/network/{types.ts → pool/agent-config.ts} +1 -1
- package/src/network/pool/agent.ts +2 -2
- package/src/network/{pool-cooldown-store.ts → pool/cooldown-store.ts} +7 -7
- package/src/network/{pool-health-machine.ts → pool/health.ts} +205 -6
- package/src/network/pool/resolver.ts +10 -849
- package/src/network/pool/selector.ts +2 -2
- package/src/network/ssrf.ts +1 -1
- package/src/network/{retry.ts → util/retry.ts} +1 -1
- package/src/observability/telemetry-buffer.ts +1 -1
- package/src/persistence/schema.ts +9 -0
- package/src/persistence/ttl-cache.ts +1 -1
- package/src/protocol/codecs.ts +58 -1
- package/src/protocol/request/messages.ts +31 -18
- package/src/protocol/response/messages.ts +34 -7
- package/src/protocol/translation/quirks.ts +15 -0
- package/src/protocol/upstream/send-claude-messages.ts +2 -2
- package/src/providers/adapters/compatible-adapter.ts +5 -0
- package/src/providers/authentication/oauth-client.ts +40 -6
- package/src/providers/authentication/oauth-device-flow.ts +7 -3
- package/src/providers/authentication/oauth-flow-store.ts +82 -1
- package/src/providers/authentication/oauth-refresh-service.ts +766 -739
- package/src/providers/default-registry.ts +76 -0
- package/src/providers/discovery/discovery-types.ts +7 -0
- package/src/providers/discovery/probe-phases.ts +6 -2
- package/src/providers/discovery/probing-service.ts +7 -0
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +11 -0
- package/src/providers/integrations/buddy/account.ts +969 -0
- package/src/providers/integrations/buddy/capabilities.ts +10 -10
- package/src/providers/integrations/buddy/{buddy-catalog-shared.ts → catalog.ts} +198 -136
- package/src/providers/integrations/buddy/{buddy-chat-shared.ts → chat.ts} +5 -5
- package/src/providers/integrations/buddy/codebuddy/index.ts +429 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +4 -4
- package/src/providers/integrations/buddy/{buddy-identity.ts → headers.ts} +138 -140
- package/src/providers/integrations/buddy/lifecycle.ts +1018 -0
- package/src/providers/integrations/buddy/{buddy-media.ts → media.ts} +1 -1
- package/src/providers/integrations/cline/cline-oauth.ts +10 -5
- package/src/providers/integrations/cline/cline.ts +3 -4
- package/src/providers/integrations/clixad/clixad-oauth.ts +98 -0
- package/src/providers/integrations/clixad/clixad-quota.ts +132 -0
- package/src/providers/integrations/clixad/provider.ts +145 -0
- package/src/providers/integrations/codex/codex-oauth.ts +8 -5
- package/src/providers/integrations/cursor/cursor-auth.ts +1 -1
- package/src/providers/integrations/cursor/cursor-hardening.ts +279 -0
- package/src/providers/integrations/cursor/cursor-http2.ts +605 -6
- package/src/providers/integrations/cursor/cursor-shared.ts +1 -1
- package/src/providers/integrations/cursor/cursor.ts +485 -70
- package/src/providers/integrations/deepai/deepai-catalog.ts +149 -0
- package/src/providers/integrations/deepai/deepai-common.ts +145 -0
- package/src/providers/integrations/deepai/deepai-oauth.ts +129 -0
- package/src/providers/integrations/deepai/deepai-quota.ts +97 -0
- package/src/providers/integrations/deepai/provider.ts +42 -0
- package/src/providers/integrations/devin/devin-auth.ts +7 -0
- package/src/providers/integrations/factory/factory-oauth.ts +16 -7
- package/src/providers/integrations/freebuff/freebuff.ts +2 -2
- package/src/providers/integrations/freepi/freepi-catalog.ts +5 -0
- package/src/providers/integrations/freepi/freepi-discovery.ts +2 -2
- package/src/providers/integrations/freepi/freepi-headers.ts +2 -2
- package/src/providers/integrations/freepi/freepi-protocol.ts +11 -2
- package/src/providers/integrations/freepi/freepi-realm.ts +0 -3
- package/src/providers/integrations/freepi/freepi-session.ts +158 -0
- package/src/providers/integrations/freepi/freepi.ts +80 -54
- package/src/providers/integrations/github/github-discovery.ts +30 -13
- package/src/providers/integrations/github/github-oauth.ts +217 -44
- package/src/providers/integrations/github/github-quota.ts +22 -5
- package/src/providers/integrations/github/github.ts +40 -32
- package/src/providers/integrations/grok/grok-oauth.ts +4 -4
- package/src/providers/integrations/hermes/hermes-oauth.ts +3 -3
- package/src/providers/integrations/hermes/hermes.ts +34 -5
- package/src/providers/integrations/kilo/kilo-oauth.ts +4 -4
- package/src/providers/integrations/kilo/kilo.ts +1 -1
- package/src/providers/integrations/kimi/kimi-oauth.ts +3 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +2 -2
- package/src/providers/integrations/muse/muse-oauth.ts +5 -5
- package/src/providers/integrations/opencode/fingerprint.ts +1 -1
- package/src/providers/integrations/openrouter/provider.ts +1 -1
- package/src/providers/integrations/perch/perch-protocol.ts +0 -3
- package/src/providers/integrations/perch/perch.ts +3 -3
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +1 -1
- package/src/providers/integrations/qoder/qoder-adapter.ts +19 -113
- package/src/providers/integrations/qoder/qoder-auth.ts +8 -1
- package/src/providers/integrations/qoder/qoder-catalog.ts +1 -1
- package/src/providers/integrations/qoder/qoder-chat.ts +25 -8
- package/src/providers/integrations/qoder/qoder-checkin.ts +1 -1
- package/src/providers/integrations/qoder/qoder-cosy.ts +37 -9
- package/src/providers/integrations/qoder/qoder-oauth.ts +9 -2
- package/src/providers/integrations/qoder/qoder-realm.ts +13 -36
- package/src/providers/integrations/qoder/qoder-sse.ts +447 -68
- package/src/providers/integrations/qoder/qoder-types.ts +9 -0
- package/src/providers/integrations/qoder/qoder.ts +3 -25
- package/src/providers/integrations/sensenova/provider.ts +144 -0
- package/src/providers/integrations/trae/trae-quota.ts +15 -1
- package/src/providers/integrations/vercel/provider.ts +117 -0
- package/src/providers/integrations/vercel/vercel-quota.ts +96 -0
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode-start-plan/gifts.ts +1 -1
- package/src/providers/integrations/zcode-start-plan/oauth.ts +3 -3
- package/src/providers/integrations/zro/zro.ts +2 -1
- package/src/providers/operations/account-refresh-status.ts +14 -0
- package/src/providers/operations/client-versions.ts +95 -30
- package/src/providers/operations/oauth-refresh-lead.ts +46 -22
- package/src/providers/operations/provider-caches.ts +1 -1
- package/src/providers/operations/provider-credential-service.ts +22 -25
- package/src/providers/operations/session-resolution.ts +17 -1
- package/src/providers/provider-contracts.ts +2 -2
- package/src/providers/provider-metadata.ts +30 -0
- package/src/providers/quota/quota-contracts.ts +2 -0
- package/src/providers/quota/refresh.ts +25 -3
- package/src/security/ip-boundary.ts +1 -1
- package/src/transport/dispatch/attempt-finalize.ts +1 -1
- package/src/transport/dispatch/attempt-loop.ts +3 -3
- package/src/transport/dispatch/handler-deps.ts +1 -1
- package/src/transport/dispatch/leases.ts +1 -1
- package/src/transport/dispatch/retry-policy.ts +1 -1
- package/src/transport/dispatch/streaming/finalize.ts +2 -2
- package/src/transport/dispatch/streaming/stream.ts +1 -1
- package/src/transport/dispatch/upstream.ts +1 -1
- package/src/transport/shutdown-notice.ts +1 -1
- package/src/workers/buddy-growth-tasks.ts +8 -8
- package/src/workers/daily-checkin.ts +4 -4
- package/src/workers/quota-refresh-sweep.ts +1 -1
- package/src/workers/zcode-gift-claim.ts +1 -1
- package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-Bqj2aa1T.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-CXsaOAO2.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-BWFLECmz.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-CgoPc5B9.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-D9bFQern.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js +0 -8
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BwNC_-Cx.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BwNC_-Cx.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CctTga2C.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-febLU4r1.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-M6fvR5Wz.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-nyeuRqz9.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BFOlvrJC.js.gz +0 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css +0 -2
- package/dist/dashboard/assets/app-Dx2QgsNj.css.gz +0 -0
- package/dist/dashboard/assets/assert-CqTLw5e7.js.gz +0 -0
- package/dist/dashboard/assets/badge-C83EqLB0.js.gz +0 -0
- package/dist/dashboard/assets/banner-D1xn7pIe.js.gz +0 -0
- package/dist/dashboard/assets/card-DU3Lq5Lm.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-Dw1U_drK.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-CEL5Sg_J.js.gz +0 -0
- package/dist/dashboard/assets/dialog-BjFR5UHy.js.gz +0 -0
- package/dist/dashboard/assets/drawer-HvBW0AjI.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js.gz +0 -0
- package/dist/dashboard/assets/entry-CECVELyy.js.gz +0 -0
- package/dist/dashboard/assets/entry-DYYofQ7W.js.gz +0 -0
- package/dist/dashboard/assets/formatters-DLW4i8zK.js.gz +0 -0
- package/dist/dashboard/assets/index-1-fCqe64.js.gz +0 -0
- package/dist/dashboard/assets/inline-DGvU2oLK.js.gz +0 -0
- package/dist/dashboard/assets/input-iNnO1X2K.js.gz +0 -0
- package/dist/dashboard/assets/layout-0q8UGypb.js.gz +0 -0
- package/dist/dashboard/assets/list-row-C0w2bQjJ.js.gz +0 -0
- package/dist/dashboard/assets/live-M5aJ_xCa.js.gz +0 -0
- package/dist/dashboard/assets/network-BKeQGT3K.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CivAk3da.js.gz +0 -0
- package/dist/dashboard/assets/pagination-CpzvI5ep.js.gz +0 -0
- package/dist/dashboard/assets/routing-BFQX2VBc.js.gz +0 -0
- package/dist/dashboard/assets/select-CXbck0jG.js.gz +0 -0
- package/dist/dashboard/assets/settings-C_XvMHh9.js.gz +0 -0
- package/dist/dashboard/assets/stack-DggRiCxE.js.gz +0 -0
- package/dist/dashboard/assets/state-ClFzfbYp.js.gz +0 -0
- package/dist/dashboard/assets/switch-CTIFxKqS.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BClG3yWj.js.gz +0 -0
- package/src/console/providers/catalog/discover-constants.ts +0 -6
- package/src/network/pool-health.ts +0 -198
- package/src/providers/integrations/buddy/buddy-checkin.ts +0 -521
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +0 -76
- package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -130
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +0 -234
- package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -496
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +0 -341
- package/src/providers/integrations/buddy/buddy-quota-shared.ts +0 -417
- package/src/providers/integrations/buddy/buddy-server-tools.ts +0 -240
- package/src/providers/integrations/buddy/buddy-usage-shared.ts +0 -221
- package/src/providers/integrations/buddy/buddy-usage-store.ts +0 -181
- package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +0 -37
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +0 -188
- package/src/providers/integrations/buddy/codebuddy/oauth.ts +0 -47
- package/src/providers/integrations/buddy/codebuddy/provider.ts +0 -179
- package/src/providers/integrations/buddy/codebuddy/quota.ts +0 -154
- package/src/providers/integrations/qoder/chat-proto.ts +0 -328
- package/src/providers/integrations/qoder/qoder-grpc.ts +0 -870
- package/src/providers/integrations/qoder/qoder-ide.ts +0 -481
- /package/dist/dashboard/assets/{app-DIXLjojg.js → app-C0gTXEoN.js} +0 -0
- /package/dist/dashboard/assets/{app-DIXLjojg.js.gz → app-C0gTXEoN.js.gz} +0 -0
- /package/src/network/{http2-bidi.ts → bidi.ts} +0 -0
- /package/src/network/pool/{byte-accounting.ts → accounting.ts} +0 -0
- /package/src/network/pool/{pool-scripts.ts → scripts.ts} +0 -0
- /package/src/network/pool/{pool-state.ts → state.ts} +0 -0
- /package/src/network/{backoff.ts → util/backoff.ts} +0 -0
- /package/src/network/{deduplication.ts → util/dedupe.ts} +0 -0
- /package/src/network/{ip-utils.ts → util/ip.ts} +0 -0
- /package/src/network/{rate-limit-verdict.ts → verdict.ts} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
proxyCooldownProvidersKey,
|
|
23
23
|
proxyInflightKey,
|
|
24
24
|
proxyProviderInflightKey,
|
|
25
|
-
} from "./
|
|
25
|
+
} from "./scripts";
|
|
26
26
|
import {
|
|
27
27
|
advanceRotation,
|
|
28
28
|
createPoolLocalState,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
type PoolRotation,
|
|
35
35
|
type PoolUsageSnapshot,
|
|
36
36
|
type ProxyCooldownEntry,
|
|
37
|
-
} from "./
|
|
37
|
+
} from "./state";
|
|
38
38
|
|
|
39
39
|
export type { PoolRotation, ProxyCooldownEntry };
|
|
40
40
|
|
package/src/network/ssrf.ts
CHANGED
|
@@ -174,7 +174,7 @@ const DRAIN_MAX_ATTEMPTS = 5;
|
|
|
174
174
|
const DRAIN_RETRY_BASE_MS = 25;
|
|
175
175
|
const DRAIN_RETRY_MAX_MS = 1_000;
|
|
176
176
|
|
|
177
|
-
import { exponentialBackoff, type BackoffOptions } from "../network/backoff";
|
|
177
|
+
import { exponentialBackoff, type BackoffOptions } from "../network/util/backoff";
|
|
178
178
|
|
|
179
179
|
/** Exponential retry delay for the `attempt`-th retry, clamped to the ceiling. */
|
|
180
180
|
function drainRetryDelayMs(attempt: number, baseDelayMs = DRAIN_RETRY_BASE_MS): number {
|
|
@@ -816,6 +816,12 @@ export const providerRoutingSettings = pgTable(
|
|
|
816
816
|
// dispatch automatically selects among every active network pool the
|
|
817
817
|
// tenant owns (least-loaded/non-cooldown) — never an admin-pinned pool.
|
|
818
818
|
skipProxy: boolean("skip_proxy").notNull().default(false),
|
|
819
|
+
// How device-code OAuth flows (start + poll) choose their egress:
|
|
820
|
+
// 'random' (default) routes them through a randomly selected active
|
|
821
|
+
// network pool so the upstream sees a rotating IP (avoids "multiple codes
|
|
822
|
+
// from one IP" detection for Cursor/Grok/device-code providers); 'direct'
|
|
823
|
+
// always dials direct egress.
|
|
824
|
+
deviceFlowProxy: text("device_flow_proxy").$type<DeviceFlowProxyMode>().notNull().default("random"),
|
|
819
825
|
},
|
|
820
826
|
(table) => ({
|
|
821
827
|
tenantProviderUnique: uniqueIndex("provider_routing_settings_tenant_provider_idx").on(
|
|
@@ -835,6 +841,9 @@ export const poolRoutingStrategy = pgEnum("pool_routing_strategy", [
|
|
|
835
841
|
]);
|
|
836
842
|
export type PoolRoutingStrategy = (typeof poolRoutingStrategy.enumValues)[number];
|
|
837
843
|
|
|
844
|
+
/** Egress mode for device-code OAuth flows: random active pool, or direct. */
|
|
845
|
+
export type DeviceFlowProxyMode = "random" | "direct";
|
|
846
|
+
|
|
838
847
|
/**
|
|
839
848
|
* Per-tenant selection strategy across the tenant's active network pools —
|
|
840
849
|
* the pool-group counterpart to `provider_routing_settings`. `least_loaded`
|
package/src/protocol/codecs.ts
CHANGED
|
@@ -91,6 +91,63 @@ export function hash32(input: string): number {
|
|
|
91
91
|
|
|
92
92
|
const CLAUDE_TOOL_PREFIX = "_";
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Per-request tool-name rename map, mirroring the two-way alias pattern the
|
|
96
|
+
* OpenCode free-tier fingerprint uses: a caller tool whose name collides with
|
|
97
|
+
* an upstream-reserved name (or with the built-in prefix) travels under an
|
|
98
|
+
* alias, and the response side restores the caller's original name.
|
|
99
|
+
*
|
|
100
|
+
* The map is a bag of `{ sent, original }` pairs so a provider can rename at
|
|
101
|
+
* build time and restore at decode time without guessing from a fixed prefix
|
|
102
|
+
* (a fixed prefix collides when a caller already uses it — `_bash` from a
|
|
103
|
+
* caller named `bash` vs a caller already named `_bash`).
|
|
104
|
+
*/
|
|
105
|
+
export interface ToolNameAlias {
|
|
106
|
+
/** Name sent to the upstream wire. */
|
|
107
|
+
readonly sent: string;
|
|
108
|
+
/** Caller's original name; restore to this on the way back. */
|
|
109
|
+
readonly original: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Restore a sent name to the caller's original, when it was renamed. */
|
|
113
|
+
export function restoreAliasedToolName(
|
|
114
|
+
sent: string,
|
|
115
|
+
aliases: ReadonlyArray<ToolNameAlias>,
|
|
116
|
+
): string {
|
|
117
|
+
for (const alias of aliases) {
|
|
118
|
+
if (alias.sent === sent) return alias.original;
|
|
119
|
+
}
|
|
120
|
+
return sent;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Registry of per-request tool renames, keyed by the canonical request object
|
|
125
|
+
* (the same object the builder saw and the decoder receives). This is the
|
|
126
|
+
* transport-agnostic way to pair `encodeWireRequest` with `decodeWireResponse`
|
|
127
|
+
* without threading a new parameter through every adapter: a request records
|
|
128
|
+
* its aliases at build time, and any decoder that still has the request can
|
|
129
|
+
* restore the caller's original tool names exactly.
|
|
130
|
+
*
|
|
131
|
+
* The WeakMap keeps no lifetime: entries die with the request object.
|
|
132
|
+
*/
|
|
133
|
+
const toolAliasesByRequest = new WeakMap<object, readonly ToolNameAlias[]>();
|
|
134
|
+
|
|
135
|
+
/** Record the rename map a request produced. Idempotent per request. */
|
|
136
|
+
export function recordToolAliases(request: object, aliases: readonly ToolNameAlias[]): void {
|
|
137
|
+
if (aliases.length === 0) return;
|
|
138
|
+
toolAliasesByRequest.set(request, aliases);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Read the rename map a request recorded, if any. */
|
|
142
|
+
export function toolAliasesFor(request: object): readonly ToolNameAlias[] {
|
|
143
|
+
return toolAliasesByRequest.get(request) ?? [];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Restore a tool name exactly from the request's recorded renames. */
|
|
147
|
+
export function restoreToolNameFor(request: object, sent: string): string {
|
|
148
|
+
return restoreAliasedToolName(sent, toolAliasesFor(request));
|
|
149
|
+
}
|
|
150
|
+
|
|
94
151
|
export type ClaudeWireObject = Record<string, unknown>;
|
|
95
152
|
|
|
96
153
|
/**
|
|
@@ -366,7 +423,7 @@ function sanitizeSchemaWalk(value: unknown, walk: RewriteWalk): unknown {
|
|
|
366
423
|
|
|
367
424
|
// OAuth tool-name prefixing
|
|
368
425
|
|
|
369
|
-
const ANTHROPIC_BUILTIN_TOOL_NAMES = new Set([
|
|
426
|
+
export const ANTHROPIC_BUILTIN_TOOL_NAMES = new Set([
|
|
370
427
|
"web_search",
|
|
371
428
|
"web_fetch",
|
|
372
429
|
"code_execution",
|
|
@@ -17,11 +17,13 @@ import {
|
|
|
17
17
|
normalizeAnthropicToolCallId,
|
|
18
18
|
parseArguments,
|
|
19
19
|
prefixClaudeToolName,
|
|
20
|
+
recordToolAliases,
|
|
20
21
|
sanitizeSchemaForAnthropic,
|
|
21
22
|
stringValue,
|
|
22
23
|
toWellFormedDeep,
|
|
23
24
|
toWellFormedString,
|
|
24
25
|
type ClaudeWireObject,
|
|
26
|
+
type ToolNameAlias,
|
|
25
27
|
isRecord,
|
|
26
28
|
resolveImageSource,
|
|
27
29
|
splitDataUrl,
|
|
@@ -287,6 +289,7 @@ function partToClaudeBlock(
|
|
|
287
289
|
idMap: Map<string, string>;
|
|
288
290
|
isOAuth: boolean;
|
|
289
291
|
imageCount: number;
|
|
292
|
+
toolAliases: ToolNameAlias[];
|
|
290
293
|
maxBytesOverride?: number;
|
|
291
294
|
},
|
|
292
295
|
): ClaudeWireObject | undefined {
|
|
@@ -336,10 +339,12 @@ function partToClaudeBlock(
|
|
|
336
339
|
// stamp every call with its array position, so copying it here leaked a
|
|
337
340
|
// stream-only field into a request. The position is not lost: the block
|
|
338
341
|
// order in `content[]` already expresses it.
|
|
342
|
+
const sentName = prefixClaudeToolName(part.name, ctx?.isOAuth ?? false);
|
|
343
|
+
if (sentName !== part.name) ctx?.toolAliases.push({ sent: sentName, original: part.name });
|
|
339
344
|
return {
|
|
340
345
|
type: "tool_use",
|
|
341
346
|
id: normalized,
|
|
342
|
-
name:
|
|
347
|
+
name: sentName,
|
|
343
348
|
input: toWellFormedDeep(parseArguments(part.arguments)),
|
|
344
349
|
...(part.namespace === undefined ? {} : { namespace: part.namespace }),
|
|
345
350
|
};
|
|
@@ -577,6 +582,7 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
577
582
|
idMap,
|
|
578
583
|
isOAuth: options.isOAuth ?? false,
|
|
579
584
|
imageCount,
|
|
585
|
+
toolAliases: [] as ToolNameAlias[],
|
|
580
586
|
...(options.maxBytesOverride === undefined
|
|
581
587
|
? {}
|
|
582
588
|
: { maxBytesOverride: options.maxBytesOverride }),
|
|
@@ -755,27 +761,34 @@ export function canonicalToClaudeMessagesPayload(
|
|
|
755
761
|
});
|
|
756
762
|
}
|
|
757
763
|
if (request.tools?.length) {
|
|
758
|
-
payload.tools = request.tools.map((tool) =>
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
:
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
764
|
+
payload.tools = request.tools.map((tool) => {
|
|
765
|
+
const sentName = prefixClaudeToolName(tool.name, isOAuth);
|
|
766
|
+
if (sentName !== tool.name) ctx.toolAliases.push({ sent: sentName, original: tool.name });
|
|
767
|
+
return {
|
|
768
|
+
name: sentName,
|
|
769
|
+
...(tool.description === undefined
|
|
770
|
+
? {}
|
|
771
|
+
: { description: toWellFormedDeep(tool.description) }),
|
|
772
|
+
input_schema: sanitizeSchemaForAnthropic(tool.jsonSchema),
|
|
773
|
+
...(tool.strict === true ? { strict: true } : {}),
|
|
774
|
+
...(tool.eager_input_streaming === undefined
|
|
775
|
+
? {}
|
|
776
|
+
: { eager_input_streaming: tool.eager_input_streaming }),
|
|
777
|
+
...(tool.defer_loading === undefined
|
|
778
|
+
? {}
|
|
779
|
+
: { defer_loading: tool.defer_loading }),
|
|
780
|
+
...(tool.input_examples === undefined ? {} : { input_examples: tool.input_examples }),
|
|
781
|
+
...(tool.allowed_callers === undefined ? {} : { allowed_callers: tool.allowed_callers }),
|
|
782
|
+
};
|
|
783
|
+
});
|
|
774
784
|
}
|
|
775
785
|
const rawToolChoice = canonicalToolChoice(request.tool_choice);
|
|
776
786
|
if (isRecord(rawToolChoice) && rawToolChoice.type === "tool" && stringValue(rawToolChoice.name)) {
|
|
777
|
-
|
|
787
|
+
const sentName = prefixClaudeToolName(rawToolChoice.name, isOAuth);
|
|
788
|
+
if (sentName !== rawToolChoice.name) ctx.toolAliases.push({ sent: sentName, original: rawToolChoice.name });
|
|
789
|
+
rawToolChoice.name = sentName;
|
|
778
790
|
}
|
|
791
|
+
recordToolAliases(request, ctx.toolAliases);
|
|
779
792
|
const parallelToolCallsDisabled =
|
|
780
793
|
request.generation_controls.parallel_tool_calls === false;
|
|
781
794
|
const supportsToolChoice = options.dialectPolicy?.supportsToolChoice ?? true;
|
|
@@ -12,12 +12,33 @@ import { usageFromProvider } from '../../providers/provider-usage';
|
|
|
12
12
|
import { mapClaudeStreamError } from '../messages-errors';
|
|
13
13
|
import {
|
|
14
14
|
finiteNumber,
|
|
15
|
+
restoreAliasedToolName,
|
|
15
16
|
stringValue,
|
|
17
|
+
toolAliasesFor,
|
|
16
18
|
unprefixClaudeToolName,
|
|
17
19
|
type ClaudeWireObject,
|
|
20
|
+
type ToolNameAlias,
|
|
18
21
|
isRecord,
|
|
19
22
|
} from '../codecs';
|
|
20
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Restore a tool name from the wire to the caller's original, exactly.
|
|
26
|
+
*
|
|
27
|
+
* A name the builder renamed (recorded in `aliases`) is restored verbatim; any
|
|
28
|
+
* other name falls back to the OAuth underscore-unprefixing rule. This is the
|
|
29
|
+
* single restoration point for the Claude wire, so the two rules can never
|
|
30
|
+
* disagree between the stream and non-stream decoders.
|
|
31
|
+
*/
|
|
32
|
+
function restoreClaudeToolName(
|
|
33
|
+
sent: string,
|
|
34
|
+
isOAuth: boolean,
|
|
35
|
+
aliases: ReadonlyArray<ToolNameAlias>,
|
|
36
|
+
): string {
|
|
37
|
+
const restored = restoreAliasedToolName(sent, aliases);
|
|
38
|
+
if (restored !== sent) return restored;
|
|
39
|
+
return unprefixClaudeToolName(sent, isOAuth);
|
|
40
|
+
}
|
|
41
|
+
|
|
21
42
|
export function mapClaudeStopReason(raw: string): CanonicalStopReason {
|
|
22
43
|
switch (raw) {
|
|
23
44
|
case "end_turn":
|
|
@@ -38,7 +59,7 @@ export function mapClaudeStopReason(raw: string): CanonicalStopReason {
|
|
|
38
59
|
}
|
|
39
60
|
}
|
|
40
61
|
|
|
41
|
-
export function parseClaudeContent(value: unknown, isOAuth = false): ContentPart {
|
|
62
|
+
export function parseClaudeContent(value: unknown, isOAuth = false, aliases: ReadonlyArray<ToolNameAlias> = []): ContentPart {
|
|
42
63
|
if (stringValue(value)) return { kind: "text", text: value };
|
|
43
64
|
if (!isRecord(value))
|
|
44
65
|
return { kind: "extension", name: "messages:unknown", payload: value };
|
|
@@ -59,7 +80,7 @@ export function parseClaudeContent(value: unknown, isOAuth = false): ContentPart
|
|
|
59
80
|
return {
|
|
60
81
|
kind: "toolCall",
|
|
61
82
|
call_id: value.id,
|
|
62
|
-
name:
|
|
83
|
+
name: restoreClaudeToolName(value.name, isOAuth, aliases),
|
|
63
84
|
arguments: value.input ?? {},
|
|
64
85
|
...(finiteNumber(value.index) ? { index: value.index } : {}),
|
|
65
86
|
};
|
|
@@ -77,7 +98,7 @@ export function parseClaudeContent(value: unknown, isOAuth = false): ContentPart
|
|
|
77
98
|
const content = stringValue(value.content)
|
|
78
99
|
? value.content
|
|
79
100
|
: Array.isArray(value.content)
|
|
80
|
-
? value.content.map((content) => parseClaudeContent(content, isOAuth))
|
|
101
|
+
? value.content.map((content) => parseClaudeContent(content, isOAuth, aliases))
|
|
81
102
|
: value.content == null
|
|
82
103
|
? ""
|
|
83
104
|
: [{ kind: "text" as const, text: String(value.content) }];
|
|
@@ -239,8 +260,9 @@ export function claudeResponseToEvents(
|
|
|
239
260
|
model,
|
|
240
261
|
},
|
|
241
262
|
];
|
|
263
|
+
const aliases = toolAliasesFor(request);
|
|
242
264
|
const blocks = Array.isArray(json.content)
|
|
243
|
-
? json.content.map((content) => parseClaudeContent(content, isOAuth))
|
|
265
|
+
? json.content.map((content) => parseClaudeContent(content, isOAuth, aliases))
|
|
244
266
|
: [];
|
|
245
267
|
let sequence = 2;
|
|
246
268
|
for (const block of blocks) {
|
|
@@ -292,6 +314,8 @@ interface ClaudeStreamState {
|
|
|
292
314
|
rawUsage: Record<string, unknown> | undefined;
|
|
293
315
|
sawMessageStop: boolean;
|
|
294
316
|
isOAuth: boolean;
|
|
317
|
+
/** Tool renames recorded for this request, for exact restore. */
|
|
318
|
+
aliases: ReadonlyArray<ToolNameAlias>;
|
|
295
319
|
}
|
|
296
320
|
|
|
297
321
|
function streamEventToCanonical(
|
|
@@ -321,7 +345,7 @@ function streamEventToCanonical(
|
|
|
321
345
|
state.calls.set(index, {
|
|
322
346
|
call_id: block.id,
|
|
323
347
|
...(stringValue(block.name)
|
|
324
|
-
? { name:
|
|
348
|
+
? { name: restoreClaudeToolName(block.name, state.isOAuth, state.aliases) }
|
|
325
349
|
: {}),
|
|
326
350
|
});
|
|
327
351
|
// Anthropic sends `input: {}` as a *placeholder* on content_block_start,
|
|
@@ -332,13 +356,14 @@ function streamEventToCanonical(
|
|
|
332
356
|
// send complete arguments here still gets them through.
|
|
333
357
|
if (
|
|
334
358
|
isRecord(block.input) &&
|
|
335
|
-
Object.keys(block.input).length > 0
|
|
359
|
+
Object.keys(block.input).length > 0 &&
|
|
360
|
+
stringValue(block.name)
|
|
336
361
|
) {
|
|
337
362
|
events.push({
|
|
338
363
|
type: "tool_call_delta",
|
|
339
364
|
sequence_number: next++,
|
|
340
365
|
call_id: block.id,
|
|
341
|
-
|
|
366
|
+
name: restoreClaudeToolName(block.name, state.isOAuth, state.aliases),
|
|
342
367
|
arguments_delta: JSON.stringify(block.input),
|
|
343
368
|
});
|
|
344
369
|
}
|
|
@@ -446,6 +471,7 @@ export async function* parseClaudeSseStream(
|
|
|
446
471
|
body: ReadableStream<Uint8Array>,
|
|
447
472
|
signal?: AbortSignal,
|
|
448
473
|
isOAuth = false,
|
|
474
|
+
aliases: ReadonlyArray<ToolNameAlias> = [],
|
|
449
475
|
): AsyncIterable<CanonicalEvent> {
|
|
450
476
|
const state: ClaudeStreamState = {
|
|
451
477
|
calls: new Map(),
|
|
@@ -455,6 +481,7 @@ export async function* parseClaudeSseStream(
|
|
|
455
481
|
rawUsage: undefined,
|
|
456
482
|
sawMessageStop: false,
|
|
457
483
|
isOAuth,
|
|
484
|
+
aliases,
|
|
458
485
|
};
|
|
459
486
|
let sequence = 1;
|
|
460
487
|
for await (const sse of decodeSseEvents(body, { signal })) {
|
|
@@ -158,6 +158,21 @@ const PARAM_QUIRKS: readonly ParamQuirk[] = [
|
|
|
158
158
|
// confirms that the selected-model request must not carry temperature.
|
|
159
159
|
stripControls: ["temperature"],
|
|
160
160
|
},
|
|
161
|
+
{
|
|
162
|
+
provider: "nvidia",
|
|
163
|
+
// NVIDIA NIM rejects a set of cross-wire fields with 400 even though the
|
|
164
|
+
// OpenAI-compatible chat wire permits them. Stripping them here keeps the
|
|
165
|
+
// dispatch on the same wire shape the upstream accepts.
|
|
166
|
+
stripControls: [
|
|
167
|
+
"extension:client_metadata",
|
|
168
|
+
"extension:prompt_cache_key",
|
|
169
|
+
"service_tier",
|
|
170
|
+
"extension:anthropic_beta",
|
|
171
|
+
"extension:thinking_budget",
|
|
172
|
+
"extension:metadata_user_id",
|
|
173
|
+
"extension:custom_field",
|
|
174
|
+
],
|
|
175
|
+
},
|
|
161
176
|
{
|
|
162
177
|
provider: "anthropic",
|
|
163
178
|
matchModel: rejectsSamplingParams,
|
|
@@ -9,7 +9,7 @@ import { GatewayError } from '../gateway-error';
|
|
|
9
9
|
import { applyRouteUserAgent, type ProviderDispatchContext } from "../../providers/provider-contracts";
|
|
10
10
|
import { abortGatewayError, createUpstreamDeadlineLifecycle } from '../../providers/operations/upstream-deadline';
|
|
11
11
|
import { mapClaudeHttpError } from '../messages-errors';
|
|
12
|
-
import { isRecord } from '../codecs';
|
|
12
|
+
import { isRecord, toolAliasesFor } from '../codecs';
|
|
13
13
|
import { upstreamMessageAsIs, MAX_UPSTREAM_ERROR_BYTES } from '../../transport/failure-policy';
|
|
14
14
|
import { parseClaudeSseStream, claudeResponseToEvents } from '../response/messages';
|
|
15
15
|
|
|
@@ -60,7 +60,7 @@ export async function* sendClaudeMessagesRequest(
|
|
|
60
60
|
{},
|
|
61
61
|
"upstream",
|
|
62
62
|
);
|
|
63
|
-
yield* parseClaudeSseStream(response.body, context.abort_signal, isOAuth);
|
|
63
|
+
yield* parseClaudeSseStream(response.body, context.abort_signal, isOAuth, toolAliasesFor(request));
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
const body = await response.text().catch(() => "");
|
|
@@ -310,6 +310,11 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
|
|
|
310
310
|
// plus `message_delta.usage` — so nothing is lost by omitting it.
|
|
311
311
|
const existing = payload["stream_options"] as Record<string, unknown> | undefined;
|
|
312
312
|
payload["stream_options"] = { ...(existing ?? {}), include_usage: true };
|
|
313
|
+
} else if (!effectiveRequest.stream && payload["stream_options"] !== undefined) {
|
|
314
|
+
// A non-streaming request must not carry `stream_options`: several
|
|
315
|
+
// OpenAI-compatible upstreams (NVIDIA NIM, DeepSeek) reject the body
|
|
316
|
+
// with 400 "Stream options can only be defined when stream=True".
|
|
317
|
+
delete payload["stream_options"];
|
|
313
318
|
}
|
|
314
319
|
// Apply structured_output configuration
|
|
315
320
|
if (this.config.structured_output?.enabled) {
|
|
@@ -12,18 +12,20 @@ import {
|
|
|
12
12
|
record,
|
|
13
13
|
} from "./oauth-flow-store";
|
|
14
14
|
import type {
|
|
15
|
+
OAuthAccountIdentity,
|
|
15
16
|
OAuthAuthorizeRequest,
|
|
16
17
|
OAuthCodeExchangeContext,
|
|
17
18
|
OAuthExchangeResult,
|
|
18
19
|
OAuthLoginClient,
|
|
19
20
|
} from "./oauth-flow-store";
|
|
21
|
+
import { oauthAccountIdentity } from "./oauth-flow-store";
|
|
20
22
|
import type { OAuthTokenRefreshResult, OAuthTokenRefresher } from "./oauth-refresh-service";
|
|
21
23
|
|
|
22
24
|
/** Minimal fetch surface accepted by the generic OAuth client. */
|
|
23
25
|
export type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
24
26
|
|
|
25
27
|
/** Normalized token shape returned by provider token endpoints. */
|
|
26
|
-
export interface NormalizedTokenResponse {
|
|
28
|
+
export interface NormalizedTokenResponse extends OAuthAccountIdentity {
|
|
27
29
|
readonly access: string;
|
|
28
30
|
readonly refresh: string;
|
|
29
31
|
readonly expiresAt: Date;
|
|
@@ -83,12 +85,32 @@ export abstract class OAuthClient implements OAuthLoginClient, OAuthTokenRefresh
|
|
|
83
85
|
*/
|
|
84
86
|
readonly browserRedirectUri?: string;
|
|
85
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Custom state generator; `undefined` keeps the shared base64url state.
|
|
90
|
+
* A provider whose authorization server validates the format (e.g. DeepAI
|
|
91
|
+
* requires 32 hex chars) overrides this.
|
|
92
|
+
*/
|
|
93
|
+
generateState(): string | undefined {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
protected readonly fetchFn: FetchLike;
|
|
87
98
|
|
|
88
99
|
constructor(fetchFn: FetchLike = globalThis.fetch) {
|
|
89
100
|
this.fetchFn = fetchFn;
|
|
90
101
|
}
|
|
91
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Resolves the transport a flow should use. When the console injects a
|
|
105
|
+
* `fetchFn` in the flow context (device-code OAuth routed through a network
|
|
106
|
+
* pool, see `device_flow_proxy`), that override wins; otherwise the
|
|
107
|
+
* client's own fetch is used. Every start/poll/exchange request that talks
|
|
108
|
+
* to the provider MUST route through this so the override is honored.
|
|
109
|
+
*/
|
|
110
|
+
protected fetchFor(context?: { readonly fetchFn?: FetchLike | undefined }): FetchLike {
|
|
111
|
+
return context?.fetchFn ?? this.fetchFn;
|
|
112
|
+
}
|
|
113
|
+
|
|
92
114
|
// ---------------------------------------------------------------------------
|
|
93
115
|
// Public OAuthLoginClient surface
|
|
94
116
|
// ---------------------------------------------------------------------------
|
|
@@ -135,8 +157,9 @@ export abstract class OAuthClient implements OAuthLoginClient, OAuthTokenRefresh
|
|
|
135
157
|
}
|
|
136
158
|
|
|
137
159
|
/** Extracts an account label from a token exchange/refresh response. */
|
|
138
|
-
protected extractAccountLabel(
|
|
139
|
-
|
|
160
|
+
protected extractAccountLabel(data: unknown): string | undefined {
|
|
161
|
+
const identity = oauthAccountIdentity(data);
|
|
162
|
+
return identity.accountEmail ?? identity.accountName;
|
|
140
163
|
}
|
|
141
164
|
|
|
142
165
|
/** Calculates an expiry Date from an `expires_in` value. */
|
|
@@ -172,7 +195,14 @@ export abstract class OAuthClient implements OAuthLoginClient, OAuthTokenRefresh
|
|
|
172
195
|
const refresh = nonEmptyString(body.refresh_token) ?? fallbackRefresh ?? "";
|
|
173
196
|
const expiresAt = this.calculateExpiry(body.expires_in);
|
|
174
197
|
const accountLabel = this.extractAccountLabel(data);
|
|
175
|
-
|
|
198
|
+
const identity = oauthAccountIdentity(data);
|
|
199
|
+
return {
|
|
200
|
+
access,
|
|
201
|
+
refresh,
|
|
202
|
+
expiresAt,
|
|
203
|
+
...identity,
|
|
204
|
+
...(accountLabel ? { accountLabel } : {}),
|
|
205
|
+
};
|
|
176
206
|
}
|
|
177
207
|
|
|
178
208
|
/** Builds a PKCE authorization URL using the shared helper. */
|
|
@@ -231,22 +261,26 @@ export abstract class OAuthClient implements OAuthLoginClient, OAuthTokenRefresh
|
|
|
231
261
|
// ---------------------------------------------------------------------------
|
|
232
262
|
|
|
233
263
|
protected toExchangeResult(normalized: NormalizedTokenResponse): OAuthExchangeResult {
|
|
234
|
-
const { access, refresh, expiresAt, accountLabel, auth_state } = normalized;
|
|
264
|
+
const { access, refresh, expiresAt, accountLabel, accountEmail, accountName, auth_state } = normalized;
|
|
235
265
|
return {
|
|
236
266
|
access,
|
|
237
267
|
refresh,
|
|
238
268
|
expiresAt,
|
|
269
|
+
...(accountEmail === undefined ? {} : { accountEmail }),
|
|
270
|
+
...(accountName === undefined ? {} : { accountName }),
|
|
239
271
|
...(accountLabel ? { accountLabel } : {}),
|
|
240
272
|
...(auth_state === undefined ? {} : { auth_state }),
|
|
241
273
|
};
|
|
242
274
|
}
|
|
243
275
|
|
|
244
276
|
protected toRefreshResult(normalized: NormalizedTokenResponse): OAuthTokenRefreshResult {
|
|
245
|
-
const { access, refresh, expiresAt, accountLabel, auth_state } = normalized;
|
|
277
|
+
const { access, refresh, expiresAt, accountLabel, accountEmail, accountName, auth_state } = normalized;
|
|
246
278
|
return {
|
|
247
279
|
access,
|
|
248
280
|
...(refresh ? { refresh } : {}),
|
|
249
281
|
expiresAt,
|
|
282
|
+
...(accountEmail === undefined ? {} : { accountEmail }),
|
|
283
|
+
...(accountName === undefined ? {} : { accountName }),
|
|
250
284
|
...(accountLabel ? { accountLabel } : {}),
|
|
251
285
|
...(auth_state === undefined ? {} : { auth_state }),
|
|
252
286
|
};
|
|
@@ -37,9 +37,12 @@ export abstract class OAuthDeviceFlow extends OAuthClient {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/** Standard device-authorization start. Override the body builder for custom providers. */
|
|
40
|
-
protected async startGenericDeviceAuth(
|
|
40
|
+
protected async startGenericDeviceAuth(
|
|
41
|
+
config: DeviceFlowConfig,
|
|
42
|
+
context?: OAuthDeviceFlowContext,
|
|
43
|
+
): Promise<OAuthDeviceStartResult> {
|
|
41
44
|
const body = this.buildDeviceStartBody(config);
|
|
42
|
-
const response = await this.
|
|
45
|
+
const response = await this.fetchFor(context)(config.deviceAuthUrl, {
|
|
43
46
|
method: "POST",
|
|
44
47
|
...(config.formHeaders === undefined ? {} : { headers: config.formHeaders }),
|
|
45
48
|
body,
|
|
@@ -124,8 +127,9 @@ export abstract class OAuthDeviceFlow extends OAuthClient {
|
|
|
124
127
|
protected async pollGenericDeviceAuth(
|
|
125
128
|
deviceAuthId: string,
|
|
126
129
|
config: DeviceFlowConfig,
|
|
130
|
+
context?: OAuthDeviceFlowContext,
|
|
127
131
|
): Promise<OAuthDevicePollResult> {
|
|
128
|
-
const response = await this.
|
|
132
|
+
const response = await this.fetchFor(context)(config.tokenUrl, {
|
|
129
133
|
method: "POST",
|
|
130
134
|
...(config.formHeaders === undefined ? {} : { headers: config.formHeaders }),
|
|
131
135
|
body: new URLSearchParams({
|