cartethyia 2.7.2 → 2.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/dist/dashboard/assets/{BannedPage-XaUmiBrC.js → BannedPage-ChG5svFb.js} +1 -1
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +1 -0
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +1 -0
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-CXGS_Ct-.js → CombosPage-DCgm5g6g.js} +1 -1
- package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
- package/dist/dashboard/assets/{HealthEventsModal-BKtAPYVF.js → HealthEventsModal-DzSWzE_j.js} +1 -1
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-BdmRLnq2.js → LoginPage-U6AKaJcF.js} +1 -1
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BH8Tehdi.js → ModelPicker-BMS2t8BA.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +1 -0
- package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js +9 -0
- package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js +1 -0
- package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +1 -0
- package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js +1 -0
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-Dqf4zpS-.js → SortableList-ClzpwyET.js} +1 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-Byj2lAEm.js → StudioPage-Cq5tW7hW.js} +3 -3
- package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +56 -0
- package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js +1 -0
- package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
- package/dist/dashboard/assets/app-a159k0ub.css +2 -0
- package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
- package/dist/dashboard/assets/arrow-up-59ms1iiT.js +1 -0
- package/dist/dashboard/assets/arrow-up-59ms1iiT.js.gz +0 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js +15 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/{badge-DC2L43Mj.js → badge-D9CS6dZk.js} +1 -1
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/{banner-BBVcb0J3.js → banner-DympBNq4.js} +1 -1
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/{card-Cca1XC6G.js → card-ibRWU_uT.js} +1 -1
- package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js +1 -0
- package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DUzEbynq.js → clipboard-button-DJm-9pz7.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-DFvWhwTa.js → dialog-8fiE6tec.js} +1 -1
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js +1 -0
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/{entry-Bqy8RFvM.js → entry-BSAsYsmV.js} +1 -1
- package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js +4 -0
- package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js +1 -0
- package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
- package/dist/dashboard/assets/{concurrency-BDF0ok7y.js → fingerprint-pattern-BWuHtbW4.js} +1 -1
- package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-CWWZ-uCZ.js → formatters-D-MTJxMr.js} +1 -1
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-C9e8Ts7e.js → github-badge-CPK47xQx.js} +1 -1
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/{index-DFVFrnWW.js → index-DBNPOfhV.js} +2 -2
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/{inline-BFUcvllj.js → inline-BT0zntEr.js} +1 -1
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/{input-C_ILAvBb.js → input-Da2ZViWg.js} +1 -1
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/{layout-CBIyT6Rt.js → layout-BXNeLw6M.js} +1 -1
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-ebJ_-Nsb.js → list-row-BycOrrIV.js} +1 -1
- package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js +1 -0
- package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +1 -0
- package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
- package/dist/dashboard/assets/{mutation-sMD965oO.js → mutation-Rr0TIvcj.js} +1 -1
- package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js +1 -0
- package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
- package/dist/dashboard/assets/{numbers-BO9dKaFr.js → numbers-CEagj6ZZ.js} +2 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CfL_Zdoh.js → query-keys-BloKtaXJ.js} +1 -1
- package/dist/dashboard/assets/query-keys-BloKtaXJ.js.gz +0 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js +1 -0
- package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js +1 -0
- package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
- package/dist/dashboard/assets/{select-DBNVLdUu.js → select-BIYIBkMU.js} +2 -2
- package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
- package/dist/dashboard/assets/settings-2-Ds9DQp0t.js +1 -0
- package/dist/dashboard/assets/settings-2-Ds9DQp0t.js.gz +0 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js +1 -0
- package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
- package/dist/dashboard/assets/{stack-EMrOMt4I.js → stack-DfgnFDWY.js} +1 -1
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/{state-CWoo7ty5.js → state-CkfdYWel.js} +1 -1
- package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
- package/dist/dashboard/assets/{switch-CCjT6IkF.js → switch-SYm237HG.js} +1 -1
- package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-DjkLHUcE.js → useMutation-BQqCRNIi.js} +1 -1
- package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
- package/dist/dashboard/index.html +3 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +118 -115
- package/migrations/full-postgres/0026_add_qoder_native_identity.sql +20 -0
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +21 -0
- package/migrations/full-postgres/0028_add_family_template_key_telemetry.sql +40 -0
- package/migrations/full-postgres/0029_null_share_child_policy_columns.sql +38 -0
- package/migrations/full-postgres/0030_add_api_key_max_children.sql +10 -0
- package/migrations/full-postgres/0031_tenant_system_prompts.sql +16 -0
- package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
- package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
- package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
- package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
- package/migrations/lite-sqlite3/0026_add_qoder_native_identity.sql +15 -0
- package/migrations/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +21 -0
- package/migrations/lite-sqlite3/0028_add_family_template_key_telemetry.sql +40 -0
- package/migrations/lite-sqlite3/0029_null_share_child_policy_columns.sql +38 -0
- package/migrations/lite-sqlite3/0030_add_api_key_max_children.sql +10 -0
- package/migrations/lite-sqlite3/0031_tenant_system_prompts.sql +10 -0
- package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
- package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
- package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
- package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -0
- package/package.json +2 -1
- package/src/boot/app.ts +9 -8
- package/src/config/network.ts +7 -3
- package/src/console/api-keys/bucket-spend.ts +7 -7
- package/src/console/api-keys/contracts.ts +475 -410
- package/src/console/api-keys/routes.ts +211 -23
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/account-reset.ts +4 -4
- package/src/console/auth/session.ts +3 -3
- package/src/console/backup/contracts.ts +2 -0
- package/src/console/backup/export-endpoint.ts +14 -17
- package/src/console/backup/routes.ts +43 -11
- package/src/console/backup/service.ts +11 -6
- package/src/console/backup/store.ts +384 -88
- package/src/console/cli-tools/routes.ts +3 -3
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +4 -4
- package/src/console/dashboard-assets.ts +16 -1
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +4 -2
- package/src/console/observability/contracts.ts +4 -0
- package/src/console/observability/live.ts +3 -3
- package/src/console/observability/logs.ts +3 -3
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/store.ts +16 -16
- package/src/console/providers/catalog/contracts.ts +43 -22
- package/src/console/providers/catalog/provider-operations.ts +17 -2
- package/src/console/providers/catalog/routes.ts +3 -3
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1523 -1292
- package/src/console/providers/detail/routes.ts +3 -3
- package/src/console/providers/oauth/routes.ts +3 -3
- package/src/console/quota/account-quota-tenant.ts +34 -2
- package/src/console/quota/account-quota.ts +4 -1
- package/src/console/quota/account-test-egress.ts +4 -4
- package/src/console/quota/native-identity.ts +189 -0
- package/src/console/remote-support/contracts.ts +12 -6
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +11 -8
- package/src/console/routing/pools/operations.ts +14 -7
- package/src/console/routing/pools/probe-verdict.ts +8 -3
- package/src/console/routing/pools/relay-deploy.ts +9 -9
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/routes.ts +3 -3
- package/src/console/share/share-router.ts +51 -18
- package/src/console/share/share-stats.ts +158 -49
- package/src/console/share/share-usage.ts +24 -7
- package/src/console/shared/read-through-cache.ts +38 -2
- package/src/console/system-prompt/contracts.ts +102 -0
- package/src/console/system-prompt/routes.ts +165 -0
- package/src/console/updates/routes.ts +7 -4
- package/src/main.ts +11 -0
- package/src/network/outbound-fetch.ts +75 -4
- package/src/network/pool/resolver.ts +39 -39
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +21 -1
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/ssrf.ts +4 -4
- package/src/observability/event-query.ts +437 -22
- package/src/observability/telemetry-status.ts +1 -1
- package/src/persistence/db-pg.ts +42 -0
- package/src/persistence/db-sqlite.ts +7 -2
- package/src/persistence/readiness.ts +18 -6
- package/src/persistence/schema.ts +162 -1
- package/src/persistence/stores/api-key-store.ts +849 -581
- package/src/persistence/stores/share-store.ts +65 -13
- package/src/persistence/stores/telemetry-store.ts +58 -2
- package/src/persistence/system-prompt-store.ts +104 -0
- package/src/protocol/codecs.ts +6 -6
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-generation.ts +2 -2
- package/src/protocol/reasoning.ts +65 -1
- package/src/protocol/request/chat.ts +1 -0
- package/src/protocol/response/chat.ts +2 -2
- package/src/protocol/response/codex.ts +1 -1
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +5 -5
- package/src/protocol/response/responses.ts +2 -2
- package/src/protocol/sse-decoder.ts +14 -3
- package/src/protocol/translation/capabilities.ts +2 -2
- package/src/protocol/upstream/send-claude-messages.ts +3 -3
- package/src/providers/adapters/base-adapter.ts +1 -1
- package/src/providers/adapters/compatible-adapter.ts +2 -2
- package/src/providers/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/configured-provider.ts +1 -1
- package/src/providers/discovery/probe-phases.ts +2 -2
- package/src/providers/discovery/probing-service.ts +12 -12
- package/src/providers/integrations/agentrouter/agentrouter.ts +2 -3
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- package/src/providers/integrations/antigravity/antigravity.ts +33 -47
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +30 -2
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +22 -1
- package/src/providers/integrations/buddy/buddy-media.ts +21 -17
- package/src/providers/integrations/buddy/codebuddy/provider.ts +6 -2
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -2
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-credentials.ts +1 -1
- package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
- package/src/providers/integrations/claude/claude.ts +3 -10
- package/src/providers/integrations/cline/cline.ts +8 -1
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +4 -4
- package/src/providers/integrations/commandcode/quota.ts +5 -1
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -11
- package/src/providers/integrations/cursor/cursor.ts +15 -15
- package/src/providers/integrations/factory/factory.ts +4 -4
- package/src/providers/integrations/gemini.ts +11 -11
- package/src/providers/integrations/github/github.ts +26 -7
- package/src/providers/integrations/grok/grok.ts +2 -6
- package/src/providers/integrations/hermes.ts +5 -1
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo.ts +4 -0
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- package/src/providers/integrations/kiro/kiro.ts +10 -10
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/openrouter/provider.ts +4 -0
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +47 -9
- package/src/providers/integrations/qoder/qoder-checkin.ts +242 -51
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +157 -0
- package/src/providers/integrations/qoder/qoder-oauth.ts +12 -3
- package/src/providers/integrations/qoder/qoder-realm.ts +15 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +287 -0
- package/src/providers/integrations/qoder/qoder-virtual.ts +2 -2
- package/src/providers/integrations/qoder/qoder.ts +192 -24
- package/src/providers/integrations/tokenharbor.ts +2 -2
- package/src/providers/integrations/trae/trae.ts +6 -9
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/operations/account-error-classification.ts +6 -8
- package/src/providers/operations/account-health-service.ts +14 -16
- package/src/providers/operations/client-versions.ts +37 -22
- package/src/providers/operations/provider-catalog-service.ts +4 -4
- package/src/providers/operations/provider-credential-service.ts +16 -4
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +55 -3
- package/src/providers/provider-credential-resolver.ts +1 -1
- package/src/providers/provider-registry.ts +4 -4
- package/src/providers/quota/quota-contracts.ts +24 -10
- package/src/providers/quota/refresh.ts +2 -2
- package/src/providers/search/search-provider.ts +5 -5
- package/src/security/abuse.ts +4 -4
- package/src/security/access-control.ts +19 -0
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/api-key-auth.ts +18 -5
- package/src/shared/coerce.ts +19 -0
- package/src/transport/dispatch/attempt-finalize.ts +4 -3
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/empty-stream.ts +6 -6
- package/src/transport/dispatch/generation.ts +9 -9
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/proxy-request.ts +38 -9
- package/src/transport/dispatch/responses-compact.ts +11 -11
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/finalize.ts +9 -8
- package/src/transport/dispatch/streaming/stream.ts +16 -1
- package/src/transport/dispatch/systemone.ts +8 -8
- package/src/transport/dispatch/token-count.ts +9 -9
- package/src/transport/dispatch/upstream.ts +10 -0
- package/src/transport/dispatch/websearch.ts +6 -6
- package/src/transport/drain-endpoint.ts +2 -2
- package/src/transport/failure-policy.ts +13 -6
- package/src/transport/guards/auth-guard.ts +6 -5
- package/src/transport/guards/body-policy.ts +4 -4
- package/src/transport/guards/error-lifecycle.ts +18 -3
- package/src/transport/guards/guard-errors.ts +7 -3
- package/src/transport/guards/headroom-guard.ts +1 -1
- package/src/transport/guards/pipeline.ts +6 -6
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +3 -3
- package/src/transport/request/preparer.ts +37 -21
- package/src/transport/request/state.ts +4 -7
- package/src/transport/request/system-prompt-injection.ts +89 -0
- package/src/transport/request/tenant-preferences.ts +43 -0
- package/src/transport/routing/admission.ts +13 -3
- package/src/transport/routing/route-catalog.ts +104 -2
- package/src/transport/routing/route-model.ts +60 -7
- package/src/transport/routing/router.ts +306 -256
- package/src/transport/shutdown-notice.ts +19 -7
- package/src/transport/surface/completion.ts +1 -1
- package/src/transport/surface/messages/encode.ts +1 -1
- package/src/workers/daily-checkin.ts +2 -0
- package/dist/dashboard/assets/BannedPage-XaUmiBrC.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-CqD7QiLM.js +0 -1
- package/dist/dashboard/assets/CliToolDetailPage-CqD7QiLM.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-0XUo4UMn.js +0 -1
- package/dist/dashboard/assets/CliToolsPage-0XUo4UMn.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-CXGS_Ct-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-DGnGNYnM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-DGnGNYnM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-DAG5J9EY.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-DAG5J9EY.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-BKtAPYVF.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-BdmRLnq2.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BH8Tehdi.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CqMxibJB.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CqMxibJB.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-CqMh2NRX.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-CqMh2NRX.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-B9uWu4Nz.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-B9uWu4Nz.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-BoWOhpDO.js +0 -9
- package/dist/dashboard/assets/ProxyPage-BoWOhpDO.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-7P2n--Fv.js +0 -1
- package/dist/dashboard/assets/QuotaPage-7P2n--Fv.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CxZ1fTkN.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CxZ1fTkN.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-Co12Zzaw.js +0 -1
- package/dist/dashboard/assets/SetupPage-Co12Zzaw.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-Dqf4zpS-.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-Byj2lAEm.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-CTkLAuRc.js +0 -56
- package/dist/dashboard/assets/UsagePage-CTkLAuRc.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-CUi6UXsR.js +0 -1
- package/dist/dashboard/assets/api-keys-CUi6UXsR.js.gz +0 -0
- package/dist/dashboard/assets/app-KvsUJUMF.css +0 -2
- package/dist/dashboard/assets/app-KvsUJUMF.css.gz +0 -0
- package/dist/dashboard/assets/assert-67xXH5rf.js +0 -1
- package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
- package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
- package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
- package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js +0 -1
- package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
- package/dist/dashboard/assets/concurrency-BDF0ok7y.js.gz +0 -0
- package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
- package/dist/dashboard/assets/drawer-CFM2sMX1.js +0 -1
- package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
- package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
- package/dist/dashboard/assets/entry-ClCMCWWQ.js +0 -4
- package/dist/dashboard/assets/entry-ClCMCWWQ.js.gz +0 -0
- package/dist/dashboard/assets/entry-_xHo5x6r.js +0 -1
- package/dist/dashboard/assets/entry-_xHo5x6r.js.gz +0 -0
- package/dist/dashboard/assets/formatters-CWWZ-uCZ.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
- package/dist/dashboard/assets/index-DFVFrnWW.js.gz +0 -0
- package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
- package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
- package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
- package/dist/dashboard/assets/list-row-ebJ_-Nsb.js.gz +0 -0
- package/dist/dashboard/assets/live-D0mm--ME.js +0 -1
- package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
- package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
- package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BO9dKaFr.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CfL_Zdoh.js.gz +0 -0
- package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
- package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
- package/dist/dashboard/assets/routing-BnIpi1IJ.js +0 -1
- package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
- package/dist/dashboard/assets/select-DBNVLdUu.js.gz +0 -0
- package/dist/dashboard/assets/settings-BAFhDgX8.js +0 -1
- package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
- package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
- package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
- package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-DjkLHUcE.js.gz +0 -0
- /package/dist/dashboard/assets/{app-BaWd0puM.js → app-BayTTy01.js} +0 -0
- /package/dist/dashboard/assets/{app-BaWd0puM.js.gz → app-BayTTy01.js.gz} +0 -0
|
@@ -152,14 +152,14 @@ function finishImage(bytes: Uint8Array): CursorImageInput {
|
|
|
152
152
|
throw new GatewayError(
|
|
153
153
|
"invalid_request",
|
|
154
154
|
400,
|
|
155
|
-
"Cursor accepts PNG, JPEG, WebP and GIF image input only",
|
|
155
|
+
"Cursor accepts PNG, JPEG, WebP and GIF image input only (request {requestId}). Check the shape of what you sent — then resend 🪞",
|
|
156
156
|
);
|
|
157
157
|
}
|
|
158
158
|
if (bytes.byteLength > MAX_IMAGE_BYTES) {
|
|
159
159
|
throw new GatewayError(
|
|
160
160
|
"invalid_request",
|
|
161
161
|
400,
|
|
162
|
-
`Cursor image input exceeds the ${MAX_IMAGE_BYTES}-byte limit
|
|
162
|
+
`Cursor image input exceeds the ${MAX_IMAGE_BYTES}-byte limit (request {requestId}). We love long reads, but not that long 📚`,
|
|
163
163
|
);
|
|
164
164
|
}
|
|
165
165
|
return { data: bytes, mimeType };
|
|
@@ -183,7 +183,7 @@ async function resolveImageInput(
|
|
|
183
183
|
if (dataUrl !== undefined) {
|
|
184
184
|
const bytes = base64ToBytes(dataUrl.data);
|
|
185
185
|
if (bytes === undefined) {
|
|
186
|
-
throw new GatewayError("invalid_request", 400, "Cursor image attachment is not valid base64");
|
|
186
|
+
throw new GatewayError("invalid_request", 400, "Cursor image attachment is not valid base64 (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
187
187
|
}
|
|
188
188
|
return finishImage(bytes);
|
|
189
189
|
}
|
|
@@ -192,7 +192,7 @@ async function resolveImageInput(
|
|
|
192
192
|
throw new GatewayError(
|
|
193
193
|
"invalid_request",
|
|
194
194
|
400,
|
|
195
|
-
"Cursor image URLs must be HTTPS; private and non-TLS sources are not fetched",
|
|
195
|
+
"Cursor image URLs must be HTTPS; private and non-TLS sources are not fetched (request {requestId}). Check the shape of what you sent — then resend 🪞",
|
|
196
196
|
);
|
|
197
197
|
}
|
|
198
198
|
const fetcher = context.outbound_attachment_fetch;
|
|
@@ -200,7 +200,7 @@ async function resolveImageInput(
|
|
|
200
200
|
throw new GatewayError(
|
|
201
201
|
"invalid_request",
|
|
202
202
|
400,
|
|
203
|
-
"Cursor has no validated egress to fetch this image URL",
|
|
203
|
+
"Cursor has no validated egress to fetch this image URL (request {requestId}). All roads blocked — time to find a new route 🗺️",
|
|
204
204
|
);
|
|
205
205
|
}
|
|
206
206
|
// Redirects are not followed: reject the response rather than letting a
|
|
@@ -222,7 +222,7 @@ async function resolveImageInput(
|
|
|
222
222
|
throw new GatewayError(
|
|
223
223
|
"invalid_request",
|
|
224
224
|
400,
|
|
225
|
-
`Cursor image input exceeds the ${MAX_IMAGE_BYTES}-byte limit
|
|
225
|
+
`Cursor image input exceeds the ${MAX_IMAGE_BYTES}-byte limit (request {requestId}). We love long reads, but not that long 📚`,
|
|
226
226
|
);
|
|
227
227
|
}
|
|
228
228
|
return finishImage(body);
|
|
@@ -503,7 +503,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
503
503
|
throw new GatewayError(
|
|
504
504
|
"invalid_request",
|
|
505
505
|
400,
|
|
506
|
-
"This tool result cannot be matched to a live Cursor Run; resend the complete conversation.",
|
|
506
|
+
"This tool result cannot be matched to a live Cursor Run (request {requestId}); resend the complete conversation. The session went cold — reconnect or resend 🔌",
|
|
507
507
|
);
|
|
508
508
|
}
|
|
509
509
|
const resolvedAll = pending.map((item) => cursorRunSessions.resolveCall(item.callId, scope));
|
|
@@ -530,7 +530,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
530
530
|
throw new GatewayError(
|
|
531
531
|
"invalid_request",
|
|
532
532
|
400,
|
|
533
|
-
"This tool result refers to a Cursor tool call that is no longer pending. Resend the complete conversation.",
|
|
533
|
+
"This tool result refers to a Cursor tool call that is no longer pending (request {requestId}). Resend the complete conversation. The session went cold — reconnect or resend 🔌",
|
|
534
534
|
{ callIds: pending.map((item) => item.callId) },
|
|
535
535
|
);
|
|
536
536
|
}
|
|
@@ -538,12 +538,12 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
538
538
|
throw new GatewayError(
|
|
539
539
|
"invalid_request",
|
|
540
540
|
400,
|
|
541
|
-
"These tool results belong to different Cursor Runs; resend them one Run at a time.",
|
|
541
|
+
"These tool results belong to different Cursor Runs (request {requestId}); resend them one Run at a time. The session went cold — reconnect or resend 🔌",
|
|
542
542
|
);
|
|
543
543
|
}
|
|
544
544
|
const session = cursorRunSessions.get(runId);
|
|
545
545
|
if (session === undefined) {
|
|
546
|
-
throw new GatewayError("invalid_request", 400, "Cursor Run is no longer live");
|
|
546
|
+
throw new GatewayError("invalid_request", 400, "Cursor Run is no longer live (request {requestId}). The session went cold — reconnect or resend 🔌");
|
|
547
547
|
}
|
|
548
548
|
const handle = this.#handles.get(runId);
|
|
549
549
|
if (handle === undefined) {
|
|
@@ -605,7 +605,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
605
605
|
throw new GatewayError(
|
|
606
606
|
"admission_unavailable",
|
|
607
607
|
503,
|
|
608
|
-
"Cursor requires validated HTTP/2 egress; none is configured for this route",
|
|
608
|
+
"Cursor requires validated HTTP/2 egress (request {requestId}); none is configured for this route. No bridge to cross — configure a pool first 🏗️",
|
|
609
609
|
{ providerId: CURSOR_PROVIDER_ID },
|
|
610
610
|
);
|
|
611
611
|
}
|
|
@@ -784,7 +784,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
784
784
|
: new GatewayError(
|
|
785
785
|
"platform_unavailable",
|
|
786
786
|
502,
|
|
787
|
-
`Cursor Run failed: ${error instanceof Error ? error.message : String(error)}
|
|
787
|
+
`Cursor Run failed (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The upstream came back empty-handed — retry 🌙`,
|
|
788
788
|
{ providerId: CURSOR_PROVIDER_ID },
|
|
789
789
|
"upstream",
|
|
790
790
|
);
|
|
@@ -828,7 +828,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
828
828
|
throw new GatewayError(
|
|
829
829
|
"platform_unavailable",
|
|
830
830
|
502,
|
|
831
|
-
`Cursor Run origin could not be resolved: ${error instanceof Error ? error.message : String(error)}
|
|
831
|
+
`Cursor Run origin could not be resolved (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`,
|
|
832
832
|
{ providerId: CURSOR_PROVIDER_ID },
|
|
833
833
|
"upstream",
|
|
834
834
|
);
|
|
@@ -890,7 +890,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
890
890
|
}
|
|
891
891
|
const message = item;
|
|
892
892
|
if (context.abort_signal.aborted) {
|
|
893
|
-
failure = new GatewayError("transport_closed", 499, "request was cancelled");
|
|
893
|
+
failure = new GatewayError("transport_closed", 499, "The request was cancelled (request {requestId}). Send it again whenever ready 🙃");
|
|
894
894
|
break;
|
|
895
895
|
}
|
|
896
896
|
const execServer = recordOf(message["exec_server_message"]);
|
|
@@ -994,7 +994,7 @@ class CursorAdapter implements ProviderAdapter {
|
|
|
994
994
|
: new GatewayError(
|
|
995
995
|
"platform_unavailable",
|
|
996
996
|
502,
|
|
997
|
-
`Cursor Run failed: ${error instanceof Error ? error.message : String(error)}
|
|
997
|
+
`Cursor Run failed (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The upstream came back empty-handed — retry 🌙`,
|
|
998
998
|
{ providerId: CURSOR_PROVIDER_ID },
|
|
999
999
|
"upstream",
|
|
1000
1000
|
);
|
|
@@ -270,7 +270,7 @@ export function factoryRegionUnavailable(modelId: string, region: string): Gatew
|
|
|
270
270
|
return new GatewayError(
|
|
271
271
|
"capability_unsupported",
|
|
272
272
|
400,
|
|
273
|
-
`factory: ${modelId} is unavailable in this account region (${region})
|
|
273
|
+
`factory: ${modelId} is unavailable in this account region (${region}) (request {requestId}). Know your tools — this one just isn't in the box 🧰`,
|
|
274
274
|
{ model: modelId, region, reason: "Factory Droid model is unavailable in this account region." },
|
|
275
275
|
);
|
|
276
276
|
}
|
|
@@ -351,7 +351,7 @@ export function factoryRoutingHeaders(
|
|
|
351
351
|
function factoryEnvelope(context: ProviderDispatchContext): { token: string; orgId: string } {
|
|
352
352
|
const secret = context.credential.secret;
|
|
353
353
|
if (secret === undefined || secret.length === 0) {
|
|
354
|
-
throw new GatewayError("invalid_request", 400, "factory: credential is missing a secret value");
|
|
354
|
+
throw new GatewayError("invalid_request", 400, "factory: credential is missing a secret value (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
355
355
|
}
|
|
356
356
|
try {
|
|
357
357
|
const envelope = decodeFactoryDroidCredential(secret);
|
|
@@ -360,7 +360,7 @@ function factoryEnvelope(context: ProviderDispatchContext): { token: string; org
|
|
|
360
360
|
throw new GatewayError(
|
|
361
361
|
"invalid_request",
|
|
362
362
|
400,
|
|
363
|
-
`factory: ${error instanceof Error ? error.message : "stored credential is not a Factory Droid envelope"}
|
|
363
|
+
`factory: ${error instanceof Error ? error.message : "stored credential is not a Factory Droid envelope"} (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
364
364
|
);
|
|
365
365
|
}
|
|
366
366
|
}
|
|
@@ -523,7 +523,7 @@ class FactoryDroidAdapter implements ProviderAdapter {
|
|
|
523
523
|
throw new GatewayError(
|
|
524
524
|
"platform_unavailable",
|
|
525
525
|
502,
|
|
526
|
-
"factory gemini returned empty stream",
|
|
526
|
+
"factory gemini returned empty stream (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
527
527
|
{},
|
|
528
528
|
"upstream",
|
|
529
529
|
);
|
|
@@ -6,7 +6,7 @@ import { mapUpstreamHttpError } from "../../transport/failure-policy";
|
|
|
6
6
|
import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason } from "../../protocol/canonical-model";
|
|
7
7
|
import { decodeSseEvents } from "../../protocol/sse-decoder";
|
|
8
8
|
import { usageFromProvider } from "../provider-usage";
|
|
9
|
-
import { readCredentialSecret, type ImageGenerationOutcome, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext, type WebSearchOutcome, type WebSearchResult } from "../provider-contracts";
|
|
9
|
+
import { readCredentialSecret, assertWireFamily, type ImageGenerationOutcome, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext, type WebSearchOutcome, type WebSearchResult } from "../provider-contracts";
|
|
10
10
|
import type { ModelDefinition } from "../provider-model-definition";
|
|
11
11
|
import { fetchOpenAICompatibleModels } from "../discovery/openai-model-discovery";
|
|
12
12
|
import { isRecord } from "../../protocol/codecs";
|
|
@@ -181,7 +181,7 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
181
181
|
context: ProviderDispatchContext,
|
|
182
182
|
): AsyncIterable<CanonicalEvent> {
|
|
183
183
|
if (candidate.wire_family !== "chat" && candidate.wire_family !== "responses" && candidate.wire_family !== "messages") {
|
|
184
|
-
|
|
184
|
+
assertWireFamily(candidate, ["chat", "responses", "messages"], "gemini");
|
|
185
185
|
}
|
|
186
186
|
const apiKey = readCredentialSecret(context.credential, "Gemini API key is required");
|
|
187
187
|
|
|
@@ -262,7 +262,7 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
262
262
|
return;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
if (!response.body) throw new GatewayError("platform_unavailable", 502, "Gemini returned empty stream", {}, "upstream");
|
|
265
|
+
if (!response.body) throw new GatewayError("platform_unavailable", 502, "Gemini returned empty stream (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
266
266
|
let seq = 1;
|
|
267
267
|
yield { type: "response_start", sequence_number: seq++, model: request.model } as CanonicalEvent;
|
|
268
268
|
const state = { started: true, stopped: false, activeCalls: new Set<string>() };
|
|
@@ -339,7 +339,7 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
339
339
|
context: ProviderDispatchContext,
|
|
340
340
|
): Promise<WebSearchOutcome> {
|
|
341
341
|
const query = typeof body.query === "string" ? body.query.trim() : "";
|
|
342
|
-
if (!query) throw new GatewayError("invalid_request", 400, "search query is required");
|
|
342
|
+
if (!query) throw new GatewayError("invalid_request", 400, "search query is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
343
343
|
const rawMax = body.max_results;
|
|
344
344
|
const maxResults =
|
|
345
345
|
typeof rawMax === "number" && Number.isFinite(rawMax)
|
|
@@ -368,7 +368,7 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
368
368
|
throw new GatewayError(
|
|
369
369
|
"platform_unavailable",
|
|
370
370
|
502,
|
|
371
|
-
`Gemini search unreachable: ${error instanceof Error ? error.message : String(error)}
|
|
371
|
+
`Gemini search unreachable (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`,
|
|
372
372
|
);
|
|
373
373
|
}
|
|
374
374
|
if (!response.ok) throw await mapUpstreamHttpError(response, "gemini search");
|
|
@@ -376,11 +376,11 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
376
376
|
try {
|
|
377
377
|
data = await response.json();
|
|
378
378
|
} catch {
|
|
379
|
-
throw new GatewayError("platform_unavailable", 502, "Gemini search returned invalid JSON");
|
|
379
|
+
throw new GatewayError("platform_unavailable", 502, "Gemini search returned invalid JSON (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
380
380
|
}
|
|
381
381
|
const results = normalizeGroundingResults(data, maxResults);
|
|
382
382
|
if (results.length === 0)
|
|
383
|
-
throw new GatewayError("platform_unavailable", 502, "Gemini search returned no grounded results");
|
|
383
|
+
throw new GatewayError("platform_unavailable", 502, "Gemini search returned no grounded results (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
384
384
|
return { results, total_results: results.length };
|
|
385
385
|
}
|
|
386
386
|
|
|
@@ -391,7 +391,7 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
391
391
|
): Promise<ImageGenerationOutcome> {
|
|
392
392
|
const prompt = imagePrompt(body);
|
|
393
393
|
const model = candidate.model_id.length > 0 ? candidate.model_id : typeof body.model === "string" ? body.model : "";
|
|
394
|
-
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required");
|
|
394
|
+
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
395
395
|
const apiKey = readCredentialSecret(context.credential, "Gemini API key is required");
|
|
396
396
|
const outboundFetch = context.outbound_fetch ?? this.fetchFn;
|
|
397
397
|
const lifecycle = createUpstreamDeadlineLifecycle(context);
|
|
@@ -418,7 +418,7 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
418
418
|
throw new GatewayError(
|
|
419
419
|
"platform_unavailable",
|
|
420
420
|
502,
|
|
421
|
-
`Gemini image generation unreachable: ${error instanceof Error ? error.message : String(error)}
|
|
421
|
+
`Gemini image generation unreachable (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`,
|
|
422
422
|
{},
|
|
423
423
|
"upstream",
|
|
424
424
|
);
|
|
@@ -430,11 +430,11 @@ class GeminiAdapter implements ProviderAdapter {
|
|
|
430
430
|
try {
|
|
431
431
|
data = await response.json();
|
|
432
432
|
} catch {
|
|
433
|
-
throw new GatewayError("platform_unavailable", 502, "Gemini image generation returned invalid JSON", {}, "upstream");
|
|
433
|
+
throw new GatewayError("platform_unavailable", 502, "Gemini image generation returned invalid JSON (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
434
434
|
}
|
|
435
435
|
const images = geminiInlineImages(data);
|
|
436
436
|
if (images.length === 0) {
|
|
437
|
-
throw new GatewayError("platform_unavailable", 502, "Gemini image generation returned no image", {}, "upstream");
|
|
437
|
+
throw new GatewayError("platform_unavailable", 502, "Gemini image generation returned no image (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
438
438
|
}
|
|
439
439
|
return { created: imageCreatedSeconds(), data: images };
|
|
440
440
|
}
|
|
@@ -288,6 +288,23 @@ interface GithubAutoDecision {
|
|
|
288
288
|
readonly sessionToken: string;
|
|
289
289
|
readonly expiresAt: number;
|
|
290
290
|
readonly hasImage: boolean;
|
|
291
|
+
readonly route?: GithubModelRoute;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function routeFromAutoModel(value: unknown): GithubModelRoute | undefined {
|
|
295
|
+
if (!isRecord(value) || !Array.isArray(value["supported_endpoints"])) return undefined;
|
|
296
|
+
const endpoints = new Set(
|
|
297
|
+
value["supported_endpoints"]
|
|
298
|
+
.filter((endpoint): endpoint is string => typeof endpoint === "string")
|
|
299
|
+
.map((endpoint) => endpoint.replace(/^\/v1(?=\/)/, "")),
|
|
300
|
+
);
|
|
301
|
+
if (endpoints.has("/chat/completions")) {
|
|
302
|
+
return { wireFamily: "chat", endpointPath: GITHUB_ENDPOINT_PATH };
|
|
303
|
+
}
|
|
304
|
+
if (endpoints.has("/responses")) {
|
|
305
|
+
return { wireFamily: "responses", endpointPath: GITHUB_RESPONSES_ENDPOINT_PATH };
|
|
306
|
+
}
|
|
307
|
+
return undefined;
|
|
291
308
|
}
|
|
292
309
|
|
|
293
310
|
interface CopilotModelOptions {
|
|
@@ -394,7 +411,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
394
411
|
|
|
395
412
|
const secret = context.credential.secret;
|
|
396
413
|
if (secret === undefined || secret.length === 0) {
|
|
397
|
-
throw new GatewayError("authentication_failed", 401, "GitHub Copilot credential is missing");
|
|
414
|
+
throw new GatewayError("authentication_failed", 401, "GitHub Copilot credential is missing (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
398
415
|
}
|
|
399
416
|
const credential = new TextDecoder().decode(secret);
|
|
400
417
|
const autoInput = autoPrompt(request);
|
|
@@ -407,7 +424,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
407
424
|
: this.#getCachedAutoDecision(cacheKey, autoInput.hasImage);
|
|
408
425
|
if (autoDecision === undefined) {
|
|
409
426
|
if (autoInput.prompt.length === 0) {
|
|
410
|
-
throw new GatewayError("invalid_request", 400, "Copilot Auto requires a text prompt");
|
|
427
|
+
throw new GatewayError("invalid_request", 400, "Copilot Auto requires a text prompt (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
411
428
|
}
|
|
412
429
|
autoDecision = await this.#selectAutoModel(
|
|
413
430
|
autoInput.prompt,
|
|
@@ -420,7 +437,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
420
437
|
if (cacheKey !== undefined) this.#cacheAutoDecision(cacheKey, autoDecision);
|
|
421
438
|
}
|
|
422
439
|
const selectedModelId = autoDecision.modelId;
|
|
423
|
-
let route = await githubModelRoute(selectedModelId, credential);
|
|
440
|
+
let route = autoDecision.route ?? await githubModelRoute(selectedModelId, credential);
|
|
424
441
|
if (route === undefined) {
|
|
425
442
|
// dynamic-import: discovery module is only loaded when the first
|
|
426
443
|
// request routes to a model id not in the bundled roster; off the hot
|
|
@@ -445,7 +462,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
445
462
|
throw new GatewayError(
|
|
446
463
|
"upstream_unprocessable",
|
|
447
464
|
502,
|
|
448
|
-
"Copilot Auto selected a model without a discovered inference endpoint",
|
|
465
|
+
"Copilot Auto selected a model without a discovered inference endpoint (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
449
466
|
{ selected_model: selectedModelId },
|
|
450
467
|
"upstream",
|
|
451
468
|
);
|
|
@@ -481,7 +498,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
481
498
|
? undefined
|
|
482
499
|
: parseGithubCredential(new TextDecoder().decode(context.credential.secret));
|
|
483
500
|
if (credential === undefined) {
|
|
484
|
-
throw new GatewayError("authentication_failed", 401, "GitHub Copilot credential is missing");
|
|
501
|
+
throw new GatewayError("authentication_failed", 401, "GitHub Copilot credential is missing (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
485
502
|
}
|
|
486
503
|
const payload: Record<string, unknown> = { prompt, tier };
|
|
487
504
|
if (hasImage) payload.has_image = true;
|
|
@@ -505,7 +522,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
505
522
|
throw new GatewayError(
|
|
506
523
|
"upstream_unprocessable",
|
|
507
524
|
502,
|
|
508
|
-
"Copilot Auto returned an invalid routing response",
|
|
525
|
+
"Copilot Auto returned an invalid routing response (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
509
526
|
{},
|
|
510
527
|
"upstream",
|
|
511
528
|
);
|
|
@@ -528,7 +545,7 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
528
545
|
throw new GatewayError(
|
|
529
546
|
"upstream_unprocessable",
|
|
530
547
|
502,
|
|
531
|
-
"Copilot Auto did not return a selected model",
|
|
548
|
+
"Copilot Auto did not return a selected model (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
532
549
|
{},
|
|
533
550
|
"upstream",
|
|
534
551
|
);
|
|
@@ -539,11 +556,13 @@ class GithubAdapter extends OpenAICompatibleAdapter {
|
|
|
539
556
|
Number.isFinite(responsePayload.expires_at)
|
|
540
557
|
? responsePayload.expires_at
|
|
541
558
|
: 0;
|
|
559
|
+
const route = routeFromAutoModel(responsePayload.selected_model);
|
|
542
560
|
return {
|
|
543
561
|
modelId: responsePayload.selected_model.id.trim(),
|
|
544
562
|
sessionToken: responsePayload.session_token.trim(),
|
|
545
563
|
expiresAt,
|
|
546
564
|
hasImage,
|
|
565
|
+
...(route === undefined ? {} : { route }),
|
|
547
566
|
};
|
|
548
567
|
}
|
|
549
568
|
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
* OpenAI-compatible adapter.
|
|
10
10
|
*/
|
|
11
11
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
12
|
-
import { GatewayError } from "../../../protocol/gateway-error";
|
|
13
12
|
import type { CanonicalEvent, CanonicalRequest } from "../../../protocol/canonical-model";
|
|
14
13
|
import {
|
|
15
14
|
OpenAICompatibleAdapter,
|
|
16
15
|
withBearerAuthentication,
|
|
17
16
|
} from "../../adapters/compatible-adapter";
|
|
17
|
+
import { assertCredentialKind } from "../../provider-contracts";
|
|
18
18
|
import type { ProviderAdapter, ProviderDispatchTarget, ProviderDispatchContext } from "../../provider-contracts";
|
|
19
19
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
20
20
|
import { boundedUpstreamArray, boundedUpstreamNumber, sanitizeUpstreamLabel } from "../../provider-sanitize";
|
|
@@ -526,11 +526,7 @@ class GrokAdapter extends OpenAICompatibleAdapter {
|
|
|
526
526
|
context: ProviderDispatchContext,
|
|
527
527
|
): AsyncIterable<CanonicalEvent> {
|
|
528
528
|
if (context.credential.credential_kind !== "oauth") {
|
|
529
|
-
|
|
530
|
-
"invalid_request",
|
|
531
|
-
400,
|
|
532
|
-
"grok requires an xAI OAuth device credential",
|
|
533
|
-
);
|
|
529
|
+
assertCredentialKind(context.credential, "oauth", "grok");
|
|
534
530
|
}
|
|
535
531
|
yield* super.dispatch(request, candidate, context);
|
|
536
532
|
}
|
|
@@ -4,6 +4,7 @@ import type { ApiKeyProviderSpec } from "../configured-provider";
|
|
|
4
4
|
import { isRecord } from "../../protocol/codecs";
|
|
5
5
|
import { boundedUpstreamArray, boundedUpstreamNumber, sanitizeUpstreamLabel } from "../provider-sanitize";
|
|
6
6
|
import { getHermesVersion } from "../operations/client-versions";
|
|
7
|
+
import { clineReasoningReplayPrepares } from "./buddy/buddy-chat-shared";
|
|
7
8
|
|
|
8
9
|
const HERMES_PROVIDER_ID = "hermes" as const;
|
|
9
10
|
|
|
@@ -110,7 +111,10 @@ export const HERMES_MODELS: readonly ModelDefinition[] = [
|
|
|
110
111
|
export const HERMES_SPEC: ApiKeyProviderSpec = {
|
|
111
112
|
provider_id: HERMES_PROVIDER_ID,
|
|
112
113
|
endpoint_paths_by_wire_family: {},
|
|
113
|
-
prePayload:
|
|
114
|
+
prePayload: (payload, request, candidate) => {
|
|
115
|
+
injectHermesTags(payload, request, candidate);
|
|
116
|
+
for (const prepare of clineReasoningReplayPrepares) prepare(payload);
|
|
117
|
+
},
|
|
114
118
|
// The origin sits behind Cloudflare, which answers a request carrying no
|
|
115
119
|
// `user-agent` with 403 "Attention Required!" while the same request with any
|
|
116
120
|
// non-empty UA answers 200 — measured directly against the API: an empty UA
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Hybrid: the Messages-wire leg (`InferhubMessagesAdapter`, Claude Messages
|
|
2
2
|
// envelope + Bearer auth + breakpoint cache stamping) is a non-OpenAI wire and
|
|
3
3
|
// stays bespoke; the chat leg is a declarative spec row.
|
|
4
|
+
import { assertCredentialKind, assertWireFamily } from "../provider-contracts";
|
|
4
5
|
import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext } from "../provider-contracts";
|
|
5
6
|
import type { ModelDefinition } from "../provider-model-definition";
|
|
6
7
|
import type { ProviderModelDiscovery } from "../discovery/discovery-types";
|
|
@@ -326,21 +327,13 @@ export class InferhubMessagesAdapter implements ProviderAdapter {
|
|
|
326
327
|
context: ProviderDispatchContext,
|
|
327
328
|
): AsyncIterable<CanonicalEvent> {
|
|
328
329
|
if (candidate.wire_family !== "messages") {
|
|
329
|
-
|
|
330
|
-
"capability_unsupported",
|
|
331
|
-
400,
|
|
332
|
-
`inferhub messages leg supports messages only, got ${candidate.wire_family}`,
|
|
333
|
-
);
|
|
330
|
+
assertWireFamily(candidate, "messages", "inferhub messages leg");
|
|
334
331
|
}
|
|
335
332
|
if (context.credential.credential_kind !== "api_key") {
|
|
336
|
-
|
|
337
|
-
"invalid_request",
|
|
338
|
-
400,
|
|
339
|
-
`inferhub: api_key credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
340
|
-
);
|
|
333
|
+
assertCredentialKind(context.credential, "api_key", "inferhub");
|
|
341
334
|
}
|
|
342
335
|
if (context.credential.secret === undefined || context.credential.secret.length === 0) {
|
|
343
|
-
throw new GatewayError("invalid_request", 400, "inferhub: API key is missing a secret value");
|
|
336
|
+
throw new GatewayError("invalid_request", 400, "inferhub: API key is missing a secret value (request {requestId}). Wrong key, right door — check the key 🔑");
|
|
344
337
|
}
|
|
345
338
|
const apiKey = new TextDecoder().decode(context.credential.secret);
|
|
346
339
|
const customHeaders = filterClaudeCustomHeaders({
|
|
@@ -24,6 +24,7 @@ import type { CanonicalRequest } from "../../../protocol/canonical-model";
|
|
|
24
24
|
import { OpenAICompatibleAdapter, withBearerAuthentication } from "../../adapters/compatible-adapter";
|
|
25
25
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
26
26
|
import { decodeKiloCredential } from "../../../security/credential-codec";
|
|
27
|
+
import { clineReasoningReplayPrepares } from "../buddy/buddy-chat-shared";
|
|
27
28
|
|
|
28
29
|
export const KILO_PROVIDER_ID = "kilo" as const;
|
|
29
30
|
export const KILO_BASE_URL = providerBaseUrl("kilo");
|
|
@@ -117,6 +118,9 @@ class KiloAdapter extends OpenAICompatibleAdapter {
|
|
|
117
118
|
provider_id: KILO_PROVIDER_ID,
|
|
118
119
|
base_url: KILO_BASE_URL,
|
|
119
120
|
endpoint_paths_by_wire_family: { chat: KILO_ENDPOINT_PATH },
|
|
121
|
+
prePayload: (payload) => {
|
|
122
|
+
for (const prepare of clineReasoningReplayPrepares) prepare(payload);
|
|
123
|
+
},
|
|
120
124
|
...(fetchImpl ? { fetchImpl } : {}),
|
|
121
125
|
}),
|
|
122
126
|
);
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "../../../protocol/request/messages";
|
|
27
27
|
import { sendClaudeMessagesRequest } from "../../../protocol/upstream/send-claude-messages";
|
|
28
28
|
import { endpointUrl } from "../../../protocol/codecs";
|
|
29
|
+
import { assertCredentialKind, assertWireFamily } from "../../provider-contracts";
|
|
29
30
|
import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext } from "../../provider-contracts";
|
|
30
31
|
import {
|
|
31
32
|
getKimiCommonHeaders,
|
|
@@ -141,24 +142,16 @@ class KimiCodeAdapter implements ProviderAdapter {
|
|
|
141
142
|
context: ProviderDispatchContext,
|
|
142
143
|
): AsyncIterable<CanonicalEvent> {
|
|
143
144
|
if (candidate.wire_family !== "messages") {
|
|
144
|
-
|
|
145
|
-
"capability_unsupported",
|
|
146
|
-
400,
|
|
147
|
-
`kimi supports messages only, got ${candidate.wire_family}`,
|
|
148
|
-
);
|
|
145
|
+
assertWireFamily(candidate, "messages", "kimi");
|
|
149
146
|
}
|
|
150
147
|
if (context.credential.credential_kind !== "oauth") {
|
|
151
|
-
|
|
152
|
-
"invalid_request",
|
|
153
|
-
400,
|
|
154
|
-
`kimi: OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
155
|
-
);
|
|
148
|
+
assertCredentialKind(context.credential, "oauth", "kimi");
|
|
156
149
|
}
|
|
157
150
|
if (!context.credential.secret) {
|
|
158
151
|
throw new GatewayError(
|
|
159
152
|
"authentication_failed",
|
|
160
153
|
401,
|
|
161
|
-
"kimi: OAuth credential secret is required",
|
|
154
|
+
"kimi: OAuth credential secret is required (request {requestId}). Wrong key, right door — check the credential 🔑",
|
|
162
155
|
);
|
|
163
156
|
}
|
|
164
157
|
const credential = parseKimiCredential(
|
|
@@ -344,7 +344,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
344
344
|
? new TextDecoder().decode(context.credential.secret).trim()
|
|
345
345
|
: "";
|
|
346
346
|
if (secret.length === 0) {
|
|
347
|
-
throw new GatewayError("authentication_failed", 401, "Missing Kiro credential", {
|
|
347
|
+
throw new GatewayError("authentication_failed", 401, "Missing Kiro credential (request {requestId}). Wrong key, right door — check the credential 🔑", {
|
|
348
348
|
providerId: KIRO_PROVIDER_ID,
|
|
349
349
|
});
|
|
350
350
|
}
|
|
@@ -381,7 +381,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
381
381
|
throw new GatewayError(
|
|
382
382
|
"invalid_request",
|
|
383
383
|
400,
|
|
384
|
-
"Kiro cannot accept this conversation",
|
|
384
|
+
"Kiro cannot accept this conversation (request {requestId}). Check the shape of what you sent — then resend 🪞",
|
|
385
385
|
{ providerId: KIRO_PROVIDER_ID, problems: built.error.problems },
|
|
386
386
|
);
|
|
387
387
|
}
|
|
@@ -398,7 +398,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
398
398
|
machineId,
|
|
399
399
|
);
|
|
400
400
|
if (!response.body) {
|
|
401
|
-
throw new GatewayError("platform_unavailable", 502, "Kiro returned an empty body", {
|
|
401
|
+
throw new GatewayError("platform_unavailable", 502, "Kiro returned an empty body (request {requestId}). The upstream came back empty-handed — retry 🌙", {
|
|
402
402
|
providerId: KIRO_PROVIDER_ID,
|
|
403
403
|
}, "upstream");
|
|
404
404
|
}
|
|
@@ -433,14 +433,14 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
433
433
|
});
|
|
434
434
|
} catch (error) {
|
|
435
435
|
if (error instanceof Error && error.name === "AbortError") {
|
|
436
|
-
throw new GatewayError("transport_closed", 499, "request was cancelled", {
|
|
436
|
+
throw new GatewayError("transport_closed", 499, "The request was cancelled (request {requestId}). Send it again whenever ready 🙃", {
|
|
437
437
|
providerId: KIRO_PROVIDER_ID,
|
|
438
438
|
});
|
|
439
439
|
}
|
|
440
440
|
throw new GatewayError(
|
|
441
441
|
"transport_unavailable",
|
|
442
442
|
502,
|
|
443
|
-
`Kiro transport failed: ${error instanceof Error ? error.message : String(error)}
|
|
443
|
+
`Kiro transport failed (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`,
|
|
444
444
|
{ providerId: KIRO_PROVIDER_ID },
|
|
445
445
|
"network",
|
|
446
446
|
);
|
|
@@ -484,7 +484,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
484
484
|
throw new GatewayError(
|
|
485
485
|
"platform_unavailable",
|
|
486
486
|
502,
|
|
487
|
-
"Kiro EventStream exceeded the buffer bound",
|
|
487
|
+
"Kiro EventStream exceeded the buffer bound (request {requestId}). The upstream sent more than we can hold — retry 🌙",
|
|
488
488
|
{ providerId: KIRO_PROVIDER_ID },
|
|
489
489
|
"upstream",
|
|
490
490
|
);
|
|
@@ -497,7 +497,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
497
497
|
throw new GatewayError(
|
|
498
498
|
"platform_unavailable",
|
|
499
499
|
502,
|
|
500
|
-
`Kiro EventStream is corrupt: ${decoded.failure.detail}
|
|
500
|
+
`Kiro EventStream is corrupt: ${decoded.failure.detail} (request {requestId}). The upstream sent something we can't read — retry 🌙`,
|
|
501
501
|
{ providerId: KIRO_PROVIDER_ID, reason: decoded.failure.reason },
|
|
502
502
|
"upstream",
|
|
503
503
|
);
|
|
@@ -506,7 +506,7 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
506
506
|
for (const message of decoded.messages) {
|
|
507
507
|
const outcome = decoder.decode(message);
|
|
508
508
|
if (outcome.failure !== undefined) {
|
|
509
|
-
throw new GatewayError("platform_unavailable", 502, outcome.failure.message
|
|
509
|
+
throw new GatewayError("platform_unavailable", 502, `${outcome.failure.message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {
|
|
510
510
|
providerId: KIRO_PROVIDER_ID,
|
|
511
511
|
}, "upstream");
|
|
512
512
|
}
|
|
@@ -578,14 +578,14 @@ class KiroAdapter implements ProviderAdapter {
|
|
|
578
578
|
await reader.cancel().catch(() => undefined);
|
|
579
579
|
if (error instanceof GatewayError) throw error;
|
|
580
580
|
if (error instanceof Error && error.name === "AbortError") {
|
|
581
|
-
throw new GatewayError("transport_closed", 499, "request was cancelled", {
|
|
581
|
+
throw new GatewayError("transport_closed", 499, "The request was cancelled (request {requestId}). Send it again whenever ready 🙃", {
|
|
582
582
|
providerId: KIRO_PROVIDER_ID,
|
|
583
583
|
});
|
|
584
584
|
}
|
|
585
585
|
throw new GatewayError(
|
|
586
586
|
"platform_unavailable",
|
|
587
587
|
502,
|
|
588
|
-
`Kiro stream failed: ${error instanceof Error ? error.message : String(error)}
|
|
588
|
+
`Kiro stream failed (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The upstream came back empty-handed — retry 🌙`,
|
|
589
589
|
{ providerId: KIRO_PROVIDER_ID },
|
|
590
590
|
"upstream",
|
|
591
591
|
);
|
|
@@ -22,6 +22,7 @@ import type { CanonicalRequest } from "../../../protocol/canonical-model";
|
|
|
22
22
|
import { GatewayError } from "../../../protocol/gateway-error";
|
|
23
23
|
import { decodeMuseCredential } from "../../../security/credential-codec";
|
|
24
24
|
import { OpenAICompatibleAdapter, withBearerAuthentication } from "../../adapters/compatible-adapter";
|
|
25
|
+
import { assertCredentialKind } from "../../provider-contracts";
|
|
25
26
|
import type { ProviderDispatchTarget, ProviderDispatchContext, ResolvedCredential } from "../../provider-contracts";
|
|
26
27
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
27
28
|
|
|
@@ -85,19 +86,19 @@ export function parseMuseCodeCredential(
|
|
|
85
86
|
// as before the extraction.
|
|
86
87
|
const message = error instanceof Error ? error.message : "";
|
|
87
88
|
if (message.endsWith("must be a JSON object")) {
|
|
88
|
-
throw new GatewayError("invalid_request", 400, "muse: credential must be a JSON object");
|
|
89
|
+
throw new GatewayError("invalid_request", 400, "muse: credential must be a JSON object (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
89
90
|
}
|
|
90
91
|
if (message.endsWith("is not a valid JSON blob")) {
|
|
91
92
|
throw new GatewayError(
|
|
92
93
|
"invalid_request",
|
|
93
94
|
400,
|
|
94
|
-
"muse: credential is not a valid JSON blob; sign in again",
|
|
95
|
+
"muse: credential is not a valid JSON blob (request {requestId}); sign in again. Wrong key, right door — check the credential 🔑",
|
|
95
96
|
);
|
|
96
97
|
}
|
|
97
98
|
throw new GatewayError(
|
|
98
99
|
"authentication_failed",
|
|
99
100
|
401,
|
|
100
|
-
"muse: credential is missing oauthAccessToken or apiKey; sign in again",
|
|
101
|
+
"muse: credential is missing oauthAccessToken or apiKey (request {requestId}); sign in again. Wrong key, right door — check the credential 🔑",
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
}
|
|
@@ -137,17 +138,13 @@ class MuseCodeAdapter extends OpenAICompatibleAdapter {
|
|
|
137
138
|
candidate: ProviderDispatchTarget,
|
|
138
139
|
): Promise<Record<string, string>> {
|
|
139
140
|
if (context.credential.credential_kind !== "oauth") {
|
|
140
|
-
|
|
141
|
-
"invalid_request",
|
|
142
|
-
400,
|
|
143
|
-
`muse: OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
144
|
-
);
|
|
141
|
+
assertCredentialKind(context.credential, "oauth", "muse");
|
|
145
142
|
}
|
|
146
143
|
if (!context.credential.secret) {
|
|
147
144
|
throw new GatewayError(
|
|
148
145
|
"authentication_failed",
|
|
149
146
|
401,
|
|
150
|
-
"muse: OAuth credential secret is required",
|
|
147
|
+
"muse: OAuth credential secret is required (request {requestId}). Wrong key, right door — check the credential 🔑",
|
|
151
148
|
);
|
|
152
149
|
}
|
|
153
150
|
const { apiKey } = decodeMuseCredential(context.credential.secret);
|
|
@@ -5,6 +5,7 @@ import { providerBaseUrl } from "../../provider-metadata";
|
|
|
5
5
|
import type { DiscoveryInput } from "../../discovery/discovery-types";
|
|
6
6
|
import { defineModel } from "../../provider-model-definition";
|
|
7
7
|
import { openrouterFreeRoster } from "../../discovery/openrouter-free-roster";
|
|
8
|
+
import { clineReasoningReplayPrepares } from "../buddy/buddy-chat-shared";
|
|
8
9
|
|
|
9
10
|
const OPENROUTER_PROVIDER_ID = "openrouter" as const;
|
|
10
11
|
|
|
@@ -112,6 +113,9 @@ export const OPENROUTER_SPEC: ApiKeyProviderSpec = {
|
|
|
112
113
|
provider_id: OPENROUTER_PROVIDER_ID,
|
|
113
114
|
endpoint_paths_by_wire_family: {},
|
|
114
115
|
extra_headers: OPENROUTER_REQUIRED_HEADERS,
|
|
116
|
+
prePayload: (payload) => {
|
|
117
|
+
for (const prepare of clineReasoningReplayPrepares) prepare(payload);
|
|
118
|
+
},
|
|
115
119
|
};
|
|
116
120
|
|
|
117
121
|
export async function discoverOpenrouterModels(
|