cartethyia 2.7.9 → 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 +6 -5
- package/dist/dashboard/assets/{BannedPage-BxoG1MrL.js → BannedPage-Dq530awD.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Dq530awD.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-ixwgKk53.js → CliToolDetailPage-DZzaS-7S.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZzaS-7S.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BmttNV3U.js → CliToolsPage-DaZZ3cqP.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-DaZZ3cqP.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BE3qwwfC.js → CombosPage-BlC_xdkX.js} +1 -1
- package/dist/dashboard/assets/CombosPage-BlC_xdkX.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CRZdmMIX.js → ConsoleLogPage-D-rqeVtG.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-D-rqeVtG.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-Dv_FJ6Er.js → CustomizationPage-7xT5yg2E.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-7xT5yg2E.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-BOoO8rpz.js → InjectSystemPromptPanel-6Teoq9Se.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-6Teoq9Se.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-ChJuNNVN.js → LoginPage-CZuI0MAR.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CZuI0MAR.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BZAJtPg1.js → ModelPicker-C1hNTlkr.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-C1hNTlkr.js.gz +0 -0
- package/dist/dashboard/assets/{OverviewPage-BE40s3u5.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-CQ6bPUf_.js → ProviderIcon-Ddhm1InL.js} +1 -1
- package/dist/dashboard/assets/ProviderIcon-Ddhm1InL.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js +1 -0
- 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-D1RV_2BX.js +1 -0
- package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-C5HPWqEv.js → SettingsPage-BzZAvYSX.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-BzZAvYSX.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-CFNcATJJ.js → SetupPage--s-EfEIL.js} +1 -1
- package/dist/dashboard/assets/SetupPage--s-EfEIL.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-YoD4tY5l.js → StudioPage-BjXFGSK4.js} +1 -1
- package/dist/dashboard/assets/StudioPage-BjXFGSK4.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-DxjaAhb_.js → UsagePage-CP8F8BN7.js} +1 -1
- package/dist/dashboard/assets/UsagePage-CP8F8BN7.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-BTlkq_Uk.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-BMcj1xZE.js +1 -0
- package/dist/dashboard/assets/assert-BMcj1xZE.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DdbT_7Am.js → badge-DkRUuVfz.js} +1 -1
- package/dist/dashboard/assets/badge-DkRUuVfz.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CsGN-nbm.js → banner-CDjW841Q.js} +1 -1
- package/dist/dashboard/assets/banner-CDjW841Q.js.gz +0 -0
- package/dist/dashboard/assets/{card-mgZ_TLLZ.js → card-Bto5UlL9.js} +1 -1
- package/dist/dashboard/assets/card-Bto5UlL9.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-A1-v8-03.js → cli-tools-DaH6g9hL.js} +1 -1
- package/dist/dashboard/assets/cli-tools-DaH6g9hL.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-CJ4Zty89.js → clipboard-button-BYKBCzjk.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BYKBCzjk.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-B5L2jPQ_.js → dialog-DL0Zftwv.js} +1 -1
- package/dist/dashboard/assets/dialog-DL0Zftwv.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-DkjUouAj.js → drawer-Dpx_UXaS.js} +1 -1
- package/dist/dashboard/assets/drawer-Dpx_UXaS.js.gz +0 -0
- package/dist/dashboard/assets/{entry-B-LVLV6o.js → entry-BV7-1NoM.js} +1 -1
- package/dist/dashboard/assets/entry-BV7-1NoM.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CAhdYl3B.js → entry-CGvdNU6r.js} +1 -1
- package/dist/dashboard/assets/entry-CGvdNU6r.js.gz +0 -0
- package/dist/dashboard/assets/entry-DScKYvZj.js +4 -0
- package/dist/dashboard/assets/entry-DScKYvZj.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CrsdLVsn.js → formatters-BS3DZlZj.js} +1 -1
- package/dist/dashboard/assets/formatters-BS3DZlZj.js.gz +0 -0
- package/dist/dashboard/assets/{index-BU64Lqvp.js → index-SQnvvTWX.js} +2 -2
- package/dist/dashboard/assets/index-SQnvvTWX.js.gz +0 -0
- package/dist/dashboard/assets/{inline-B2aDLyyg.js → inline-Dl-cuLK0.js} +1 -1
- package/dist/dashboard/assets/inline-Dl-cuLK0.js.gz +0 -0
- package/dist/dashboard/assets/{input-BCVkdR9d.js → input-Bfx0EzRc.js} +1 -1
- package/dist/dashboard/assets/input-Bfx0EzRc.js.gz +0 -0
- package/dist/dashboard/assets/{layout-DNcAdMK-.js → layout-BxhbQ_JS.js} +1 -1
- package/dist/dashboard/assets/layout-BxhbQ_JS.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-DgrIH0hw.js → list-row-D49Y4ptn.js} +1 -1
- package/dist/dashboard/assets/list-row-D49Y4ptn.js.gz +0 -0
- package/dist/dashboard/assets/{live-Cae01iu8.js → live-CbVTdX9V.js} +1 -1
- package/dist/dashboard/assets/live-CbVTdX9V.js.gz +0 -0
- package/dist/dashboard/assets/{network-CRib7H_2.js → network-JGvDveof.js} +1 -1
- package/dist/dashboard/assets/network-JGvDveof.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BKQE8Xpz.js → numbers-Dw6kiew-.js} +1 -1
- package/dist/dashboard/assets/numbers-Dw6kiew-.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-ecPvG_8g.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/providers/zro.svg +3 -0
- package/dist/dashboard/assets/providers/zro.svg.gz +0 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js +1 -0
- package/dist/dashboard/assets/quota-DiPD6UKH.js.gz +0 -0
- package/dist/dashboard/assets/{routing-Ckm1UXuC.js → routing-8jZr-3WE.js} +1 -1
- package/dist/dashboard/assets/routing-8jZr-3WE.js.gz +0 -0
- package/dist/dashboard/assets/{select-ChoFWyKz.js → select-oO1FxMVb.js} +2 -2
- package/dist/dashboard/assets/select-oO1FxMVb.js.gz +0 -0
- package/dist/dashboard/assets/{settings-CKjFPlKW.js → settings-CLr3kdIx.js} +1 -1
- package/dist/dashboard/assets/settings-CLr3kdIx.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DWCwU3fh.js → stack-Y3pDteZr.js} +1 -1
- package/dist/dashboard/assets/stack-Y3pDteZr.js.gz +0 -0
- package/dist/dashboard/assets/{state-Cg3VL5J_.js → state-CArX_Iak.js} +1 -1
- package/dist/dashboard/assets/state-CArX_Iak.js.gz +0 -0
- package/dist/dashboard/assets/{switch-Db70BMix.js → switch-DwlwmDO-.js} +1 -1
- package/dist/dashboard/assets/switch-DwlwmDO-.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BqdE0LuM.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 +54 -53
- package/migrations/full-postgres/0046_add_accounts_quota_plan_fetched_at.sql +7 -0
- package/migrations/full-postgres/0047_add_provider_device_flow_proxy.sql +17 -0
- package/migrations/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
- package/migrations/lite-sqlite3/0047_add_provider_device_flow_proxy.sql +19 -0
- package/package.json +1 -1
- package/src/boot/app.ts +11 -14
- package/src/boot/dependencies.ts +5 -7
- package/src/boot/flush.ts +20 -0
- package/src/boot/lifecycle.ts +7 -5
- package/src/config/providers.ts +6 -5
- package/src/config/routing.ts +26 -0
- package/src/config/spec-metadata.ts +72 -0
- package/src/config/spec.ts +28 -8
- package/src/console/api-keys/contracts.ts +12 -1
- package/src/console/api-keys/routes.ts +40 -28
- package/src/console/auth/account-reset.ts +7 -9
- package/src/console/backup/contracts.ts +4 -0
- package/src/console/backup/export-endpoint.ts +7 -5
- package/src/console/backup/nine-router.ts +71 -10
- package/src/console/backup/service.ts +8 -1
- package/src/console/cli-tools/service.ts +6 -12
- package/src/console/console-router-guards.ts +23 -16
- package/src/console/console-router.ts +1 -1
- package/src/console/domain-registration.ts +7 -4
- package/src/console/inferhub/client.ts +1 -1
- package/src/console/inferhub/normalize.ts +24 -28
- package/src/console/inferhub/types.ts +3 -0
- package/src/console/ip-bans/routes.ts +7 -13
- package/src/console/observability/live.ts +2 -2
- package/src/console/observability/store.ts +0 -53
- 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 +3 -2
- package/src/console/providers/catalog/store.ts +1914 -1902
- 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-global.ts +14 -24
- package/src/console/quota/account-quota-shared.ts +49 -0
- package/src/console/quota/account-quota-tenant.ts +11 -23
- package/src/console/quota/account-test-egress.ts +2 -2
- package/src/console/quota/daily-growth-job.ts +1 -1
- package/src/console/quota/quota-view.ts +19 -3
- package/src/console/routing/pools/contracts.ts +1 -1
- package/src/console/routing/pools/operations.ts +32 -47
- 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/console/shared/errors.ts +33 -6
- package/src/main.ts +2 -3
- 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/pool/{byte-accounting.ts → accounting.ts} +3 -2
- 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} +95 -20
- 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 +184 -41
- package/src/network/ssrf.ts +7 -7
- package/src/network/{retry.ts → util/retry.ts} +1 -1
- package/src/network/{rate-limit-verdict.ts → verdict.ts} +1 -1
- package/src/observability/event-log.ts +7 -361
- package/src/observability/performance-metrics.ts +9 -0
- package/src/observability/runtime-metrics.ts +14 -9
- package/src/observability/telemetry-buffer.ts +16 -26
- package/src/observability/telemetry-reconciliation.ts +9 -37
- package/src/observability/telemetry-row.ts +125 -0
- package/src/persistence/db-mode.ts +4 -1
- package/src/persistence/dialect.ts +18 -0
- package/src/persistence/migrate.ts +6 -3
- package/src/persistence/schema.ts +17 -0
- package/src/persistence/ttl-cache.ts +21 -3
- package/src/protocol/codecs.ts +59 -2
- package/src/protocol/dsml.ts +34 -86
- package/src/protocol/markup-stream-parser.ts +195 -0
- package/src/protocol/reasoning-text.ts +19 -0
- package/src/protocol/request/chat.ts +10 -10
- package/src/protocol/request/gemini.ts +8 -2
- package/src/protocol/request/messages.ts +34 -22
- package/src/protocol/response/chat.ts +12 -20
- package/src/protocol/response/messages.ts +34 -7
- package/src/protocol/response/omp-tool-call-markup.ts +43 -86
- package/src/protocol/response/responses.ts +18 -2
- package/src/protocol/stop-reason.ts +23 -1
- package/src/protocol/think-split.ts +112 -0
- package/src/protocol/translation/dialect/qwen.ts +26 -58
- 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 +76 -12
- package/src/providers/authentication/oauth-client.ts +40 -6
- package/src/providers/authentication/oauth-device-flow.ts +105 -11
- package/src/providers/authentication/oauth-flow-store.ts +82 -1
- package/src/providers/authentication/oauth-refresh-service.ts +766 -758
- package/src/providers/configured-provider.ts +148 -0
- package/src/providers/default-registry.ts +137 -36
- package/src/providers/discovery/discovery-types.ts +7 -0
- package/src/providers/discovery/probe-phases.ts +20 -6
- package/src/providers/discovery/probing-service.ts +22 -2
- package/src/providers/integrations/alibabacp/alibabacp-models.ts +1 -2
- package/src/providers/integrations/{dashscope-models.ts → alibabacp/dashscope-models.ts} +2 -2
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +16 -1
- package/src/providers/integrations/buddy/account.ts +969 -0
- package/src/providers/integrations/buddy/capabilities.ts +12 -12
- package/src/providers/integrations/buddy/{buddy-catalog-shared.ts → catalog.ts} +198 -136
- package/src/providers/integrations/buddy/{buddy-chat-shared.ts → chat.ts} +176 -20
- package/src/providers/integrations/buddy/codebuddy/index.ts +429 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +41 -26
- package/src/providers/integrations/buddy/headers.ts +311 -0
- 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/claude/claude-quota.ts +14 -17
- package/src/providers/integrations/cline/cline-oauth.ts +10 -5
- package/src/providers/integrations/cline/cline.ts +5 -6
- 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/commandcode/quota.ts +22 -28
- package/src/providers/integrations/cursor/cursor-auth.ts +1 -9
- package/src/providers/integrations/cursor/cursor-exec.ts +9 -2
- 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-request.ts +26 -12
- package/src/providers/integrations/cursor/cursor-shared.ts +8 -5
- package/src/providers/integrations/cursor/cursor.ts +574 -110
- package/src/providers/integrations/cursor/protocol/messages.ts +22 -29
- package/src/providers/integrations/cursor/protocol/protobuf-schema.ts +37 -0
- 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/devin/protocol/devin-proto.ts +1 -27
- package/src/providers/integrations/factory/factory-oauth.ts +33 -51
- package/src/providers/integrations/freebuff/assets/official-system-manager.txt +88 -0
- package/src/providers/integrations/freebuff/assets/official-system-worker.txt +57 -0
- package/src/providers/integrations/freebuff/assets/official-tools.json +1070 -0
- package/src/providers/integrations/freebuff/freebuff-catalog.ts +120 -0
- package/src/providers/integrations/freebuff/freebuff-constants.ts +1233 -0
- package/src/providers/integrations/freebuff/freebuff-discovery.ts +108 -0
- package/src/providers/integrations/freebuff/freebuff-oauth.ts +240 -0
- package/src/providers/integrations/freebuff/freebuff-quota.ts +260 -0
- package/src/providers/integrations/freebuff/freebuff-virtual.ts +89 -0
- package/src/providers/integrations/freebuff/freebuff.ts +682 -0
- 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 +52 -49
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +10 -17
- package/src/providers/integrations/grok/grok-turn-index.ts +11 -16
- package/src/providers/integrations/hermes/hermes-oauth.ts +3 -3
- package/src/providers/integrations/{hermes.ts → hermes/hermes.ts} +42 -13
- package/src/providers/integrations/hermes/index.ts +2 -0
- 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-catalog.ts +17 -1
- package/src/providers/integrations/kiro/kiro-discovery.ts +10 -12
- package/src/providers/integrations/kiro/kiro-oauth.ts +2 -2
- package/src/providers/integrations/kiro/kiro-quota.ts +8 -4
- package/src/providers/integrations/kiro/kiro.ts +15 -19
- package/src/providers/integrations/muse/muse-oauth.ts +5 -5
- package/src/providers/integrations/ollamacloud/index.ts +2 -0
- package/src/providers/integrations/{ollamacloud-models.ts → ollamacloud/models.ts} +2 -2
- package/src/providers/integrations/{ollamacloud-quota.ts → ollamacloud/quota.ts} +3 -3
- package/src/providers/integrations/opencode/fingerprint.ts +1 -1
- package/src/providers/integrations/opencode/opencode-go-quota.ts +2 -8
- package/src/providers/integrations/openrouter/provider.ts +1 -1
- package/src/providers/integrations/perch/perch-credential.ts +25 -0
- package/src/providers/integrations/perch/perch-protocol.ts +0 -6
- package/src/providers/integrations/perch/perch-quota.ts +2 -16
- package/src/providers/integrations/perch/perch.ts +6 -16
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +19 -60
- package/src/providers/integrations/qoder/qoder-adapter.ts +20 -125
- package/src/providers/integrations/qoder/qoder-auth.ts +109 -30
- package/src/providers/integrations/qoder/qoder-catalog.ts +21 -6
- package/src/providers/integrations/qoder/qoder-chat.ts +32 -29
- package/src/providers/integrations/qoder/qoder-checkin.ts +5 -5
- 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 -26
- package/src/providers/integrations/sensenova/provider.ts +144 -0
- package/src/providers/integrations/trae/trae-protocol.ts +9 -5
- package/src/providers/integrations/trae/trae-quota.ts +21 -29
- package/src/providers/integrations/trae/trae-realm.ts +38 -0
- package/src/providers/integrations/trae/trae.ts +7 -24
- 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/zcode-start-plan/provider.ts +226 -23
- package/src/providers/integrations/zcode-start-plan/quota.ts +19 -2
- package/src/providers/integrations/zro/zro.ts +205 -0
- package/src/providers/operations/account-error-classification.ts +199 -307
- package/src/providers/operations/account-health-service.ts +82 -1
- package/src/providers/operations/account-refresh-status.ts +36 -37
- package/src/providers/operations/account-tier.ts +15 -16
- package/src/providers/operations/client-version-resolver.ts +1 -1
- package/src/providers/operations/client-versions.ts +100 -81
- package/src/providers/operations/cooldown-rules.ts +11 -16
- package/src/providers/operations/oauth-refresh-lead.ts +46 -22
- package/src/providers/operations/{model-catalog-cache.ts → provider-caches.ts} +68 -16
- package/src/providers/operations/provider-catalog-service.ts +1 -1
- package/src/providers/operations/provider-credential-service.ts +118 -51
- package/src/providers/operations/provider-rules/github.ts +48 -0
- package/src/providers/operations/provider-rules/grok.ts +33 -0
- package/src/providers/operations/provider-rules/inception.ts +49 -0
- package/src/providers/operations/provider-rules/index.ts +32 -0
- package/src/providers/operations/provider-rules/perch.ts +37 -0
- package/src/providers/operations/provider-rules/qoder.ts +70 -0
- package/src/providers/operations/provider-rules/trae.ts +81 -0
- package/src/providers/operations/session-resolution.ts +17 -1
- package/src/providers/provider-contracts.ts +6 -4
- package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
- package/src/providers/provider-metadata.ts +70 -10
- package/src/providers/provider-probe.ts +15 -1
- package/src/providers/provider-registry.ts +42 -33
- package/src/providers/quota/quota-contracts.ts +2 -0
- package/src/providers/quota/quota-limit-windows.ts +16 -5
- package/src/providers/quota/quota-support.ts +1 -1
- package/src/providers/quota/quota-window-parser.ts +90 -18
- package/src/providers/quota/refresh.ts +100 -21
- package/src/security/api-key-auth-cache.ts +1 -1
- package/src/security/api-key-auth.ts +6 -2
- package/src/security/ip-boundary.ts +1 -1
- package/src/transport/dispatch/attempt-finalize.ts +15 -14
- package/src/transport/dispatch/attempt-loop.ts +73 -19
- package/src/transport/dispatch/generation.ts +2 -8
- package/src/transport/dispatch/handler-deps.ts +1 -1
- package/src/transport/dispatch/leases.ts +1 -1
- package/src/transport/dispatch/native-shared.ts +25 -0
- package/src/transport/dispatch/proxy-request.ts +8 -46
- package/src/transport/dispatch/responses-compact.ts +2 -8
- package/src/transport/dispatch/retry-policy.ts +1 -1
- package/src/transport/dispatch/streaming/finalize.ts +10 -7
- package/src/transport/dispatch/streaming/stream.ts +9 -37
- package/src/transport/dispatch/systemone.ts +2 -8
- package/src/transport/dispatch/token-count.ts +2 -6
- package/src/transport/dispatch/upstream.ts +63 -0
- package/src/transport/drain-endpoint.ts +31 -4
- package/src/transport/failure-policy.ts +16 -30
- package/src/transport/guards/body-policy.ts +7 -1
- package/src/transport/guards/error-lifecycle.ts +13 -1
- package/src/transport/guards/request-context.ts +22 -14
- package/src/transport/request/preparer.ts +81 -71
- package/src/transport/routing/bounded-lru.ts +14 -0
- package/src/transport/routing/drain-reserve.ts +129 -0
- package/src/transport/routing/plan-gate.ts +7 -1
- package/src/transport/routing/round-robin.ts +60 -0
- package/src/transport/routing/route-catalog.ts +123 -111
- package/src/transport/routing/route-model.ts +51 -9
- package/src/transport/routing/router.ts +393 -32
- package/src/transport/shutdown-notice.ts +1 -1
- package/src/transport/surface/adapters.ts +11 -2
- package/src/transport/surface/chat/adapter.ts +2 -2
- package/src/transport/surface/chat/encode.ts +47 -4
- package/src/transport/surface/chat/parse.ts +2 -12
- package/src/transport/surface/completion.ts +44 -33
- package/src/transport/surface/content-parts.ts +21 -0
- package/src/transport/surface/messages/adapter.ts +7 -1
- package/src/transport/surface/messages/encode.ts +11 -3
- package/src/transport/surface/messages/parse.ts +2 -1
- package/src/transport/surface/messages/stream.ts +33 -17
- package/src/transport/surface/responses/encode.ts +22 -5
- package/src/transport/surface/responses/parse.ts +3 -11
- 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-BxoG1MrL.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-ixwgKk53.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-BmttNV3U.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-BE3qwwfC.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-BOoO8rpz.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-ChJuNNVN.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BZAJtPg1.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-BE40s3u5.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js +0 -8
- package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js +0 -1
- package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-CFNcATJJ.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-YoD4tY5l.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-DxjaAhb_.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-BTlkq_Uk.js.gz +0 -0
- package/dist/dashboard/assets/app-BX2nnKqs.css +0 -2
- package/dist/dashboard/assets/app-BX2nnKqs.css.gz +0 -0
- package/dist/dashboard/assets/assert-CndthXFQ.js +0 -1
- package/dist/dashboard/assets/assert-CndthXFQ.js.gz +0 -0
- package/dist/dashboard/assets/badge-DdbT_7Am.js.gz +0 -0
- package/dist/dashboard/assets/banner-CsGN-nbm.js.gz +0 -0
- package/dist/dashboard/assets/card-mgZ_TLLZ.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-A1-v8-03.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-CJ4Zty89.js.gz +0 -0
- package/dist/dashboard/assets/dialog-B5L2jPQ_.js.gz +0 -0
- package/dist/dashboard/assets/drawer-DkjUouAj.js.gz +0 -0
- package/dist/dashboard/assets/entry-B-LVLV6o.js.gz +0 -0
- package/dist/dashboard/assets/entry-CAhdYl3B.js.gz +0 -0
- package/dist/dashboard/assets/entry-D2xD0Tmd.js +0 -4
- package/dist/dashboard/assets/entry-D2xD0Tmd.js.gz +0 -0
- package/dist/dashboard/assets/formatters-CrsdLVsn.js.gz +0 -0
- package/dist/dashboard/assets/index-BU64Lqvp.js.gz +0 -0
- package/dist/dashboard/assets/inline-B2aDLyyg.js.gz +0 -0
- package/dist/dashboard/assets/input-BCVkdR9d.js.gz +0 -0
- package/dist/dashboard/assets/layout-DNcAdMK-.js.gz +0 -0
- package/dist/dashboard/assets/list-row-DgrIH0hw.js.gz +0 -0
- package/dist/dashboard/assets/live-Cae01iu8.js.gz +0 -0
- package/dist/dashboard/assets/network-CRib7H_2.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BKQE8Xpz.js.gz +0 -0
- package/dist/dashboard/assets/pagination-ecPvG_8g.js.gz +0 -0
- package/dist/dashboard/assets/quota-DJ1QlAOq.js +0 -1
- package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
- package/dist/dashboard/assets/routing-Ckm1UXuC.js.gz +0 -0
- package/dist/dashboard/assets/select-ChoFWyKz.js.gz +0 -0
- package/dist/dashboard/assets/settings-CKjFPlKW.js.gz +0 -0
- package/dist/dashboard/assets/stack-DWCwU3fh.js.gz +0 -0
- package/dist/dashboard/assets/state-Cg3VL5J_.js.gz +0 -0
- package/dist/dashboard/assets/switch-Db70BMix.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-BqdE0LuM.js.gz +0 -0
- package/src/network/pool-health.ts +0 -210
- package/src/providers/bundled-discovery-providers.ts +0 -98
- package/src/providers/configured-openai-providers.ts +0 -120
- 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-identity.ts +0 -300
- 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 -185
- package/src/providers/integrations/buddy/codebuddy/oauth.ts +0 -47
- package/src/providers/integrations/buddy/codebuddy/provider.ts +0 -175
- 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 -871
- package/src/providers/integrations/qoder/qoder-ide.ts +0 -588
- package/src/providers/operations/model-discovery-cache.ts +0 -34
- package/src/providers/operations/probe-fetch.ts +0 -15
- package/src/providers/operations/provider-version-cache.ts +0 -30
- package/src/providers/provider-capabilities.ts +0 -33
- package/src/providers/provider-credential-envelope.ts +0 -43
- /package/dist/dashboard/assets/{app-B7kIWFm5.js → app-C0gTXEoN.js} +0 -0
- /package/dist/dashboard/assets/{app-B7kIWFm5.js.gz → app-C0gTXEoN.js.gz} +0 -0
- /package/src/network/{http2-bidi.ts → bidi.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
|
@@ -21,15 +21,16 @@ import { createHash } from "node:crypto";
|
|
|
21
21
|
import { completeRequiredSchema } from "../../../protocol/codecs";
|
|
22
22
|
import type { CanonicalRequest } from "../../../protocol/canonical-model";
|
|
23
23
|
import { isRecord } from "../../../protocol/codecs";
|
|
24
|
+
import { GatewayError } from "../../../protocol/gateway-error";
|
|
24
25
|
import { applyDeepSeekReasoning, applyOpenAIReasoning, backfillDeepSeekReasoningContent, clampedEffortOutputFloor, ensureChatReasoningReplayPresence } from "../../../protocol/reasoning";
|
|
25
|
-
import { BUDDY_CN_EFFORTS, BUDDY_INTL_EFFORTS, BUDDY_SHARED_RAW } from "./
|
|
26
|
+
import { BUDDY_CN_EFFORTS, BUDDY_INTL_EFFORTS, BUDDY_SHARED_RAW } from "./catalog";
|
|
26
27
|
// Imported for the CN roster only: a CN-only id has no row in the shared
|
|
27
28
|
// table, and without one `raiseOutputForRaisedEffort` silently no-ops, so a
|
|
28
29
|
// raised effort still answers inside a budget sized for the lower one. It is
|
|
29
30
|
// read inside the function below — never at module init — so the cycle with
|
|
30
31
|
// cn-provider (which imports this module) resolves before any call.
|
|
31
|
-
import { CODEBUDDY_CN_RAW } from "./
|
|
32
|
-
import { buddyAccountUid } from "./
|
|
32
|
+
import { CODEBUDDY_CN_RAW } from "./catalog";
|
|
33
|
+
import { buddyAccountUid } from "./account";
|
|
33
34
|
import { SYSTEM_PROMPT_WRAPPER_PREFIX, SYSTEM_PROMPT_WRAPPER_SUFFIX } from "../../../console/system-prompt/contracts";
|
|
34
35
|
import type { ProviderDispatchContext } from "../../provider-contracts";
|
|
35
36
|
|
|
@@ -55,6 +56,123 @@ function normalizedToolName(value: string, index: number, used: Set<string>): st
|
|
|
55
56
|
return uniqueToolName(base || `tool_${index + 1}`, used);
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Schema keywords whose values are schemas (recursed as schema objects).
|
|
61
|
+
* Mirrors the donor gateway's `upstream_compat._SCHEMA_MAPS/_ARRAYS/CHILDREN`.
|
|
62
|
+
*/
|
|
63
|
+
const RE2_SCHEMA_MAPS: ReadonlySet<string> = new Set([
|
|
64
|
+
"properties",
|
|
65
|
+
"patternProperties",
|
|
66
|
+
"$defs",
|
|
67
|
+
"definitions",
|
|
68
|
+
"dependentSchemas",
|
|
69
|
+
"dependencies",
|
|
70
|
+
]);
|
|
71
|
+
const RE2_SCHEMA_ARRAYS: ReadonlySet<string> = new Set([
|
|
72
|
+
"allOf",
|
|
73
|
+
"anyOf",
|
|
74
|
+
"oneOf",
|
|
75
|
+
"prefixItems",
|
|
76
|
+
"items",
|
|
77
|
+
]);
|
|
78
|
+
const RE2_SCHEMA_CHILDREN: ReadonlySet<string> = new Set([
|
|
79
|
+
"items",
|
|
80
|
+
"additionalItems",
|
|
81
|
+
"contains",
|
|
82
|
+
"unevaluatedItems",
|
|
83
|
+
"additionalProperties",
|
|
84
|
+
"unevaluatedProperties",
|
|
85
|
+
"propertyNames",
|
|
86
|
+
"not",
|
|
87
|
+
"if",
|
|
88
|
+
"then",
|
|
89
|
+
"else",
|
|
90
|
+
"contentSchema",
|
|
91
|
+
]);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Removes unescaped backslashes before underscores in one regex pattern. The
|
|
95
|
+
* CodeBuddy upstream validates tool schemas with RE2, which does not support
|
|
96
|
+
* `\_` escapes — a client schema that serializes `\_` (a common JSON
|
|
97
|
+
* representation of a literal underscore) is rejected with a 400. The donor
|
|
98
|
+
* gateway normalizes this before dispatch; a backslash that escapes a
|
|
99
|
+
* backslash is preserved.
|
|
100
|
+
*/
|
|
101
|
+
function normalizeRe2Pattern(value: string): string {
|
|
102
|
+
let out = "";
|
|
103
|
+
for (let i = 0; i < value.length; i++) {
|
|
104
|
+
const char = value[i];
|
|
105
|
+
if (char === "\\" && value[i + 1] === "\\") {
|
|
106
|
+
// Escaped backslash: keep the pair so a following `_` stays escaped.
|
|
107
|
+
out += "\\\\";
|
|
108
|
+
i += 1;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (char === "\\" && value[i + 1] === "_") {
|
|
112
|
+
// `\_` — the upstream's RE2 rejects it; drop the backslash.
|
|
113
|
+
out += "_";
|
|
114
|
+
i += 1;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
out += char;
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Normalizes RE2-incompatible underscore escapes in schema pattern positions. */
|
|
123
|
+
function normalizeRe2SchemaPatterns(schema: unknown): void {
|
|
124
|
+
if (!isRecord(schema)) return;
|
|
125
|
+
const pattern = schema["pattern"];
|
|
126
|
+
if (typeof pattern === "string") schema["pattern"] = normalizeRe2Pattern(pattern);
|
|
127
|
+
const patternProperties = schema["patternProperties"];
|
|
128
|
+
if (isRecord(patternProperties)) {
|
|
129
|
+
const normalized: Record<string, unknown> = {};
|
|
130
|
+
for (const [key, value] of Object.entries(patternProperties)) {
|
|
131
|
+
const key2 = normalizeRe2Pattern(key);
|
|
132
|
+
if (key2 in normalized) {
|
|
133
|
+
normalized[key2] = { allOf: [normalized[key2], value] };
|
|
134
|
+
} else {
|
|
135
|
+
normalized[key2] = value;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
schema["patternProperties"] = normalized;
|
|
139
|
+
}
|
|
140
|
+
for (const key of RE2_SCHEMA_MAPS) {
|
|
141
|
+
const map = schema[key];
|
|
142
|
+
if (!isRecord(map)) continue;
|
|
143
|
+
for (const child of Object.values(map)) normalizeRe2SchemaPatterns(child);
|
|
144
|
+
}
|
|
145
|
+
for (const key of RE2_SCHEMA_ARRAYS) {
|
|
146
|
+
const list = schema[key];
|
|
147
|
+
if (!Array.isArray(list)) continue;
|
|
148
|
+
for (const child of list) normalizeRe2SchemaPatterns(child);
|
|
149
|
+
}
|
|
150
|
+
for (const key of RE2_SCHEMA_CHILDREN) {
|
|
151
|
+
normalizeRe2SchemaPatterns(schema[key]);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** JSON-serializes a value to cheaply detect a backslash-before-underscore. */
|
|
156
|
+
function hasUnderscoreEscape(value: unknown): boolean {
|
|
157
|
+
try {
|
|
158
|
+
return JSON.stringify(value).includes("\\_");
|
|
159
|
+
} catch {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Returns the declaration with RE2-safe schema patterns, or the same object. */
|
|
165
|
+
function normalizeRe2Declaration(declaration: Record<string, unknown>): Record<string, unknown> {
|
|
166
|
+
const parameters = declaration["parameters"];
|
|
167
|
+
if (!hasUnderscoreEscape(parameters)) return declaration;
|
|
168
|
+
// Deep-copy only when a rewrite is needed; the shared object must not be
|
|
169
|
+
// mutated for every dispatch.
|
|
170
|
+
const out: Record<string, unknown> = { ...declaration };
|
|
171
|
+
out["parameters"] = structuredClone(parameters);
|
|
172
|
+
normalizeRe2SchemaPatterns(out["parameters"]);
|
|
173
|
+
return out;
|
|
174
|
+
}
|
|
175
|
+
|
|
58
176
|
/**
|
|
59
177
|
* Buddy's Chat Completions wire has no `web_search_preview` hosted tool; its
|
|
60
178
|
* search is an ordinary function named `web_search` with a `{query}` schema.
|
|
@@ -102,29 +220,28 @@ export function normalizeBuddyToolNames(payload: Record<string, unknown>): void
|
|
|
102
220
|
const name = normalizedToolName(sourceName, index, used);
|
|
103
221
|
used.add(name);
|
|
104
222
|
if (!replacements.has(sourceName)) replacements.set(sourceName, name);
|
|
105
|
-
if (fn !== undefined)
|
|
106
|
-
|
|
107
|
-
...
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
name,
|
|
111
|
-
...(fn["parameters"] === undefined ? {} : { parameters: completeRequiredSchema(fn["parameters"]) }),
|
|
112
|
-
},
|
|
223
|
+
if (fn !== undefined) {
|
|
224
|
+
const fnOut = {
|
|
225
|
+
...fn,
|
|
226
|
+
name,
|
|
227
|
+
...(fn["parameters"] === undefined ? {} : { parameters: completeRequiredSchema(fn["parameters"]) }),
|
|
113
228
|
};
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
},
|
|
229
|
+
return { ...rawTool, function: normalizeRe2Declaration(fnOut) };
|
|
230
|
+
}
|
|
231
|
+
if (custom !== undefined) {
|
|
232
|
+
const customOut = {
|
|
233
|
+
...custom,
|
|
234
|
+
name,
|
|
235
|
+
...(custom["format"] === undefined ? {} : { format: completeRequiredSchema(custom["format"]) }),
|
|
122
236
|
};
|
|
123
|
-
|
|
237
|
+
return { ...rawTool, custom: normalizeRe2Declaration(customOut) };
|
|
238
|
+
}
|
|
239
|
+
const bareOut = {
|
|
124
240
|
...rawTool,
|
|
125
241
|
name,
|
|
126
242
|
...(rawTool["parameters"] === undefined ? {} : { parameters: completeRequiredSchema(rawTool["parameters"]) }),
|
|
127
243
|
};
|
|
244
|
+
return { ...bareOut, ...normalizeRe2Declaration(bareOut) };
|
|
128
245
|
});
|
|
129
246
|
const messages = payload["messages"];
|
|
130
247
|
if (Array.isArray(messages)) {
|
|
@@ -138,6 +255,13 @@ export function normalizeBuddyToolNames(payload: Record<string, unknown>): void
|
|
|
138
255
|
}
|
|
139
256
|
}
|
|
140
257
|
}
|
|
258
|
+
const responseFormat = payload["response_format"];
|
|
259
|
+
if (isRecord(responseFormat) && hasUnderscoreEscape(responseFormat)) {
|
|
260
|
+
const copied = structuredClone(responseFormat) as Record<string, unknown>;
|
|
261
|
+
const jsonSchema = copied["json_schema"];
|
|
262
|
+
if (isRecord(jsonSchema)) normalizeRe2SchemaPatterns(jsonSchema["schema"]);
|
|
263
|
+
payload["response_format"] = copied;
|
|
264
|
+
}
|
|
141
265
|
const choice = payload["tool_choice"];
|
|
142
266
|
if (!isRecord(choice)) return;
|
|
143
267
|
if (choice["type"] === "allowed_tools" && Array.isArray(choice["tools"])) {
|
|
@@ -477,6 +601,10 @@ export function buddyPrePayloadCommon(
|
|
|
477
601
|
normalizeBuddyImageUrl(payload);
|
|
478
602
|
// developer role → system (buddy whitelist rejects developer, 11128)
|
|
479
603
|
normalizeBuddyRoles(payload);
|
|
604
|
+
// Validate the *caller's* thinking controls before the DeepSeek contract may
|
|
605
|
+
// inject its own `thinking` (an injected `{type:"enabled"}` has no budget and
|
|
606
|
+
// must not be rejected as a malformed client shape).
|
|
607
|
+
validateBuddyThinking(payload);
|
|
480
608
|
applyOpenAIReasoning(payload, request);
|
|
481
609
|
applyDeepSeekReasoning(payload);
|
|
482
610
|
// sol family defaults to high reasoning like reference thinking.go defaultDeepSeekEffort — sol without effort gets 500/invoke error otherwise
|
|
@@ -516,6 +644,34 @@ export function buddyPrePayloadCommon(
|
|
|
516
644
|
delete payload["agent_prompt"];
|
|
517
645
|
}
|
|
518
646
|
|
|
647
|
+
/**
|
|
648
|
+
* Validates the reasoning controls the CodeBuddy Chat wire accepts, mirroring
|
|
649
|
+
* the donor gateway's `map_reasoning_controls`. The upstream rejects the whole
|
|
650
|
+
* request for shapes it does not model, so a client that sends an unsupported
|
|
651
|
+
* `thinking` shape is failed here with a 400 that names the field — instead of
|
|
652
|
+
* an opaque upstream error.
|
|
653
|
+
*/
|
|
654
|
+
function validateBuddyThinking(payload: Record<string, unknown>): void {
|
|
655
|
+
const thinking = isRecord(payload["thinking"]) ? payload["thinking"] : undefined;
|
|
656
|
+
if (thinking === undefined) return;
|
|
657
|
+
const mode = typeof thinking["type"] === "string" ? (thinking["type"] as string) : "";
|
|
658
|
+
if (mode !== "enabled" && mode !== "adaptive" && mode !== "disabled") {
|
|
659
|
+
throw new GatewayError("invalid_request", 400, `CodeBuddy thinking.type must be enabled, adaptive or disabled (got ${JSON.stringify(mode)}) (request {requestId}). Check the shape of what you sent — then resend 🪞`);
|
|
660
|
+
}
|
|
661
|
+
if (mode === "enabled") {
|
|
662
|
+
const budget = thinking["budget_tokens"];
|
|
663
|
+
if (typeof budget !== "number" || !Number.isInteger(budget) || budget < 1024) {
|
|
664
|
+
throw new GatewayError("invalid_request", 400, "CodeBuddy thinking.budget_tokens must be an integer >= 1024 (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
665
|
+
}
|
|
666
|
+
} else if (thinking["budget_tokens"] !== undefined) {
|
|
667
|
+
throw new GatewayError("invalid_request", 400, "CodeBuddy thinking.budget_tokens requires thinking.type=enabled (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
668
|
+
}
|
|
669
|
+
const display = thinking["display"];
|
|
670
|
+
if (display !== undefined && display !== null && display !== "summarized") {
|
|
671
|
+
throw new GatewayError("invalid_request", 400, "CodeBuddy thinking.display supports only summarized (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
519
675
|
function injectSolReasoningDefault(payload: Record<string, unknown>): void {
|
|
520
676
|
const model = typeof payload["model"] === "string" ? (payload["model"] as string) : "";
|
|
521
677
|
const isSol = model.toLowerCase().includes("sol");
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { BuddyMediaAdapter } from "../media";
|
|
2
|
+
import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderAdapter } from "../../../provider-contracts";
|
|
3
|
+
import type { ModelDefinition } from "../../../provider-model-definition";
|
|
4
|
+
import type { DiscoveryInput } from "../../../discovery/discovery-types";
|
|
5
|
+
import { GatewayError } from "../../../../protocol/gateway-error";
|
|
6
|
+
import type { CanonicalRequest } from "../../../../protocol/canonical-model";
|
|
7
|
+
import { providerBaseUrl } from "../../../provider-metadata";
|
|
8
|
+
import { ensurePayloadModel } from "../../../configured-provider";
|
|
9
|
+
import { codebuddyAdapterConfig, codebuddyDomain, codebuddyHeaders } from "./shared";
|
|
10
|
+
import {
|
|
11
|
+
BUDDY_SHARED_RAW,
|
|
12
|
+
BUDDY_IMAGE_MODEL_ID_SET,
|
|
13
|
+
BUDDY_VIDEO_MODEL_ID_SET,
|
|
14
|
+
BUDDY_INTL_MODELS_PATH,
|
|
15
|
+
BUDDY_CN_MODELS_PATH,
|
|
16
|
+
BUDDY_CN_IMAGE_MODEL_ID_SET,
|
|
17
|
+
BUDDY_CN_VIDEO_MODEL_ID_SET,
|
|
18
|
+
CODEBUDDY_CN_RAW,
|
|
19
|
+
type BuddyRawEntry,
|
|
20
|
+
makeBuddyModel,
|
|
21
|
+
makeBuddyImageModels,
|
|
22
|
+
makeBuddyVideoModels,
|
|
23
|
+
makeBuddyCnImageModels,
|
|
24
|
+
makeBuddyCnVideoModels,
|
|
25
|
+
fetchBuddyDirectoryModels,
|
|
26
|
+
} from "../catalog";
|
|
27
|
+
import {
|
|
28
|
+
applyBuddySystemPrompt,
|
|
29
|
+
buddyPrePayloadCommon,
|
|
30
|
+
finalizeBuddyMessages,
|
|
31
|
+
injectBuddyParallelToolCalls,
|
|
32
|
+
normalizeBuddyToolNames,
|
|
33
|
+
} from "../chat";
|
|
34
|
+
import {
|
|
35
|
+
BuddyOAuthClient,
|
|
36
|
+
type BuddyOAuthVariant,
|
|
37
|
+
strictResponseCode,
|
|
38
|
+
fetchTencentBillingQuota,
|
|
39
|
+
fetchBuddyRequestUsage,
|
|
40
|
+
type BuddyUsageResult,
|
|
41
|
+
} from "../account";
|
|
42
|
+
import { buildCodeBuddyUserAgent } from "../../../operations/client-versions";
|
|
43
|
+
import type { FetchLike, ProviderQuotaResult } from "../../../quota/quota-contracts";
|
|
44
|
+
|
|
45
|
+
// ── codebuddy/provider ──────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
export const CODEBUDDY_PROVIDER_ID = "cb" as const;
|
|
48
|
+
|
|
49
|
+
export const CODEBUDDY_BASE_URL = providerBaseUrl("cb");
|
|
50
|
+
|
|
51
|
+
export const CODEBUDDY_SYSTEM_PROMPT = "You are a helpful assistant.";
|
|
52
|
+
|
|
53
|
+
function codeBuddyIntlPrePayload(
|
|
54
|
+
payload: Record<string, unknown>,
|
|
55
|
+
request: CanonicalRequest,
|
|
56
|
+
candidate: ProviderDispatchTarget,
|
|
57
|
+
context?: ProviderDispatchContext,
|
|
58
|
+
): void {
|
|
59
|
+
// International ladder: DeepSeek Flash and friends serve only `high`.
|
|
60
|
+
buddyPrePayloadCommon(payload, request, "intl", context);
|
|
61
|
+
const rawModel = payload["model"];
|
|
62
|
+
const source =
|
|
63
|
+
typeof rawModel === "string" && rawModel.length > 0
|
|
64
|
+
? rawModel
|
|
65
|
+
: candidate.model_id;
|
|
66
|
+
if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
67
|
+
const messages = payload["messages"];
|
|
68
|
+
if (Array.isArray(messages)) {
|
|
69
|
+
applyBuddySystemPrompt(
|
|
70
|
+
messages as Array<Record<string, unknown>>,
|
|
71
|
+
CODEBUDDY_SYSTEM_PROMPT,
|
|
72
|
+
context?.tenant_system_prompt,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
normalizeBuddyToolNames(payload);
|
|
76
|
+
injectBuddyParallelToolCalls(payload, request);
|
|
77
|
+
void request;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const CODEBUDDY_INTL_RAW: readonly BuddyRawEntry[] = BUDDY_SHARED_RAW;
|
|
81
|
+
|
|
82
|
+
export const CODEBUDDY_IMAGE_MODELS: readonly ModelDefinition[] = makeBuddyImageModels(
|
|
83
|
+
"cb",
|
|
84
|
+
"/images/generations",
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
export const CODEBUDDY_VIDEO_MODELS: readonly ModelDefinition[] = makeBuddyVideoModels(
|
|
88
|
+
"cb",
|
|
89
|
+
"/videos/generations",
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
export const CODEBUDDY_MODELS: readonly ModelDefinition[] = [
|
|
93
|
+
...CODEBUDDY_INTL_RAW.filter(
|
|
94
|
+
(entry) => !BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]) && !BUDDY_VIDEO_MODEL_ID_SET.has(entry[0]),
|
|
95
|
+
).map((entry) => makeBuddyModel(entry, "cb")),
|
|
96
|
+
...CODEBUDDY_IMAGE_MODELS,
|
|
97
|
+
...CODEBUDDY_VIDEO_MODELS,
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
export async function discoverCodeBuddyModels(
|
|
101
|
+
input: DiscoveryInput,
|
|
102
|
+
): Promise<readonly ModelDefinition[] | null> {
|
|
103
|
+
return fetchBuddyDirectoryModels({
|
|
104
|
+
siteUrl: CODEBUDDY_BASE_URL,
|
|
105
|
+
providerId: CODEBUDDY_PROVIDER_ID,
|
|
106
|
+
credential: input.credential,
|
|
107
|
+
modelsPath: BUDDY_INTL_MODELS_PATH,
|
|
108
|
+
endpoint: undefined,
|
|
109
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
110
|
+
...(input.fetcher ? { fetcher: input.fetcher } : {}),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function createCodeBuddyAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
|
|
115
|
+
return new BuddyMediaAdapter(
|
|
116
|
+
codebuddyAdapterConfig({
|
|
117
|
+
providerId: CODEBUDDY_PROVIDER_ID,
|
|
118
|
+
baseUrl: CODEBUDDY_BASE_URL,
|
|
119
|
+
variant: "IDE",
|
|
120
|
+
cliIdentity: true,
|
|
121
|
+
prePayload: codeBuddyIntlPrePayload,
|
|
122
|
+
// The intl CLI profile gzips the chat body and recovers a channel-check
|
|
123
|
+
// 400 by retrying once on the console chat endpoint (donor behavior).
|
|
124
|
+
requestCompression: "gzip",
|
|
125
|
+
channelFallbackPath: "/console/chat/completions",
|
|
126
|
+
...(fetchImpl ? { fetchImpl } : {}),
|
|
127
|
+
}),
|
|
128
|
+
{
|
|
129
|
+
variant: "IDE",
|
|
130
|
+
// BuddyMediaConfig has no `cliIdentity`; the CLI identity is selected by
|
|
131
|
+
// supplying the builder that takes it.
|
|
132
|
+
buildHeaders: (context, request) => codebuddyHeaders("IDE", context, request, true),
|
|
133
|
+
systemPrompt: CODEBUDDY_SYSTEM_PROMPT,
|
|
134
|
+
baseUrl: CODEBUDDY_BASE_URL,
|
|
135
|
+
imageGenerationPath: "/images/generations",
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── codebuddy/cn-provider ──────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
export const CODEBUDDY_CN_PROVIDER_ID = "cbcn" as const;
|
|
143
|
+
|
|
144
|
+
export const CODEBUDDY_CN_BASE_URL = providerBaseUrl("cbcn");
|
|
145
|
+
|
|
146
|
+
function isAgentPromptText(text: string): boolean {
|
|
147
|
+
return /you are claude code|claude.?code.+official.+cli|anthropic.+official.+cli|anxthxropic.+official.+cli|you are (?:cursor|windsurf|cline|aider|continue|copilot|cody)|you are an? (?:ai )?(?:coding |code )?agent|cc_entrypoint\s*=\s*(?:cli|vscode|jetbrains|gui)|claude.?code.+issues|give feedback.+claude.?code|you are .{0,30}(?:powerful )?ai agent|orchestration capabilities|OhMyOpenCode|<agent-identity>|<Role>|<Behavior_Instructions>/i.test(
|
|
148
|
+
text,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const CODEBUDDY_CN_NEUTRAL_PROMPT = "You are a helpful assistant.";
|
|
153
|
+
|
|
154
|
+
function flattenContent(content: unknown): string {
|
|
155
|
+
if (typeof content === "string") return content;
|
|
156
|
+
if (!Array.isArray(content)) return "";
|
|
157
|
+
return content
|
|
158
|
+
.map((part) =>
|
|
159
|
+
part !== null && typeof part === "object" && "text" in part
|
|
160
|
+
? String((part as Record<string, unknown>)["text"] ?? "")
|
|
161
|
+
: "",
|
|
162
|
+
)
|
|
163
|
+
.join("\n");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function neutralizeCnMessages(messages: Array<Record<string, unknown>>): void {
|
|
167
|
+
for (let index = 0; index < messages.length; index += 1) {
|
|
168
|
+
const message = messages[index];
|
|
169
|
+
if (!message || message["role"] !== "system") continue;
|
|
170
|
+
const content = message["content"];
|
|
171
|
+
const text = flattenContent(content);
|
|
172
|
+
if (text.length <= 2_000 && !isAgentPromptText(text)) continue;
|
|
173
|
+
messages[index] =
|
|
174
|
+
typeof content === "string"
|
|
175
|
+
? { ...message, content: CODEBUDDY_CN_NEUTRAL_PROMPT }
|
|
176
|
+
: {
|
|
177
|
+
...message,
|
|
178
|
+
content: [{ type: "text", text: CODEBUDDY_CN_NEUTRAL_PROMPT }],
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function codeBuddyCnPrePayload(
|
|
184
|
+
payload: Record<string, unknown>,
|
|
185
|
+
request: CanonicalRequest,
|
|
186
|
+
candidate: ProviderDispatchTarget,
|
|
187
|
+
context?: ProviderDispatchContext,
|
|
188
|
+
): void {
|
|
189
|
+
// CN ladder: the CN backend serves `low`/`max` levels the international one
|
|
190
|
+
// rejects, so the realm must be named rather than left to default to intl.
|
|
191
|
+
buddyPrePayloadCommon(payload, request, "cn", context);
|
|
192
|
+
if (Array.isArray(payload["messages"])) {
|
|
193
|
+
const messages = payload["messages"] as Array<Record<string, unknown>>;
|
|
194
|
+
neutralizeCnMessages(messages);
|
|
195
|
+
finalizeBuddyMessages(messages, { leadPrompt: CODEBUDDY_CN_NEUTRAL_PROMPT });
|
|
196
|
+
}
|
|
197
|
+
ensurePayloadModel(payload, candidate, "CodeBuddy CN");
|
|
198
|
+
normalizeBuddyToolNames(payload);
|
|
199
|
+
injectBuddyParallelToolCalls(payload, request);
|
|
200
|
+
void request;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export { CODEBUDDY_CN_RAW };
|
|
204
|
+
|
|
205
|
+
export const CODEBUDDY_CN_IMAGE_MODELS: readonly ModelDefinition[] = makeBuddyCnImageModels(
|
|
206
|
+
CODEBUDDY_CN_PROVIDER_ID,
|
|
207
|
+
"/images/generations",
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
export const CODEBUDDY_CN_VIDEO_MODELS: readonly ModelDefinition[] = makeBuddyCnVideoModels(
|
|
211
|
+
CODEBUDDY_CN_PROVIDER_ID,
|
|
212
|
+
"/videos/generations",
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
export const CODEBUDDY_CN_MODELS: readonly ModelDefinition[] = [
|
|
216
|
+
...CODEBUDDY_CN_RAW.filter(
|
|
217
|
+
(entry) =>
|
|
218
|
+
!BUDDY_CN_IMAGE_MODEL_ID_SET.has(entry[0]) &&
|
|
219
|
+
!BUDDY_CN_VIDEO_MODEL_ID_SET.has(entry[0]),
|
|
220
|
+
).map((entry) =>
|
|
221
|
+
makeBuddyModel(entry, CODEBUDDY_CN_PROVIDER_ID, undefined, "cn"),
|
|
222
|
+
),
|
|
223
|
+
...CODEBUDDY_CN_IMAGE_MODELS,
|
|
224
|
+
...CODEBUDDY_CN_VIDEO_MODELS,
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
export async function discoverCodeBuddyCnModels(
|
|
228
|
+
input: DiscoveryInput,
|
|
229
|
+
): Promise<readonly ModelDefinition[] | null> {
|
|
230
|
+
return fetchBuddyDirectoryModels({
|
|
231
|
+
siteUrl: CODEBUDDY_CN_BASE_URL,
|
|
232
|
+
providerId: CODEBUDDY_CN_PROVIDER_ID,
|
|
233
|
+
credential: input.credential,
|
|
234
|
+
modelsPath: BUDDY_CN_MODELS_PATH,
|
|
235
|
+
endpoint: undefined,
|
|
236
|
+
...(input.signal ? { signal: input.signal } : {}),
|
|
237
|
+
...(input.fetcher ? { fetcher: input.fetcher } : {}),
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function createCodeBuddyCnAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
|
|
242
|
+
// BuddyMediaAdapter, not OpenAICompatibleAdapter: the CN realm publishes an
|
|
243
|
+
// image-generation row, and the plain compatible adapter has no image path,
|
|
244
|
+
// so `hunyuan-image-alpha` would route to /chat/completions and fail.
|
|
245
|
+
return new BuddyMediaAdapter(
|
|
246
|
+
codebuddyAdapterConfig({
|
|
247
|
+
providerId: CODEBUDDY_CN_PROVIDER_ID,
|
|
248
|
+
baseUrl: CODEBUDDY_CN_BASE_URL,
|
|
249
|
+
variant: "CLI",
|
|
250
|
+
prePayload: codeBuddyCnPrePayload,
|
|
251
|
+
// The CN CLI profile gzips the chat body (donor behavior). The console
|
|
252
|
+
// channel fallback is an intl-only recovery; CN has no second endpoint.
|
|
253
|
+
requestCompression: "gzip",
|
|
254
|
+
...(fetchImpl ? { fetchImpl } : {}),
|
|
255
|
+
}),
|
|
256
|
+
{
|
|
257
|
+
variant: "CLI",
|
|
258
|
+
// The CN realm has no separate system prompt of its own; the neutral CN
|
|
259
|
+
// prompt is applied by `codeBuddyCnPrePayload`, so the media config
|
|
260
|
+
// reuses the intl one purely to satisfy the required field. Image
|
|
261
|
+
// generation sends a prompt, not a conversation, so this turn is
|
|
262
|
+
// discarded by the image path in every case.
|
|
263
|
+
systemPrompt: CODEBUDDY_SYSTEM_PROMPT,
|
|
264
|
+
baseUrl: CODEBUDDY_CN_BASE_URL,
|
|
265
|
+
imageGenerationPath: "/images/generations",
|
|
266
|
+
},
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ── codebuddy/oauth ──────────────────────────────────────────
|
|
271
|
+
|
|
272
|
+
const CODEBUDDY_INTL_DEVICE_START_URL = `${providerBaseUrl("cb")}/plugin/auth/state`;
|
|
273
|
+
|
|
274
|
+
const CODEBUDDY_INTL_DEVICE_POLL_URL = `${providerBaseUrl("cb")}/plugin/auth/token`;
|
|
275
|
+
|
|
276
|
+
const CODEBUDDY_INTL_REFRESH_URL = `${providerBaseUrl("cb")}/plugin/auth/token/refresh`;
|
|
277
|
+
|
|
278
|
+
const CODEBUDDY_CN_DEVICE_START_URL = `${providerBaseUrl("cbcn")}/plugin/auth/state`;
|
|
279
|
+
|
|
280
|
+
const CODEBUDDY_CN_DEVICE_POLL_URL = `${providerBaseUrl("cbcn")}/plugin/auth/token`;
|
|
281
|
+
|
|
282
|
+
const CODEBUDDY_CN_REFRESH_URL = `${providerBaseUrl("cbcn")}/plugin/auth/token/refresh`;
|
|
283
|
+
|
|
284
|
+
export const CODEBUDDY_INTL_VARIANT: BuddyOAuthVariant = {
|
|
285
|
+
providerId: "cb",
|
|
286
|
+
providerLabel: "CodeBuddy",
|
|
287
|
+
domain: "www.codebuddy.ai",
|
|
288
|
+
platform: "ide",
|
|
289
|
+
userAgent: async () => {
|
|
290
|
+
return buildCodeBuddyUserAgent("IDE");
|
|
291
|
+
},
|
|
292
|
+
deviceStartUrl: CODEBUDDY_INTL_DEVICE_START_URL,
|
|
293
|
+
devicePollUrl: CODEBUDDY_INTL_DEVICE_POLL_URL,
|
|
294
|
+
refreshUrl: CODEBUDDY_INTL_REFRESH_URL,
|
|
295
|
+
responseCode: strictResponseCode,
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export const CODEBUDDY_CN_VARIANT: BuddyOAuthVariant = {
|
|
299
|
+
providerId: "cbcn",
|
|
300
|
+
providerLabel: "CodeBuddy",
|
|
301
|
+
domain: "copilot.tencent.com",
|
|
302
|
+
platform: "CLI",
|
|
303
|
+
userAgent: async () => {
|
|
304
|
+
return buildCodeBuddyUserAgent("CLI");
|
|
305
|
+
},
|
|
306
|
+
deviceStartUrl: CODEBUDDY_CN_DEVICE_START_URL,
|
|
307
|
+
devicePollUrl: CODEBUDDY_CN_DEVICE_POLL_URL,
|
|
308
|
+
refreshUrl: CODEBUDDY_CN_REFRESH_URL,
|
|
309
|
+
responseCode: strictResponseCode,
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
export const codeBuddyOAuthClient = new BuddyOAuthClient(CODEBUDDY_INTL_VARIANT);
|
|
313
|
+
|
|
314
|
+
export const codeBuddyCnOAuthClient = new BuddyOAuthClient(CODEBUDDY_CN_VARIANT);
|
|
315
|
+
|
|
316
|
+
// ── codebuddy/quota ──────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
export const CODEBUDDY_CN_USAGE_URL =
|
|
319
|
+
`${providerBaseUrl("cbcn")}/billing/meter/get-user-resource`;
|
|
320
|
+
|
|
321
|
+
export const CODEBUDDY_INTL_USAGE_URL =
|
|
322
|
+
`${providerBaseUrl("cb")}/billing/meter/get-user-resource`;
|
|
323
|
+
|
|
324
|
+
const CODEBUDDY_CN_REQUEST_USAGE_URL =
|
|
325
|
+
`${providerBaseUrl("cbcn")}/billing/meter/get-user-request-usage`;
|
|
326
|
+
|
|
327
|
+
const CODEBUDDY_INTL_REQUEST_USAGE_URL =
|
|
328
|
+
`${providerBaseUrl("cb")}/billing/meter/get-user-request-usage`;
|
|
329
|
+
|
|
330
|
+
type CodeBuddyProviderId = "cb" | "cbcn";
|
|
331
|
+
|
|
332
|
+
async function cnHeaders(enterpriseId?: string): Promise<Record<string, string>> {
|
|
333
|
+
return {
|
|
334
|
+
"User-Agent": buildCodeBuddyUserAgent("CLI"),
|
|
335
|
+
"X-Product": "SaaS",
|
|
336
|
+
"X-IDE-Type": "CLI",
|
|
337
|
+
"X-IDE-Name": "CLI",
|
|
338
|
+
"X-Domain": codebuddyDomain("CLI"),
|
|
339
|
+
"x-requested-with": "XMLHttpRequest",
|
|
340
|
+
"x-codebuddy-request": "1",
|
|
341
|
+
...(enterpriseId === undefined || enterpriseId.length === 0
|
|
342
|
+
? {}
|
|
343
|
+
: { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async function intlHeaders(enterpriseId?: string): Promise<Record<string, string>> {
|
|
348
|
+
return {
|
|
349
|
+
"User-Agent": buildCodeBuddyUserAgent("IDE"),
|
|
350
|
+
"X-Product": "SaaS",
|
|
351
|
+
"X-IDE-Type": "IDE",
|
|
352
|
+
"X-IDE-Name": "IDE",
|
|
353
|
+
"X-Domain": codebuddyDomain("IDE"),
|
|
354
|
+
"x-requested-with": "XMLHttpRequest",
|
|
355
|
+
"x-codebuddy-request": "1",
|
|
356
|
+
...(enterpriseId === undefined || enterpriseId.length === 0
|
|
357
|
+
? {}
|
|
358
|
+
: { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function parseProviderId(providerId: string): CodeBuddyProviderId {
|
|
363
|
+
const value = providerId.trim().toLowerCase();
|
|
364
|
+
if (value === "cb") return "cb";
|
|
365
|
+
if (value === "cbcn") return "cbcn";
|
|
366
|
+
throw new Error(`Unsupported CodeBuddy provider ${providerId}`);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async function providerConfig(
|
|
370
|
+
providerId: CodeBuddyProviderId,
|
|
371
|
+
enterpriseId?: string,
|
|
372
|
+
): Promise<{
|
|
373
|
+
url: string;
|
|
374
|
+
headers: Record<string, string>;
|
|
375
|
+
display: string;
|
|
376
|
+
}> {
|
|
377
|
+
if (providerId === "cb") {
|
|
378
|
+
return { url: CODEBUDDY_INTL_USAGE_URL, headers: await intlHeaders(enterpriseId), display: "CodeBuddy" };
|
|
379
|
+
}
|
|
380
|
+
return { url: CODEBUDDY_CN_USAGE_URL, headers: await cnHeaders(enterpriseId), display: "CodeBuddy CN" };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export async function fetchCodeBuddyQuota(
|
|
384
|
+
credential: string,
|
|
385
|
+
fetcher: FetchLike,
|
|
386
|
+
providerId: string = "cbcn",
|
|
387
|
+
enterpriseId?: string,
|
|
388
|
+
): Promise<ProviderQuotaResult> {
|
|
389
|
+
const source = parseProviderId(providerId);
|
|
390
|
+
const cfg = await providerConfig(source, enterpriseId);
|
|
391
|
+
return fetchTencentBillingQuota({
|
|
392
|
+
source,
|
|
393
|
+
display: cfg.display,
|
|
394
|
+
url: cfg.url,
|
|
395
|
+
headers: cfg.headers,
|
|
396
|
+
credential,
|
|
397
|
+
fetcher,
|
|
398
|
+
defaultPlan: "CodeBuddy",
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export const fetchCodeBuddyCnQuota = (
|
|
403
|
+
credential: string,
|
|
404
|
+
fetcher: FetchLike,
|
|
405
|
+
): Promise<ProviderQuotaResult> => fetchCodeBuddyQuota(credential, fetcher, "cbcn");
|
|
406
|
+
|
|
407
|
+
export const fetchCodeBuddyIntlQuota = (
|
|
408
|
+
credential: string,
|
|
409
|
+
fetcher: FetchLike,
|
|
410
|
+
): Promise<ProviderQuotaResult> => fetchCodeBuddyQuota(credential, fetcher, "cb");
|
|
411
|
+
|
|
412
|
+
export async function fetchCodeBuddyRequestUsage(
|
|
413
|
+
credential: string,
|
|
414
|
+
fetcher: FetchLike,
|
|
415
|
+
providerId: string = "cbcn",
|
|
416
|
+
days: number = 30,
|
|
417
|
+
enterpriseId?: string,
|
|
418
|
+
): Promise<BuddyUsageResult> {
|
|
419
|
+
const source = parseProviderId(providerId);
|
|
420
|
+
const cfg = await providerConfig(source, enterpriseId);
|
|
421
|
+
return fetchBuddyRequestUsage({
|
|
422
|
+
url:
|
|
423
|
+
source === "cb" ? CODEBUDDY_INTL_REQUEST_USAGE_URL : CODEBUDDY_CN_REQUEST_USAGE_URL,
|
|
424
|
+
headers: cfg.headers,
|
|
425
|
+
credential,
|
|
426
|
+
fetcher,
|
|
427
|
+
days,
|
|
428
|
+
});
|
|
429
|
+
}
|