cartethyia 2.7.3 → 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/dist/dashboard/assets/{BannedPage-2TJD37Hb.js → BannedPage-ChG5svFb.js} +1 -1
- package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-xefJNRmJ.js → CliToolDetailPage-BIcWQun7.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.js → CliToolsPage-Bf2VelDe.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
- package/dist/dashboard/assets/{CombosPage-JEbYJFxw.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-DzSWzE_j.js +1 -0
- package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-C4w7vea-.js → LoginPage-U6AKaJcF.js} +1 -1
- package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BtPcAfot.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-BQS0Rx_u.js → SetupPage-f0DE1h0-.js} +1 -1
- package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
- package/dist/dashboard/assets/{SortableList-BAL5npBC.js → SortableList-ClzpwyET.js} +1 -1
- package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-TP7voAQ0.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/assert-DbRA8EG2.js +15 -0
- package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
- package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-D9CS6dZk.js} +1 -1
- package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DMrMPmth.js → banner-DympBNq4.js} +1 -1
- package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
- package/dist/dashboard/assets/{card-Be5Uzamx.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-DOfrVmsi.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-C9omdjQt.js → dialog-8fiE6tec.js} +1 -1
- package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bm8WKaGY.js → drawer-CqGYeOrd.js} +1 -1
- package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
- package/dist/dashboard/assets/{entry-q5HwZ8nN.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/{formatters-BTScrQpe.js → formatters-D-MTJxMr.js} +1 -1
- package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-CPK47xQx.js} +1 -1
- package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
- package/dist/dashboard/assets/{index-cPrX5vn6.js → index-DBNPOfhV.js} +2 -2
- package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-BT0zntEr.js} +1 -1
- package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
- package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-Da2ZViWg.js} +1 -1
- package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
- package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-BXNeLw6M.js} +1 -1
- package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
- package/dist/dashboard/assets/{list-row-CzFvogbj.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-JJGQm8TD.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-BNDZnsUE.js → numbers-CEagj6ZZ.js} +2 -2
- package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
- package/dist/dashboard/assets/{query-keys-CLaNz8Xz.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-B3iTetHN.js → select-BIYIBkMU.js} +2 -2
- package/dist/dashboard/assets/select-BIYIBkMU.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-KrOrm7JZ.js → stack-DfgnFDWY.js} +1 -1
- package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
- package/dist/dashboard/assets/{state-DLS7IDMy.js → state-CkfdYWel.js} +1 -1
- package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
- package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-SYm237HG.js} +1 -1
- package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.js → useMutation-BQqCRNIi.js} +1 -1
- package/dist/dashboard/assets/useMutation-BQqCRNIi.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 +55 -54
- package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +9 -10
- 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/0027_qoder_identity_genuine_seed.sql +9 -10
- 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/contracts.ts +52 -0
- package/src/console/api-keys/routes.ts +93 -4
- 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 +6 -6
- package/src/console/backup/routes.ts +3 -3
- 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/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +2 -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 +26 -1
- package/src/console/quota/account-test-egress.ts +4 -4
- 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 +12 -12
- package/src/console/share/share-stats.ts +105 -35
- package/src/console/shared/read-through-cache.ts +38 -2
- package/src/console/updates/routes.ts +7 -4
- 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 +320 -16
- package/src/observability/telemetry-status.ts +1 -1
- package/src/persistence/db-sqlite.ts +7 -2
- package/src/persistence/readiness.ts +18 -6
- package/src/persistence/schema.ts +66 -7
- package/src/persistence/stores/api-key-store.ts +99 -3
- package/src/persistence/stores/telemetry-store.ts +1 -1
- 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/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 +13 -24
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
- 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 +16 -16
- package/src/providers/integrations/buddy/codebuddy/provider.ts +1 -1
- package/src/providers/integrations/buddy/workbuddy/provider.ts +1 -1
- 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 +1 -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 +6 -6
- package/src/providers/integrations/grok/grok.ts +2 -6
- package/src/providers/integrations/inferhub.ts +4 -11
- 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/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +47 -9
- package/src/providers/integrations/qoder/qoder-checkin.ts +26 -8
- package/src/providers/integrations/qoder/qoder-native-identity-store.ts +9 -8
- package/src/providers/integrations/qoder/qoder-realm.ts +15 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +12 -13
- package/src/providers/integrations/qoder/qoder-virtual.ts +2 -2
- package/src/providers/integrations/qoder/qoder.ts +188 -22
- 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/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 +47 -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/admission/reasons.ts +17 -17
- package/src/security/api-key-auth.ts +4 -4
- 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 +7 -7
- 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/systemone.ts +8 -8
- package/src/transport/dispatch/token-count.ts +9 -9
- 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 +20 -20
- package/src/transport/request/state.ts +4 -7
- package/src/transport/routing/route-catalog.ts +97 -2
- package/src/transport/routing/route-model.ts +7 -7
- package/src/transport/routing/router.ts +2 -2
- 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/dist/dashboard/assets/BannedPage-2TJD37Hb.js.gz +0 -0
- package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
- package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js +0 -1
- package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +0 -1
- package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +0 -1
- package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
- package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
- package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +0 -1
- package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +0 -4
- package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js +0 -1
- package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +0 -9
- package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js +0 -1
- package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js +0 -1
- package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
- package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
- package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
- package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js +0 -56
- package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js +0 -1
- package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
- package/dist/dashboard/assets/app-B2vyPoII.css +0 -2
- package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
- package/dist/dashboard/assets/assert-C0YYuZJ4.js +0 -1
- package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
- package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
- package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
- package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
- package/dist/dashboard/assets/cli-tools-muFRphDu.js +0 -1
- package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
- package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
- package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
- package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
- package/dist/dashboard/assets/entry-DS90gUks.js +0 -1
- package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
- package/dist/dashboard/assets/entry-j40LJotO.js +0 -4
- package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
- package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
- package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
- package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
- package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
- package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
- package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
- package/dist/dashboard/assets/layout-C_7A6H55.js.gz +0 -0
- package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
- package/dist/dashboard/assets/live-KaG15HLQ.js +0 -1
- package/dist/dashboard/assets/live-KaG15HLQ.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-JJGQm8TD.js.gz +0 -0
- package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
- package/dist/dashboard/assets/query-keys-CLaNz8Xz.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-BEH32QOC.js +0 -1
- package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
- package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js +0 -1
- package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
- package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
- package/dist/dashboard/assets/state-DLS7IDMy.js.gz +0 -0
- package/dist/dashboard/assets/switch-42ItvbAs.js.gz +0 -0
- package/dist/dashboard/assets/useMutation-Dmnfh1Ue.js.gz +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js → app-BayTTy01.js} +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js.gz → app-BayTTy01.js.gz} +0 -0
|
@@ -304,7 +304,7 @@ export class ProviderProbingService {
|
|
|
304
304
|
throw new GatewayError(
|
|
305
305
|
"capability_unsupported",
|
|
306
306
|
400,
|
|
307
|
-
`Provider ${providerId} has no web search transport
|
|
307
|
+
`Provider ${providerId} has no web search transport (request {requestId}). Know your tools — this one just isn't in the box 🧰`,
|
|
308
308
|
);
|
|
309
309
|
}
|
|
310
310
|
const searchProbeQuery = request.prompt?.trim() || "Cartethyia gateway probe";
|
|
@@ -325,14 +325,14 @@ export class ProviderProbingService {
|
|
|
325
325
|
snippet: hit.snippet,
|
|
326
326
|
}));
|
|
327
327
|
if (!response.results || response.results.length === 0) {
|
|
328
|
-
dispatchError = new GatewayError("platform_unavailable", 502, "web search returned no results");
|
|
328
|
+
dispatchError = new GatewayError("platform_unavailable", 502, "web search returned no results (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
329
329
|
}
|
|
330
330
|
} else if (serviceKind === "systemone") {
|
|
331
331
|
if (typeof adapter.systemone !== "function") {
|
|
332
332
|
throw new GatewayError(
|
|
333
333
|
"capability_unsupported",
|
|
334
334
|
400,
|
|
335
|
-
`Provider ${providerId} has no System One transport
|
|
335
|
+
`Provider ${providerId} has no System One transport (request {requestId}). Know your tools — this one just isn't in the box 🧰`,
|
|
336
336
|
);
|
|
337
337
|
}
|
|
338
338
|
const response = await adapter.systemone(
|
|
@@ -360,14 +360,14 @@ export class ProviderProbingService {
|
|
|
360
360
|
dispatchError = new GatewayError(
|
|
361
361
|
response.status >= 500 ? "platform_unavailable" : "invalid_request",
|
|
362
362
|
response.status,
|
|
363
|
-
`System One upstream error: ${raw.slice(0, 240)}`,
|
|
363
|
+
`System One upstream error (request {requestId}): ${raw.slice(0, 240)}`,
|
|
364
364
|
);
|
|
365
365
|
} else {
|
|
366
366
|
let parsed: unknown;
|
|
367
367
|
try {
|
|
368
368
|
parsed = raw ? JSON.parse(raw) : null;
|
|
369
369
|
} catch {
|
|
370
|
-
dispatchError = new GatewayError("platform_unavailable", 502, "System One returned invalid JSON");
|
|
370
|
+
dispatchError = new GatewayError("platform_unavailable", 502, "System One returned invalid JSON (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
371
371
|
}
|
|
372
372
|
if (parsed !== null && parsed !== undefined) {
|
|
373
373
|
const answers =
|
|
@@ -381,7 +381,7 @@ export class ProviderProbingService {
|
|
|
381
381
|
dispatchError = new GatewayError(
|
|
382
382
|
"platform_unavailable",
|
|
383
383
|
502,
|
|
384
|
-
"System One returned no answers",
|
|
384
|
+
"System One returned no answers (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
385
385
|
);
|
|
386
386
|
}
|
|
387
387
|
}
|
|
@@ -709,7 +709,7 @@ export class ProviderProbingService {
|
|
|
709
709
|
throw new GatewayError(
|
|
710
710
|
"transport_unavailable",
|
|
711
711
|
502,
|
|
712
|
-
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"}
|
|
712
|
+
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"} (request {requestId}). The connection ghosted us — come back in a moment 👻`,
|
|
713
713
|
{},
|
|
714
714
|
"upstream",
|
|
715
715
|
);
|
|
@@ -718,7 +718,7 @@ export class ProviderProbingService {
|
|
|
718
718
|
throw new GatewayError(
|
|
719
719
|
"transport_unavailable",
|
|
720
720
|
502,
|
|
721
|
-
`Model discovery failed for ${providerId}: endpoint returned no usable models
|
|
721
|
+
`Model discovery failed for ${providerId}: endpoint returned no usable models (request {requestId}). The upstream came back empty-handed — retry 🌙`,
|
|
722
722
|
{},
|
|
723
723
|
"upstream",
|
|
724
724
|
);
|
|
@@ -764,7 +764,7 @@ export class ProviderProbingService {
|
|
|
764
764
|
throw new GatewayError(
|
|
765
765
|
"transport_unavailable",
|
|
766
766
|
502,
|
|
767
|
-
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"}
|
|
767
|
+
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"} (request {requestId}). The connection ghosted us — come back in a moment 👻`,
|
|
768
768
|
{},
|
|
769
769
|
"upstream",
|
|
770
770
|
);
|
|
@@ -799,7 +799,7 @@ export class ProviderProbingService {
|
|
|
799
799
|
throw new GatewayError(
|
|
800
800
|
"invalid_request",
|
|
801
801
|
400,
|
|
802
|
-
`Add an account for ${providerId} first — model listing needs a credential
|
|
802
|
+
`Add an account for ${providerId} first — model listing needs a credential (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
803
803
|
{},
|
|
804
804
|
"cartethyia",
|
|
805
805
|
);
|
|
@@ -811,7 +811,7 @@ export class ProviderProbingService {
|
|
|
811
811
|
throw new GatewayError(
|
|
812
812
|
"invalid_request",
|
|
813
813
|
400,
|
|
814
|
-
`Add an account for ${providerId} before fetching its models
|
|
814
|
+
`Add an account for ${providerId} before fetching its models (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
815
815
|
{},
|
|
816
816
|
"cartethyia",
|
|
817
817
|
);
|
|
@@ -821,7 +821,7 @@ export class ProviderProbingService {
|
|
|
821
821
|
throw new GatewayError(
|
|
822
822
|
"capability_unsupported",
|
|
823
823
|
400,
|
|
824
|
-
`${providerId} publishes no model-listing endpoint. Its catalog ships with Cartethyia; new models appear with an update
|
|
824
|
+
`${providerId} publishes no model-listing endpoint (request {requestId}). Its catalog ships with Cartethyia; new models appear with an update. Know your tools — this one just isn't in the box 🧰`,
|
|
825
825
|
{},
|
|
826
826
|
"cartethyia",
|
|
827
827
|
);
|
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
// `x-stainless-*` family, `x-claude-code-session-id`, and `anthropic-version`
|
|
12
12
|
// for operator-supplied headers, so they are layered onto the built headers
|
|
13
13
|
// at this call site instead.
|
|
14
|
-
import { GatewayError } from "../../../protocol/gateway-error";
|
|
15
14
|
import type { CanonicalEvent, CanonicalRequest } from "../../../protocol/canonical-model";
|
|
16
|
-
import { readCredentialSecret, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext } from "../../provider-contracts";
|
|
15
|
+
import { readCredentialSecret, assertWireFamily, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext } from "../../provider-contracts";
|
|
17
16
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
18
17
|
import { buildClaudeMessagesRequest } from "../shared/claude-messages";
|
|
19
18
|
import { sendClaudeMessagesRequest } from "../../../protocol/upstream/send-claude-messages";
|
|
@@ -87,7 +86,7 @@ class AgentRouterAdapter implements ProviderAdapter {
|
|
|
87
86
|
context: ProviderDispatchContext,
|
|
88
87
|
): AsyncIterable<CanonicalEvent> {
|
|
89
88
|
if (candidate.wire_family !== "messages") {
|
|
90
|
-
|
|
89
|
+
assertWireFamily(candidate, "messages", "agentrouter");
|
|
91
90
|
}
|
|
92
91
|
const apiKey = readCredentialSecret(context.credential, "AgentRouter API key is required");
|
|
93
92
|
|
|
@@ -61,7 +61,7 @@ function alibabaSpec(envelope: AlibabaCodingPlanEnvelope): ApiKeyProviderSpec {
|
|
|
61
61
|
function alibabaEnvelope(context: ProviderDispatchContext): AlibabaCodingPlanEnvelope {
|
|
62
62
|
const secret = context.credential.secret;
|
|
63
63
|
if (secret === undefined || secret.length === 0) {
|
|
64
|
-
throw new GatewayError("invalid_request", 400, "alibabacp: credential is missing a secret value");
|
|
64
|
+
throw new GatewayError("invalid_request", 400, "alibabacp: credential is missing a secret value (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
65
65
|
}
|
|
66
66
|
let envelope: AlibabaCodingPlanEnvelope;
|
|
67
67
|
try {
|
|
@@ -70,7 +70,7 @@ function alibabaEnvelope(context: ProviderDispatchContext): AlibabaCodingPlanEnv
|
|
|
70
70
|
throw new GatewayError(
|
|
71
71
|
"invalid_request",
|
|
72
72
|
400,
|
|
73
|
-
`alibabacp: ${error instanceof Error ? error.message : "stored credential is not an Alibaba envelope"}
|
|
73
|
+
`alibabacp: ${error instanceof Error ? error.message : "stored credential is not an Alibaba envelope"} (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
return envelope;
|
|
@@ -18,6 +18,7 @@ import { GatewayError } from "../../protocol/gateway-error";
|
|
|
18
18
|
import { buildClaudeMessagesRequest, filterClaudeCustomHeaders } from "./shared/claude-messages";
|
|
19
19
|
import { sendClaudeMessagesRequest } from "../../protocol/upstream/send-claude-messages";
|
|
20
20
|
import { applyParamQuirks } from "../../protocol/translation/quirks";
|
|
21
|
+
import { assertCredentialKind, assertWireFamily } from "../provider-contracts";
|
|
21
22
|
import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext, ProviderId } from "../provider-contracts";
|
|
22
23
|
import { providerBaseUrl } from "../provider-metadata";
|
|
23
24
|
|
|
@@ -58,18 +59,10 @@ export class AnthropicApiKeyAdapter implements ProviderAdapter {
|
|
|
58
59
|
context: ProviderDispatchContext,
|
|
59
60
|
): AsyncIterable<CanonicalEvent> {
|
|
60
61
|
if (candidate.wire_family !== "messages") {
|
|
61
|
-
|
|
62
|
-
"capability_unsupported",
|
|
63
|
-
400,
|
|
64
|
-
`${this.provider_id} supports messages only`,
|
|
65
|
-
);
|
|
62
|
+
assertWireFamily(candidate, "messages", this.provider_id);
|
|
66
63
|
}
|
|
67
64
|
if (context.credential.credential_kind !== "api_key") {
|
|
68
|
-
|
|
69
|
-
"invalid_request",
|
|
70
|
-
400,
|
|
71
|
-
`${this.provider_id}: x-api-key credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
72
|
-
);
|
|
65
|
+
assertCredentialKind(context.credential, "api_key", this.provider_id);
|
|
73
66
|
}
|
|
74
67
|
if (
|
|
75
68
|
context.credential.secret === undefined ||
|
|
@@ -78,7 +71,7 @@ export class AnthropicApiKeyAdapter implements ProviderAdapter {
|
|
|
78
71
|
throw new GatewayError(
|
|
79
72
|
"invalid_request",
|
|
80
73
|
400,
|
|
81
|
-
`${this.provider_id}: API key is missing a secret value
|
|
74
|
+
`${this.provider_id}: API key is missing a secret value (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
82
75
|
);
|
|
83
76
|
}
|
|
84
77
|
const apiKey = new TextDecoder().decode(context.credential.secret);
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
loadAntigravityProject,
|
|
47
47
|
normalizeAntigravityToolSchemas,
|
|
48
48
|
} from "./antigravity-protocol";
|
|
49
|
+
import { assertCredentialKind, assertWireFamily } from "../../provider-contracts";
|
|
49
50
|
import type { ImageGenerationOutcome, ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext, WebSearchOutcome, WebSearchResult } from "../../provider-contracts";
|
|
50
51
|
import { providerBaseUrl } from "../../provider-metadata";
|
|
51
52
|
import { abortGatewayError, createUpstreamDeadlineLifecycle } from "../../operations/upstream-deadline";
|
|
@@ -188,18 +189,10 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
188
189
|
candidate.wire_family !== "responses" &&
|
|
189
190
|
candidate.wire_family !== "messages"
|
|
190
191
|
) {
|
|
191
|
-
|
|
192
|
-
"capability_unsupported",
|
|
193
|
-
400,
|
|
194
|
-
`antigravity supports chat/responses/messages, got ${candidate.wire_family}`,
|
|
195
|
-
);
|
|
192
|
+
assertWireFamily(candidate, ["chat", "responses", "messages"], "antigravity");
|
|
196
193
|
}
|
|
197
194
|
if (context.credential.credential_kind !== "oauth") {
|
|
198
|
-
|
|
199
|
-
"invalid_request",
|
|
200
|
-
400,
|
|
201
|
-
`antigravity: Google OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
202
|
-
);
|
|
195
|
+
assertCredentialKind(context.credential, "oauth", "antigravity");
|
|
203
196
|
}
|
|
204
197
|
const accessToken = context.credential.secret
|
|
205
198
|
? new TextDecoder().decode(context.credential.secret).trim()
|
|
@@ -208,7 +201,7 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
208
201
|
throw new GatewayError(
|
|
209
202
|
"authentication_failed",
|
|
210
203
|
401,
|
|
211
|
-
"antigravity: OAuth access token is required",
|
|
204
|
+
"antigravity: OAuth access token is required (request {requestId}). Wrong key, right door — check the credential 🔑",
|
|
212
205
|
);
|
|
213
206
|
}
|
|
214
207
|
|
|
@@ -360,7 +353,7 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
360
353
|
throw new GatewayError(
|
|
361
354
|
"platform_unavailable",
|
|
362
355
|
502,
|
|
363
|
-
"antigravity returned empty stream",
|
|
356
|
+
"antigravity returned empty stream (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
364
357
|
{},
|
|
365
358
|
"upstream",
|
|
366
359
|
);
|
|
@@ -508,7 +501,7 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
508
501
|
context: ProviderDispatchContext,
|
|
509
502
|
): Promise<WebSearchOutcome> {
|
|
510
503
|
const query = typeof body.query === "string" ? body.query.trim() : "";
|
|
511
|
-
if (!query) throw new GatewayError("invalid_request", 400, "search query is required");
|
|
504
|
+
if (!query) throw new GatewayError("invalid_request", 400, "search query is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
512
505
|
const rawMax = body.max_results;
|
|
513
506
|
const maxResults =
|
|
514
507
|
typeof rawMax === "number" && Number.isFinite(rawMax)
|
|
@@ -531,7 +524,7 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
531
524
|
}
|
|
532
525
|
const results = normalizeAntigravityGrounding(grounded, maxResults);
|
|
533
526
|
if (results.length === 0)
|
|
534
|
-
throw new GatewayError("platform_unavailable", 502, "Antigravity search returned no grounded results");
|
|
527
|
+
throw new GatewayError("platform_unavailable", 502, "Antigravity search returned no grounded results (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
535
528
|
return { results, total_results: results.length };
|
|
536
529
|
}
|
|
537
530
|
|
|
@@ -541,21 +534,17 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
541
534
|
context: ProviderDispatchContext,
|
|
542
535
|
): Promise<ImageGenerationOutcome> {
|
|
543
536
|
if (context.credential.credential_kind !== "oauth") {
|
|
544
|
-
|
|
545
|
-
"invalid_request",
|
|
546
|
-
400,
|
|
547
|
-
`antigravity: Google OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
548
|
-
);
|
|
537
|
+
assertCredentialKind(context.credential, "oauth", "antigravity");
|
|
549
538
|
}
|
|
550
539
|
const accessToken = context.credential.secret
|
|
551
540
|
? new TextDecoder().decode(context.credential.secret).trim()
|
|
552
541
|
: "";
|
|
553
542
|
if (!accessToken) {
|
|
554
|
-
throw new GatewayError("authentication_failed", 401, "antigravity: OAuth access token is required");
|
|
543
|
+
throw new GatewayError("authentication_failed", 401, "antigravity: OAuth access token is required (request {requestId}). Wrong key, right door — check the credential 🔑");
|
|
555
544
|
}
|
|
556
545
|
const prompt = imagePrompt(body);
|
|
557
546
|
const model = candidate.model_id.length > 0 ? candidate.model_id : typeof body.model === "string" ? body.model : "";
|
|
558
|
-
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required");
|
|
547
|
+
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
559
548
|
const outboundFetch: typeof fetch = (context.outbound_fetch as unknown as typeof fetch) ?? this.fetchFn;
|
|
560
549
|
const projectId = await loadAntigravityProject(accessToken, {
|
|
561
550
|
baseUrl: this.baseUrl,
|
|
@@ -624,7 +613,7 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
624
613
|
throw new GatewayError(
|
|
625
614
|
"platform_unavailable",
|
|
626
615
|
502,
|
|
627
|
-
`Antigravity image generation unreachable: ${error instanceof Error ? error.message : String(error)}
|
|
616
|
+
`Antigravity image generation unreachable (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`,
|
|
628
617
|
{},
|
|
629
618
|
"upstream",
|
|
630
619
|
);
|
|
@@ -646,12 +635,12 @@ class AntigravityAdapter implements ProviderAdapter {
|
|
|
646
635
|
try {
|
|
647
636
|
parsed = JSON.parse(event.data);
|
|
648
637
|
} catch {
|
|
649
|
-
throw new GatewayError("platform_unavailable", 502, "Antigravity image stream returned malformed JSON", {}, "upstream");
|
|
638
|
+
throw new GatewayError("platform_unavailable", 502, "Antigravity image stream returned malformed JSON (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
650
639
|
}
|
|
651
640
|
images.push(...geminiInlineImages(parsed));
|
|
652
641
|
}
|
|
653
642
|
if (images.length === 0) {
|
|
654
|
-
throw new GatewayError("platform_unavailable", 502, "Antigravity image generation returned no image", {}, "upstream");
|
|
643
|
+
throw new GatewayError("platform_unavailable", 502, "Antigravity image generation returned no image (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
655
644
|
}
|
|
656
645
|
return { created: imageCreatedSeconds(), data: images };
|
|
657
646
|
}
|
|
@@ -273,7 +273,7 @@ export function makeBuddyModel(
|
|
|
273
273
|
endpoint?: string,
|
|
274
274
|
realm: "intl" | "cn" = "intl",
|
|
275
275
|
): ModelDefinition {
|
|
276
|
-
if (!entry[0]) throw new GatewayError("invalid_request", 400, "invalid model");
|
|
276
|
+
if (!entry[0]) throw new GatewayError("invalid_request", 400, "invalid model (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
277
277
|
const image = BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]);
|
|
278
278
|
const efforts = (realm === "cn" ? BUDDY_CN_EFFORTS : BUDDY_INTL_EFFORTS)[entry[0].toLowerCase()];
|
|
279
279
|
// Refused on free is only a question for the intl realm. cbcn serves every
|
|
@@ -100,12 +100,43 @@ export async function fetchBuddyDirectoryModels(args: {
|
|
|
100
100
|
readonly fetcher?: typeof fetch | undefined;
|
|
101
101
|
}): Promise<readonly ModelDefinition[] | null> {
|
|
102
102
|
const fetcher = args.fetcher ?? globalThis.fetch;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
|
|
103
|
+
// Fetch both catalog scopes and merge them. `/v3/config` is ranked higher and
|
|
104
|
+
// is the primary source (matches the reference gateways), but the personal
|
|
105
|
+
// models path carries models the v3 response does not always publish — so a
|
|
106
|
+
// single-source read can silently miss models that are callable. Merging with
|
|
107
|
+
// dedupe by model id gives the union, mirroring the upstream codebuddy2api
|
|
108
|
+
// catalog aggregation. Each failure falls through to the other source, so a
|
|
109
|
+
// host that answers only one behaves exactly as it does today.
|
|
110
|
+
const v3 = await fetchBuddyDirectoryOnce(args, fetcher, BUDDY_CONFIG_PATH);
|
|
111
|
+
const personal = await fetchBuddyDirectoryOnce(args, fetcher, args.modelsPath);
|
|
112
|
+
if (v3 !== null && personal !== null) return mergeBuddyDirectories(v3, personal);
|
|
113
|
+
return v3 ?? personal;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Merges two buddy directory reads into one roster, preserving each source's
|
|
118
|
+
* declaration order and de-duplicating by model id. `primary` wins when both
|
|
119
|
+
* sources declare the same id; models present only in `supplemental` are
|
|
120
|
+
* appended. Both lists are already filtered (disabled/CLI-roster/not-chat),
|
|
121
|
+
* so the merge only has to combine them.
|
|
122
|
+
*/
|
|
123
|
+
function mergeBuddyDirectories(
|
|
124
|
+
primary: readonly ModelDefinition[],
|
|
125
|
+
supplemental: readonly ModelDefinition[],
|
|
126
|
+
): readonly ModelDefinition[] {
|
|
127
|
+
const seen = new Set<string>();
|
|
128
|
+
const merged: ModelDefinition[] = [];
|
|
129
|
+
for (const model of primary) {
|
|
130
|
+
if (seen.has(model.modelId)) continue;
|
|
131
|
+
seen.add(model.modelId);
|
|
132
|
+
merged.push(model);
|
|
133
|
+
}
|
|
134
|
+
for (const model of supplemental) {
|
|
135
|
+
if (seen.has(model.modelId)) continue;
|
|
136
|
+
seen.add(model.modelId);
|
|
137
|
+
merged.push(model);
|
|
138
|
+
}
|
|
139
|
+
return merged;
|
|
109
140
|
}
|
|
110
141
|
|
|
111
142
|
/** Reads one directory path; `null` on any transport, status, or shape miss. */
|
|
@@ -108,10 +108,17 @@ export function buddyEnterprise(context?: ProviderDispatchContext): string | und
|
|
|
108
108
|
*
|
|
109
109
|
* Resolution order:
|
|
110
110
|
* 1. `auth_state.qimei36` — explicit operator-set binding (imported or edited).
|
|
111
|
-
* 2.
|
|
111
|
+
* 2. Derived deterministically from the internal account id (sha256 → 32 hex).
|
|
112
112
|
* This keeps the binding stable across restarts without a database write,
|
|
113
113
|
* and gives each freshly-added account its own id automatically.
|
|
114
114
|
*
|
|
115
|
+
* IMPORTANT — the derived fallback is **not portable across instances**:
|
|
116
|
+
* export/import mints a NEW account id, so the derived binding changes and the
|
|
117
|
+
* upstream channel check (11128) rejects the re-imported account. The export
|
|
118
|
+
* path therefore materializes the raw result of this resolver into
|
|
119
|
+
* `auth_state.qimei36` whenever an account relies on the derivation, so a
|
|
120
|
+
* re-import carries the exact same device identity.
|
|
121
|
+
*
|
|
115
122
|
* Returns `undefined` only when no account id is available (unauthenticated).
|
|
116
123
|
*/
|
|
117
124
|
export function resolveBuddyDeviceBinding(context?: ProviderDispatchContext): string | undefined {
|
|
@@ -121,3 +128,17 @@ export function resolveBuddyDeviceBinding(context?: ProviderDispatchContext): st
|
|
|
121
128
|
if (accountId === undefined || accountId.length === 0) return undefined;
|
|
122
129
|
return createHash("sha256").update(`wb2a:qimei36:${accountId}`).digest("hex").slice(0, 32);
|
|
123
130
|
}
|
|
131
|
+
|
|
132
|
+
/** Materializes the portable binding for an account into a stored auth-state
|
|
133
|
+
* map, when the account does not already pin one explicitly. Used by the
|
|
134
|
+
* export path so a re-import keeps the exact qimei36 device identity. */
|
|
135
|
+
export function materializeBuddyDeviceBinding(
|
|
136
|
+
accountId: string,
|
|
137
|
+
authState: Readonly<Record<string, unknown>> | undefined,
|
|
138
|
+
): Record<string, unknown> | undefined {
|
|
139
|
+
const existing = authState?.["qimei36"];
|
|
140
|
+
if (typeof existing === "string" && existing.trim().length > 0) return undefined;
|
|
141
|
+
if (accountId.length === 0) return undefined;
|
|
142
|
+
const derived = createHash("sha256").update(`wb2a:qimei36:${accountId}`).digest("hex").slice(0, 32);
|
|
143
|
+
return { ...(authState ?? {}), qimei36: derived };
|
|
144
|
+
}
|
|
@@ -108,7 +108,7 @@ export async function buddyGenerateImage(
|
|
|
108
108
|
context: ProviderDispatchContext,
|
|
109
109
|
): Promise<ImageGenerationOutcome> {
|
|
110
110
|
const model = modelOf(body, candidate);
|
|
111
|
-
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required");
|
|
111
|
+
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
112
112
|
const prompt = imagePrompt(body);
|
|
113
113
|
if (config.imageGenerationPath !== undefined) {
|
|
114
114
|
const requestBody: Record<string, unknown> = { model, prompt };
|
|
@@ -134,28 +134,28 @@ export async function buddyGenerateImage(
|
|
|
134
134
|
release();
|
|
135
135
|
}
|
|
136
136
|
if (!isRecord(responseBody)) {
|
|
137
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned an invalid response", {}, "upstream");
|
|
137
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned an invalid response (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
138
138
|
}
|
|
139
139
|
const providerError = buddyErrorOf(responseBody);
|
|
140
140
|
if (providerError !== undefined) {
|
|
141
|
-
throw new GatewayError("platform_unavailable", 502, providerError
|
|
141
|
+
throw new GatewayError("platform_unavailable", 502, `${providerError} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
142
142
|
}
|
|
143
143
|
if (responseBody.code !== undefined && responseBody.code !== 0 && responseBody.code !== "0") {
|
|
144
144
|
const message =
|
|
145
145
|
typeof responseBody.msg === "string" && responseBody.msg.trim().length > 0
|
|
146
146
|
? responseBody.msg.trim()
|
|
147
147
|
: `CodeBuddy image generation failed with code ${String(responseBody.code)}`;
|
|
148
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
148
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
149
149
|
}
|
|
150
150
|
if (!isRecord(responseBody.data)) {
|
|
151
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no image data", {}, "upstream");
|
|
151
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no image data (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
152
152
|
}
|
|
153
153
|
const result = responseBody.data;
|
|
154
154
|
if (!Array.isArray(result.data) || result.data.some((image) => !isRecord(image))) {
|
|
155
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned malformed image data", {}, "upstream");
|
|
155
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned malformed image data (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
156
156
|
}
|
|
157
157
|
if (result.data.length === 0) {
|
|
158
|
-
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no images", {}, "upstream");
|
|
158
|
+
throw new GatewayError("platform_unavailable", 502, "CodeBuddy image generation returned no images (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
|
|
159
159
|
}
|
|
160
160
|
return {
|
|
161
161
|
...(typeof result.created === "number" ? { created: result.created } : {}),
|
|
@@ -217,7 +217,7 @@ export async function buddyGenerateImage(
|
|
|
217
217
|
if (!contentType.includes("text/event-stream")) {
|
|
218
218
|
const parsed: unknown = await response.json().catch(() => null);
|
|
219
219
|
const message = buddyErrorOf(parsed) ?? "CodeBuddy image generation returned a non-stream body";
|
|
220
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
220
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
221
221
|
}
|
|
222
222
|
let content = "";
|
|
223
223
|
for await (const event of decodeSseEvents(response.body, { signal: context.abort_signal })) {
|
|
@@ -232,7 +232,7 @@ export async function buddyGenerateImage(
|
|
|
232
232
|
if (!isRecord(parsed)) continue;
|
|
233
233
|
if (isRecord(parsed.error)) {
|
|
234
234
|
const message = isRecord(parsed.error) && typeof parsed.error.message === "string" ? parsed.error.message : "CodeBuddy image generation failed";
|
|
235
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
235
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
236
236
|
}
|
|
237
237
|
const choices = parsed.choices;
|
|
238
238
|
if (!Array.isArray(choices) || !isRecord(choices[0])) continue;
|
|
@@ -244,7 +244,7 @@ export async function buddyGenerateImage(
|
|
|
244
244
|
throw new GatewayError(
|
|
245
245
|
"platform_unavailable",
|
|
246
246
|
502,
|
|
247
|
-
"CodeBuddy image generation returned no image in the chat stream",
|
|
247
|
+
"CodeBuddy image generation returned no image in the chat stream (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
248
248
|
{},
|
|
249
249
|
"upstream",
|
|
250
250
|
);
|
|
@@ -318,7 +318,7 @@ export async function buddyGenerateVideo(
|
|
|
318
318
|
context: ProviderDispatchContext,
|
|
319
319
|
): Promise<Record<string, unknown>> {
|
|
320
320
|
const model = modelOf(body, candidate);
|
|
321
|
-
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required");
|
|
321
|
+
if (model.length === 0) throw new GatewayError("invalid_request", 400, "model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
322
322
|
const prompt = imagePrompt(body);
|
|
323
323
|
const submitBody: Record<string, unknown> = { model, prompt };
|
|
324
324
|
if (typeof body.n === "number" && Number.isFinite(body.n)) submitBody["n"] = Math.max(1, Math.floor(body.n));
|
|
@@ -354,14 +354,14 @@ export async function buddyGenerateVideo(
|
|
|
354
354
|
if (url !== undefined) return { data: [{ url }] };
|
|
355
355
|
// Otherwise cb refused (HTTP 200 error envelope) — surface its own reason.
|
|
356
356
|
const message = buddyErrorOf(submitted) ?? "CodeBuddy video submit returned no task id";
|
|
357
|
-
throw new GatewayError("platform_unavailable", 502, message
|
|
357
|
+
throw new GatewayError("platform_unavailable", 502, `${message} (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
358
358
|
}
|
|
359
359
|
// Poll the sibling task endpoint until the clip is ready.
|
|
360
360
|
const taskPath = `${submitUrl.replace(/\/+$/, "")}/${taskId}`;
|
|
361
361
|
const deadline = Date.now() + VIDEO_POLL_TIMEOUT_MS;
|
|
362
362
|
for (;;) {
|
|
363
363
|
if (context.abort_signal?.aborted) {
|
|
364
|
-
throw new GatewayError("transport_closed", 499, "video generation aborted");
|
|
364
|
+
throw new GatewayError("transport_closed", 499, "video generation aborted (request {requestId}). Send it again whenever ready 🙃");
|
|
365
365
|
}
|
|
366
366
|
const lifecycle = createUpstreamDeadlineLifecycle(context);
|
|
367
367
|
let statusRes: Response;
|
|
@@ -374,7 +374,7 @@ export async function buddyGenerateVideo(
|
|
|
374
374
|
} catch (error: unknown) {
|
|
375
375
|
const abortError = abortGatewayError(lifecycle, error, context.abort_signal);
|
|
376
376
|
if (abortError) throw abortError;
|
|
377
|
-
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video status unreachable: ${error instanceof Error ? error.message : String(error)}
|
|
377
|
+
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video status unreachable (request {requestId}): ${error instanceof Error ? error.message : String(error)}. The connection ghosted us — come back in a moment 👻`, {}, "upstream");
|
|
378
378
|
} finally {
|
|
379
379
|
lifecycle.release();
|
|
380
380
|
}
|
|
@@ -386,10 +386,10 @@ export async function buddyGenerateVideo(
|
|
|
386
386
|
if (url !== undefined) return { data: [{ url }], task_id: taskId };
|
|
387
387
|
const status = videoStatusOf(payload);
|
|
388
388
|
if (status !== undefined && !VIDEO_PENDING.has(status)) {
|
|
389
|
-
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video task ended in state "${status}" with no clip
|
|
389
|
+
throw new GatewayError("platform_unavailable", 502, `CodeBuddy video task ended in state "${status}" with no clip (request {requestId}). The upstream came back empty-handed — retry 🌙`, {}, "upstream");
|
|
390
390
|
}
|
|
391
391
|
if (Date.now() > deadline) {
|
|
392
|
-
throw new GatewayError("platform_unavailable", 504, `CodeBuddy video task ${taskId} did not finish within ${VIDEO_POLL_TIMEOUT_MS}ms
|
|
392
|
+
throw new GatewayError("platform_unavailable", 504, `CodeBuddy video task ${taskId} did not finish within ${VIDEO_POLL_TIMEOUT_MS}ms (request {requestId}). Some things just take longer 🐢`, {}, "upstream");
|
|
393
393
|
}
|
|
394
394
|
await new Promise((resolve) => setTimeout(resolve, VIDEO_POLL_INTERVAL_MS));
|
|
395
395
|
}
|
|
@@ -81,7 +81,7 @@ function codeBuddyIntlPrePayload(
|
|
|
81
81
|
typeof rawModel === "string" && rawModel.length > 0
|
|
82
82
|
? rawModel
|
|
83
83
|
: candidate.model_id;
|
|
84
|
-
if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required");
|
|
84
|
+
if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
85
85
|
const messages = payload["messages"];
|
|
86
86
|
if (Array.isArray(messages)) {
|
|
87
87
|
applyBuddySystemPrompt(
|
|
@@ -134,7 +134,7 @@ export function workbuddyPrePayload(
|
|
|
134
134
|
const rawModel = payload["model"];
|
|
135
135
|
const source =
|
|
136
136
|
typeof rawModel === "string" && rawModel.length > 0 ? rawModel : candidate.model_id;
|
|
137
|
-
if (!source) throw new GatewayError("invalid_request", 400, "WorkBuddy model is required");
|
|
137
|
+
if (!source) throw new GatewayError("invalid_request", 400, "WorkBuddy model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
138
138
|
const messages = payload["messages"];
|
|
139
139
|
if (Array.isArray(messages)) {
|
|
140
140
|
const normalizedMessages = messages as Array<Record<string, unknown>>;
|
|
@@ -67,7 +67,7 @@ export const ANTHROPIC_BETA_CAPABILITIES: Readonly<Record<string, readonly strin
|
|
|
67
67
|
const BETA_TOKEN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
68
68
|
|
|
69
69
|
function invalidBeta(message: string, value: unknown): GatewayError {
|
|
70
|
-
return new GatewayError("invalid_request", 400, message
|
|
70
|
+
return new GatewayError("invalid_request", 400, `${message} (request {requestId}). Check the shape of what you sent — then resend 🪞`, { field: "anthropic-beta", value });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/**
|
|
@@ -10,7 +10,7 @@ function invalidHeader(
|
|
|
10
10
|
message: string,
|
|
11
11
|
details: Readonly<Record<string, unknown>> = {},
|
|
12
12
|
): GatewayError {
|
|
13
|
-
return new GatewayError("invalid_request", 400, message
|
|
13
|
+
return new GatewayError("invalid_request", 400, `${message} (request {requestId}). Check the shape of what you sent — then resend 🪞`, details);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function decodeSecret(secret: Uint8Array | undefined): string | undefined {
|
|
@@ -96,5 +96,5 @@ export function planSlowLaneRetry(
|
|
|
96
96
|
|
|
97
97
|
/** Typed error for a caller-aborted wait, so it is never read as a failure. */
|
|
98
98
|
export function slowLaneAborted(): GatewayError {
|
|
99
|
-
return new GatewayError("transport_closed", 499, "
|
|
99
|
+
return new GatewayError("transport_closed", 499, "The request was cancelled during the slow-lane capacity wait (request {requestId}). Send it again whenever ready 🙃");
|
|
100
100
|
}
|
|
@@ -61,6 +61,7 @@ import {
|
|
|
61
61
|
refusalCreditToken,
|
|
62
62
|
sharedFallbackCreditCache,
|
|
63
63
|
} from "./fallback-credit";
|
|
64
|
+
import { assertCredentialKind, assertWireFamily } from "../../provider-contracts";
|
|
64
65
|
import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext } from "../../provider-contracts";
|
|
65
66
|
import { defineModel } from "../../provider-model-definition";
|
|
66
67
|
import type { ModelDefinition } from "../../provider-model-definition";
|
|
@@ -185,21 +186,13 @@ export class ClaudeAdapter implements ProviderAdapter {
|
|
|
185
186
|
context: ProviderDispatchContext,
|
|
186
187
|
): AsyncIterable<CanonicalEvent> {
|
|
187
188
|
if (candidate.wire_family !== "messages") {
|
|
188
|
-
|
|
189
|
-
"capability_unsupported",
|
|
190
|
-
400,
|
|
191
|
-
"claude supports messages only",
|
|
192
|
-
);
|
|
189
|
+
assertWireFamily(candidate, "messages", "claude");
|
|
193
190
|
}
|
|
194
191
|
if (
|
|
195
192
|
context.credential.credential_kind !== "oauth" &&
|
|
196
193
|
context.credential.credential_kind !== "scoped_access_token"
|
|
197
194
|
) {
|
|
198
|
-
|
|
199
|
-
"invalid_request",
|
|
200
|
-
400,
|
|
201
|
-
`claude: the assistant OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
|
|
202
|
-
);
|
|
195
|
+
assertCredentialKind(context.credential, ["oauth", "scoped_access_token"], "claude");
|
|
203
196
|
}
|
|
204
197
|
const customHeaders = filterClaudeCustomHeaders({
|
|
205
198
|
...this.customHeaders,
|
|
@@ -150,7 +150,7 @@ function clinePrePayload(
|
|
|
150
150
|
const cur = typeof payload["max_tokens"] === "number" ? (payload["max_tokens"] as number) : 0;
|
|
151
151
|
payload["max_tokens"] = Math.max(cur, 256);
|
|
152
152
|
// keep GatewayError reachable
|
|
153
|
-
if (!model) throw new GatewayError("invalid_request", 400, "Cline model is required");
|
|
153
|
+
if (!model) throw new GatewayError("invalid_request", 400, "Cline model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|