cartethyia 2.7.9 → 2.8.0
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 -2
- package/dist/dashboard/assets/{BannedPage-BxoG1MrL.js → BannedPage-Cc0vKpMG.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cc0vKpMG.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-ixwgKk53.js → CliToolDetailPage-Bqj2aa1T.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-Bqj2aa1T.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-BmttNV3U.js → CliToolsPage-CXsaOAO2.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-CXsaOAO2.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-BE3qwwfC.js → CombosPage-BeLpJ4ma.js} +1 -1
- package/dist/dashboard/assets/CombosPage-BeLpJ4ma.js.gz +0 -0
- package/dist/dashboard/assets/{ConsoleLogPage-CRZdmMIX.js → ConsoleLogPage-DnV0uZ3m.js} +1 -1
- package/dist/dashboard/assets/ConsoleLogPage-DnV0uZ3m.js.gz +0 -0
- package/dist/dashboard/assets/{CustomizationPage-Dv_FJ6Er.js → CustomizationPage-CBxAjo63.js} +1 -1
- package/dist/dashboard/assets/CustomizationPage-CBxAjo63.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-B5yEE0k6.js.gz +0 -0
- package/dist/dashboard/assets/{InjectSystemPromptPanel-BOoO8rpz.js → InjectSystemPromptPanel-BWFLECmz.js} +2 -2
- package/dist/dashboard/assets/InjectSystemPromptPanel-BWFLECmz.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-ChJuNNVN.js → LoginPage-CgoPc5B9.js} +1 -1
- package/dist/dashboard/assets/LoginPage-CgoPc5B9.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BZAJtPg1.js → ModelPicker-D9bFQern.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-D9bFQern.js.gz +0 -0
- package/dist/dashboard/assets/{OverviewPage-BE40s3u5.js → OverviewPage-B_p4tL8k.js} +1 -1
- package/dist/dashboard/assets/OverviewPage-B_p4tL8k.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js +8 -0
- package/dist/dashboard/assets/ProviderDetailPage-rs5E2rxv.js.gz +0 -0
- package/dist/dashboard/assets/{ProviderIcon-CQ6bPUf_.js → ProviderIcon-D_0PiZtg.js} +1 -1
- package/dist/dashboard/assets/ProviderIcon-D_0PiZtg.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CLI2bJTK.js.gz +0 -0
- package/dist/dashboard/assets/{ProxyPage-BJ87Pp0U.js → ProxyPage-BwNC_-Cx.js} +1 -1
- package/dist/dashboard/assets/ProxyPage-BwNC_-Cx.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js +1 -0
- package/dist/dashboard/assets/QuotaPage-DA-a1iSN.js.gz +0 -0
- package/dist/dashboard/assets/{SettingsPage-C5HPWqEv.js → SettingsPage-CctTga2C.js} +1 -1
- package/dist/dashboard/assets/SettingsPage-CctTga2C.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-CFNcATJJ.js → SetupPage-febLU4r1.js} +1 -1
- package/dist/dashboard/assets/SetupPage-febLU4r1.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-YoD4tY5l.js → StudioPage-M6fvR5Wz.js} +1 -1
- package/dist/dashboard/assets/StudioPage-M6fvR5Wz.js.gz +0 -0
- package/dist/dashboard/assets/{UsagePage-DxjaAhb_.js → UsagePage-nyeuRqz9.js} +1 -1
- package/dist/dashboard/assets/UsagePage-nyeuRqz9.js.gz +0 -0
- package/dist/dashboard/assets/{api-keys-BTlkq_Uk.js → api-keys-BFOlvrJC.js} +1 -1
- package/dist/dashboard/assets/api-keys-BFOlvrJC.js.gz +0 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css +2 -0
- package/dist/dashboard/assets/app-Dx2QgsNj.css.gz +0 -0
- package/dist/dashboard/assets/assert-CqTLw5e7.js +1 -0
- package/dist/dashboard/assets/assert-CqTLw5e7.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DdbT_7Am.js → badge-C83EqLB0.js} +1 -1
- package/dist/dashboard/assets/badge-C83EqLB0.js.gz +0 -0
- package/dist/dashboard/assets/{banner-CsGN-nbm.js → banner-D1xn7pIe.js} +1 -1
- package/dist/dashboard/assets/banner-D1xn7pIe.js.gz +0 -0
- package/dist/dashboard/assets/{card-mgZ_TLLZ.js → card-DU3Lq5Lm.js} +1 -1
- package/dist/dashboard/assets/card-DU3Lq5Lm.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-A1-v8-03.js → cli-tools-Dw1U_drK.js} +1 -1
- package/dist/dashboard/assets/cli-tools-Dw1U_drK.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-CJ4Zty89.js → clipboard-button-CEL5Sg_J.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-CEL5Sg_J.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-B5L2jPQ_.js → dialog-BjFR5UHy.js} +1 -1
- package/dist/dashboard/assets/dialog-BjFR5UHy.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-DkjUouAj.js → drawer-HvBW0AjI.js} +1 -1
- package/dist/dashboard/assets/drawer-HvBW0AjI.js.gz +0 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js +4 -0
- package/dist/dashboard/assets/entry-BSu3gFlt.js.gz +0 -0
- package/dist/dashboard/assets/{entry-B-LVLV6o.js → entry-CECVELyy.js} +1 -1
- package/dist/dashboard/assets/entry-CECVELyy.js.gz +0 -0
- package/dist/dashboard/assets/{entry-CAhdYl3B.js → entry-DYYofQ7W.js} +1 -1
- package/dist/dashboard/assets/entry-DYYofQ7W.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CrsdLVsn.js → formatters-DLW4i8zK.js} +1 -1
- package/dist/dashboard/assets/formatters-DLW4i8zK.js.gz +0 -0
- package/dist/dashboard/assets/{index-BU64Lqvp.js → index-1-fCqe64.js} +2 -2
- package/dist/dashboard/assets/index-1-fCqe64.js.gz +0 -0
- package/dist/dashboard/assets/{inline-B2aDLyyg.js → inline-DGvU2oLK.js} +1 -1
- package/dist/dashboard/assets/inline-DGvU2oLK.js.gz +0 -0
- package/dist/dashboard/assets/{input-BCVkdR9d.js → input-iNnO1X2K.js} +1 -1
- package/dist/dashboard/assets/input-iNnO1X2K.js.gz +0 -0
- package/dist/dashboard/assets/{layout-DNcAdMK-.js → layout-0q8UGypb.js} +1 -1
- package/dist/dashboard/assets/layout-0q8UGypb.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-DgrIH0hw.js → list-row-C0w2bQjJ.js} +1 -1
- package/dist/dashboard/assets/list-row-C0w2bQjJ.js.gz +0 -0
- package/dist/dashboard/assets/{live-Cae01iu8.js → live-M5aJ_xCa.js} +1 -1
- package/dist/dashboard/assets/live-M5aJ_xCa.js.gz +0 -0
- package/dist/dashboard/assets/{network-CRib7H_2.js → network-BKeQGT3K.js} +1 -1
- package/dist/dashboard/assets/network-BKeQGT3K.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BKQE8Xpz.js → numbers-CivAk3da.js} +1 -1
- package/dist/dashboard/assets/numbers-CivAk3da.js.gz +0 -0
- package/dist/dashboard/assets/{pagination-ecPvG_8g.js → pagination-CpzvI5ep.js} +1 -1
- package/dist/dashboard/assets/pagination-CpzvI5ep.js.gz +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-BFQX2VBc.js} +1 -1
- package/dist/dashboard/assets/routing-BFQX2VBc.js.gz +0 -0
- package/dist/dashboard/assets/{select-ChoFWyKz.js → select-CXbck0jG.js} +2 -2
- package/dist/dashboard/assets/select-CXbck0jG.js.gz +0 -0
- package/dist/dashboard/assets/{settings-CKjFPlKW.js → settings-C_XvMHh9.js} +1 -1
- package/dist/dashboard/assets/settings-C_XvMHh9.js.gz +0 -0
- package/dist/dashboard/assets/{stack-DWCwU3fh.js → stack-DggRiCxE.js} +1 -1
- package/dist/dashboard/assets/stack-DggRiCxE.js.gz +0 -0
- package/dist/dashboard/assets/{state-Cg3VL5J_.js → state-ClFzfbYp.js} +1 -1
- package/dist/dashboard/assets/state-ClFzfbYp.js.gz +0 -0
- package/dist/dashboard/assets/{switch-Db70BMix.js → switch-CTIFxKqS.js} +1 -1
- package/dist/dashboard/assets/switch-CTIFxKqS.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-BqdE0LuM.js → useMutation-BClG3yWj.js} +1 -1
- package/dist/dashboard/assets/useMutation-BClG3yWj.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/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
- package/package.json +1 -1
- package/src/boot/app.ts +10 -13
- package/src/boot/dependencies.ts +1 -1
- package/src/boot/flush.ts +20 -0
- package/src/boot/lifecycle.ts +7 -5
- package/src/config/routing.ts +26 -0
- package/src/config/spec-metadata.ts +72 -0
- package/src/config/spec.ts +20 -0
- 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/cli-tools/service.ts +6 -12
- package/src/console/console-router-guards.ts +23 -16
- package/src/console/domain-registration.ts +0 -2
- 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/store.ts +0 -53
- package/src/console/providers/catalog/contracts.ts +2 -2
- package/src/console/providers/catalog/discover-constants.ts +6 -0
- package/src/console/providers/catalog/routes.ts +1 -0
- package/src/console/providers/catalog/store.ts +21 -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 +6 -18
- package/src/console/quota/quota-view.ts +19 -3
- package/src/console/routing/pools/operations.ts +31 -46
- package/src/console/shared/errors.ts +33 -6
- package/src/main.ts +2 -3
- package/src/network/pool/byte-accounting.ts +3 -2
- package/src/network/pool/selector.ts +182 -39
- package/src/network/pool-cooldown-store.ts +89 -14
- package/src/network/pool-health.ts +49 -61
- package/src/network/rate-limit-verdict.ts +1 -1
- package/src/network/ssrf.ts +6 -6
- 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 +15 -25
- 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 +8 -0
- package/src/persistence/ttl-cache.ts +20 -2
- package/src/protocol/codecs.ts +1 -1
- 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 +3 -4
- package/src/protocol/response/chat.ts +12 -20
- 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/providers/adapters/compatible-adapter.ts +71 -12
- package/src/providers/authentication/oauth-client.ts +1 -1
- package/src/providers/authentication/oauth-device-flow.ts +98 -8
- package/src/providers/authentication/oauth-refresh-service.ts +30 -49
- package/src/providers/configured-provider.ts +148 -0
- package/src/providers/default-registry.ts +61 -36
- package/src/providers/discovery/probe-phases.ts +14 -4
- package/src/providers/discovery/probing-service.ts +15 -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 +5 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +173 -17
- package/src/providers/integrations/buddy/buddy-identity.ts +19 -6
- package/src/providers/integrations/buddy/capabilities.ts +2 -2
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +3 -0
- package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -0
- package/src/providers/integrations/buddy/codebuddy/shared.ts +37 -22
- package/src/providers/integrations/claude/claude-quota.ts +14 -17
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/commandcode/quota.ts +22 -28
- package/src/providers/integrations/cursor/cursor-auth.ts +0 -8
- package/src/providers/integrations/cursor/cursor-exec.ts +9 -2
- package/src/providers/integrations/cursor/cursor-request.ts +26 -12
- package/src/providers/integrations/cursor/cursor-shared.ts +7 -4
- package/src/providers/integrations/cursor/cursor.ts +89 -40
- 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/devin/protocol/devin-proto.ts +1 -27
- package/src/providers/integrations/factory/factory-oauth.ts +17 -44
- 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/grok/grok-oauth.ts +48 -45
- 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.ts → hermes/hermes.ts} +9 -9
- package/src/providers/integrations/hermes/index.ts +2 -0
- 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-quota.ts +8 -4
- package/src/providers/integrations/kiro/kiro.ts +15 -19
- 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/opencode-go-quota.ts +2 -8
- package/src/providers/integrations/perch/perch-credential.ts +25 -0
- package/src/providers/integrations/perch/perch-protocol.ts +0 -3
- package/src/providers/integrations/perch/perch-quota.ts +2 -16
- package/src/providers/integrations/perch/perch.ts +3 -13
- package/src/providers/integrations/qoder/claim-qoder-credits.ts +18 -59
- package/src/providers/integrations/qoder/qoder-adapter.ts +1 -12
- package/src/providers/integrations/qoder/qoder-auth.ts +101 -29
- package/src/providers/integrations/qoder/qoder-catalog.ts +20 -5
- package/src/providers/integrations/qoder/qoder-chat.ts +7 -21
- package/src/providers/integrations/qoder/qoder-checkin.ts +4 -4
- package/src/providers/integrations/qoder/qoder-grpc.ts +0 -1
- package/src/providers/integrations/qoder/qoder-ide.ts +0 -107
- package/src/providers/integrations/qoder/qoder.ts +0 -1
- package/src/providers/integrations/trae/trae-protocol.ts +9 -5
- package/src/providers/integrations/trae/trae-quota.ts +6 -28
- package/src/providers/integrations/trae/trae-realm.ts +38 -0
- package/src/providers/integrations/trae/trae.ts +7 -24
- 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 +204 -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 +22 -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 +5 -51
- package/src/providers/operations/cooldown-rules.ts +11 -16
- 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 +102 -32
- 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/provider-contracts.ts +4 -2
- package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
- package/src/providers/provider-metadata.ts +40 -10
- package/src/providers/provider-probe.ts +15 -1
- package/src/providers/provider-registry.ts +42 -33
- 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 +75 -18
- package/src/security/api-key-auth-cache.ts +1 -1
- package/src/security/api-key-auth.ts +6 -2
- package/src/transport/dispatch/attempt-finalize.ts +14 -13
- package/src/transport/dispatch/attempt-loop.ts +71 -17
- package/src/transport/dispatch/generation.ts +2 -8
- 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/streaming/finalize.ts +9 -6
- package/src/transport/dispatch/streaming/stream.ts +8 -36
- 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/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/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.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/providers/bundled-discovery-providers.ts +0 -98
- package/src/providers/configured-openai-providers.ts +0 -120
- 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-DIXLjojg.js} +0 -0
- /package/dist/dashboard/assets/{app-B7kIWFm5.js.gz → app-DIXLjojg.js.gz} +0 -0
|
@@ -3,6 +3,7 @@ import type { CanonicalRequest, WireFamily } from "../protocol/canonical-model";
|
|
|
3
3
|
import { GatewayError } from "../protocol/gateway-error";
|
|
4
4
|
import { OpenAICompatibleAdapter, withBearerAuthentication } from "./adapters/compatible-adapter";
|
|
5
5
|
import { providerBaseUrl } from "./provider-metadata";
|
|
6
|
+
import type { ProviderModule } from "./provider-registry";
|
|
6
7
|
|
|
7
8
|
export function ensurePayloadModel(
|
|
8
9
|
payload: Record<string, unknown>,
|
|
@@ -15,6 +16,7 @@ export function ensurePayloadModel(
|
|
|
15
16
|
payload["model"] = model;
|
|
16
17
|
return model;
|
|
17
18
|
}
|
|
19
|
+
|
|
18
20
|
/**
|
|
19
21
|
* Declarative description of one bearer-authenticated OpenAI-compatible provider.
|
|
20
22
|
*
|
|
@@ -98,3 +100,149 @@ export function createApiKeyAdapter(
|
|
|
98
100
|
}),
|
|
99
101
|
);
|
|
100
102
|
}
|
|
103
|
+
|
|
104
|
+
function apiKeySpec(
|
|
105
|
+
providerId: ProviderId,
|
|
106
|
+
paths: Readonly<Partial<Record<"chat" | "responses", string>>>,
|
|
107
|
+
): ApiKeyProviderSpec {
|
|
108
|
+
return {
|
|
109
|
+
provider_id: providerId,
|
|
110
|
+
endpoint_paths_by_wire_family: paths,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const BEARER_PATHS = { chat: "/chat/completions", responses: "/responses" } as const;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Builtin providers whose entire adapter contract is "bearer auth against the
|
|
118
|
+
* provider's `BUNDLED_PROVIDER_METADATA` base URL, OpenAI-compatible chat +
|
|
119
|
+
* responses, with endpoint paths declared below the base's version root".
|
|
120
|
+
*/
|
|
121
|
+
export const GENERIC_API_KEY_SPECS = {
|
|
122
|
+
larprouter: apiKeySpec("larprouter", BEARER_PATHS),
|
|
123
|
+
mistral: apiKeySpec("mistral", BEARER_PATHS),
|
|
124
|
+
fireworks: apiKeySpec("fireworks", BEARER_PATHS),
|
|
125
|
+
nvidia: apiKeySpec("nvidia", BEARER_PATHS),
|
|
126
|
+
gmi: apiKeySpec("gmi", BEARER_PATHS),
|
|
127
|
+
ollamacloud: apiKeySpec("ollamacloud", BEARER_PATHS),
|
|
128
|
+
together: apiKeySpec("together", BEARER_PATHS),
|
|
129
|
+
siliconflow: apiKeySpec("siliconflow", BEARER_PATHS),
|
|
130
|
+
siliconflowcn: apiKeySpec("siliconflowcn", BEARER_PATHS),
|
|
131
|
+
nanogpt: apiKeySpec("nanogpt", BEARER_PATHS),
|
|
132
|
+
baseten: apiKeySpec("baseten", BEARER_PATHS),
|
|
133
|
+
synthetic: apiKeySpec("synthetic", BEARER_PATHS),
|
|
134
|
+
stepfun: apiKeySpec("stepfun", BEARER_PATHS),
|
|
135
|
+
sakana: apiKeySpec("sakana", BEARER_PATHS),
|
|
136
|
+
helmcode: apiKeySpec("helmcode", BEARER_PATHS),
|
|
137
|
+
coralbricks: apiKeySpec("coralbricks", BEARER_PATHS),
|
|
138
|
+
aiand: apiKeySpec("aiand", BEARER_PATHS),
|
|
139
|
+
wafer: apiKeySpec("wafer", BEARER_PATHS),
|
|
140
|
+
coreweave: apiKeySpec("coreweave", BEARER_PATHS),
|
|
141
|
+
dashscope: apiKeySpec("dashscope", BEARER_PATHS),
|
|
142
|
+
"qwen-portal": apiKeySpec("qwen-portal", BEARER_PATHS),
|
|
143
|
+
} satisfies Readonly<Record<string, ApiKeyProviderSpec>>;
|
|
144
|
+
|
|
145
|
+
export type GenericApiKeyProviderId = keyof typeof GENERIC_API_KEY_SPECS;
|
|
146
|
+
|
|
147
|
+
export const GENERIC_API_KEY_PROVIDER_IDS = Object.keys(
|
|
148
|
+
GENERIC_API_KEY_SPECS,
|
|
149
|
+
) as readonly GenericApiKeyProviderId[];
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Ids whose base URL already ends at a version segment.
|
|
153
|
+
*/
|
|
154
|
+
export const VERSIONED_ROOT_API_KEY_SPECS = {
|
|
155
|
+
groq: apiKeySpec("groq", BEARER_PATHS),
|
|
156
|
+
deepinfra: apiKeySpec("deepinfra", BEARER_PATHS),
|
|
157
|
+
novita: apiKeySpec("novita", BEARER_PATHS),
|
|
158
|
+
venice: apiKeySpec("venice", BEARER_PATHS),
|
|
159
|
+
qianfan: apiKeySpec("qianfan", BEARER_PATHS),
|
|
160
|
+
zhipucoding: apiKeySpec("zhipucoding", BEARER_PATHS),
|
|
161
|
+
firepass: apiKeySpec("firepass", BEARER_PATHS),
|
|
162
|
+
} satisfies Readonly<Record<string, ApiKeyProviderSpec>>;
|
|
163
|
+
|
|
164
|
+
export type VersionedRootApiKeyProviderId =
|
|
165
|
+
keyof typeof VERSIONED_ROOT_API_KEY_SPECS;
|
|
166
|
+
|
|
167
|
+
export const VERSIONED_ROOT_API_KEY_PROVIDER_IDS = Object.keys(
|
|
168
|
+
VERSIONED_ROOT_API_KEY_SPECS,
|
|
169
|
+
) as readonly VersionedRootApiKeyProviderId[];
|
|
170
|
+
|
|
171
|
+
type DiscoveryBackedCapabilities = Pick<
|
|
172
|
+
ProviderModule,
|
|
173
|
+
"endpointPathsByWireFamily" | "loadAdapter" | "loadModelDiscovery"
|
|
174
|
+
>;
|
|
175
|
+
|
|
176
|
+
type ModelDiscoveryFactory = NonNullable<ProviderModule["loadModelDiscovery"]>;
|
|
177
|
+
export type OpenAIModelDiscoveryFactory = (
|
|
178
|
+
providerId: string,
|
|
179
|
+
options?: {
|
|
180
|
+
readonly headers?: (credential: string) => Readonly<Record<string, string>>;
|
|
181
|
+
},
|
|
182
|
+
) => ModelDiscoveryFactory;
|
|
183
|
+
|
|
184
|
+
const DISCOVERY_BACKED_PROVIDER_SPECS = {
|
|
185
|
+
groq: VERSIONED_ROOT_API_KEY_SPECS.groq,
|
|
186
|
+
larprouter: GENERIC_API_KEY_SPECS.larprouter,
|
|
187
|
+
together: GENERIC_API_KEY_SPECS.together,
|
|
188
|
+
deepinfra: VERSIONED_ROOT_API_KEY_SPECS.deepinfra,
|
|
189
|
+
siliconflow: GENERIC_API_KEY_SPECS.siliconflow,
|
|
190
|
+
siliconflowcn: GENERIC_API_KEY_SPECS.siliconflowcn,
|
|
191
|
+
novita: VERSIONED_ROOT_API_KEY_SPECS.novita,
|
|
192
|
+
venice: VERSIONED_ROOT_API_KEY_SPECS.venice,
|
|
193
|
+
nanogpt: GENERIC_API_KEY_SPECS.nanogpt,
|
|
194
|
+
baseten: GENERIC_API_KEY_SPECS.baseten,
|
|
195
|
+
synthetic: GENERIC_API_KEY_SPECS.synthetic,
|
|
196
|
+
stepfun: GENERIC_API_KEY_SPECS.stepfun,
|
|
197
|
+
sakana: GENERIC_API_KEY_SPECS.sakana,
|
|
198
|
+
helmcode: GENERIC_API_KEY_SPECS.helmcode,
|
|
199
|
+
coralbricks: GENERIC_API_KEY_SPECS.coralbricks,
|
|
200
|
+
aiand: GENERIC_API_KEY_SPECS.aiand,
|
|
201
|
+
wafer: GENERIC_API_KEY_SPECS.wafer,
|
|
202
|
+
firepass: VERSIONED_ROOT_API_KEY_SPECS.firepass,
|
|
203
|
+
zhipucoding: VERSIONED_ROOT_API_KEY_SPECS.zhipucoding,
|
|
204
|
+
dashscope: GENERIC_API_KEY_SPECS.dashscope,
|
|
205
|
+
qianfan: VERSIONED_ROOT_API_KEY_SPECS.qianfan,
|
|
206
|
+
} satisfies Readonly<Record<string, ApiKeyProviderSpec>>;
|
|
207
|
+
|
|
208
|
+
type DiscoveryBackedProviderId = keyof typeof DISCOVERY_BACKED_PROVIDER_SPECS;
|
|
209
|
+
|
|
210
|
+
/** Canonical discovery-backed provider ids, in declaration order. */
|
|
211
|
+
export const DISCOVERY_BACKED_PROVIDER_IDS = Object.keys(
|
|
212
|
+
DISCOVERY_BACKED_PROVIDER_SPECS,
|
|
213
|
+
) as readonly DiscoveryBackedProviderId[];
|
|
214
|
+
|
|
215
|
+
export function discoveryBackedCapabilities(
|
|
216
|
+
providerId: string,
|
|
217
|
+
spec: ApiKeyProviderSpec,
|
|
218
|
+
openAIModelDiscovery: OpenAIModelDiscoveryFactory,
|
|
219
|
+
): DiscoveryBackedCapabilities {
|
|
220
|
+
return {
|
|
221
|
+
...(spec.endpoint_paths_by_wire_family === undefined
|
|
222
|
+
? {}
|
|
223
|
+
: { endpointPathsByWireFamily: spec.endpoint_paths_by_wire_family }),
|
|
224
|
+
loadAdapter: async () => createApiKeyAdapter(spec),
|
|
225
|
+
loadModelDiscovery: openAIModelDiscovery(providerId, {
|
|
226
|
+
headers: (credential) => ({ authorization: `Bearer ${credential}` }),
|
|
227
|
+
}),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Creates the standard provider capability table using the registry's shared
|
|
233
|
+
* discovery loader, keeping its lazy import and authentication behavior intact.
|
|
234
|
+
*/
|
|
235
|
+
export function createDiscoveryBackedProviderCapabilities(
|
|
236
|
+
openAIModelDiscovery: OpenAIModelDiscoveryFactory,
|
|
237
|
+
): Readonly<Record<DiscoveryBackedProviderId, DiscoveryBackedCapabilities>> {
|
|
238
|
+
const capabilities = {} as Record<DiscoveryBackedProviderId, DiscoveryBackedCapabilities>;
|
|
239
|
+
for (const providerId of DISCOVERY_BACKED_PROVIDER_IDS) {
|
|
240
|
+
capabilities[providerId] = discoveryBackedCapabilities(
|
|
241
|
+
providerId,
|
|
242
|
+
DISCOVERY_BACKED_PROVIDER_SPECS[providerId],
|
|
243
|
+
openAIModelDiscovery,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return capabilities;
|
|
247
|
+
}
|
|
248
|
+
|
|
@@ -4,13 +4,20 @@
|
|
|
4
4
|
// drag every integration into memory at process start.
|
|
5
5
|
import {
|
|
6
6
|
GENERIC_API_KEY_SPECS,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
createDiscoveryBackedProviderCapabilities,
|
|
8
|
+
discoveryBackedCapabilities,
|
|
9
|
+
createApiKeyAdapter,
|
|
10
|
+
type ApiKeyProviderSpec,
|
|
11
|
+
} from "./configured-provider";
|
|
12
12
|
import { BUDDY_PROVIDER_CAPABILITIES } from "./integrations/buddy/capabilities";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
ProviderRegistry,
|
|
15
|
+
toRegistration,
|
|
16
|
+
oauthCapability,
|
|
17
|
+
quotaCapability,
|
|
18
|
+
type ProviderModule,
|
|
19
|
+
type ProviderModuleCapabilities,
|
|
20
|
+
} from "./provider-registry";
|
|
14
21
|
import { BUNDLED_PROVIDER_METADATA, PROVIDER_COMPATIBILITY_PROFILES, providerBaseUrl, providerRequiresAccount, providerUpstreamHost, providerDefaultWireFamily, type BundledProviderId } from "./provider-metadata";
|
|
15
22
|
import { createAnthropicCompatibleAdapter } from "./integrations/anthropic";
|
|
16
23
|
import { defineModel } from "./provider-model-definition";
|
|
@@ -31,6 +38,29 @@ function configuredProvider(
|
|
|
31
38
|
};
|
|
32
39
|
}
|
|
33
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Extracts a bearer token from a JSON credential object when the stored secret
|
|
43
|
+
* is a JSON account export, falling back to the raw secret otherwise. Several
|
|
44
|
+
* discovery paths accept both a bare token and a JSON export, and each used to
|
|
45
|
+
* re-implement this same parse + key-pick; this keeps the reading in one place.
|
|
46
|
+
*
|
|
47
|
+
* Preserves the exact fallback semantics: an unparseable secret, or a JSON
|
|
48
|
+
* object with none of the recognized token keys, yields the raw secret.
|
|
49
|
+
*/
|
|
50
|
+
function extractJsonCredentialToken(secret: string): string {
|
|
51
|
+
if (!secret.startsWith("{")) return secret;
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(secret) as Record<string, unknown>;
|
|
54
|
+
const found = ["accessToken", "access_token", "token"].find(
|
|
55
|
+
(key) => typeof parsed[key] === "string" && (parsed[key] as string).length > 0,
|
|
56
|
+
);
|
|
57
|
+
if (found !== undefined) return parsed[found] as string;
|
|
58
|
+
} catch {
|
|
59
|
+
// Use the raw secret as the token.
|
|
60
|
+
}
|
|
61
|
+
return secret;
|
|
62
|
+
}
|
|
63
|
+
|
|
34
64
|
/**
|
|
35
65
|
* Qoder's live model list for one realm.
|
|
36
66
|
*
|
|
@@ -60,18 +90,7 @@ function traeDiscovery(
|
|
|
60
90
|
if (secret.length === 0 || fetcher === undefined) {
|
|
61
91
|
return realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
|
|
62
92
|
}
|
|
63
|
-
|
|
64
|
-
if (secret.startsWith("{")) {
|
|
65
|
-
try {
|
|
66
|
-
const parsed = JSON.parse(secret) as Record<string, unknown>;
|
|
67
|
-
const found = ["accessToken", "access_token", "token"].find(
|
|
68
|
-
(key) => typeof parsed[key] === "string" && (parsed[key] as string).length > 0,
|
|
69
|
-
);
|
|
70
|
-
if (found !== undefined) token = parsed[found] as string;
|
|
71
|
-
} catch {
|
|
72
|
-
// Use the raw secret as the token.
|
|
73
|
-
}
|
|
74
|
-
}
|
|
93
|
+
const token = extractJsonCredentialToken(secret);
|
|
75
94
|
const region = request.authState?.["region"];
|
|
76
95
|
const rows = await discoverTraeModels({
|
|
77
96
|
realm,
|
|
@@ -545,18 +564,7 @@ export const PROVIDER_CAPABILITIES = {
|
|
|
545
564
|
const secret = request.credential.trim();
|
|
546
565
|
const fetcher = request.fetcher as unknown as typeof fetch | undefined;
|
|
547
566
|
if (secret.length === 0 || fetcher === undefined) return FREEPI_MODELS;
|
|
548
|
-
|
|
549
|
-
if (secret.startsWith("{")) {
|
|
550
|
-
try {
|
|
551
|
-
const parsed = JSON.parse(secret) as Record<string, unknown>;
|
|
552
|
-
const found = ["accessToken", "access_token", "token"].find(
|
|
553
|
-
(key) => typeof parsed[key] === "string" && (parsed[key] as string).length > 0,
|
|
554
|
-
);
|
|
555
|
-
if (found !== undefined) token = parsed[found] as string;
|
|
556
|
-
} catch {
|
|
557
|
-
// Use the raw secret as the token.
|
|
558
|
-
}
|
|
559
|
-
}
|
|
567
|
+
const token = extractJsonCredentialToken(secret);
|
|
560
568
|
const rows = await discoverFreepiModels({ token, fetcher });
|
|
561
569
|
if (rows.length === 0) return FREEPI_MODELS;
|
|
562
570
|
return rows;
|
|
@@ -670,9 +678,7 @@ export const PROVIDER_CAPABILITIES = {
|
|
|
670
678
|
// dressed ZCode client request (see the integration). The credential is a
|
|
671
679
|
// ZCode login JWT — pasted, or minted by the sign-in flow below.
|
|
672
680
|
loadAdapter: async () =>
|
|
673
|
-
|
|
674
|
-
(await import("./integrations/zcode-start-plan/provider")).ZCODE_START_PLAN_SPEC,
|
|
675
|
-
),
|
|
681
|
+
(await import("./integrations/zcode-start-plan/provider")).createZcodeStartPlanAdapter(),
|
|
676
682
|
loadModels: async () =>
|
|
677
683
|
(await import("./integrations/zcode-start-plan/provider")).ZCODE_START_PLAN_MODELS,
|
|
678
684
|
// The device flow stores the issued ZCode login JWT, not a Coding Plan key.
|
|
@@ -783,10 +789,29 @@ export const PROVIDER_CAPABILITIES = {
|
|
|
783
789
|
responses: "/responses",
|
|
784
790
|
},
|
|
785
791
|
loadAdapter: async () => createApiKeyAdapter(GENERIC_API_KEY_SPECS.ollamacloud),
|
|
786
|
-
loadModels: async () => (await import("./integrations/ollamacloud
|
|
787
|
-
loadQuotaCollector: quotaCapability(() => import("./integrations/ollamacloud
|
|
792
|
+
loadModels: async () => (await import("./integrations/ollamacloud")).OLLAMACLOUD_MODELS,
|
|
793
|
+
loadQuotaCollector: quotaCapability(() => import("./integrations/ollamacloud"), "fetchOllamaQuota"),
|
|
788
794
|
loadModelDiscovery: openAIModelDiscovery("ollamacloud", { headers: (credential) => ({ authorization: `Bearer ${credential}` }) }),
|
|
789
795
|
},
|
|
796
|
+
freebuff: {
|
|
797
|
+
// Freebuff chat is OpenAI-compatible on `/api/v1/chat/completions`, but the
|
|
798
|
+
// adapter runs a stateful preflight (session admission + agent-runs START)
|
|
799
|
+
// and a device-signature header set — see the integration.
|
|
800
|
+
endpointPathsByWireFamily: { chat: "/api/v1/chat/completions" },
|
|
801
|
+
loadAdapter: async () => (await import("./integrations/freebuff/freebuff")).createFreebuffAdapter(),
|
|
802
|
+
loadModels: async () => (await import("./integrations/freebuff/freebuff-catalog")).FREEBUFF_MODELS,
|
|
803
|
+
loadAuthentication: oauthCapability(() => import("./integrations/freebuff/freebuff-oauth"), "freebuffOAuthClient"),
|
|
804
|
+
loadQuotaCollector: quotaCapability(() => import("./integrations/freebuff/freebuff-quota"), "fetchFreebuffQuota"),
|
|
805
|
+
loadModelDiscovery: async () =>
|
|
806
|
+
(await import("./integrations/freebuff/freebuff-discovery")).freebuffModelDiscovery(),
|
|
807
|
+
},
|
|
808
|
+
zro: {
|
|
809
|
+
endpointPathsByWireFamily: { messages: "/v1/messages" },
|
|
810
|
+
loadAdapter: async () => (await import("./integrations/zro/zro")).createZroAdapter(),
|
|
811
|
+
loadModels: async () => (await import("./integrations/zro/zro")).ZRO_MODELS,
|
|
812
|
+
loadQuotaCollector: quotaCapability(() => import("./integrations/zro/zro"), "fetchZroQuota"),
|
|
813
|
+
loadModelDiscovery: async () => (await import("./integrations/zro/zro")).zroModelDiscovery()(),
|
|
814
|
+
},
|
|
790
815
|
|
|
791
816
|
...createDiscoveryBackedProviderCapabilities(openAIModelDiscovery),
|
|
792
817
|
|
|
@@ -835,7 +860,7 @@ export const PROVIDER_CAPABILITIES = {
|
|
|
835
860
|
// the provider usable before anyone syncs.
|
|
836
861
|
dashscope: {
|
|
837
862
|
...discoveryBackedCapabilities("dashscope", GENERIC_API_KEY_SPECS.dashscope, openAIModelDiscovery),
|
|
838
|
-
loadModels: async () => (await import("./integrations/dashscope-models")).DASHSCOPE_MODELS,
|
|
863
|
+
loadModels: async () => (await import("./integrations/alibabacp/dashscope-models")).DASHSCOPE_MODELS,
|
|
839
864
|
},
|
|
840
865
|
|
|
841
866
|
// Anthropic-Messages providers reached with a plain key. The wire path is
|
|
@@ -472,8 +472,9 @@ export async function selectProbeAccount(args: {
|
|
|
472
472
|
* back to the generic OpenAI-compatible adapter so probe/dispatch still works.
|
|
473
473
|
* The low-level compatible adapter is used directly to avoid importing concrete
|
|
474
474
|
* integrations from discovery (which would violate the provider-architecture
|
|
475
|
-
* layering test). `
|
|
476
|
-
*
|
|
475
|
+
* layering test). `resolve(..., { force: true })` rebuilds the bundled adapter
|
|
476
|
+
* against the current registration; `undefined` means "no bundled adapter"; a
|
|
477
|
+
* throw is a registry failure and propagates rather than being reported as
|
|
477
478
|
* "no adapter registered".
|
|
478
479
|
*/
|
|
479
480
|
export async function resolveProbeAdapter(args: {
|
|
@@ -482,7 +483,7 @@ export async function resolveProbeAdapter(args: {
|
|
|
482
483
|
readonly providerWireRow: ProbeProviderRow | undefined;
|
|
483
484
|
}): Promise<ProviderAdapter | undefined> {
|
|
484
485
|
const { providerRegistry, providerId, providerWireRow } = args;
|
|
485
|
-
let adapter = await providerRegistry.
|
|
486
|
+
let adapter = await providerRegistry.resolve(providerId, { force: true });
|
|
486
487
|
if (!adapter) {
|
|
487
488
|
try {
|
|
488
489
|
if (providerWireRow?.baseUrl) {
|
|
@@ -665,8 +666,16 @@ export function buildProbeCanonicalRequest(args: {
|
|
|
665
666
|
* probe.
|
|
666
667
|
*/
|
|
667
668
|
readonly providerSystemPrompt?: string | undefined;
|
|
669
|
+
/**
|
|
670
|
+
* A provider-specific default probe prompt, used when the operator sent no
|
|
671
|
+
* prompt. Lets a provider whose policy gate flags repeated identical probes
|
|
672
|
+
* (Freebuff: `prompt_policy_refused` / "same message sent over and over")
|
|
673
|
+
* receive a minimal, per-model-varying probe instead of the shared identity
|
|
674
|
+
* question every provider otherwise sends.
|
|
675
|
+
*/
|
|
676
|
+
readonly defaultPromptOverride?: string | undefined;
|
|
668
677
|
}): CanonicalRequest {
|
|
669
|
-
const { modelId, request, probeReasoning, sourceSurface, maxOutputTokens, providerSystemPrompt } = args;
|
|
678
|
+
const { modelId, request, probeReasoning, sourceSurface, maxOutputTokens, providerSystemPrompt, defaultPromptOverride } = args;
|
|
670
679
|
const fast = maxOutputTokens === PROBE_FAST_MAX_OUTPUT_TOKENS;
|
|
671
680
|
return {
|
|
672
681
|
model: modelId,
|
|
@@ -681,6 +690,7 @@ export function buildProbeCanonicalRequest(args: {
|
|
|
681
690
|
kind: "text",
|
|
682
691
|
text:
|
|
683
692
|
request.prompt ??
|
|
693
|
+
defaultPromptOverride ??
|
|
684
694
|
(fast ? PROBE_FAST_DEFAULT_PROMPT : "What model are you, and what is your knowledge cutoff date? Answer in one sentence."),
|
|
685
695
|
},
|
|
686
696
|
],
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
wireContextFrom,
|
|
57
57
|
type ProbeProviderRow,
|
|
58
58
|
} from "./probe-phases";
|
|
59
|
-
import { createProbeFetch } from "../
|
|
59
|
+
import { createProbeFetch } from "../provider-probe";
|
|
60
60
|
import { authHeaders } from "../adapters/compatible-adapter";
|
|
61
61
|
import {
|
|
62
62
|
byokAuthHeaderShape,
|
|
@@ -263,7 +263,20 @@ export class ProviderProbingService {
|
|
|
263
263
|
...(preferences.maxOutputTokens === undefined
|
|
264
264
|
? {}
|
|
265
265
|
: { maxOutputTokens: preferences.maxOutputTokens }),
|
|
266
|
-
|
|
266
|
+
// Freebuff's admission policy gate flags repeated identical probes as
|
|
267
|
+
// automated farming (`prompt_policy_refused` / "same message sent over
|
|
268
|
+
// and over"). Its probe must be minimal and always distinct per model —
|
|
269
|
+
// no worker system template, no shared identity question. `ping` is the
|
|
270
|
+
// same minimal greeting the fast-probe path already uses; the model id
|
|
271
|
+
// keeps every probe distinct so the "same message over and over" gate
|
|
272
|
+
// cannot flag a batch run.
|
|
273
|
+
...(providerId === "freebuff"
|
|
274
|
+
? {
|
|
275
|
+
defaultPromptOverride: `ping ${modelId}`,
|
|
276
|
+
providerSystemPrompt: undefined,
|
|
277
|
+
}
|
|
278
|
+
: {}),
|
|
279
|
+
...(typeof adapter?.systemPrompt === "function" && providerId !== "freebuff"
|
|
267
280
|
? { providerSystemPrompt: adapter.systemPrompt() }
|
|
268
281
|
: {}),
|
|
269
282
|
});
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { defineModel } from "../../provider-model-definition";
|
|
21
21
|
import type { ModelDefinition } from "../../provider-model-definition";
|
|
22
|
-
|
|
23
|
-
export const ALIBABACP_PROVIDER_ID = "alibabacp" as const;
|
|
22
|
+
import { ALIBABACP_PROVIDER_ID } from "./alibabacp";
|
|
24
23
|
|
|
25
24
|
/** Chat path below the region's `/compatible-mode/v1` base. */
|
|
26
25
|
const CHAT_ENDPOINT = "/chat/completions";
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* does not publish yet arrives through the sync control instead of being
|
|
18
18
|
* asserted ahead of the upstream.
|
|
19
19
|
*/
|
|
20
|
-
import { defineModel } from "
|
|
21
|
-
import type { ModelDefinition } from "
|
|
20
|
+
import { defineModel } from "../../provider-model-definition";
|
|
21
|
+
import type { ModelDefinition } from "../../provider-model-definition";
|
|
22
22
|
|
|
23
23
|
export const DASHSCOPE_PROVIDER_ID = "dashscope" as const;
|
|
24
24
|
|
|
@@ -400,7 +400,11 @@ export function dropAntigravityUnsignedReasoning(
|
|
|
400
400
|
if (message.role !== "assistant") return message;
|
|
401
401
|
const content = message.content.filter((part) => {
|
|
402
402
|
if (part.kind !== "reasoning") return true;
|
|
403
|
-
|
|
403
|
+
// A present-but-empty signature is still unsigned: upstream rejects a
|
|
404
|
+
// `thinking` part whose `signature` is missing *or* empty with
|
|
405
|
+
// `400 messages.N.content.0.thinking.signature: Field required`. Only a
|
|
406
|
+
// non-empty signature is a real one.
|
|
407
|
+
if (typeof part.signature === "string" && part.signature.length > 0) return true;
|
|
404
408
|
changed = true;
|
|
405
409
|
return false;
|
|
406
410
|
});
|
|
@@ -21,6 +21,7 @@ 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
26
|
import { BUDDY_CN_EFFORTS, BUDDY_INTL_EFFORTS, BUDDY_SHARED_RAW } from "./buddy-catalog-shared";
|
|
26
27
|
// Imported for the CN roster only: a CN-only id has no row in the shared
|
|
@@ -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 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 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");
|