cartethyia 2.7.3 → 2.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -0
- package/README.md +17 -5
- package/dist/dashboard/assets/{BannedPage-2TJD37Hb.js → BannedPage-Cj15GsMp.js} +1 -1
- package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
- package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolDetailPage-xefJNRmJ.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
- package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
- package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.js → CliToolsPage-BIccZmeL.js} +1 -1
- package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
- package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
- package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js +1 -0
- package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
- package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
- package/dist/dashboard/assets/{LoginPage-C4w7vea-.js → LoginPage-DkXb6dx-.js} +1 -1
- package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
- package/dist/dashboard/assets/{ModelPicker-BtPcAfot.js → ModelPicker-DnQPSIA8.js} +1 -1
- package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
- package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
- package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
- package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
- package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js +9 -0
- package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
- package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
- package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
- package/dist/dashboard/assets/{SetupPage-BQS0Rx_u.js → SetupPage-WTa0sktC.js} +1 -1
- package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
- package/dist/dashboard/assets/{StudioPage-TP7voAQ0.js → StudioPage-BfAb5-o_.js} +3 -3
- package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
- package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
- package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
- package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
- package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
- package/dist/dashboard/assets/{assert-C0YYuZJ4.js → assert-C0K-c4eo.js} +1 -1
- package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
- package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-DfbhQU4k.js} +1 -1
- package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
- package/dist/dashboard/assets/{banner-DMrMPmth.js → banner-BllT4LcF.js} +1 -1
- package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
- package/dist/dashboard/assets/brand/login_register.jpg +0 -0
- package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
- package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
- package/dist/dashboard/assets/brand/og_image.jpg +0 -0
- package/dist/dashboard/assets/{card-Be5Uzamx.js → card-CtkX66Wd.js} +1 -1
- package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
- package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
- package/dist/dashboard/assets/{cli-tools-muFRphDu.js → cli-tools-CQXVMn4P.js} +1 -1
- package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
- package/dist/dashboard/assets/{clipboard-button-DOfrVmsi.js → clipboard-button-BQqBQd2n.js} +1 -1
- package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
- package/dist/dashboard/assets/{dialog-C9omdjQt.js → dialog-BEK7KP0H.js} +1 -1
- package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
- package/dist/dashboard/assets/{drawer-Bm8WKaGY.js → drawer-BrTEZ8zu.js} +1 -1
- package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
- package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
- package/dist/dashboard/assets/{entry-q5HwZ8nN.js → entry-EBHJ3DrE.js} +1 -1
- package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
- package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
- package/dist/dashboard/assets/{formatters-BTScrQpe.js → formatters-BAACA727.js} +1 -1
- package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
- package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-YSCE4UC2.js} +1 -1
- package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
- package/dist/dashboard/assets/{index-cPrX5vn6.js → index-FQlj0HUT.js} +2 -2
- package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
- package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-C4gU5iOL.js} +1 -1
- package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
- package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-BHHX_Tmm.js} +1 -1
- package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
- package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-CajrYUnD.js} +1 -1
- package/dist/dashboard/assets/{layout-C_7A6H55.js.gz → layout-CajrYUnD.js.gz} +0 -0
- package/dist/dashboard/assets/{list-row-CzFvogbj.js → list-row-Bx2I7XUe.js} +1 -1
- package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
- package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
- package/dist/dashboard/assets/live-DNNqRbj2.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-C5UBACrJ.js +1 -0
- package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
- package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
- package/dist/dashboard/assets/pagination-Xsi9Qx04.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-DvQbD_sr.js +1 -0
- package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
- package/dist/dashboard/assets/{routing-BEH32QOC.js → routing-in0f_IfK.js} +1 -1
- package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
- package/dist/dashboard/assets/{select-B3iTetHN.js → select-BLULNqTp.js} +2 -2
- package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
- package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
- package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
- package/dist/dashboard/assets/{stack-KrOrm7JZ.js → stack-D2lIR0tg.js} +1 -1
- package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
- package/dist/dashboard/assets/{state-DLS7IDMy.js → state-DTARjfiW.js} +1 -1
- package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
- package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-c0oPSnqW.js} +1 -1
- package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
- package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.js → useMutation-m8WGNPrz.js} +1 -1
- package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
- package/dist/dashboard/console-backgrounds.jpg +0 -0
- package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/dashboard/index.html.gz +0 -0
- package/dist/dashboard/precompressed-assets.json +59 -57
- 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/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
- package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
- package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
- package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
- package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
- package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -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/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
- package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
- package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
- package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
- package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
- package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
- package/package.json +4 -5
- package/scripts/cli/update.ts +15 -41
- package/src/boot/app.ts +67 -10
- package/src/boot/dependencies.ts +786 -732
- package/src/boot/lifecycle.ts +11 -12
- package/src/config/cooldowns.ts +34 -55
- package/src/config/network.ts +8 -4
- package/src/config/package-paths.ts +1 -1
- package/src/config/providers.ts +13 -14
- package/src/config/resources.ts +0 -5
- package/src/config/runtime.ts +2 -5
- package/src/config/spec.ts +26 -6
- package/src/console/api-keys/ban-constants.ts +38 -0
- package/src/console/api-keys/contracts.ts +92 -31
- package/src/console/api-keys/routes.ts +131 -6
- package/src/console/audit/routes.ts +3 -3
- package/src/console/auth/access.ts +4 -4
- package/src/console/auth/account-reset.ts +5 -5
- package/src/console/auth/audit-recorder.ts +1 -1
- package/src/console/auth/lockout.ts +7 -3
- package/src/console/auth/row-coercion.ts +57 -12
- package/src/console/auth/session-resolver.ts +1 -1
- package/src/console/auth/session-service.ts +8 -2
- package/src/console/auth/session.ts +40 -34
- package/src/console/auth/setup-service.ts +4 -3
- package/src/console/auth/user-store.ts +1 -1
- package/src/console/backup/9router-map.ts +0 -3
- package/src/console/backup/contracts.ts +11 -9
- package/src/console/backup/export-endpoint.ts +11 -12
- package/src/console/backup/nine-router.ts +1 -7
- package/src/console/backup/routes.ts +32 -36
- package/src/console/backup/service.ts +468 -468
- package/src/console/backup/store.ts +47 -29
- package/src/console/backup/validate.ts +11 -1
- package/src/console/cli-tools/contracts.ts +7 -7
- package/src/console/cli-tools/injectors/cline.ts +110 -110
- package/src/console/cli-tools/injectors/codex.ts +181 -181
- package/src/console/cli-tools/injectors/copilot.ts +108 -108
- package/src/console/cli-tools/injectors/driver.ts +247 -247
- package/src/console/cli-tools/injectors/jcode.ts +115 -115
- package/src/console/cli-tools/injectors/openclaw.ts +161 -161
- package/src/console/cli-tools/injectors/opencode.ts +153 -153
- package/src/console/cli-tools/routes.ts +4 -4
- package/src/console/cli-tools/service.ts +1 -1
- package/src/console/cli-tools/store.ts +2 -2
- package/src/console/console-router-guards.ts +2 -2
- package/src/console/console-router.ts +36 -4
- package/src/console/dashboard-assets.ts +9 -9
- package/src/console/data-management/routes.ts +3 -3
- package/src/console/domain-registration.ts +18 -4
- package/src/console/inferhub/client.ts +0 -7
- package/src/console/inferhub/key-store.ts +1 -1
- package/src/console/inferhub/normalize.ts +2 -2
- package/src/console/inferhub/routes.ts +1 -1
- package/src/console/inferhub/types.ts +1 -1
- package/src/console/observability/contracts.ts +5 -1
- package/src/console/observability/live.ts +34 -21
- package/src/console/observability/logs.ts +4 -4
- package/src/console/observability/performance.ts +3 -3
- package/src/console/observability/routes.ts +3 -3
- package/src/console/observability/sse.ts +62 -8
- package/src/console/observability/store.ts +36 -20
- package/src/console/providers/catalog/catalog-projections.ts +1 -1
- package/src/console/providers/catalog/contracts.ts +82 -22
- package/src/console/providers/catalog/model-operations.ts +1 -1
- package/src/console/providers/catalog/provider-operations.ts +110 -17
- package/src/console/providers/catalog/public-model-store.ts +0 -0
- package/src/console/providers/catalog/routes.ts +30 -6
- package/src/console/providers/catalog/store-helpers.ts +349 -326
- package/src/console/providers/catalog/store.ts +1662 -1292
- package/src/console/providers/detail/routes.ts +4 -4
- package/src/console/providers/oauth/callback-listener.ts +100 -18
- package/src/console/providers/oauth/routes.ts +95 -16
- package/src/console/quota/account-quota-global.ts +41 -3
- package/src/console/quota/account-quota-shared.ts +10 -3
- package/src/console/quota/account-quota-tenant.ts +285 -67
- package/src/console/quota/account-test-egress.ts +4 -4
- package/src/console/quota/daily-growth-job.ts +308 -0
- package/src/console/quota/native-identity.ts +2 -2
- package/src/console/quota/quota-view.ts +1 -1
- package/src/console/remote-support/routes.ts +1 -1
- package/src/console/remote-support/service.ts +2 -2
- package/src/console/routing/model/contracts.ts +1 -1
- package/src/console/routing/model/routes.ts +3 -3
- package/src/console/routing/pools/contracts.ts +13 -10
- package/src/console/routing/pools/import-parse.ts +3 -3
- 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 +12 -12
- package/src/console/routing/pools/routes.ts +3 -3
- package/src/console/routing/pools/store.ts +21 -1
- package/src/console/settings/contracts.ts +29 -2
- package/src/console/settings/routes.ts +3 -3
- package/src/console/settings/store.ts +20 -0
- package/src/console/share/share-router.ts +112 -44
- package/src/console/share/share-stats.ts +109 -39
- package/src/console/share/share-usage.ts +1 -1
- package/src/console/shared/errors.ts +2 -2
- package/src/console/shared/object.ts +18 -0
- package/src/console/shared/read-through-cache.ts +42 -6
- package/src/console/shared/transaction.ts +14 -0
- package/src/console/system-prompt/contracts.ts +89 -12
- package/src/console/system-prompt/routes.ts +98 -45
- package/src/console/updates/apply-update.ts +244 -0
- package/src/console/updates/routes.ts +256 -98
- package/src/main.ts +11 -5
- package/src/network/http2-bidi.ts +1 -1
- package/src/network/ip-utils.ts +298 -0
- package/src/network/outbound-fetch.ts +76 -5
- package/src/network/pool/agent.ts +7 -6
- package/src/network/pool/byte-accounting.ts +1 -1
- package/src/network/pool/resolver.ts +55 -51
- package/src/network/pool/selector.ts +150 -136
- package/src/network/pool-cooldown-store.ts +71 -16
- package/src/network/pool-health-machine.ts +22 -2
- package/src/network/rate-limit-verdict.ts +68 -0
- package/src/network/retry.ts +1 -1
- package/src/network/ssrf.ts +24 -75
- package/src/observability/event-log.ts +2 -2
- package/src/observability/event-query.ts +286 -214
- package/src/observability/log-sanitize.ts +1 -1
- package/src/observability/metrics.ts +4 -4
- package/src/observability/payload-capture.ts +6 -5
- package/src/observability/payload-store.ts +1 -1
- package/src/observability/runtime-metrics.ts +1 -1
- package/src/observability/telemetry-buffer.ts +12 -3
- package/src/observability/telemetry-reconciliation.ts +3 -3
- package/src/observability/telemetry-status.ts +1 -1
- package/src/observability/token-speed.ts +1 -1
- package/src/persistence/connection-url.ts +1 -1
- package/src/persistence/db-handle.ts +1 -1
- package/src/persistence/db-pg.ts +2 -2
- package/src/persistence/db-sqlite.ts +10 -5
- package/src/persistence/dialect.ts +5 -1
- package/src/persistence/readiness.ts +19 -7
- package/src/persistence/redis.ts +1 -1
- package/src/persistence/schema.ts +177 -45
- package/src/persistence/shared-cache.ts +2 -2
- package/src/persistence/sort-order.ts +1 -1
- package/src/persistence/stores/api-key-store.ts +109 -4
- package/src/persistence/stores/share-store.ts +20 -8
- package/src/persistence/stores/telemetry-store.ts +1 -1
- package/src/persistence/system-prompt-store.ts +63 -18
- package/src/persistence/tenant-preferences.ts +1 -1
- package/src/persistence/ttl-cache.ts +3 -3
- package/src/persistence/usage-flush.ts +7 -2
- package/src/protocol/canonical-model.ts +1 -1
- package/src/protocol/codecs.ts +12 -16
- package/src/protocol/dsml.ts +3 -49
- package/src/protocol/gateway-error.ts +6 -3
- package/src/protocol/image-clamp.ts +2 -2
- package/src/protocol/image-generation.ts +2 -2
- package/src/protocol/reasoning-text.ts +1 -1
- package/src/protocol/reasoning.ts +7 -52
- package/src/protocol/registry.ts +50 -15
- package/src/protocol/request/chat.ts +46 -19
- package/src/protocol/request/codex.ts +1 -1
- package/src/protocol/request/messages.ts +46 -14
- package/src/protocol/request/responses.ts +19 -10
- package/src/protocol/response/chat.ts +27 -12
- package/src/protocol/response/codex.ts +2 -2
- package/src/protocol/response/gemini.ts +1 -1
- package/src/protocol/response/messages.ts +6 -6
- package/src/protocol/response/omp-tool-call-markup.ts +1 -1
- package/src/protocol/response/responses.ts +3 -3
- package/src/protocol/sse-decoder.ts +64 -4
- package/src/protocol/stop-reason.ts +2 -2
- package/src/protocol/think-split.ts +347 -0
- package/src/protocol/translation/attachment-integrity.ts +3 -3
- package/src/protocol/translation/cache-controls.ts +8 -20
- package/src/protocol/translation/capabilities.ts +8 -8
- package/src/protocol/translation/dialect/deepseek.ts +10 -0
- package/src/protocol/translation/dialect/inband.ts +39 -0
- package/src/protocol/translation/dialect/model-thinking.ts +89 -0
- package/src/protocol/translation/dialect/qwen.ts +114 -0
- package/src/protocol/translation/dialect/resolver.ts +83 -0
- package/src/protocol/translation/dialect/rules.ts +93 -0
- package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
- package/src/protocol/translation/dialect/types.ts +58 -0
- package/src/protocol/translation/quirks.ts +18 -4
- package/src/protocol/translation/thinking.ts +12 -252
- package/src/protocol/translation/tool-id.ts +3 -3
- package/src/protocol/translation/tool-repair.ts +1 -1
- package/src/protocol/upstream/post-json.ts +6 -1
- 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 +44 -5
- package/src/providers/authentication/jwt-validator.ts +0 -5
- package/src/providers/authentication/oauth-client.ts +254 -253
- package/src/providers/authentication/oauth-flow-store.ts +42 -7
- package/src/providers/authentication/oauth-refresh-service.ts +2 -2
- package/src/providers/bundled-discovery-providers.ts +6 -30
- package/src/providers/configured-openai-providers.ts +82 -97
- package/src/providers/configured-provider.ts +1 -1
- package/src/providers/default-registry.ts +23 -35
- package/src/providers/discovery/catalog/catalog-format.ts +13 -2
- package/src/providers/discovery/discovery-types.ts +0 -1
- package/src/providers/discovery/openai-model-discovery.ts +2 -2
- package/src/providers/discovery/probe-phases.ts +50 -15
- package/src/providers/discovery/probing-service.ts +18 -20
- package/src/providers/integrations/agentrouter/agentrouter.ts +14 -5
- package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
- package/src/providers/integrations/anthropic.ts +4 -11
- package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
- package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
- package/src/providers/integrations/antigravity/antigravity.ts +15 -26
- package/src/providers/integrations/buddy/buddy-catalog-shared.ts +2 -2
- package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
- package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
- package/src/providers/integrations/buddy/buddy-discovery-shared.ts +37 -6
- package/src/providers/integrations/buddy/buddy-identity.ts +108 -1
- package/src/providers/integrations/buddy/buddy-media.ts +16 -16
- package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
- package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
- package/src/providers/integrations/buddy/codebuddy/provider.ts +5 -16
- package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
- package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -10
- package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
- package/src/providers/integrations/claude/claude-betas.ts +1 -1
- package/src/providers/integrations/claude/claude-cch.ts +148 -148
- 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/claude/fallback-credit.ts +3 -7
- package/src/providers/integrations/cline/cline.ts +2 -2
- package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
- package/src/providers/integrations/codex/codex-device-code.ts +101 -101
- package/src/providers/integrations/codex/codex-errors.ts +1 -1
- package/src/providers/integrations/codex/codex-oauth.ts +0 -1
- package/src/providers/integrations/codex/codex.ts +14 -15
- package/src/providers/integrations/commandcode/commandcode.ts +76 -116
- package/src/providers/integrations/commandcode/quota.ts +132 -48
- package/src/providers/integrations/cursor/cursor-http2.ts +11 -14
- package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
- package/src/providers/integrations/cursor/cursor-request.ts +0 -87
- package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
- package/src/providers/integrations/cursor/cursor.ts +53 -20
- package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
- package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
- package/src/providers/integrations/factory/factory.ts +13 -13
- package/src/providers/integrations/gemini.ts +11 -11
- package/src/providers/integrations/github/github-discovery.ts +55 -10
- package/src/providers/integrations/github/github-oauth.ts +6 -5
- package/src/providers/integrations/github/github.ts +47 -20
- package/src/providers/integrations/grok/grok-oauth.ts +261 -261
- package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
- package/src/providers/integrations/grok/grok-quota.ts +16 -7
- package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
- package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
- package/src/providers/integrations/grok/grok.ts +88 -42
- package/src/providers/integrations/inferhub.ts +4 -11
- package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
- package/src/providers/integrations/kimi/kimi.ts +4 -11
- package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
- package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
- package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
- package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
- package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
- package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
- package/src/providers/integrations/kiro/kiro-request.ts +8 -11
- package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
- package/src/providers/integrations/kiro/kiro.ts +91 -78
- package/src/providers/integrations/muse/muse-oauth.ts +0 -1
- package/src/providers/integrations/muse/muse-quota.ts +0 -4
- package/src/providers/integrations/muse/muse.ts +6 -9
- package/src/providers/integrations/opencode/fingerprint.ts +7 -5
- package/src/providers/integrations/opencode/provider.ts +17 -24
- package/src/providers/integrations/perplexity.ts +2 -2
- package/src/providers/integrations/qoder/qoder-catalog.ts +132 -17
- 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-oauth.ts +165 -25
- package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
- package/src/providers/integrations/qoder/qoder-realm.ts +22 -28
- package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
- package/src/providers/integrations/qoder/qoder-umid.ts +33 -38
- package/src/providers/integrations/qoder/qoder-virtual.ts +14 -2
- package/src/providers/integrations/qoder/qoder.ts +521 -63
- package/src/providers/integrations/shared/connect.ts +0 -54
- package/src/providers/integrations/shared/hash.ts +15 -0
- package/src/providers/integrations/shared/session-cache.ts +136 -0
- package/src/providers/integrations/tokenharbor.ts +2 -2
- package/src/providers/integrations/trae/trae-cache.ts +7 -87
- package/src/providers/integrations/trae/trae-catalog.ts +1 -6
- package/src/providers/integrations/trae/trae-protocol.ts +17 -8
- package/src/providers/integrations/trae/trae-realm.ts +0 -7
- package/src/providers/integrations/trae/trae.ts +59 -19
- package/src/providers/integrations/xai/xai-oauth.ts +5 -5
- package/src/providers/integrations/zcode/oauth.ts +1 -1
- package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
- package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
- package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
- package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
- package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
- package/src/providers/operations/account-error-classification.ts +131 -116
- package/src/providers/operations/account-health-service.ts +31 -39
- package/src/providers/operations/account-reset-service.ts +58 -1
- package/src/providers/operations/cli-platform.ts +31 -5
- package/src/providers/operations/client-version-resolver.ts +4 -6
- package/src/providers/operations/client-versions.ts +10 -7
- package/src/providers/operations/provider-catalog-seeder.ts +2 -0
- package/src/providers/operations/provider-catalog-service.ts +22 -6
- package/src/providers/operations/provider-credential-service.ts +35 -6
- package/src/providers/operations/upstream-deadline.ts +3 -3
- package/src/providers/provider-contracts.ts +65 -10
- package/src/providers/provider-credential-resolver.ts +1 -1
- package/src/providers/provider-metadata.ts +17 -2
- package/src/providers/provider-model-definition.ts +22 -1
- package/src/providers/provider-probe.ts +4 -2
- package/src/providers/provider-registry.ts +4 -4
- package/src/providers/provider-usage.ts +81 -16
- package/src/providers/quota/cache.ts +29 -0
- package/src/providers/quota/quota-contracts.ts +28 -10
- package/src/providers/quota/refresh.ts +29 -6
- package/src/providers/quota/snapshot.ts +94 -0
- package/src/providers/search/search-provider.ts +6 -8
- package/src/providers/search/search-providers.ts +2 -1
- package/src/security/abuse.ts +8 -8
- package/src/security/admission/reasons.ts +17 -17
- package/src/security/admission/service.ts +2 -2
- package/src/security/admission/ttl.ts +61 -61
- package/src/security/api-key-auth.ts +20 -8
- package/src/security/client-router-fingerprint.ts +4 -4
- package/src/security/credential-codec.ts +3 -3
- package/src/security/csrf.ts +2 -2
- package/src/security/ip-boundary.ts +16 -189
- package/src/security/model-access-rule.ts +1 -1
- package/src/security/outbound-headers.ts +18 -0
- package/src/shared/coerce.ts +19 -0
- package/src/shared/invoke-guard.ts +47 -0
- package/src/transport/contracts.ts +13 -4
- package/src/transport/dispatch/attempt-finalize.ts +5 -4
- package/src/transport/dispatch/attempt-loop.ts +10 -7
- package/src/transport/dispatch/capture-policy.ts +34 -37
- package/src/transport/dispatch/empty-stream.ts +28 -25
- package/src/transport/dispatch/generation.ts +33 -53
- package/src/transport/dispatch/leases.ts +8 -8
- package/src/transport/dispatch/native-shared.ts +127 -0
- package/src/transport/dispatch/proxy-request.ts +10 -8
- package/src/transport/dispatch/responses-compact.ts +35 -56
- package/src/transport/dispatch/retry-policy.ts +4 -67
- package/src/transport/dispatch/stream-bridge.ts +1 -1
- package/src/transport/dispatch/streaming/encoder.ts +18 -72
- package/src/transport/dispatch/streaming/finalize.ts +11 -10
- package/src/transport/dispatch/streaming/stream.ts +7 -3
- package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
- package/src/transport/dispatch/systemone.ts +27 -55
- package/src/transport/dispatch/token-count.ts +49 -46
- package/src/transport/dispatch/websearch.ts +24 -50
- package/src/transport/drain-endpoint.ts +3 -3
- package/src/transport/failure-policy.ts +19 -6
- package/src/transport/guards/auth-guard.ts +6 -11
- package/src/transport/guards/body-policy.ts +7 -7
- 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 +2 -2
- package/src/transport/guards/pipeline.ts +7 -7
- package/src/transport/guards/readiness-guard.ts +16 -2
- package/src/transport/guards/request-context.ts +15 -20
- package/src/transport/request/preparer.ts +306 -27
- package/src/transport/request/rtk/compress-request.ts +3 -3
- package/src/transport/request/rtk/rtk-constants.ts +2 -2
- package/src/transport/request/rtk/rtk-filters.ts +8 -8
- package/src/transport/request/state.ts +5 -20
- package/src/transport/request/system-prompt-injection.ts +74 -11
- package/src/transport/request/tenant-preferences.ts +22 -0
- package/src/transport/routing/candidate-index.ts +2 -2
- package/src/transport/routing/round-robin.ts +1 -1
- package/src/transport/routing/route-catalog.ts +113 -19
- package/src/transport/routing/route-model.ts +131 -38
- package/src/transport/routing/router.ts +154 -39
- package/src/transport/shutdown-notice.ts +21 -9
- package/src/transport/surface/adapters.ts +3 -3
- package/src/transport/surface/chat/encode.ts +7 -7
- package/src/transport/surface/chat/parse.ts +7 -7
- package/src/transport/surface/completion.ts +3 -3
- package/src/transport/surface/content-parts.ts +1 -1
- package/src/transport/surface/dialects.ts +2 -2
- package/src/transport/surface/messages/encode.ts +1 -1
- package/src/transport/surface/messages/parse.ts +3 -3
- package/src/transport/surface/responses/adapter.ts +1 -1
- package/src/transport/surface/responses/errors.ts +0 -9
- package/src/transport/vision-handoff-cache.ts +58 -0
- package/src/transport/vision-handoff.ts +376 -0
- package/src/workers/account-identity-sweep.ts +2 -2
- package/src/workers/buddy-growth-tasks.ts +392 -346
- package/src/workers/daily-checkin.ts +102 -49
- package/src/workers/maintenance-lease.ts +2 -35
- package/src/workers/oauth-refresh-sweep.ts +8 -1
- package/src/workers/quota-refresh-sweep.ts +120 -82
- package/src/workers/scheduler.ts +67 -4
- package/src/workers/sweep-runner.ts +24 -5
- package/src/workers/zcode-gift-claim.ts +108 -0
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
- package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
- 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 +0 -1
- 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/ProviderIcon-FB6yS4v1.js +0 -1
- package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.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 +0 -1
- 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.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.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/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 +0 -2
- 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.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/stream-retry-5QnVuSSo.js +0 -1
- package/dist/dashboard/assets/stream-retry-5QnVuSSo.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/src/network/response-headers.ts +0 -39
- package/src/protocol/response/dsml.ts +0 -38
- package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js → app-Bgd3zANQ.js} +0 -0
- /package/dist/dashboard/assets/{app-wvwCi4Eh.js.gz → app-Bgd3zANQ.js.gz} +0 -0
- /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
- /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
resolveProbeAdapter,
|
|
51
51
|
resolveProbeTarget,
|
|
52
52
|
selectProbeAccount,
|
|
53
|
+
selectUsableAccount,
|
|
53
54
|
wireContextFrom,
|
|
54
55
|
type ProbeProviderRow,
|
|
55
56
|
} from "./probe-phases";
|
|
@@ -304,7 +305,7 @@ export class ProviderProbingService {
|
|
|
304
305
|
throw new GatewayError(
|
|
305
306
|
"capability_unsupported",
|
|
306
307
|
400,
|
|
307
|
-
`Provider ${providerId} has no web search transport
|
|
308
|
+
`Provider ${providerId} has no web search transport (request {requestId}). Know your tools — this one just isn't in the box 🧰`,
|
|
308
309
|
);
|
|
309
310
|
}
|
|
310
311
|
const searchProbeQuery = request.prompt?.trim() || "Cartethyia gateway probe";
|
|
@@ -325,14 +326,14 @@ export class ProviderProbingService {
|
|
|
325
326
|
snippet: hit.snippet,
|
|
326
327
|
}));
|
|
327
328
|
if (!response.results || response.results.length === 0) {
|
|
328
|
-
dispatchError = new GatewayError("platform_unavailable", 502, "web search returned no results");
|
|
329
|
+
dispatchError = new GatewayError("platform_unavailable", 502, "web search returned no results (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
329
330
|
}
|
|
330
331
|
} else if (serviceKind === "systemone") {
|
|
331
332
|
if (typeof adapter.systemone !== "function") {
|
|
332
333
|
throw new GatewayError(
|
|
333
334
|
"capability_unsupported",
|
|
334
335
|
400,
|
|
335
|
-
`Provider ${providerId} has no System One transport
|
|
336
|
+
`Provider ${providerId} has no System One transport (request {requestId}). Know your tools — this one just isn't in the box 🧰`,
|
|
336
337
|
);
|
|
337
338
|
}
|
|
338
339
|
const response = await adapter.systemone(
|
|
@@ -360,14 +361,14 @@ export class ProviderProbingService {
|
|
|
360
361
|
dispatchError = new GatewayError(
|
|
361
362
|
response.status >= 500 ? "platform_unavailable" : "invalid_request",
|
|
362
363
|
response.status,
|
|
363
|
-
`System One upstream error: ${raw.slice(0, 240)}`,
|
|
364
|
+
`System One upstream error (request {requestId}): ${raw.slice(0, 240)}`,
|
|
364
365
|
);
|
|
365
366
|
} else {
|
|
366
367
|
let parsed: unknown;
|
|
367
368
|
try {
|
|
368
369
|
parsed = raw ? JSON.parse(raw) : null;
|
|
369
370
|
} catch {
|
|
370
|
-
dispatchError = new GatewayError("platform_unavailable", 502, "System One returned invalid JSON");
|
|
371
|
+
dispatchError = new GatewayError("platform_unavailable", 502, "System One returned invalid JSON (request {requestId}). The upstream came back empty-handed — retry 🌙");
|
|
371
372
|
}
|
|
372
373
|
if (parsed !== null && parsed !== undefined) {
|
|
373
374
|
const answers =
|
|
@@ -381,7 +382,7 @@ export class ProviderProbingService {
|
|
|
381
382
|
dispatchError = new GatewayError(
|
|
382
383
|
"platform_unavailable",
|
|
383
384
|
502,
|
|
384
|
-
"System One returned no answers",
|
|
385
|
+
"System One returned no answers (request {requestId}). The upstream came back empty-handed — retry 🌙",
|
|
385
386
|
);
|
|
386
387
|
}
|
|
387
388
|
}
|
|
@@ -709,7 +710,7 @@ export class ProviderProbingService {
|
|
|
709
710
|
throw new GatewayError(
|
|
710
711
|
"transport_unavailable",
|
|
711
712
|
502,
|
|
712
|
-
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"}
|
|
713
|
+
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"} (request {requestId}). The connection ghosted us — come back in a moment 👻`,
|
|
713
714
|
{},
|
|
714
715
|
"upstream",
|
|
715
716
|
);
|
|
@@ -718,7 +719,7 @@ export class ProviderProbingService {
|
|
|
718
719
|
throw new GatewayError(
|
|
719
720
|
"transport_unavailable",
|
|
720
721
|
502,
|
|
721
|
-
`Model discovery failed for ${providerId}: endpoint returned no usable models
|
|
722
|
+
`Model discovery failed for ${providerId}: endpoint returned no usable models (request {requestId}). The upstream came back empty-handed — retry 🌙`,
|
|
722
723
|
{},
|
|
723
724
|
"upstream",
|
|
724
725
|
);
|
|
@@ -764,7 +765,7 @@ export class ProviderProbingService {
|
|
|
764
765
|
throw new GatewayError(
|
|
765
766
|
"transport_unavailable",
|
|
766
767
|
502,
|
|
767
|
-
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"}
|
|
768
|
+
`Model discovery failed for ${providerId}: ${error instanceof Error ? error.message : "unknown error"} (request {requestId}). The connection ghosted us — come back in a moment 👻`,
|
|
768
769
|
{},
|
|
769
770
|
"upstream",
|
|
770
771
|
);
|
|
@@ -799,7 +800,7 @@ export class ProviderProbingService {
|
|
|
799
800
|
throw new GatewayError(
|
|
800
801
|
"invalid_request",
|
|
801
802
|
400,
|
|
802
|
-
`Add an account for ${providerId} first — model listing needs a credential
|
|
803
|
+
`Add an account for ${providerId} first — model listing needs a credential (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
803
804
|
{},
|
|
804
805
|
"cartethyia",
|
|
805
806
|
);
|
|
@@ -811,7 +812,7 @@ export class ProviderProbingService {
|
|
|
811
812
|
throw new GatewayError(
|
|
812
813
|
"invalid_request",
|
|
813
814
|
400,
|
|
814
|
-
`Add an account for ${providerId} before fetching its models
|
|
815
|
+
`Add an account for ${providerId} before fetching its models (request {requestId}). Wrong key, right door — check the credential 🔑`,
|
|
815
816
|
{},
|
|
816
817
|
"cartethyia",
|
|
817
818
|
);
|
|
@@ -821,7 +822,7 @@ export class ProviderProbingService {
|
|
|
821
822
|
throw new GatewayError(
|
|
822
823
|
"capability_unsupported",
|
|
823
824
|
400,
|
|
824
|
-
`${providerId} publishes no model-listing endpoint. Its catalog ships with Cartethyia; new models appear with an update
|
|
825
|
+
`${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
826
|
{},
|
|
826
827
|
"cartethyia",
|
|
827
828
|
);
|
|
@@ -915,6 +916,9 @@ export class ProviderProbingService {
|
|
|
915
916
|
source: discDef?.freeTier === true ? "auto_free" : "discovered",
|
|
916
917
|
sourceUpdatedAt,
|
|
917
918
|
enabled: true,
|
|
919
|
+
...(discDef?.dialect === undefined && knownDefinition?.dialect === undefined
|
|
920
|
+
? {}
|
|
921
|
+
: { dialect: discDef?.dialect ?? knownDefinition?.dialect }),
|
|
918
922
|
});
|
|
919
923
|
}
|
|
920
924
|
// One statement per chunk (500, the account-health batch step) instead of
|
|
@@ -936,6 +940,7 @@ export class ProviderProbingService {
|
|
|
936
940
|
cost: sql`excluded.cost`,
|
|
937
941
|
proOnly: sql`excluded.pro_only`,
|
|
938
942
|
freeTier: sql`excluded.free_tier`,
|
|
943
|
+
dialect: sql`excluded.dialect`,
|
|
939
944
|
// The proposed row's own source, not a constant: a free-tier
|
|
940
945
|
// discovery and an ordinary one write the same upsert, and pinning
|
|
941
946
|
// this to `discovered` would relabel every free-tier row on the
|
|
@@ -1000,14 +1005,7 @@ export class ProviderProbingService {
|
|
|
1000
1005
|
globalOrOwnedBy(providerAccounts.tenantId, tenantId),
|
|
1001
1006
|
),
|
|
1002
1007
|
);
|
|
1003
|
-
const
|
|
1004
|
-
const usable = rows
|
|
1005
|
-
.filter(
|
|
1006
|
-
(row) =>
|
|
1007
|
-
row.status !== "disabled" &&
|
|
1008
|
-
(row.cooldownUntil === null || row.cooldownUntil.getTime() <= now),
|
|
1009
|
-
)
|
|
1010
|
-
.sort((left, right) => Number(right.tenantId !== null) - Number(left.tenantId !== null))[0];
|
|
1008
|
+
const usable = selectUsableAccount(rows);
|
|
1011
1009
|
if (!usable?.credentialCiphertext) return undefined;
|
|
1012
1010
|
const authState = isRecord(usable.authState) ? usable.authState as Readonly<Record<string, unknown>> : undefined;
|
|
1013
1011
|
return {
|
|
@@ -11,15 +11,24 @@
|
|
|
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";
|
|
19
|
+
import { ANTHROPIC_BETA_CAPABILITIES } from "../claude/claude-betas";
|
|
20
20
|
|
|
21
21
|
export const AGENTROUTER_PROVIDER_ID = "agentrouter" as const;
|
|
22
|
-
|
|
22
|
+
const AGENTROUTER_BASE_URL = `${providerBaseUrl("agentrouter")}/v1/messages?beta=true`;
|
|
23
|
+
|
|
24
|
+
/** The CLI beta set, typed against the canonical Anthropic beta vocabulary. */
|
|
25
|
+
const AGENTROUTER_ANTHROPIC_BETAS: ReadonlyArray<
|
|
26
|
+
keyof typeof ANTHROPIC_BETA_CAPABILITIES
|
|
27
|
+
> = [
|
|
28
|
+
"claude-code-20250219",
|
|
29
|
+
"interleaved-thinking-2025-05-14",
|
|
30
|
+
"effort-2025-11-24",
|
|
31
|
+
];
|
|
23
32
|
|
|
24
33
|
/**
|
|
25
34
|
* The AgentRouter CLI fingerprint headers. Every value is part of the
|
|
@@ -30,7 +39,7 @@ export const AGENTROUTER_BASE_URL = `${providerBaseUrl("agentrouter")}/v1/messag
|
|
|
30
39
|
*/
|
|
31
40
|
function agentRouterFingerprintHeaders(stream: boolean): Record<string, string> {
|
|
32
41
|
return {
|
|
33
|
-
"anthropic-beta": "
|
|
42
|
+
"anthropic-beta": AGENTROUTER_ANTHROPIC_BETAS.join(","),
|
|
34
43
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
35
44
|
"x-app": "cli",
|
|
36
45
|
"user-agent": "claude-cli/2.1.195 (external, sdk-cli)",
|
|
@@ -87,7 +96,7 @@ class AgentRouterAdapter implements ProviderAdapter {
|
|
|
87
96
|
context: ProviderDispatchContext,
|
|
88
97
|
): AsyncIterable<CanonicalEvent> {
|
|
89
98
|
if (candidate.wire_family !== "messages") {
|
|
90
|
-
|
|
99
|
+
assertWireFamily(candidate, "messages", "agentrouter");
|
|
91
100
|
}
|
|
92
101
|
const apiKey = readCredentialSecret(context.credential, "AgentRouter API key is required");
|
|
93
102
|
|
|
@@ -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);
|
|
@@ -257,8 +257,6 @@ export function normalizeAntigravityToolSchemas(request: CanonicalRequest): Cano
|
|
|
257
257
|
const lastGoodEndpoints = new Map<string, string>();
|
|
258
258
|
const LAST_GOOD_ENDPOINT_MAX = 256;
|
|
259
259
|
|
|
260
|
-
const DEFAULT_ORDER_INDEX = Number.MAX_SAFE_INTEGER;
|
|
261
|
-
|
|
262
260
|
/**
|
|
263
261
|
* Records the endpoint that just served a successful turn. Call this with the
|
|
264
262
|
* `endpoint` reported by empty-stream recovery (or the URL that produced a
|
|
@@ -301,18 +299,6 @@ export function orderAntigravityEndpoints(
|
|
|
301
299
|
return [sticky, ...endpoints.slice(0, index), ...endpoints.slice(index + 1)];
|
|
302
300
|
}
|
|
303
301
|
|
|
304
|
-
/**
|
|
305
|
-
* Position of `endpoint` in the caller's own endpoint order, used to log a
|
|
306
|
-
* failover without the caller re-deriving the list.
|
|
307
|
-
*/
|
|
308
|
-
export function antigravityEndpointOrderIndex(
|
|
309
|
-
endpoints: readonly string[],
|
|
310
|
-
endpoint: string,
|
|
311
|
-
): number {
|
|
312
|
-
const index = endpoints.indexOf(endpoint);
|
|
313
|
-
return index < 0 ? DEFAULT_ORDER_INDEX : index;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
302
|
// Model discovery (`v1internal:fetchAvailableModels`) — live catalog.
|
|
317
303
|
|
|
318
304
|
const ANTIGRAVITY_DISCOVERY_PATH = "/v1internal:fetchAvailableModels";
|
|
@@ -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
|
}
|
|
@@ -769,7 +758,7 @@ export class AntigravitySessionStore {
|
|
|
769
758
|
* `"-" + (sha256(first-user-text)[0:8] & INT63 | random <9e18)`.
|
|
770
759
|
* A positive or hyphenated-UUID value here is a one-glance synthetic signal.
|
|
771
760
|
*/
|
|
772
|
-
|
|
761
|
+
function signedAntigravitySessionId(seed?: string): string {
|
|
773
762
|
if (seed !== undefined && /^-?\d+$/.test(seed)) return seed;
|
|
774
763
|
const text = seed !== undefined && seed.length > 0 ? seed : randomUUID();
|
|
775
764
|
const head = BigInt(`0x${createHash("sha256").update(text).digest("hex").slice(0, 8)}`);
|
|
@@ -780,7 +769,7 @@ export function signedAntigravitySessionId(seed?: string): string {
|
|
|
780
769
|
}
|
|
781
770
|
|
|
782
771
|
/** Thinking budget per wire model, matching the client's effort tiers. */
|
|
783
|
-
|
|
772
|
+
function antigravityThinkingBudget(modelId: string): number | undefined {
|
|
784
773
|
if (!modelId.includes("claude") && !modelId.includes("gemini-3")) return undefined;
|
|
785
774
|
if (modelId.endsWith("-low")) return 1_000;
|
|
786
775
|
if (modelId.endsWith("-medium")) return 4_000;
|
|
@@ -160,7 +160,7 @@ export function makeBuddyCnImageModels(
|
|
|
160
160
|
* plan rather than about the model. A pro account serves all six. The pill is
|
|
161
161
|
* therefore a hint about a free account, and a dispatch is what settles it.
|
|
162
162
|
*
|
|
163
|
-
* @see
|
|
163
|
+
* @see `documentation/research/codebuddy/2026-10-19-codebuddy-chat-dispatch-headers.md`
|
|
164
164
|
*/
|
|
165
165
|
export const BUDDY_PRO_ONLY_MODEL_IDS: ReadonlySet<string> = new Set([
|
|
166
166
|
"primary-model",
|
|
@@ -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
|
|
@@ -168,10 +168,11 @@ export function normalizeBuddyToolNames(payload: Record<string, unknown>): void
|
|
|
168
168
|
* Both realms have a "let the backend choose" id, and the reference rewrites
|
|
169
169
|
* `auto` onto it before anything downstream keys on the name — so eligibility,
|
|
170
170
|
* cooldowns and the catalog all see one id. CN's is `default`; intl's is
|
|
171
|
-
* `default-model
|
|
171
|
+
* `default-model` (confirmed from live CLI session logs, which send
|
|
172
|
+
* `model=default-model` for the intl auto path).
|
|
172
173
|
*/
|
|
173
174
|
const BUDDY_AUTO_TARGET: Readonly<Record<"intl" | "cn", string>> = {
|
|
174
|
-
intl: "
|
|
175
|
+
intl: "default-model",
|
|
175
176
|
cn: "default",
|
|
176
177
|
};
|
|
177
178
|
|
|
@@ -348,8 +349,8 @@ const DSH_MINIMAL_PATTERN = buddyTemplatePattern("You are a helpful software eng
|
|
|
348
349
|
const DSH_DIRECT_PATTERN = buddyTemplatePattern("You are DeepSeek Harness");
|
|
349
350
|
const DSH_WEB_GUI_PATTERN = buddyTemplatePattern("DeepSeek Harness Web GUI");
|
|
350
351
|
|
|
351
|
-
/** The identity DSH role prompts are rewritten to;
|
|
352
|
-
const DSH_WORKBUDDY_IDENTITY = "You are
|
|
352
|
+
/** The identity DSH role prompts are rewritten to; neutral and minimal. */
|
|
353
|
+
const DSH_WORKBUDDY_IDENTITY = "You are a helpful assistant";
|
|
353
354
|
|
|
354
355
|
/**
|
|
355
356
|
* Rewrites DeepSeek Harness role identities in one message's text back to the
|
|
@@ -425,6 +426,20 @@ export const clineReasoningReplayPrepares: readonly ((
|
|
|
425
426
|
},
|
|
426
427
|
];
|
|
427
428
|
|
|
429
|
+
/**
|
|
430
|
+
* The reference injects `cache_retention` on every chat body: `long` by
|
|
431
|
+
* default, `short` when prompt caching for 1h is disabled
|
|
432
|
+
* (`CODEBUDDY_DISABLE_PROMPT_CACHING_1H`). Matching the client keeps the
|
|
433
|
+
* upstream's prompt-caching behavior and price on the same path the CLI uses.
|
|
434
|
+
*/
|
|
435
|
+
function injectBuddyCacheRetention(payload: Record<string, unknown>): void {
|
|
436
|
+
if (payload["cache_retention"] !== undefined) return;
|
|
437
|
+
const disabled =
|
|
438
|
+
process.env.CODEBUDDY_DISABLE_PROMPT_CACHING_1H?.trim() === "1" ||
|
|
439
|
+
process.env.CODEBUDDY_DISABLE_PROMPT_CACHING_1H?.trim().toLowerCase() === "true";
|
|
440
|
+
payload["cache_retention"] = disabled ? "short" : "long";
|
|
441
|
+
}
|
|
442
|
+
|
|
428
443
|
/**
|
|
429
444
|
* Payload prefix shared by the buddy pre-payload hooks: force `stream=true`,
|
|
430
445
|
* apply the provider's DeepSeek thinking contract, opt `reasoning_summary` in
|
|
@@ -437,6 +452,7 @@ export function buddyPrePayloadCommon(
|
|
|
437
452
|
context?: ProviderDispatchContext,
|
|
438
453
|
): void {
|
|
439
454
|
injectBuddyPromptCacheKey(payload, request, context);
|
|
455
|
+
injectBuddyCacheRetention(payload);
|
|
440
456
|
// `auto` and `default-model` are the same upstream model under two names, and
|
|
441
457
|
// the reference resolves one to the other everywhere — catalog, eligibility,
|
|
442
458
|
// cooldown keys. Treating them as two independent rows meant a client that
|
|
@@ -3,51 +3,19 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Everything here comes from the two reference gateways, which agree: the
|
|
5
5
|
* desktop product sends conversation/tracing headers and a device token, while
|
|
6
|
-
* the CLI sends the agent envelope
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* `*-shared.ts`.
|
|
6
|
+
* the CLI sends the agent envelope. The CLI still drops the browser *transport*
|
|
7
|
+
* headers (`origin`, `referer`, `accept-language`) and the device token, but
|
|
8
|
+
* keeps the request-shape markers (`x-requested-with`, `x-codebuddy-request`)
|
|
9
|
+
* the reference sends on every call regardless of transport — see the CLI
|
|
10
|
+
* branches in each provider's `*-shared.ts`.
|
|
12
11
|
*
|
|
13
|
-
* The
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* risk model has seen for this client brand, and an easy outlier to key on.
|
|
12
|
+
* The CLI's cloud chat transport is axios (`RestOperations`), not the OpenAI
|
|
13
|
+
* Node SDK, so it sends **no** `x-stainless-*` fingerprint. The reference's
|
|
14
|
+
* chat request helper sets only `Content-Type`, `Accept`, and `Authorization`
|
|
15
|
+
* before the conversation/agent/identity headers are injected; the stainless
|
|
16
|
+
* set belongs to the SDK-backed secondary clients, not to CodeBuddy chat.
|
|
19
17
|
*/
|
|
20
18
|
|
|
21
|
-
/** OpenAI Node SDK 6.25.0 `x-stainless-*` fingerprint; both references agree. */
|
|
22
|
-
const STAINLESS_PACKAGE_VERSION = "6.25.0";
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The pinned Node runtime the fingerprint claims. Held constant across
|
|
26
|
-
* dispatches: a drifting `process.version` would advertise a different Node
|
|
27
|
-
* build per deployment, which is not what one installed client looks like.
|
|
28
|
-
*/
|
|
29
|
-
const STAINLESS_RUNTIME_VERSION = "v24.21.0";
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* The SDK fingerprint headers.
|
|
33
|
-
*
|
|
34
|
-
* `x-stainless-timeout` is in the hub only and `x-stainless-retry-count` is in
|
|
35
|
-
* both; the SDK sends both, so both go out. The OS/arch pair is the pinned
|
|
36
|
-
* macOS fingerprint rather than this process's host.
|
|
37
|
-
*/
|
|
38
|
-
export function buddyStainlessHeaders(): Record<string, string> {
|
|
39
|
-
return {
|
|
40
|
-
"x-stainless-lang": "js",
|
|
41
|
-
"x-stainless-package-version": STAINLESS_PACKAGE_VERSION,
|
|
42
|
-
"x-stainless-os": "MacOS",
|
|
43
|
-
"x-stainless-arch": "x64",
|
|
44
|
-
"x-stainless-runtime": "node",
|
|
45
|
-
"x-stainless-runtime-version": STAINLESS_RUNTIME_VERSION,
|
|
46
|
-
"x-stainless-retry-count": "0",
|
|
47
|
-
"x-stainless-timeout": "1200",
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
19
|
/**
|
|
52
20
|
* The trace family the CLI carries as a child span.
|
|
53
21
|
*
|
|
@@ -69,13 +37,18 @@ export function buddyCliTraceHeaders(
|
|
|
69
37
|
/**
|
|
70
38
|
* The full CLI identity envelope, minus what each caller already supplies.
|
|
71
39
|
*
|
|
72
|
-
* The caller keeps ownership of `User-Agent`, `X-IDE-*`, `X-Domain`,
|
|
73
|
-
* conversation family,
|
|
74
|
-
*
|
|
40
|
+
* The caller keeps ownership of `User-Agent`, `X-IDE-*`, `X-Domain`, the
|
|
41
|
+
* conversation family, and the OAuth identity headers; only the headers that
|
|
42
|
+
* are the same for every CLI dispatch are built here.
|
|
43
|
+
*
|
|
44
|
+
* No `x-stainless-*` fingerprint: the CLI's chat transport is axios, not the
|
|
45
|
+
* OpenAI Node SDK. `X-Private-Data` is added by the caller only when the
|
|
46
|
+
* dispatch is actually private — the reference never sends it as `false`.
|
|
75
47
|
*/
|
|
76
48
|
export function buddyCliHeaders(args: {
|
|
77
49
|
readonly userId: string;
|
|
78
50
|
readonly enterpriseId?: string | undefined;
|
|
51
|
+
readonly privateData?: boolean;
|
|
79
52
|
}): Record<string, string> {
|
|
80
53
|
const enterpriseId =
|
|
81
54
|
args.enterpriseId !== undefined && args.enterpriseId.trim().length > 0
|
|
@@ -89,12 +62,7 @@ export function buddyCliHeaders(args: {
|
|
|
89
62
|
// of the three, so "other" is the honest value rather than a guess.
|
|
90
63
|
"X-Agent-Runtime": "other",
|
|
91
64
|
"X-User-Id": args.userId,
|
|
92
|
-
|
|
93
|
-
// id. A personal account stays `false`; an enterprise account flips to
|
|
94
|
-
// `true` and names the enterprise, because the two travel together — a
|
|
95
|
-
// `true` with no id, or an id under `false`, is a combination no real
|
|
96
|
-
// client produces.
|
|
97
|
-
"X-Private-Data": enterpriseId === undefined ? "false" : "true",
|
|
65
|
+
...(args.privateData === true ? { "X-Private-Data": "true" } : {}),
|
|
98
66
|
...(enterpriseId === undefined
|
|
99
67
|
? {}
|
|
100
68
|
: {
|
|
@@ -104,6 +72,5 @@ export function buddyCliHeaders(args: {
|
|
|
104
72
|
// reads both.
|
|
105
73
|
"X-Tenant-Id": enterpriseId,
|
|
106
74
|
}),
|
|
107
|
-
...buddyStainlessHeaders(),
|
|
108
75
|
};
|
|
109
76
|
}
|
|
@@ -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. */
|