cartethyia 2.7.4 → 2.7.6

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.
Files changed (595) hide show
  1. package/.env.example +5 -0
  2. package/README.md +18 -6
  3. package/dist/dashboard/assets/BannedPage-B1N603cM.js +1 -0
  4. package/dist/dashboard/assets/BannedPage-B1N603cM.js.gz +0 -0
  5. package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js +3 -0
  6. package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js.gz +0 -0
  7. package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js +1 -0
  8. package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js.gz +0 -0
  9. package/dist/dashboard/assets/CombosPage-D762MIkp.js +1 -0
  10. package/dist/dashboard/assets/CombosPage-D762MIkp.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js.gz +0 -0
  13. package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js +1 -0
  14. package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js.gz +0 -0
  17. package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js +899 -0
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js.gz +0 -0
  19. package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js +1 -0
  20. package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-C6WlpU5E.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js +5 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js.gz +0 -0
  31. package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-DxjvUzSD.js} +1 -1
  32. package/dist/dashboard/assets/ProxyPage-DxjvUzSD.js.gz +0 -0
  33. package/dist/dashboard/assets/QuotaPage-OaHScjpX.js +1 -0
  34. package/dist/dashboard/assets/QuotaPage-OaHScjpX.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js.gz +0 -0
  37. package/dist/dashboard/assets/SetupPage-44BZrxFC.js +1 -0
  38. package/dist/dashboard/assets/SetupPage-44BZrxFC.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-DRPavCdU.js} +4 -4
  40. package/dist/dashboard/assets/StudioPage-DRPavCdU.js.gz +0 -0
  41. package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js +1 -0
  42. package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js.gz +0 -0
  43. package/dist/dashboard/assets/UsagePage-B7M7LvMM.js +56 -0
  44. package/dist/dashboard/assets/UsagePage-B7M7LvMM.js.gz +0 -0
  45. package/dist/dashboard/assets/api-keys-KvX83mRe.js +1 -0
  46. package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
  47. package/dist/dashboard/assets/app-DRnQLhsc.js +9 -0
  48. package/dist/dashboard/assets/app-DRnQLhsc.js.gz +0 -0
  49. package/dist/dashboard/assets/app-mweRcsKp.css +2 -0
  50. package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
  51. package/dist/dashboard/assets/assert-CidQVoNo.js +1 -0
  52. package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
  53. package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-BaX2GTrn.js} +1 -1
  54. package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
  55. package/dist/dashboard/assets/{banner-DympBNq4.js → banner-DFH4Bkte.js} +1 -1
  56. package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
  57. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  58. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  59. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  60. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  61. package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CxDw0lK6.js} +1 -1
  62. package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
  63. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
  64. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
  65. package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js +1 -0
  66. package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js.gz +0 -0
  67. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +1 -0
  68. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
  69. package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-DfS1ntiq.js} +1 -1
  70. package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
  71. package/dist/dashboard/assets/dialog-BK-NRr5u.js +1 -0
  72. package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
  73. package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-QqPul6sC.js} +1 -1
  74. package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
  75. package/dist/dashboard/assets/entry-BMlYJVFj.js +1 -0
  76. package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
  77. package/dist/dashboard/assets/entry-D6WvojeD.js +4 -0
  78. package/dist/dashboard/assets/entry-D6WvojeD.js.gz +0 -0
  79. package/dist/dashboard/assets/entry-Dmx7gBiN.js +1 -0
  80. package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
  81. package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-u7JPB5BX.js} +1 -1
  82. package/dist/dashboard/assets/formatters-u7JPB5BX.js.gz +0 -0
  83. package/dist/dashboard/assets/house-h9AZlJuT.js +1 -0
  84. package/dist/dashboard/assets/house-h9AZlJuT.js.gz +0 -0
  85. package/dist/dashboard/assets/{index-DBNPOfhV.js → index-Ko4dLRnV.js} +2 -2
  86. package/dist/dashboard/assets/index-Ko4dLRnV.js.gz +0 -0
  87. package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-CHJQwxLa.js} +1 -1
  88. package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
  89. package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BlmlizVV.js} +1 -1
  90. package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
  91. package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-Bz93I-yE.js} +1 -1
  92. package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
  93. package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Ml16KCfu.js} +1 -1
  94. package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
  95. package/dist/dashboard/assets/live-7_QpnYGu.js +1 -0
  96. package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
  97. package/dist/dashboard/assets/{mutation-Rr0TIvcj.js → mutation-GU7XdEjz.js} +1 -1
  98. package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
  99. package/dist/dashboard/assets/network-CuMDaTzT.js +1 -0
  100. package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
  101. package/dist/dashboard/assets/numbers-CoqpaDMx.js +2 -0
  102. package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
  103. package/dist/dashboard/assets/pagination-B5aOoweZ.js +1 -0
  104. package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
  105. package/dist/dashboard/assets/providers/zai.webp +0 -0
  106. package/dist/dashboard/assets/providers/zcode.webp +0 -0
  107. package/dist/dashboard/assets/{query-keys-BloKtaXJ.js → query-keys-YSoQOUh6.js} +1 -1
  108. package/dist/dashboard/assets/{query-keys-BloKtaXJ.js.gz → query-keys-YSoQOUh6.js.gz} +0 -0
  109. package/dist/dashboard/assets/quota-DJ1QlAOq.js +1 -0
  110. package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
  111. package/dist/dashboard/assets/routing-fnCsxgNO.js +1 -0
  112. package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
  113. package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BHqpd-bg.js} +2 -2
  114. package/dist/dashboard/assets/select-BHqpd-bg.js.gz +0 -0
  115. package/dist/dashboard/assets/settings-BxslsErn.js +1 -0
  116. package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
  117. package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
  118. package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
  119. package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-j7cXjgYX.js} +1 -1
  120. package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
  121. package/dist/dashboard/assets/{state-CkfdYWel.js → state-DHmEnLa2.js} +1 -1
  122. package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
  123. package/dist/dashboard/assets/{switch-SYm237HG.js → switch-DmZcyTIC.js} +1 -1
  124. package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
  125. package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-CbCP4w1o.js} +1 -1
  126. package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
  127. package/dist/dashboard/console-backgrounds.jpg +0 -0
  128. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  129. package/dist/dashboard/index.html +2 -2
  130. package/dist/dashboard/index.html.gz +0 -0
  131. package/dist/dashboard/precompressed-assets.json +60 -59
  132. package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
  133. package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
  134. package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
  135. package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
  136. package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
  137. package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
  138. package/migrations/full-postgres/0042_add_telemetry_degenerate_stop.sql +14 -0
  139. package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
  140. package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
  141. package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
  142. package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
  143. package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
  144. package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
  145. package/migrations/lite-sqlite3/0042_add_telemetry_degenerate_stop.sql +12 -0
  146. package/package.json +4 -6
  147. package/scripts/cli/update.ts +15 -41
  148. package/src/boot/app.ts +58 -2
  149. package/src/boot/dependencies.ts +794 -732
  150. package/src/boot/lifecycle.ts +11 -12
  151. package/src/config/cooldowns.ts +34 -55
  152. package/src/config/network.ts +1 -1
  153. package/src/config/package-paths.ts +1 -1
  154. package/src/config/providers.ts +19 -14
  155. package/src/config/resources.ts +0 -5
  156. package/src/config/runtime.ts +2 -5
  157. package/src/config/spec.ts +33 -6
  158. package/src/config/usage.ts +27 -0
  159. package/src/console/api-keys/ban-constants.ts +38 -0
  160. package/src/console/api-keys/contracts.ts +71 -62
  161. package/src/console/api-keys/routes.ts +56 -24
  162. package/src/console/auth/access.ts +4 -4
  163. package/src/console/auth/account-reset.ts +1 -1
  164. package/src/console/auth/audit-recorder.ts +1 -1
  165. package/src/console/auth/lockout.ts +7 -3
  166. package/src/console/auth/row-coercion.ts +57 -12
  167. package/src/console/auth/session-resolver.ts +1 -1
  168. package/src/console/auth/session-service.ts +8 -2
  169. package/src/console/auth/session.ts +37 -31
  170. package/src/console/auth/setup-service.ts +4 -3
  171. package/src/console/auth/user-store.ts +1 -1
  172. package/src/console/backup/9router-map.ts +0 -3
  173. package/src/console/backup/contracts.ts +9 -9
  174. package/src/console/backup/export-endpoint.ts +5 -6
  175. package/src/console/backup/nine-router.ts +1 -7
  176. package/src/console/backup/routes.ts +29 -33
  177. package/src/console/backup/service.ts +468 -468
  178. package/src/console/backup/store.ts +47 -29
  179. package/src/console/backup/validate.ts +11 -1
  180. package/src/console/cli-tools/contracts.ts +43 -299
  181. package/src/console/cli-tools/fs-ops.ts +29 -0
  182. package/src/console/cli-tools/injectors/claude.ts +3 -3
  183. package/src/console/cli-tools/injectors/codex.ts +181 -181
  184. package/src/console/cli-tools/injectors/driver.ts +150 -247
  185. package/src/console/cli-tools/injectors/kilo.ts +146 -21
  186. package/src/console/cli-tools/injectors/opencode.ts +176 -153
  187. package/src/console/cli-tools/routes.ts +7 -1
  188. package/src/console/cli-tools/service.ts +8 -7
  189. package/src/console/cli-tools/store.ts +2 -2
  190. package/src/console/console-router.ts +32 -0
  191. package/src/console/dashboard-assets.ts +9 -9
  192. package/src/console/domain-registration.ts +16 -2
  193. package/src/console/inferhub/client.ts +0 -7
  194. package/src/console/inferhub/key-store.ts +1 -1
  195. package/src/console/inferhub/normalize.ts +2 -2
  196. package/src/console/inferhub/routes.ts +1 -1
  197. package/src/console/inferhub/types.ts +1 -1
  198. package/src/console/observability/contracts.ts +7 -1
  199. package/src/console/observability/live.ts +31 -18
  200. package/src/console/observability/logs.ts +1 -1
  201. package/src/console/observability/sse.ts +62 -8
  202. package/src/console/observability/store.ts +23 -4
  203. package/src/console/providers/catalog/catalog-projections.ts +1 -1
  204. package/src/console/providers/catalog/contracts.ts +39 -0
  205. package/src/console/providers/catalog/model-operations.ts +1 -1
  206. package/src/console/providers/catalog/provider-operations.ts +95 -17
  207. package/src/console/providers/catalog/public-model-store.ts +0 -0
  208. package/src/console/providers/catalog/routes.ts +27 -3
  209. package/src/console/providers/catalog/store.ts +147 -8
  210. package/src/console/providers/detail/routes.ts +1 -1
  211. package/src/console/providers/oauth/callback-listener.ts +100 -18
  212. package/src/console/providers/oauth/routes.ts +92 -13
  213. package/src/console/quota/account-quota-global.ts +41 -3
  214. package/src/console/quota/account-quota-shared.ts +10 -3
  215. package/src/console/quota/account-quota-tenant.ts +259 -66
  216. package/src/console/quota/daily-growth-job.ts +308 -0
  217. package/src/console/quota/native-identity.ts +2 -2
  218. package/src/console/quota/quota-view.ts +1 -1
  219. package/src/console/remote-support/routes.ts +1 -1
  220. package/src/console/remote-support/service.ts +2 -2
  221. package/src/console/routing/model/contracts.ts +1 -1
  222. package/src/console/routing/pools/contracts.ts +2 -2
  223. package/src/console/routing/pools/import-parse.ts +3 -3
  224. package/src/console/routing/pools/relay-deploy.ts +3 -3
  225. package/src/console/settings/contracts.ts +29 -2
  226. package/src/console/settings/store.ts +20 -0
  227. package/src/console/share/share-router.ts +100 -32
  228. package/src/console/share/share-stats.ts +11 -13
  229. package/src/console/share/share-usage.ts +1 -1
  230. package/src/console/shared/errors.ts +2 -2
  231. package/src/console/shared/object.ts +18 -0
  232. package/src/console/shared/read-through-cache.ts +4 -4
  233. package/src/console/shared/transaction.ts +14 -0
  234. package/src/console/system-prompt/contracts.ts +89 -12
  235. package/src/console/system-prompt/routes.ts +98 -45
  236. package/src/console/updates/apply-update.ts +244 -0
  237. package/src/console/updates/routes.ts +252 -97
  238. package/src/main.ts +11 -5
  239. package/src/network/http2-bidi.ts +1 -1
  240. package/src/network/ip-utils.ts +298 -0
  241. package/src/network/outbound-fetch.ts +1 -1
  242. package/src/network/pool/agent.ts +7 -6
  243. package/src/network/pool/byte-accounting.ts +1 -1
  244. package/src/network/pool/resolver.ts +16 -12
  245. package/src/network/pool/selector.ts +150 -136
  246. package/src/network/pool-health-machine.ts +1 -1
  247. package/src/network/rate-limit-verdict.ts +1 -1
  248. package/src/network/retry.ts +1 -1
  249. package/src/network/ssrf.ts +20 -71
  250. package/src/observability/event-log.ts +9 -2
  251. package/src/observability/event-query.ts +61 -291
  252. package/src/observability/log-sanitize.ts +1 -1
  253. package/src/observability/metrics.ts +4 -4
  254. package/src/observability/payload-capture.ts +6 -5
  255. package/src/observability/payload-store.ts +1 -1
  256. package/src/observability/runtime-metrics.ts +1 -1
  257. package/src/observability/telemetry-buffer.ts +19 -3
  258. package/src/observability/telemetry-reconciliation.ts +3 -3
  259. package/src/observability/token-speed.ts +1 -1
  260. package/src/persistence/connection-url.ts +1 -1
  261. package/src/persistence/db-handle.ts +1 -1
  262. package/src/persistence/db-pg.ts +2 -2
  263. package/src/persistence/db-sqlite.ts +3 -3
  264. package/src/persistence/dialect.ts +5 -1
  265. package/src/persistence/readiness.ts +1 -1
  266. package/src/persistence/redis.ts +1 -1
  267. package/src/persistence/schema.ts +121 -40
  268. package/src/persistence/shared-cache.ts +2 -2
  269. package/src/persistence/sort-order.ts +1 -1
  270. package/src/persistence/stores/api-key-store.ts +29 -2
  271. package/src/persistence/stores/share-store.ts +20 -8
  272. package/src/persistence/system-prompt-store.ts +63 -18
  273. package/src/persistence/tenant-preferences.ts +1 -1
  274. package/src/persistence/ttl-cache.ts +3 -3
  275. package/src/persistence/usage-flush.ts +7 -2
  276. package/src/protocol/canonical-model.ts +1 -1
  277. package/src/protocol/codecs.ts +6 -10
  278. package/src/protocol/dsml.ts +8 -125
  279. package/src/protocol/image-clamp.ts +2 -2
  280. package/src/protocol/reasoning-text.ts +1 -1
  281. package/src/protocol/reasoning.ts +7 -52
  282. package/src/protocol/registry.ts +50 -15
  283. package/src/protocol/request/chat.ts +46 -19
  284. package/src/protocol/request/codex.ts +1 -1
  285. package/src/protocol/request/messages.ts +46 -14
  286. package/src/protocol/request/responses.ts +19 -10
  287. package/src/protocol/response/chat.ts +25 -10
  288. package/src/protocol/response/codex.ts +1 -1
  289. package/src/protocol/response/messages.ts +1 -1
  290. package/src/protocol/response/omp-tool-call-markup.ts +1 -1
  291. package/src/protocol/response/responses.ts +1 -1
  292. package/src/protocol/sse-decoder.ts +50 -1
  293. package/src/protocol/stop-reason.ts +2 -2
  294. package/src/protocol/think-split.ts +347 -0
  295. package/src/protocol/translation/attachment-integrity.ts +3 -3
  296. package/src/protocol/translation/cache-controls.ts +8 -20
  297. package/src/protocol/translation/capabilities.ts +6 -6
  298. package/src/protocol/translation/dialect/deepseek.ts +10 -0
  299. package/src/protocol/translation/dialect/inband.ts +39 -0
  300. package/src/protocol/translation/dialect/model-thinking.ts +89 -0
  301. package/src/protocol/translation/dialect/qwen.ts +114 -0
  302. package/src/protocol/translation/dialect/resolver.ts +83 -0
  303. package/src/protocol/translation/dialect/rules.ts +93 -0
  304. package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
  305. package/src/protocol/translation/dialect/types.ts +58 -0
  306. package/src/protocol/translation/quirks.ts +18 -4
  307. package/src/protocol/translation/thinking.ts +12 -252
  308. package/src/protocol/translation/tool-id.ts +3 -3
  309. package/src/protocol/translation/tool-repair.ts +1 -1
  310. package/src/protocol/upstream/post-json.ts +6 -1
  311. package/src/providers/adapters/compatible-adapter.ts +71 -4
  312. package/src/providers/authentication/jwt-validator.ts +0 -5
  313. package/src/providers/authentication/oauth-client.ts +254 -253
  314. package/src/providers/authentication/oauth-flow-store.ts +42 -7
  315. package/src/providers/bundled-discovery-providers.ts +6 -30
  316. package/src/providers/configured-openai-providers.ts +82 -97
  317. package/src/providers/default-registry.ts +35 -37
  318. package/src/providers/discovery/catalog/catalog-format.ts +13 -2
  319. package/src/providers/discovery/discovery-types.ts +0 -1
  320. package/src/providers/discovery/openai-model-discovery.ts +2 -2
  321. package/src/providers/discovery/probe-phases.ts +48 -13
  322. package/src/providers/discovery/probing-service.ts +6 -8
  323. package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
  324. package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
  325. package/src/providers/integrations/antigravity/antigravity-protocol.ts +88 -28
  326. package/src/providers/integrations/antigravity/antigravity-quota.ts +18 -6
  327. package/src/providers/integrations/antigravity/antigravity.ts +22 -13
  328. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
  329. package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
  330. package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
  331. package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
  332. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
  333. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
  334. package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
  335. package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
  336. package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
  337. package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
  338. package/src/providers/integrations/claude/claude-cch.ts +148 -148
  339. package/src/providers/integrations/claude/fallback-credit.ts +3 -7
  340. package/src/providers/integrations/cline/cline.ts +1 -1
  341. package/src/providers/integrations/codex/codex-device-code.ts +101 -101
  342. package/src/providers/integrations/codex/codex-oauth.ts +0 -1
  343. package/src/providers/integrations/commandcode/commandcode.ts +75 -115
  344. package/src/providers/integrations/commandcode/quota.ts +131 -51
  345. package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
  346. package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
  347. package/src/providers/integrations/cursor/cursor-request.ts +0 -87
  348. package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
  349. package/src/providers/integrations/cursor/cursor.ts +35 -3
  350. package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
  351. package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
  352. package/src/providers/integrations/factory/factory.ts +9 -9
  353. package/src/providers/integrations/github/github-discovery.ts +70 -12
  354. package/src/providers/integrations/github/github-oauth.ts +184 -14
  355. package/src/providers/integrations/github/github.ts +134 -26
  356. package/src/providers/integrations/grok/grok-oauth.ts +261 -261
  357. package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
  358. package/src/providers/integrations/grok/grok-quota.ts +16 -7
  359. package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
  360. package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
  361. package/src/providers/integrations/grok/grok.ts +86 -36
  362. package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
  363. package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
  364. package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
  365. package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
  366. package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
  367. package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
  368. package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
  369. package/src/providers/integrations/kiro/kiro-request.ts +8 -11
  370. package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
  371. package/src/providers/integrations/kiro/kiro.ts +80 -68
  372. package/src/providers/integrations/muse/muse-oauth.ts +0 -1
  373. package/src/providers/integrations/muse/muse-quota.ts +0 -4
  374. package/src/providers/integrations/opencode/fingerprint.ts +7 -5
  375. package/src/providers/integrations/opencode/provider.ts +17 -24
  376. package/src/providers/integrations/qoder/qoder-catalog.ts +94 -11
  377. package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
  378. package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
  379. package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
  380. package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
  381. package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
  382. package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
  383. package/src/providers/integrations/qoder/qoder.ts +422 -71
  384. package/src/providers/integrations/shared/connect.ts +0 -54
  385. package/src/providers/integrations/shared/hash.ts +15 -0
  386. package/src/providers/integrations/shared/session-cache.ts +136 -0
  387. package/src/providers/integrations/trae/trae-cache.ts +7 -87
  388. package/src/providers/integrations/trae/trae-catalog.ts +1 -6
  389. package/src/providers/integrations/trae/trae-protocol.ts +17 -8
  390. package/src/providers/integrations/trae/trae-realm.ts +0 -7
  391. package/src/providers/integrations/trae/trae.ts +51 -8
  392. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  393. package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
  394. package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
  395. package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
  396. package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
  397. package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
  398. package/src/providers/operations/account-error-classification.ts +198 -133
  399. package/src/providers/operations/account-health-service.ts +31 -39
  400. package/src/providers/operations/account-reset-service.ts +58 -1
  401. package/src/providers/operations/byok-wire-profile.ts +19 -15
  402. package/src/providers/operations/cli-platform.ts +31 -5
  403. package/src/providers/operations/client-version-resolver.ts +4 -6
  404. package/src/providers/operations/client-versions.ts +10 -7
  405. package/src/providers/operations/provider-catalog-seeder.ts +2 -0
  406. package/src/providers/operations/provider-catalog-service.ts +18 -2
  407. package/src/providers/operations/provider-credential-service.ts +19 -2
  408. package/src/providers/provider-contracts.ts +18 -7
  409. package/src/providers/provider-metadata.ts +17 -2
  410. package/src/providers/provider-model-definition.ts +22 -1
  411. package/src/providers/provider-probe.ts +4 -2
  412. package/src/providers/provider-usage.ts +50 -19
  413. package/src/providers/quota/cache.ts +29 -0
  414. package/src/providers/quota/quota-contracts.ts +4 -0
  415. package/src/providers/quota/refresh.ts +27 -4
  416. package/src/providers/quota/snapshot.ts +94 -0
  417. package/src/providers/search/search-provider.ts +1 -3
  418. package/src/providers/search/search-providers.ts +2 -1
  419. package/src/security/abuse.ts +4 -4
  420. package/src/security/admission/service.ts +13 -6
  421. package/src/security/admission/ttl.ts +61 -61
  422. package/src/security/api-key-auth.ts +17 -3
  423. package/src/security/client-router-fingerprint.ts +4 -4
  424. package/src/security/credential-codec.ts +3 -3
  425. package/src/security/csrf.ts +2 -2
  426. package/src/security/ip-boundary.ts +16 -189
  427. package/src/security/model-access-rule.ts +1 -1
  428. package/src/security/outbound-headers.ts +18 -0
  429. package/src/shared/invoke-guard.ts +47 -0
  430. package/src/transport/contracts.ts +13 -4
  431. package/src/transport/dispatch/attempt-finalize.ts +70 -22
  432. package/src/transport/dispatch/attempt-loop.ts +22 -0
  433. package/src/transport/dispatch/capture-policy.ts +34 -37
  434. package/src/transport/dispatch/empty-stream.ts +23 -20
  435. package/src/transport/dispatch/generation.ts +25 -45
  436. package/src/transport/dispatch/native-shared.ts +127 -0
  437. package/src/transport/dispatch/proxy-request.ts +3 -1
  438. package/src/transport/dispatch/responses-compact.ts +25 -46
  439. package/src/transport/dispatch/streaming/encoder.ts +18 -72
  440. package/src/transport/dispatch/streaming/finalize.ts +2 -2
  441. package/src/transport/dispatch/streaming/stream.ts +7 -3
  442. package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
  443. package/src/transport/dispatch/systemone.ts +20 -48
  444. package/src/transport/dispatch/token-count.ts +41 -38
  445. package/src/transport/dispatch/websearch.ts +19 -45
  446. package/src/transport/drain-endpoint.ts +1 -1
  447. package/src/transport/failure-policy.ts +21 -1
  448. package/src/transport/guards/auth-guard.ts +0 -6
  449. package/src/transport/guards/body-policy.ts +3 -3
  450. package/src/transport/guards/error-lifecycle.ts +4 -0
  451. package/src/transport/guards/headroom-guard.ts +1 -1
  452. package/src/transport/guards/pipeline.ts +1 -1
  453. package/src/transport/guards/request-context.ts +12 -17
  454. package/src/transport/request/preparer.ts +286 -7
  455. package/src/transport/request/rtk/compress-request.ts +3 -3
  456. package/src/transport/request/rtk/rtk-constants.ts +2 -2
  457. package/src/transport/request/rtk/rtk-filters.ts +8 -8
  458. package/src/transport/request/state.ts +7 -13
  459. package/src/transport/request/system-prompt-injection.ts +74 -11
  460. package/src/transport/request/tenant-preferences.ts +22 -0
  461. package/src/transport/routing/candidate-index.ts +2 -2
  462. package/src/transport/routing/round-robin.ts +1 -1
  463. package/src/transport/routing/route-catalog.ts +17 -18
  464. package/src/transport/routing/route-model.ts +126 -33
  465. package/src/transport/routing/router.ts +159 -37
  466. package/src/transport/shutdown-notice.ts +2 -2
  467. package/src/transport/surface/adapters.ts +3 -3
  468. package/src/transport/surface/chat/encode.ts +7 -7
  469. package/src/transport/surface/chat/parse.ts +7 -7
  470. package/src/transport/surface/completion.ts +2 -2
  471. package/src/transport/surface/content-parts.ts +1 -1
  472. package/src/transport/surface/dialects.ts +2 -2
  473. package/src/transport/surface/messages/parse.ts +3 -3
  474. package/src/transport/surface/reasoning-summary.ts +9 -14
  475. package/src/transport/surface/responses/adapter.ts +1 -1
  476. package/src/transport/surface/responses/errors.ts +0 -9
  477. package/src/transport/vision-handoff-cache.ts +58 -0
  478. package/src/transport/vision-handoff.ts +431 -0
  479. package/src/workers/account-identity-sweep.ts +2 -2
  480. package/src/workers/buddy-growth-tasks.ts +392 -346
  481. package/src/workers/daily-checkin.ts +102 -49
  482. package/src/workers/maintenance-lease.ts +2 -35
  483. package/src/workers/oauth-refresh-sweep.ts +8 -1
  484. package/src/workers/quota-refresh-sweep.ts +120 -82
  485. package/src/workers/scheduler.ts +67 -4
  486. package/src/workers/sweep-runner.ts +24 -5
  487. package/src/workers/zcode-gift-claim.ts +108 -0
  488. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
  489. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
  490. package/dist/dashboard/assets/BannedPage-ChG5svFb.js +0 -1
  491. package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
  492. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +0 -1
  493. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
  494. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +0 -1
  495. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
  496. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
  497. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
  498. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
  499. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
  500. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js +0 -1
  501. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
  502. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
  503. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
  504. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js +0 -1
  505. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
  506. package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
  507. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
  508. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
  509. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
  510. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
  511. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
  512. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  513. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
  514. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
  515. package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
  516. package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
  517. package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
  518. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
  519. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
  520. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js +0 -1
  521. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
  522. package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
  523. package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
  524. package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
  525. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js +0 -1
  526. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
  527. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
  528. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
  529. package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
  530. package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
  531. package/dist/dashboard/assets/app-BayTTy01.js +0 -9
  532. package/dist/dashboard/assets/app-BayTTy01.js.gz +0 -0
  533. package/dist/dashboard/assets/app-a159k0ub.css +0 -2
  534. package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
  535. package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
  536. package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
  537. package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
  538. package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
  539. package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
  540. package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
  541. package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
  542. package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
  543. package/dist/dashboard/assets/dialog-8fiE6tec.js +0 -1
  544. package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
  545. package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
  546. package/dist/dashboard/assets/entry-BSAsYsmV.js +0 -1
  547. package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
  548. package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
  549. package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
  550. package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
  551. package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
  552. package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
  553. package/dist/dashboard/assets/github-badge-CPK47xQx.js +0 -1
  554. package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
  555. package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
  556. package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
  557. package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
  558. package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
  559. package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
  560. package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
  561. package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
  562. package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
  563. package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
  564. package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
  565. package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
  566. package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
  567. package/dist/dashboard/assets/providers/zai-coding-plan.svg +0 -6
  568. package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
  569. package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
  570. package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
  571. package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
  572. package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
  573. package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
  574. package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
  575. package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
  576. package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
  577. package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
  578. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
  579. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  580. package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
  581. package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
  582. package/src/console/cli-tools/injectors/cline.ts +0 -110
  583. package/src/console/cli-tools/injectors/copilot.ts +0 -108
  584. package/src/console/cli-tools/injectors/cowork.ts +0 -64
  585. package/src/console/cli-tools/injectors/deepseek-tui.ts +0 -85
  586. package/src/console/cli-tools/injectors/droid.ts +0 -96
  587. package/src/console/cli-tools/injectors/grok-build.ts +0 -70
  588. package/src/console/cli-tools/injectors/hermes.ts +0 -101
  589. package/src/console/cli-tools/injectors/jcode.ts +0 -115
  590. package/src/console/cli-tools/injectors/openclaw.ts +0 -161
  591. package/src/network/response-headers.ts +0 -39
  592. package/src/protocol/response/dsml.ts +0 -38
  593. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
  594. /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
  595. /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
@@ -10,39 +10,13 @@ import { createApiKeyAdapter, type ApiKeyProviderSpec } from "./configured-provi
10
10
  * OpenAI-compatible contract. Providers with static catalogs or additional
11
11
  * upstream behavior remain declared beside their special handling.
12
12
  */
13
- export const DISCOVERY_BACKED_PROVIDER_IDS = [
14
- "groq",
15
- "together",
16
- "deepinfra",
17
- "siliconflow",
18
- "siliconflowcn",
19
- "novita",
20
- "larprouter",
21
- "venice",
22
- "nanogpt",
23
- "baseten",
24
- "synthetic",
25
- "stepfun",
26
- "sakana",
27
- "helmcode",
28
- "coralbricks",
29
- "aiand",
30
- "wafer",
31
- "firepass",
32
- "zhipucoding",
33
- "dashscope",
34
- "qianfan",
35
- ] as const;
36
-
37
- export type DiscoveryBackedProviderId = (typeof DISCOVERY_BACKED_PROVIDER_IDS)[number];
38
-
39
13
  type DiscoveryBackedCapabilities = Pick<
40
14
  ProviderModule,
41
15
  "endpointPathsByWireFamily" | "loadAdapter" | "loadModelDiscovery"
42
16
  >;
43
17
 
44
18
  type ModelDiscoveryFactory = NonNullable<ProviderModule["loadModelDiscovery"]>;
45
- type OpenAIModelDiscoveryFactory = (
19
+ export type OpenAIModelDiscoveryFactory = (
46
20
  providerId: string,
47
21
  options?: {
48
22
  readonly headers?: (credential: string) => Readonly<Record<string, string>>;
@@ -71,10 +45,12 @@ const DISCOVERY_BACKED_PROVIDER_SPECS = {
71
45
  zhipucoding: VERSIONED_ROOT_API_KEY_SPECS.zhipucoding,
72
46
  dashscope: GENERIC_API_KEY_SPECS.dashscope,
73
47
  qianfan: VERSIONED_ROOT_API_KEY_SPECS.qianfan,
74
- } satisfies Readonly<Record<DiscoveryBackedProviderId, ApiKeyProviderSpec>>;
48
+ } satisfies Readonly<Record<string, ApiKeyProviderSpec>>;
75
49
 
76
- function discoveryBackedCapabilities(
77
- providerId: DiscoveryBackedProviderId,
50
+ type DiscoveryBackedProviderId = keyof typeof DISCOVERY_BACKED_PROVIDER_SPECS;
51
+
52
+ export function discoveryBackedCapabilities(
53
+ providerId: string,
78
54
  spec: ApiKeyProviderSpec,
79
55
  openAIModelDiscovery: OpenAIModelDiscoveryFactory,
80
56
  ): DiscoveryBackedCapabilities {
@@ -1,12 +1,36 @@
1
1
  import type { ApiKeyProviderSpec } from "./configured-provider";
2
2
  import type { ProviderId } from "./provider-contracts";
3
3
 
4
+ /**
5
+ * The shared spec builder for every builtin bearer-AI provider: "bearer auth
6
+ * against the provider's `BUNDLED_PROVIDER_METADATA` base URL, OpenAI-compatible
7
+ * chat + responses, with the endpoint paths declared *below* the version root".
8
+ *
9
+ * `joinUrl` is plain concatenation and nothing rewrites a declared path, so a
10
+ * base already rooted at a version (`/openai/v1`, `/v1/openai`, `/v3/openai`,
11
+ * `/api/v1`, `/v2`, `/inference/v1`) plus a `/v1/…` path would double the
12
+ * segment and 404 every request. These specs therefore declare the path below
13
+ * the version root — the provider stating the truth about its own wire, not a
14
+ * correction applied to it.
15
+ */
16
+ function apiKeySpec(
17
+ providerId: ProviderId,
18
+ paths: Readonly<Partial<Record<"chat" | "responses", string>>>,
19
+ ): ApiKeyProviderSpec {
20
+ return {
21
+ provider_id: providerId,
22
+ endpoint_paths_by_wire_family: paths,
23
+ };
24
+ }
25
+
26
+ const BEARER_PATHS = { chat: "/chat/completions", responses: "/responses" } as const;
27
+
4
28
  /**
5
29
  * Builtin providers whose entire adapter contract is "bearer auth against the
6
30
  * provider's `BUNDLED_PROVIDER_METADATA` base URL, OpenAI-compatible chat +
7
- * responses, `/v1`-prefixed paths". They carry no catalog, no OAuth, and no
8
- * provider-specific payload hook, so they share one spec shape rather than
9
- * one module each.
31
+ * responses, with endpoint paths declared below the base's version root". They
32
+ * carry no catalog, no OAuth, and no provider-specific payload hook, so they
33
+ * share one spec shape rather than one module each.
10
34
  *
11
35
  * `base_url` is resolved per provider by `providerBaseUrl(provider_id)`.
12
36
  *
@@ -14,29 +38,31 @@ import type { ProviderId } from "./provider-contracts";
14
38
  * than a static catalog: every one of them republishes an aggregator's whole
15
39
  * roster, which changes faster than a committed array can. Each registry row
16
40
  * pairs this spec with `openAIModelDiscovery`.
41
+ *
42
+ * The id list is derived from the spec record so the two cannot drift apart.
17
43
  */
18
- export const GENERIC_API_KEY_PROVIDER_IDS = [
19
- "larprouter",
20
- "mistral",
21
- "fireworks",
22
- "nvidia",
23
- "gmi",
24
- "ollamacloud",
25
- "together",
26
- "siliconflow",
27
- "siliconflowcn",
28
- "nanogpt",
29
- "baseten",
30
- "synthetic",
31
- "stepfun",
32
- "sakana",
33
- "helmcode",
34
- "coralbricks",
35
- "aiand",
36
- "wafer",
37
- "coreweave",
38
- "qwen-portal",
39
- "dashscope",
44
+ export const GENERIC_API_KEY_SPECS = {
45
+ larprouter: apiKeySpec("larprouter", BEARER_PATHS),
46
+ mistral: apiKeySpec("mistral", BEARER_PATHS),
47
+ fireworks: apiKeySpec("fireworks", BEARER_PATHS),
48
+ nvidia: apiKeySpec("nvidia", BEARER_PATHS),
49
+ gmi: apiKeySpec("gmi", BEARER_PATHS),
50
+ ollamacloud: apiKeySpec("ollamacloud", BEARER_PATHS),
51
+ together: apiKeySpec("together", BEARER_PATHS),
52
+ siliconflow: apiKeySpec("siliconflow", BEARER_PATHS),
53
+ siliconflowcn: apiKeySpec("siliconflowcn", BEARER_PATHS),
54
+ nanogpt: apiKeySpec("nanogpt", BEARER_PATHS),
55
+ baseten: apiKeySpec("baseten", BEARER_PATHS),
56
+ synthetic: apiKeySpec("synthetic", BEARER_PATHS),
57
+ stepfun: apiKeySpec("stepfun", BEARER_PATHS),
58
+ sakana: apiKeySpec("sakana", BEARER_PATHS),
59
+ helmcode: apiKeySpec("helmcode", BEARER_PATHS),
60
+ coralbricks: apiKeySpec("coralbricks", BEARER_PATHS),
61
+ aiand: apiKeySpec("aiand", BEARER_PATHS),
62
+ wafer: apiKeySpec("wafer", BEARER_PATHS),
63
+ coreweave: apiKeySpec("coreweave", BEARER_PATHS),
64
+ dashscope: apiKeySpec("dashscope", BEARER_PATHS),
65
+ "qwen-portal": apiKeySpec("qwen-portal", BEARER_PATHS),
40
66
  // `deepseek` is intentionally absent: it dispatches on the Anthropic Messages
41
67
  // wire at its `/anthropic` root, not the OpenAI chat/responses wires, so it
42
68
  // carries a dedicated entry in `default-registry.ts` instead.
@@ -45,10 +71,24 @@ export const GENERIC_API_KEY_PROVIDER_IDS = [
45
71
  // already rooted at a version segment that the `/v1`-prefixed path this shape
46
72
  // pins would duplicate (`/openai/v1`, `/v1/openai`, `/v3/openai`, `/api/v1`,
47
73
  // `/v2`, and `/inference/v1`), so `joinUrl` would produce
48
- // `…/v1/v1/chat/completions`. They use `versionedRootApiKeySpec` instead,
74
+ // `…/v1/v1/chat/completions`. They use the versioned-root spec instead,
49
75
  // which pins the path below the version root — the same reason `cerebras`
50
76
  // declares `/chat/completions` explicitly.
51
- ] as const;
77
+ } satisfies Readonly<Record<string, ApiKeyProviderSpec>>;
78
+
79
+ /**
80
+ * One id that has both a generic spec and a registry row.
81
+ *
82
+ * Exported so the registry can be checked against the spec list rather than
83
+ * repeating the id as a string: `discoveryBackedProvider` takes this type, so a
84
+ * row naming a provider with no spec is a compile error instead of an
85
+ * `undefined` adapter at first dispatch.
86
+ */
87
+ export type GenericApiKeyProviderId = keyof typeof GENERIC_API_KEY_SPECS;
88
+
89
+ export const GENERIC_API_KEY_PROVIDER_IDS = Object.keys(
90
+ GENERIC_API_KEY_SPECS,
91
+ ) as readonly GenericApiKeyProviderId[];
52
92
 
53
93
  /**
54
94
  * Ids whose base URL already ends at a version segment.
@@ -59,77 +99,22 @@ export const GENERIC_API_KEY_PROVIDER_IDS = [
59
99
  * version root. That is the provider stating the truth about its own wire, not
60
100
  * a correction applied to it: a wrong path now reaches the operator as the
61
101
  * wrong URL instead of being quietly rewritten into a different address.
62
- */
63
- export const VERSIONED_ROOT_API_KEY_PROVIDER_IDS = [
64
- "groq",
65
- "deepinfra",
66
- "novita",
67
- "venice",
68
- "qianfan",
69
- "zhipucoding",
70
- "firepass",
71
- ] as const;
72
-
73
- export type VersionedRootApiKeyProviderId =
74
- (typeof VERSIONED_ROOT_API_KEY_PROVIDER_IDS)[number];
75
-
76
- function versionedRootApiKeySpec(providerId: ProviderId): ApiKeyProviderSpec {
77
- return {
78
- provider_id: providerId,
79
- endpoint_paths_by_wire_family: {
80
- chat: "/chat/completions",
81
- responses: "/responses",
82
- },
83
- };
84
- }
85
-
86
- export const VERSIONED_ROOT_API_KEY_SPECS = {
87
- groq: versionedRootApiKeySpec("groq"),
88
- deepinfra: versionedRootApiKeySpec("deepinfra"),
89
- novita: versionedRootApiKeySpec("novita"),
90
- venice: versionedRootApiKeySpec("venice"),
91
- qianfan: versionedRootApiKeySpec("qianfan"),
92
- zhipucoding: versionedRootApiKeySpec("zhipucoding"),
93
- firepass: versionedRootApiKeySpec("firepass"),
94
- } satisfies Readonly<Record<VersionedRootApiKeyProviderId, ApiKeyProviderSpec>>;
95
-
96
- /**
97
- * One id that has both a generic spec and a registry row.
98
102
  *
99
- * Exported so the registry can be checked against the spec list rather than
100
- * repeating the id as a string: `discoveryBackedProvider` takes this type, so a
101
- * row naming a provider with no spec is a compile error instead of an
102
- * `undefined` adapter at first dispatch.
103
+ * The id list is derived from the spec record so the two cannot drift apart.
103
104
  */
104
- export type GenericApiKeyProviderId = (typeof GENERIC_API_KEY_PROVIDER_IDS)[number];
105
+ export const VERSIONED_ROOT_API_KEY_SPECS = {
106
+ groq: apiKeySpec("groq", BEARER_PATHS),
107
+ deepinfra: apiKeySpec("deepinfra", BEARER_PATHS),
108
+ novita: apiKeySpec("novita", BEARER_PATHS),
109
+ venice: apiKeySpec("venice", BEARER_PATHS),
110
+ qianfan: apiKeySpec("qianfan", BEARER_PATHS),
111
+ zhipucoding: apiKeySpec("zhipucoding", BEARER_PATHS),
112
+ firepass: apiKeySpec("firepass", BEARER_PATHS),
113
+ } satisfies Readonly<Record<string, ApiKeyProviderSpec>>;
105
114
 
106
- function genericApiKeySpec(providerId: GenericApiKeyProviderId): ApiKeyProviderSpec {
107
- // These roots are *not* bare hosts — every one of them already ends at `/v1`
108
- // — so the path is declared below that root. Both spec shapes declare the same
109
- // thing, so this is the one implementation.
110
- return versionedRootApiKeySpec(providerId);
111
- }
115
+ export type VersionedRootApiKeyProviderId =
116
+ keyof typeof VERSIONED_ROOT_API_KEY_SPECS;
112
117
 
113
- export const GENERIC_API_KEY_SPECS = {
114
- larprouter: genericApiKeySpec("larprouter"),
115
- mistral: genericApiKeySpec("mistral"),
116
- fireworks: genericApiKeySpec("fireworks"),
117
- nvidia: genericApiKeySpec("nvidia"),
118
- gmi: genericApiKeySpec("gmi"),
119
- ollamacloud: genericApiKeySpec("ollamacloud"),
120
- together: genericApiKeySpec("together"),
121
- siliconflow: genericApiKeySpec("siliconflow"),
122
- siliconflowcn: genericApiKeySpec("siliconflowcn"),
123
- nanogpt: genericApiKeySpec("nanogpt"),
124
- baseten: genericApiKeySpec("baseten"),
125
- synthetic: genericApiKeySpec("synthetic"),
126
- stepfun: genericApiKeySpec("stepfun"),
127
- sakana: genericApiKeySpec("sakana"),
128
- helmcode: genericApiKeySpec("helmcode"),
129
- coralbricks: genericApiKeySpec("coralbricks"),
130
- aiand: genericApiKeySpec("aiand"),
131
- wafer: genericApiKeySpec("wafer"),
132
- coreweave: genericApiKeySpec("coreweave"),
133
- dashscope: genericApiKeySpec("dashscope"),
134
- "qwen-portal": genericApiKeySpec("qwen-portal"),
135
- } satisfies Readonly<Record<GenericApiKeyProviderId, ApiKeyProviderSpec>>;
118
+ export const VERSIONED_ROOT_API_KEY_PROVIDER_IDS = Object.keys(
119
+ VERSIONED_ROOT_API_KEY_SPECS,
120
+ ) as readonly VersionedRootApiKeyProviderId[];
@@ -5,7 +5,7 @@
5
5
  import {
6
6
  GENERIC_API_KEY_SPECS,
7
7
  } from "./configured-openai-providers";
8
- import { createDiscoveryBackedProviderCapabilities } from "./bundled-discovery-providers";
8
+ import { createDiscoveryBackedProviderCapabilities, discoveryBackedCapabilities } from "./bundled-discovery-providers";
9
9
  import { createApiKeyAdapter } from "./configured-provider";
10
10
  import type { ApiKeyProviderSpec } from "./configured-provider";
11
11
  import { oauthCapability, quotaCapability, type ProviderModuleCapabilities } from "./provider-capabilities";
@@ -131,39 +131,6 @@ function qoderDiscovery(
131
131
  }
132
132
 
133
133
 
134
- /**
135
- * Builds the `loadAdapter` + `loadModelDiscovery` pair every plain bearer
136
- * provider needs.
137
- *
138
- * Only the base URL differs between them, so both halves are shared: the
139
- * adapter is the generic spec and the discovery call is a bearer
140
- * `GET {base}/models`. Keeping them in one function is what stops the pairing
141
- * from drifting — registering a provider with one half and not the other is
142
- * exactly how `gmi`, `nvidia`, and `fireworks` came to ship with no catalog
143
- * *and* no discovery, which is a provider that lists zero models with no way to
144
- * fetch any. `test/providers/generic-provider-completeness.test.ts` holds both.
145
- */
146
- function discoveryBacked(
147
- providerId: string,
148
- spec: ApiKeyProviderSpec,
149
- ): ProviderModuleCapabilities {
150
- return {
151
- // The registry map is what discovery and probing read
152
- // (`discoveryPathsFor`), while the spec's copy is what the adapter
153
- // dispatches on. Setting only the spec leaves a discovered model resolving
154
- // its wire from the generic default instead of the path the adapter will
155
- // actually call, which is how a probe verifies one endpoint while dispatch
156
- // hits another.
157
- ...(spec.endpoint_paths_by_wire_family === undefined
158
- ? {}
159
- : { endpointPathsByWireFamily: spec.endpoint_paths_by_wire_family }),
160
- loadAdapter: async () => createApiKeyAdapter(spec),
161
- loadModelDiscovery: openAIModelDiscovery(providerId, {
162
- headers: (credential) => ({ authorization: `Bearer ${credential}` }),
163
- }),
164
- };
165
- }
166
-
167
134
  function openAIModelDiscovery(
168
135
  providerId: string,
169
136
  options?: {
@@ -272,8 +239,18 @@ export const PROVIDER_CAPABILITIES = {
272
239
  loadAuthentication: oauthCapability(() => import("./integrations/antigravity/antigravity-oauth"), "antigravityOAuthClient", { withRefresher: true }),
273
240
  loadQuotaCollector: quotaCapability(() => import("./integrations/antigravity/antigravity-quota"), "fetchAntigravityQuota"),
274
241
  loadModelDiscovery: async () => async ({ baseUrl, credential, fetcher }) => {
275
- const { discoverAntigravityModels } = await import("./integrations/antigravity/antigravity-protocol");
276
- return discoverAntigravityModels(credential, { baseUrl, ...(fetcher ? { fetcher } : {}) });
242
+ const { discoverAntigravityModels, loadAntigravityProject } = await import("./integrations/antigravity/antigravity-protocol");
243
+ // The reference client resolves the project before catalog calls; the
244
+ // live backend accepts both, but sending it matches the captured wire.
245
+ const projectId = await loadAntigravityProject(credential, {
246
+ ...(baseUrl === undefined ? {} : { baseUrl }),
247
+ ...(fetcher ? { fetcher } : {}),
248
+ }).catch(() => undefined);
249
+ return discoverAntigravityModels(credential, {
250
+ baseUrl,
251
+ ...(fetcher ? { fetcher } : {}),
252
+ ...(projectId === undefined ? {} : { projectId }),
253
+ });
277
254
  },
278
255
  },
279
256
  muse: {
@@ -617,6 +594,27 @@ export const PROVIDER_CAPABILITIES = {
617
594
  // and Z.AI publishes no refresh grant for it (`refresh "none"` upstream).
618
595
  loadAuthentication: oauthCapability(() => import("./integrations/zcode/oauth"), "zcodeOAuthClient"),
619
596
  },
597
+ "zcode-start": {
598
+ // Free plan surface: an Anthropic-Messages endpoint that only accepts the
599
+ // dressed ZCode client request (see the integration). The credential is a
600
+ // ZCode login JWT — pasted, or minted by the sign-in flow below.
601
+ loadAdapter: async () =>
602
+ createApiKeyAdapter(
603
+ (await import("./integrations/zcode-start-plan/provider")).ZCODE_START_PLAN_SPEC,
604
+ ),
605
+ loadModels: async () =>
606
+ (await import("./integrations/zcode-start-plan/provider")).ZCODE_START_PLAN_MODELS,
607
+ // The device flow stores the issued ZCode login JWT, not a Coding Plan key.
608
+ loadAuthentication: oauthCapability(
609
+ () => import("./integrations/zcode-start-plan/oauth"),
610
+ "zcodeStartPlanOAuthClient",
611
+ ),
612
+ // Keep each reported entitlement and activation/reset window separate.
613
+ loadQuotaCollector: quotaCapability(
614
+ () => import("./integrations/zcode-start-plan/quota"),
615
+ "fetchZcodeStartPlanQuota",
616
+ ),
617
+ },
620
618
  "factory": {
621
619
  loadAdapter: async () => (await import("./integrations/factory/factory")).factoryAdapter,
622
620
  // Factory publishes no model-listing endpoint — the roster is a client-side
@@ -765,7 +763,7 @@ export const PROVIDER_CAPABILITIES = {
765
763
  // synced account sees whatever the plan currently serves. The catalog keeps
766
764
  // the provider usable before anyone syncs.
767
765
  dashscope: {
768
- ...discoveryBacked("dashscope", GENERIC_API_KEY_SPECS.dashscope),
766
+ ...discoveryBackedCapabilities("dashscope", GENERIC_API_KEY_SPECS.dashscope, openAIModelDiscovery),
769
767
  loadModels: async () => (await import("./integrations/dashscope-models")).DASHSCOPE_MODELS,
770
768
  },
771
769
 
@@ -420,13 +420,24 @@ export class PackedCatalog {
420
420
  return metadata;
421
421
  }
422
422
 
423
- /** Stated context limit, or `null`. */
423
+ /**
424
+ * Stated context limit, or `null`.
425
+ *
426
+ * Stored in a `Uint32Array` column; the generator
427
+ * (`scripts/tools/generate-models.ts`) refuses to write a value ≥ 2^31
428
+ * (`checkedPackedLimit`), so no row here can wrap modulo 2^32 and decode as a
429
+ * garbage limit.
430
+ */
424
431
  rowContext(index: number): number | null {
425
432
  const value = this.u32At(this.layout.ctx + index * 4);
426
433
  return value > 0 ? value : null;
427
434
  }
428
435
 
429
- /** Stated output limit, or `null`. */
436
+ /**
437
+ * Stated output limit, or `null`.
438
+ *
439
+ * Same u32 storage contract as `rowContext` — see the generator guard.
440
+ */
430
441
  rowOutput(index: number): number | null {
431
442
  const value = this.u32At(this.layout.out + index * 4);
432
443
  return value > 0 ? value : null;
@@ -1,7 +1,6 @@
1
1
  import type { FetchLike } from "../quota/quota-contracts";
2
2
  import type { ModelDefinition } from "../provider-model-definition";
3
3
  import type { ServiceKind } from "../../protocol/canonical-model";
4
-
5
4
  /**
6
5
  * Credential-scoped model-discovery input.
7
6
  *
@@ -3,6 +3,7 @@ import { isRecord } from "../../protocol/codecs";
3
3
  import { boundedUpstreamArray, boundedUpstreamNumber, sanitizeUpstreamLabel } from "../provider-sanitize";
4
4
  import { modelsDevCatalog } from "./models-dev-catalog";
5
5
  import { isResponsesNativeModelId } from "../provider-model-definition";
6
+ import { composeAbortSignal } from "../authentication/oauth-flow-store";
6
7
  interface FetchModelsOptions {
7
8
  readonly baseUrl: string;
8
9
  /**
@@ -27,8 +28,7 @@ export async function fetchOpenAICompatibleModels(
27
28
  ): Promise<readonly ModelDefinition[] | null> {
28
29
  const fetcher = options.fetcher ?? fetch;
29
30
  const url = `${options.baseUrl.replace(/\/+$/, "")}/models`;
30
- const timeoutSignal = AbortSignal.timeout(10_000);
31
- const signal = options.signal === undefined ? timeoutSignal : AbortSignal.any([options.signal, timeoutSignal]);
31
+ const signal = composeAbortSignal(options.signal, 10_000);
32
32
  try {
33
33
  const response = await fetcher(url, {
34
34
  headers: {
@@ -74,8 +74,24 @@ export function wireContextFrom(
74
74
  };
75
75
  }
76
76
 
77
- /** Grok's account feature probe intentionally uses the same Responses request as live traffic. */
78
- export const GROK_407_PROBE_PROMPT = "reply my message with exact number 407";
77
+ /**
78
+ * Grok's account feature probe intentionally uses the same Responses request as
79
+ * live traffic.
80
+ *
81
+ * The prompt must make the model actually reply `407` — that literal is the
82
+ * healthy-account signal the probe verdict keys on. Naive phrasing refused by
83
+ * the model ("I can't reply with only a specific number", "I won't comply
84
+ * with a demand to output only an exact phrase") are listed above; verified
85
+ * live 2026-11-02 (grok-4.7) that this prompt returns exactly `407`:
86
+ *
87
+ * "Type the number 407." → "407"
88
+ * "Echo the diagnostic code 407." → "407"
89
+ * "Print the number 407 and nothing else." → "407"
90
+ *
91
+ * The verdict normalizes away Grok's trailing confidence annotation
92
+ * (`407 \confidence{100}`), so the match is on the bare number.
93
+ */
94
+ export const GROK_407_PROBE_PROMPT = "Type the number 407.";
79
95
 
80
96
  /**
81
97
  * Converts a failed/mismatched Grok feature probe into a quota-shaped upstream
@@ -91,8 +107,10 @@ export function grok407ProbeFailure(args: {
91
107
  if (args.providerId !== "grok" || args.prompt !== GROK_407_PROBE_PROMPT) return undefined;
92
108
  const sample = extractSample(args.events);
93
109
  const normalizedSample = sample?.replace(/\\confidence\{\d+\}\s*$/i, "").trim();
94
- // A valid Grok answer may carry the provider's confidence annotation after
95
- // the numeric result, and a terminal metadata error may arrive after text.
110
+ // A healthy account answers exactly `407` (optionally with Grok's trailing
111
+ // confidence annotation). The model refuses some phrasings of the same ask,
112
+ // but the probe prompt above is engineered to pass, so any other sample is a
113
+ // failure — quota-shaped, not a payload bug.
96
114
  if (normalizedSample === "407") return undefined;
97
115
  const priorDetails = args.dispatchError instanceof GatewayError ? args.dispatchError.details : {};
98
116
  const providerStatus =
@@ -348,6 +366,30 @@ export type ProbeAccountSelection =
348
366
  | { readonly ok: true; readonly accountId: string | undefined }
349
367
  | { readonly ok: false; readonly error: string };
350
368
 
369
+ /**
370
+ * Selects the first usable account row: status ≠ disabled, cooldown elapsed
371
+ * (unless `allowCoolingAccount`), preferring a tenant-owned account over a
372
+ * shared global one. Shared by the discovery and probing paths so both
373
+ * agree on which account a provider answers as.
374
+ */
375
+ export function selectUsableAccount<T extends {
376
+ readonly tenantId: string | null;
377
+ readonly status: string;
378
+ readonly cooldownUntil: Date | null;
379
+ }>(
380
+ rows: readonly T[],
381
+ allowCoolingAccount = false,
382
+ now = Date.now(),
383
+ ): T | undefined {
384
+ return rows
385
+ .filter(
386
+ (row) =>
387
+ row.status !== "disabled" &&
388
+ (allowCoolingAccount || row.cooldownUntil === null || row.cooldownUntil.getTime() <= now),
389
+ )
390
+ .sort((left, right) => Number(right.tenantId !== null) - Number(left.tenantId !== null))[0];
391
+ }
392
+
351
393
  /**
352
394
  * Phase 2 — pick the account the probe runs as. Snapshot-equivalent health
353
395
  * filtering: disabled accounts and live cooldowns never route, so probes must
@@ -388,15 +430,8 @@ export async function selectProbeAccount(args: {
388
430
  ),
389
431
  )
390
432
  : [];
391
- const now = Date.now();
392
- const usableAccounts = accountRows
393
- .filter(
394
- (row) =>
395
- row.status !== "disabled" &&
396
- (allowCoolingAccount || row.cooldownUntil === null || row.cooldownUntil.getTime() <= now),
397
- )
398
- .sort((left, right) => Number(right.tenantId !== null) - Number(left.tenantId !== null));
399
- const accountId = requestedAccountId ?? usableAccounts[0]?.id;
433
+ const usableAccount = selectUsableAccount(accountRows, allowCoolingAccount);
434
+ const accountId = requestedAccountId ?? usableAccount?.id;
400
435
  if (!accountId && requiresAccount) {
401
436
  return {
402
437
  ok: false,
@@ -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";
@@ -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 now = Date.now();
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 {
@@ -16,9 +16,19 @@ import { readCredentialSecret, assertWireFamily, type ProviderDispatchTarget, ty
16
16
  import { providerBaseUrl } from "../../provider-metadata";
17
17
  import { buildClaudeMessagesRequest } from "../shared/claude-messages";
18
18
  import { sendClaudeMessagesRequest } from "../../../protocol/upstream/send-claude-messages";
19
+ import { ANTHROPIC_BETA_CAPABILITIES } from "../claude/claude-betas";
19
20
 
20
21
  export const AGENTROUTER_PROVIDER_ID = "agentrouter" as const;
21
- export const AGENTROUTER_BASE_URL = `${providerBaseUrl("agentrouter")}/v1/messages?beta=true`;
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
+ ];
22
32
 
23
33
  /**
24
34
  * The AgentRouter CLI fingerprint headers. Every value is part of the
@@ -29,7 +39,7 @@ export const AGENTROUTER_BASE_URL = `${providerBaseUrl("agentrouter")}/v1/messag
29
39
  */
30
40
  function agentRouterFingerprintHeaders(stream: boolean): Record<string, string> {
31
41
  return {
32
- "anthropic-beta": "claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24",
42
+ "anthropic-beta": AGENTROUTER_ANTHROPIC_BETAS.join(","),
33
43
  "anthropic-dangerous-direct-browser-access": "true",
34
44
  "x-app": "cli",
35
45
  "user-agent": "claude-cli/2.1.195 (external, sdk-cli)",
@@ -212,4 +212,3 @@ export class AntigravityOAuthClient extends OAuthClient {
212
212
  }
213
213
 
214
214
  export const antigravityOAuthClient = new AntigravityOAuthClient();
215
- export { exchangeCodeForToken };