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
|
@@ -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({
|
|
@@ -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);
|
|
@@ -69,11 +69,11 @@ export function createPerplexityAdapter(fetchImpl?: typeof fetch): ProviderAdapt
|
|
|
69
69
|
void _candidate;
|
|
70
70
|
const query = extractSearchQuery(request);
|
|
71
71
|
if (!query) {
|
|
72
|
-
throw new GatewayError("invalid_request", 400, "Search query is required.");
|
|
72
|
+
throw new GatewayError("invalid_request", 400, "Search query is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
|
|
73
73
|
}
|
|
74
74
|
const token = tokenFromContext(context);
|
|
75
75
|
if (!token) {
|
|
76
|
-
throw new GatewayError("authentication_failed", 401, "Missing Perplexity API key");
|
|
76
|
+
throw new GatewayError("authentication_failed", 401, "Missing Perplexity API key (request {requestId}). Wrong key, right door — check the key 🔑");
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
const fetchFn = (context.outbound_fetch as unknown as typeof fetch | undefined) ?? fetchImpl ?? globalThis.fetch;
|
|
@@ -133,13 +133,15 @@ export const QODER_INTL_MODEL_CONFIGS: Readonly<Record<string, QoderModelConfig>
|
|
|
133
133
|
qfmodel: { id: "qfmodel", display_name: "Qwen3.8-Flash", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_free: true, is_reasoning: true },
|
|
134
134
|
qmodel_latest: { id: "qmodel_latest", display_name: "Qwen3.7-Max", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_reasoning: false },
|
|
135
135
|
qmodel: { id: "qmodel", display_name: "Qwen3.7-Plus", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_reasoning: false },
|
|
136
|
-
kmodel_latest: { id: "kmodel_latest", display_name: "Kimi-K3", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_free: false, is_reasoning: false },
|
|
136
|
+
kmodel_latest: { id: "kmodel_latest", display_name: "Kimi-K3.1-Pro", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_free: false, is_reasoning: false },
|
|
137
137
|
kmodel: { id: "kmodel", display_name: "Kimi-K2.8-Preview", max_input_tokens: 1000000, max_output_tokens: 65_536, is_vl: true, is_free: false, is_reasoning: false },
|
|
138
138
|
gmodel: { id: "gmodel", display_name: "GLM-5.3", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_free: false, is_reasoning: true },
|
|
139
139
|
gfmodel: { id: "gfmodel", display_name: "GLM-5.3-Flash", max_input_tokens: 1000000, max_output_tokens: 131_072, is_vl: true, is_reasoning: true },
|
|
140
140
|
dmodel: { id: "dmodel", display_name: "DeepSeek-V4-Pro", max_input_tokens: 1000000, max_output_tokens: 384_000, is_vl: true, is_free: false, is_reasoning: true },
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
// Live roster (2026-11-01) reports dfmodel as billed (is_free false); it was
|
|
142
|
+
// previously marked free. Display names are corrected from the same capture.
|
|
143
|
+
dfmodel: { id: "dfmodel", display_name: "DeepSeek-Flash", max_input_tokens: 1000000, max_output_tokens: 384_000, is_vl: true, is_free: false, is_reasoning: true },
|
|
144
|
+
mmodel: { id: "mmodel", display_name: "MiniMax-M3.1-Flash", max_input_tokens: 1000000, max_output_tokens: 512_000, is_vl: true, is_free: false, is_reasoning: false },
|
|
143
145
|
};
|
|
144
146
|
|
|
145
147
|
/**
|
|
@@ -353,6 +355,14 @@ interface CachedRoster {
|
|
|
353
355
|
/** Per-realm live-list cache; keyed by realm, not by account. */
|
|
354
356
|
const discoveryCache = new Map<QoderRealm, CachedRoster>();
|
|
355
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Per-realm max-context window per roster key, taken from the live list's
|
|
360
|
+
* `context_config` (the widest selectable window). This is what dispatch reads
|
|
361
|
+
* to send `model_config.max_input_tokens`; without it the request would use the
|
|
362
|
+
* static roster's *currently active* window (often 180k) instead of the max.
|
|
363
|
+
*/
|
|
364
|
+
const discoveryMaxContextByKey = new Map<QoderRealm, Map<string, number>>();
|
|
365
|
+
|
|
356
366
|
/**
|
|
357
367
|
* Drops one realm's cached list.
|
|
358
368
|
*
|
|
@@ -361,8 +371,21 @@ const discoveryCache = new Map<QoderRealm, CachedRoster>();
|
|
|
361
371
|
* previous assertion left behind.
|
|
362
372
|
*/
|
|
363
373
|
export function resetQoderDiscoveryCache(realm?: QoderRealm): void {
|
|
364
|
-
if (realm === undefined)
|
|
365
|
-
|
|
374
|
+
if (realm === undefined) {
|
|
375
|
+
discoveryCache.clear();
|
|
376
|
+
discoveryMaxContextByKey.clear();
|
|
377
|
+
} else {
|
|
378
|
+
discoveryCache.delete(realm);
|
|
379
|
+
discoveryMaxContextByKey.delete(realm);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* The widest selectable context window per roster key for one realm, from the
|
|
385
|
+
* live model list. Empty when discovery has not succeeded for that realm yet.
|
|
386
|
+
*/
|
|
387
|
+
export function qoderDiscoveredMaxContexts(realm: QoderRealm): ReadonlyMap<string, number> {
|
|
388
|
+
return discoveryMaxContextByKey.get(realm) ?? new Map();
|
|
366
389
|
}
|
|
367
390
|
|
|
368
391
|
export async function discoverQoderModels(input: {
|
|
@@ -389,7 +412,7 @@ export async function discoverQoderModels(input: {
|
|
|
389
412
|
throw new GatewayError(
|
|
390
413
|
"authentication_failed",
|
|
391
414
|
401,
|
|
392
|
-
"Qoder model discovery requires an account credential.",
|
|
415
|
+
"Qoder model discovery requires an account credential (request {requestId}). Wrong key, right door — check the credential 🔑",
|
|
393
416
|
{ providerId, realm: input.realm },
|
|
394
417
|
);
|
|
395
418
|
}
|
|
@@ -398,7 +421,7 @@ export async function discoverQoderModels(input: {
|
|
|
398
421
|
throw new GatewayError(
|
|
399
422
|
"invalid_request",
|
|
400
423
|
400,
|
|
401
|
-
"Qoder model discovery requires a validated outbound fetch",
|
|
424
|
+
"Qoder model discovery requires a validated outbound fetch (request {requestId}). No bridge to cross — configure a pool first 🏗️",
|
|
402
425
|
{ providerId, realm: input.realm },
|
|
403
426
|
);
|
|
404
427
|
}
|
|
@@ -409,6 +432,11 @@ export async function discoverQoderModels(input: {
|
|
|
409
432
|
const url = `${host}${QODER_MODELS_PATH}`;
|
|
410
433
|
try {
|
|
411
434
|
const headers = await input.headers(url, signedBody);
|
|
435
|
+
// GET, not POST: upstream refuses POST on the model-list surface (400
|
|
436
|
+
// "Request method 'POST' not supported"). The signature covers the body,
|
|
437
|
+
// so the body must accompany the GET. The gateway's validated egress
|
|
438
|
+
// dials GET+body through the Node http(s) client (the runtime fetch
|
|
439
|
+
// rejects GET bodies), which is exactly the shape the donor client sends.
|
|
412
440
|
const response = await fetcher(url, {
|
|
413
441
|
method: "GET",
|
|
414
442
|
headers: headers as unknown as HeadersInit,
|
|
@@ -430,9 +458,19 @@ export async function discoverQoderModels(input: {
|
|
|
430
458
|
continue;
|
|
431
459
|
}
|
|
432
460
|
const models = enabled.map((entry) => qoderCatalogModel(entry, providerId));
|
|
461
|
+
// Index the widest selectable window per key (from `context_config`,
|
|
462
|
+
// already computed into `maxInputTokens` by `mapQoderCatalogResponse`) so
|
|
463
|
+
// dispatch can send the maximum rather than the currently active one.
|
|
464
|
+
const maxCtx = new Map<string, number>();
|
|
465
|
+
for (const entry of enabled) {
|
|
466
|
+
if (entry.maxInputTokens !== undefined && entry.key.length > 0) {
|
|
467
|
+
maxCtx.set(entry.key, entry.maxInputTokens);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
433
470
|
// Cached only after a host actually answered: a failure must stay
|
|
434
471
|
// retryable on the next call rather than being frozen for five minutes.
|
|
435
472
|
discoveryCache.set(input.realm, { at: Date.now(), models });
|
|
473
|
+
discoveryMaxContextByKey.set(input.realm, maxCtx);
|
|
436
474
|
return models;
|
|
437
475
|
} catch (error) {
|
|
438
476
|
lastError = error;
|
|
@@ -441,9 +479,9 @@ export async function discoverQoderModels(input: {
|
|
|
441
479
|
throw new GatewayError(
|
|
442
480
|
"transport_unavailable",
|
|
443
481
|
502,
|
|
444
|
-
`Qoder model discovery failed for ${input.realm}: ${
|
|
482
|
+
`Qoder model discovery failed for ${input.realm} (request {requestId}): ${
|
|
445
483
|
lastError instanceof Error ? lastError.message : "unknown error"
|
|
446
|
-
}
|
|
484
|
+
}. The connection ghosted us — come back in a moment 👻`,
|
|
447
485
|
{ providerId, realm: input.realm },
|
|
448
486
|
"upstream",
|
|
449
487
|
);
|
|
@@ -175,15 +175,18 @@ async function tryClaimDaily(
|
|
|
175
175
|
if (campaigns === null) {
|
|
176
176
|
return { state: "error", amount: 0, error: "Campaign list unavailable." };
|
|
177
177
|
}
|
|
178
|
-
|
|
178
|
+
// Claim a `CLAIMABLE` CREDITS-kind campaign. Promo rows (`VIEW_DETAILS`,
|
|
179
|
+
// no benefit) are not credit grants and must not be claimed — claiming one
|
|
180
|
+
// spends the account's daily slot for nothing and makes the sweep report a
|
|
181
|
+
// misleading `claimed` with 0 credits.
|
|
182
|
+
const claimable = campaigns.filter((c) => {
|
|
183
|
+
if (String(c["claim_status"] ?? "").toUpperCase() !== "CLAIMABLE") return false;
|
|
184
|
+
const kind = String(asRecord(c["benefit"])?.["kind"] ?? "").toUpperCase();
|
|
185
|
+
const action = String(c["action_type"] ?? "").toUpperCase();
|
|
186
|
+
return kind === "CREDITS" || action === "CLAIM_BENEFIT";
|
|
187
|
+
});
|
|
188
|
+
for (const campaign of claimable) {
|
|
179
189
|
const benefit = asRecord(campaign["benefit"]);
|
|
180
|
-
const kind = String(benefit?.["kind"] ?? "").toUpperCase();
|
|
181
|
-
if (kind !== "CREDITS" && kind !== "") continue;
|
|
182
|
-
const actionType = String(campaign["action_type"] ?? "");
|
|
183
|
-
if (actionType !== "" && actionType !== "CLAIM_BENEFIT") continue;
|
|
184
|
-
const claimStatus = String(campaign["claim_status"] ?? "").toUpperCase();
|
|
185
|
-
if (claimStatus === "CLAIMED") return { state: "already_claimed", amount: 0, error: null };
|
|
186
|
-
if (claimStatus !== "CLAIMABLE") continue;
|
|
187
190
|
const campaignId = String(campaign["campaign_id"] ?? "");
|
|
188
191
|
if (!campaignId) continue;
|
|
189
192
|
const claim = await claimWithHeaders(base, campaignId, headers, fetcher);
|
|
@@ -195,6 +198,18 @@ async function tryClaimDaily(
|
|
|
195
198
|
if (claim.state === "not_eligible") return { state: "not_eligible", amount: 0, error: null };
|
|
196
199
|
return { state: "error", amount: 0, error: "Campaign claim failed." };
|
|
197
200
|
}
|
|
201
|
+
// Nothing claimable. Only a CREDITS-kind campaign that is `CLAIMED` proves
|
|
202
|
+
// today's credit was already taken; a claimed promo (`VIEW_DETAILS`, no
|
|
203
|
+
// benefit) says nothing about the daily grant, so it must not be reported
|
|
204
|
+
// as already_claimed. When the CREDITS campaign is absent entirely, the
|
|
205
|
+
// daily grant is simply not present (or hidden) for this account.
|
|
206
|
+
const anyCreditsClaimed = campaigns.some((c) => {
|
|
207
|
+
if (String(c["claim_status"] ?? "").toUpperCase() !== "CLAIMED") return false;
|
|
208
|
+
const kind = String(asRecord(c["benefit"])?.["kind"] ?? "").toUpperCase();
|
|
209
|
+
const action = String(c["action_type"] ?? "").toUpperCase();
|
|
210
|
+
return kind === "CREDITS" || action === "CLAIM_BENEFIT";
|
|
211
|
+
});
|
|
212
|
+
if (anyCreditsClaimed) return { state: "already_claimed", amount: 0, error: null };
|
|
198
213
|
return { state: "unavailable", amount: 0, error: "No daily CREDITS campaign claimable." };
|
|
199
214
|
}
|
|
200
215
|
|
|
@@ -224,6 +239,9 @@ async function probeDailyClaim(
|
|
|
224
239
|
): Promise<{ result: { state: DailyCheckinState; amount: number; error: string | null }; identity: QoderNativeIdentity | null }> {
|
|
225
240
|
const basic = await tryClaimDaily(base, campaignHeaders(credential), fetcher);
|
|
226
241
|
if (basic.state === "claimed" || basic.state === "already_claimed") {
|
|
242
|
+
// `tryClaimDaily` only claims CREDITS-kind campaigns, so a `claimed` or
|
|
243
|
+
// `already_claimed` basic result is already about the daily credit grant —
|
|
244
|
+
// terminal, no identity probe needed.
|
|
227
245
|
return { result: basic, identity: null };
|
|
228
246
|
}
|
|
229
247
|
if (basic.state === "unavailable") {
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
* Persistence for the Qoder native machine identity (UMID) bound to an
|
|
3
3
|
* account.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Same-account probes found that daily 100-credit grant visibility does not
|
|
6
|
+
* depend on machine headers. This store preserves native identities and seeds
|
|
7
|
+
* for deterministic replay and other surfaces that may use device identity.
|
|
8
|
+
* A native identity is a deterministic function of a seed file
|
|
9
|
+
* (`~/.config/.locale_cfg`). The bound record lives in
|
|
10
|
+
* `provider_accounts.native_identity` (plain JSON, not a secret).
|
|
10
11
|
*
|
|
11
12
|
* Uniqueness of the device is enforced by the partial unique index on the
|
|
12
|
-
* extracted `machineToken`; this store keeps the JS side of that
|
|
13
|
-
* and surfaces the DB constraint as the backstop.
|
|
13
|
+
* extracted `machineToken`; this store keeps the JS side of that internal
|
|
14
|
+
* identity-allocation invariant and surfaces the DB constraint as the backstop.
|
|
14
15
|
*/
|
|
15
16
|
import { and, eq, isNotNull, ne } from "drizzle-orm";
|
|
16
17
|
import type { CartethyiaDatabase } from "../../../persistence/db-handle";
|
|
@@ -30,7 +31,7 @@ export interface QoderNativeIdentityStore {
|
|
|
30
31
|
get(providerId: string, accountId: string): Promise<NativeIdentityRecord | undefined>;
|
|
31
32
|
/**
|
|
32
33
|
* Machine tokens already bound to **other** accounts, so a caller can mint
|
|
33
|
-
* a fresh
|
|
34
|
+
* a fresh identity without colliding. A bound token represents a device identity, and
|
|
34
35
|
* the unique index that backs this spans all `provider_accounts` rows. The
|
|
35
36
|
* account's own bound token is not "occupied" — reusing one's own device is
|
|
36
37
|
* the point.
|
|
@@ -39,6 +39,21 @@ export const QODER_CHAT_PATH =
|
|
|
39
39
|
"/algo/api/v2/service/pro/sse/agent_chat_generation?FetchKeys=llm_model_result&AgentId=agent_common&Encode=1";
|
|
40
40
|
export const QODER_MODELS_PATH = "/algo/api/v2/model/list?Encode=1";
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* The modern model-server surface used by the IDE / QoderWake (OpenAI-shaped
|
|
44
|
+
* chunks, plain bearer auth). This surface streams immediately — the legacy
|
|
45
|
+
* `/algo` chat endpoint answers `10605 isQueued` and parks requests in a
|
|
46
|
+
* server-side queue, so dispatch prefers this surface when it is available.
|
|
47
|
+
*/
|
|
48
|
+
export const QODER_IDE_CHAT_PATH = "/model/v1/chat/completions";
|
|
49
|
+
|
|
50
|
+
/** The model-server host for one realm (intl: `api2-v2`, cn: gateway). */
|
|
51
|
+
export function qoderIdeChatUrl(realm: QoderRealm): string {
|
|
52
|
+
return realm === "cn"
|
|
53
|
+
? `https://gateway.qoder.com.cn${QODER_IDE_CHAT_PATH}`
|
|
54
|
+
: `https://api2-v2.qoder.sh${QODER_IDE_CHAT_PATH}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
/**
|
|
43
58
|
* Realm → deployment.
|
|
44
59
|
*
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Qoder native machine identity (UMID) — the genuine SG bridge via umidpack.
|
|
3
3
|
*
|
|
4
|
-
* Research record (2026-10-30):
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `vendor/qoder-umid/umidpack/`, auto-picked per host OS.
|
|
4
|
+
* Research record (2026-10-30): same-account controls found that the daily
|
|
5
|
+
* CREDITS campaign does not gate grants on machine identity. This module
|
|
6
|
+
* prefers the vendor bridge for stable native identity and seed replay, with
|
|
7
|
+
* a deterministic generated fallback when no bridge is available.
|
|
9
8
|
*
|
|
10
9
|
* Seed semantics (verified live): the Linux ELF resolves the user home via
|
|
11
10
|
* the passwd entry — it ignores `$HOME`/`XDG_CONFIG_HOME`, so the seed file
|
|
@@ -18,15 +17,14 @@
|
|
|
18
17
|
*
|
|
19
18
|
* Platform behavior:
|
|
20
19
|
* win32 — the exe is hardware-bound: one identity per machine, no seed.
|
|
21
|
-
* Still a genuine SG identity (accepted by the campaign surface).
|
|
22
20
|
* linux — direct spawn of the umidpack ELF, serialized seed file.
|
|
23
21
|
* darwin — the Mach-O runs directly; seed path is the macOS user home.
|
|
24
22
|
* win32 + WSL (this repo's primary deployment) — the ELF runs via WSL with
|
|
25
23
|
* flock serialization; the bridge binary is staged into /tmp once.
|
|
26
24
|
*
|
|
27
|
-
* The generated path remains a fallback for hosts with no usable bridge
|
|
28
|
-
* produces well-shaped but
|
|
29
|
-
*
|
|
25
|
+
* The generated path remains a fallback for hosts with no usable bridge. It
|
|
26
|
+
* produces deterministic, well-shaped tokens but is not an SG identity. Live
|
|
27
|
+
* controls showed that machine identity does not gate daily CREDITS grants.
|
|
30
28
|
*
|
|
31
29
|
* Bridge CLI (donor-verified):
|
|
32
30
|
* linux : runtime-info <env>
|
|
@@ -155,15 +153,16 @@ function seedPath(): string {
|
|
|
155
153
|
}
|
|
156
154
|
|
|
157
155
|
/**
|
|
158
|
-
* Mints a fresh
|
|
156
|
+
* Mints a fresh native identity: wipe the seed (under the lock), run the
|
|
159
157
|
* bridge, capture the identity AND the seed it wrote. The seed is required
|
|
160
|
-
* for later replay of this same identity. Returns `null` when the
|
|
161
|
-
* fails; falls back to the generated identity only when no bridge
|
|
158
|
+
* for later replay of this same native identity. Returns `null` when the
|
|
159
|
+
* bridge fails; falls back to the generated identity only when no bridge
|
|
160
|
+
* exists.
|
|
162
161
|
*/
|
|
163
162
|
export function mintQoderNativeIdentity(accountId: string): { identity: QoderNativeIdentity; seed: string } | null {
|
|
164
163
|
const bridge = pickBridge();
|
|
165
164
|
if (!bridge) {
|
|
166
|
-
log.warn("[qoder] no
|
|
165
|
+
log.warn("[qoder] no native bridge for this host — using generated identity fallback");
|
|
167
166
|
return { identity: mintQoderGeneratedIdentity(accountId), seed: "" };
|
|
168
167
|
}
|
|
169
168
|
|
|
@@ -37,11 +37,11 @@ export const QODER_VIRTUAL_MODELS: readonly QoderVirtualModel[] = [
|
|
|
37
37
|
{ id: "qwen3.8-flash", target: "qfmodel", displayName: "Qwen3.8-Flash" },
|
|
38
38
|
{ id: "qwen3.7-max", target: "qmodel_latest", displayName: "Qwen3.7-Max" },
|
|
39
39
|
{ id: "qwen3.7-plus", target: "qmodel", displayName: "Qwen3.7-Plus" },
|
|
40
|
-
{ id: "kimi-k3", target: "kmodel_latest", displayName: "Kimi-K3" },
|
|
40
|
+
{ id: "kimi-k3", target: "kmodel_latest", displayName: "Kimi-K3.1-Pro" },
|
|
41
41
|
{ id: "kimi-k2.8-preview", target: "kmodel", displayName: "Kimi-K2.8-Preview" },
|
|
42
42
|
{ id: "glm-5.3", target: "gmodel", displayName: "GLM-5.3" },
|
|
43
43
|
{ id: "glm-5.3-flash", target: "gfmodel", displayName: "GLM-5.3-Flash" },
|
|
44
|
-
{ id: "minimax-m3", target: "mmodel", displayName: "MiniMax-M3" },
|
|
44
|
+
{ id: "minimax-m3", target: "mmodel", displayName: "MiniMax-M3.1-Flash" },
|
|
45
45
|
];
|
|
46
46
|
|
|
47
47
|
/** Virtual id → roster key. */
|