cartethyia 2.7.9 → 2.8.1

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 (496) hide show
  1. package/.env.example +6 -5
  2. package/dist/dashboard/assets/{BannedPage-BxoG1MrL.js → BannedPage-Dq530awD.js} +1 -1
  3. package/dist/dashboard/assets/BannedPage-Dq530awD.js.gz +0 -0
  4. package/dist/dashboard/assets/{CliToolDetailPage-ixwgKk53.js → CliToolDetailPage-DZzaS-7S.js} +1 -1
  5. package/dist/dashboard/assets/CliToolDetailPage-DZzaS-7S.js.gz +0 -0
  6. package/dist/dashboard/assets/{CliToolsPage-BmttNV3U.js → CliToolsPage-DaZZ3cqP.js} +1 -1
  7. package/dist/dashboard/assets/CliToolsPage-DaZZ3cqP.js.gz +0 -0
  8. package/dist/dashboard/assets/{CombosPage-BE3qwwfC.js → CombosPage-BlC_xdkX.js} +1 -1
  9. package/dist/dashboard/assets/CombosPage-BlC_xdkX.js.gz +0 -0
  10. package/dist/dashboard/assets/{ConsoleLogPage-CRZdmMIX.js → ConsoleLogPage-D-rqeVtG.js} +1 -1
  11. package/dist/dashboard/assets/ConsoleLogPage-D-rqeVtG.js.gz +0 -0
  12. package/dist/dashboard/assets/{CustomizationPage-Dv_FJ6Er.js → CustomizationPage-7xT5yg2E.js} +1 -1
  13. package/dist/dashboard/assets/CustomizationPage-7xT5yg2E.js.gz +0 -0
  14. package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js +1 -0
  15. package/dist/dashboard/assets/HealthEventsModal-Clq8E9cW.js.gz +0 -0
  16. package/dist/dashboard/assets/{InjectSystemPromptPanel-BOoO8rpz.js → InjectSystemPromptPanel-6Teoq9Se.js} +2 -2
  17. package/dist/dashboard/assets/InjectSystemPromptPanel-6Teoq9Se.js.gz +0 -0
  18. package/dist/dashboard/assets/{LoginPage-ChJuNNVN.js → LoginPage-CZuI0MAR.js} +1 -1
  19. package/dist/dashboard/assets/LoginPage-CZuI0MAR.js.gz +0 -0
  20. package/dist/dashboard/assets/{ModelPicker-BZAJtPg1.js → ModelPicker-C1hNTlkr.js} +1 -1
  21. package/dist/dashboard/assets/ModelPicker-C1hNTlkr.js.gz +0 -0
  22. package/dist/dashboard/assets/{OverviewPage-BE40s3u5.js → OverviewPage-0yfhSI1C.js} +1 -1
  23. package/dist/dashboard/assets/OverviewPage-0yfhSI1C.js.gz +0 -0
  24. package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js +8 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-xqTxdQ4c.js.gz +0 -0
  26. package/dist/dashboard/assets/{ProviderIcon-CQ6bPUf_.js → ProviderIcon-Ddhm1InL.js} +1 -1
  27. package/dist/dashboard/assets/ProviderIcon-Ddhm1InL.js.gz +0 -0
  28. package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js +1 -0
  29. package/dist/dashboard/assets/ProvidersPage-C3fYuu6i.js.gz +0 -0
  30. package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js +9 -0
  31. package/dist/dashboard/assets/ProxyPage-CHtJtZ3u.js.gz +0 -0
  32. package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js +1 -0
  33. package/dist/dashboard/assets/QuotaPage-D1RV_2BX.js.gz +0 -0
  34. package/dist/dashboard/assets/{SettingsPage-C5HPWqEv.js → SettingsPage-BzZAvYSX.js} +1 -1
  35. package/dist/dashboard/assets/SettingsPage-BzZAvYSX.js.gz +0 -0
  36. package/dist/dashboard/assets/{SetupPage-CFNcATJJ.js → SetupPage--s-EfEIL.js} +1 -1
  37. package/dist/dashboard/assets/SetupPage--s-EfEIL.js.gz +0 -0
  38. package/dist/dashboard/assets/{StudioPage-YoD4tY5l.js → StudioPage-BjXFGSK4.js} +1 -1
  39. package/dist/dashboard/assets/StudioPage-BjXFGSK4.js.gz +0 -0
  40. package/dist/dashboard/assets/{UsagePage-DxjaAhb_.js → UsagePage-CP8F8BN7.js} +1 -1
  41. package/dist/dashboard/assets/UsagePage-CP8F8BN7.js.gz +0 -0
  42. package/dist/dashboard/assets/{api-keys-BTlkq_Uk.js → api-keys-2hc12Uz2.js} +1 -1
  43. package/dist/dashboard/assets/api-keys-2hc12Uz2.js.gz +0 -0
  44. package/dist/dashboard/assets/app-DGXbNfAR.css +2 -0
  45. package/dist/dashboard/assets/app-DGXbNfAR.css.gz +0 -0
  46. package/dist/dashboard/assets/assert-BMcj1xZE.js +1 -0
  47. package/dist/dashboard/assets/assert-BMcj1xZE.js.gz +0 -0
  48. package/dist/dashboard/assets/{badge-DdbT_7Am.js → badge-DkRUuVfz.js} +1 -1
  49. package/dist/dashboard/assets/badge-DkRUuVfz.js.gz +0 -0
  50. package/dist/dashboard/assets/{banner-CsGN-nbm.js → banner-CDjW841Q.js} +1 -1
  51. package/dist/dashboard/assets/banner-CDjW841Q.js.gz +0 -0
  52. package/dist/dashboard/assets/{card-mgZ_TLLZ.js → card-Bto5UlL9.js} +1 -1
  53. package/dist/dashboard/assets/card-Bto5UlL9.js.gz +0 -0
  54. package/dist/dashboard/assets/{cli-tools-A1-v8-03.js → cli-tools-DaH6g9hL.js} +1 -1
  55. package/dist/dashboard/assets/cli-tools-DaH6g9hL.js.gz +0 -0
  56. package/dist/dashboard/assets/{clipboard-button-CJ4Zty89.js → clipboard-button-BYKBCzjk.js} +1 -1
  57. package/dist/dashboard/assets/clipboard-button-BYKBCzjk.js.gz +0 -0
  58. package/dist/dashboard/assets/{dialog-B5L2jPQ_.js → dialog-DL0Zftwv.js} +1 -1
  59. package/dist/dashboard/assets/dialog-DL0Zftwv.js.gz +0 -0
  60. package/dist/dashboard/assets/{drawer-DkjUouAj.js → drawer-Dpx_UXaS.js} +1 -1
  61. package/dist/dashboard/assets/drawer-Dpx_UXaS.js.gz +0 -0
  62. package/dist/dashboard/assets/{entry-B-LVLV6o.js → entry-BV7-1NoM.js} +1 -1
  63. package/dist/dashboard/assets/entry-BV7-1NoM.js.gz +0 -0
  64. package/dist/dashboard/assets/{entry-CAhdYl3B.js → entry-CGvdNU6r.js} +1 -1
  65. package/dist/dashboard/assets/entry-CGvdNU6r.js.gz +0 -0
  66. package/dist/dashboard/assets/entry-DScKYvZj.js +4 -0
  67. package/dist/dashboard/assets/entry-DScKYvZj.js.gz +0 -0
  68. package/dist/dashboard/assets/{formatters-CrsdLVsn.js → formatters-BS3DZlZj.js} +1 -1
  69. package/dist/dashboard/assets/formatters-BS3DZlZj.js.gz +0 -0
  70. package/dist/dashboard/assets/{index-BU64Lqvp.js → index-SQnvvTWX.js} +2 -2
  71. package/dist/dashboard/assets/index-SQnvvTWX.js.gz +0 -0
  72. package/dist/dashboard/assets/{inline-B2aDLyyg.js → inline-Dl-cuLK0.js} +1 -1
  73. package/dist/dashboard/assets/inline-Dl-cuLK0.js.gz +0 -0
  74. package/dist/dashboard/assets/{input-BCVkdR9d.js → input-Bfx0EzRc.js} +1 -1
  75. package/dist/dashboard/assets/input-Bfx0EzRc.js.gz +0 -0
  76. package/dist/dashboard/assets/{layout-DNcAdMK-.js → layout-BxhbQ_JS.js} +1 -1
  77. package/dist/dashboard/assets/layout-BxhbQ_JS.js.gz +0 -0
  78. package/dist/dashboard/assets/{list-row-DgrIH0hw.js → list-row-D49Y4ptn.js} +1 -1
  79. package/dist/dashboard/assets/list-row-D49Y4ptn.js.gz +0 -0
  80. package/dist/dashboard/assets/{live-Cae01iu8.js → live-CbVTdX9V.js} +1 -1
  81. package/dist/dashboard/assets/live-CbVTdX9V.js.gz +0 -0
  82. package/dist/dashboard/assets/{network-CRib7H_2.js → network-JGvDveof.js} +1 -1
  83. package/dist/dashboard/assets/network-JGvDveof.js.gz +0 -0
  84. package/dist/dashboard/assets/{numbers-BKQE8Xpz.js → numbers-Dw6kiew-.js} +1 -1
  85. package/dist/dashboard/assets/numbers-Dw6kiew-.js.gz +0 -0
  86. package/dist/dashboard/assets/{pagination-ecPvG_8g.js → pagination-iUoI8GeE.js} +1 -1
  87. package/dist/dashboard/assets/pagination-iUoI8GeE.js.gz +0 -0
  88. package/dist/dashboard/assets/providers/sensenova-intl.png +0 -0
  89. package/dist/dashboard/assets/providers/sensenova.png +0 -0
  90. package/dist/dashboard/assets/providers/zro.svg +3 -0
  91. package/dist/dashboard/assets/providers/zro.svg.gz +0 -0
  92. package/dist/dashboard/assets/quota-DiPD6UKH.js +1 -0
  93. package/dist/dashboard/assets/quota-DiPD6UKH.js.gz +0 -0
  94. package/dist/dashboard/assets/{routing-Ckm1UXuC.js → routing-8jZr-3WE.js} +1 -1
  95. package/dist/dashboard/assets/routing-8jZr-3WE.js.gz +0 -0
  96. package/dist/dashboard/assets/{select-ChoFWyKz.js → select-oO1FxMVb.js} +2 -2
  97. package/dist/dashboard/assets/select-oO1FxMVb.js.gz +0 -0
  98. package/dist/dashboard/assets/{settings-CKjFPlKW.js → settings-CLr3kdIx.js} +1 -1
  99. package/dist/dashboard/assets/settings-CLr3kdIx.js.gz +0 -0
  100. package/dist/dashboard/assets/{stack-DWCwU3fh.js → stack-Y3pDteZr.js} +1 -1
  101. package/dist/dashboard/assets/stack-Y3pDteZr.js.gz +0 -0
  102. package/dist/dashboard/assets/{state-Cg3VL5J_.js → state-CArX_Iak.js} +1 -1
  103. package/dist/dashboard/assets/state-CArX_Iak.js.gz +0 -0
  104. package/dist/dashboard/assets/{switch-Db70BMix.js → switch-DwlwmDO-.js} +1 -1
  105. package/dist/dashboard/assets/switch-DwlwmDO-.js.gz +0 -0
  106. package/dist/dashboard/assets/{useMutation-BqdE0LuM.js → useMutation-DJ9GYEgf.js} +1 -1
  107. package/dist/dashboard/assets/useMutation-DJ9GYEgf.js.gz +0 -0
  108. package/dist/dashboard/index.html +2 -2
  109. package/dist/dashboard/index.html.gz +0 -0
  110. package/dist/dashboard/precompressed-assets.json +54 -53
  111. package/migrations/full-postgres/0046_add_accounts_quota_plan_fetched_at.sql +7 -0
  112. package/migrations/full-postgres/0047_add_provider_device_flow_proxy.sql +17 -0
  113. package/migrations/lite-sqlite3/0046_add_accounts_quota_plan_fetched_at.sql +4 -0
  114. package/migrations/lite-sqlite3/0047_add_provider_device_flow_proxy.sql +19 -0
  115. package/package.json +1 -1
  116. package/src/boot/app.ts +11 -14
  117. package/src/boot/dependencies.ts +5 -7
  118. package/src/boot/flush.ts +20 -0
  119. package/src/boot/lifecycle.ts +7 -5
  120. package/src/config/providers.ts +6 -5
  121. package/src/config/routing.ts +26 -0
  122. package/src/config/spec-metadata.ts +72 -0
  123. package/src/config/spec.ts +28 -8
  124. package/src/console/api-keys/contracts.ts +12 -1
  125. package/src/console/api-keys/routes.ts +40 -28
  126. package/src/console/auth/account-reset.ts +7 -9
  127. package/src/console/backup/contracts.ts +4 -0
  128. package/src/console/backup/export-endpoint.ts +7 -5
  129. package/src/console/backup/nine-router.ts +71 -10
  130. package/src/console/backup/service.ts +8 -1
  131. package/src/console/cli-tools/service.ts +6 -12
  132. package/src/console/console-router-guards.ts +23 -16
  133. package/src/console/console-router.ts +1 -1
  134. package/src/console/domain-registration.ts +7 -4
  135. package/src/console/inferhub/client.ts +1 -1
  136. package/src/console/inferhub/normalize.ts +24 -28
  137. package/src/console/inferhub/types.ts +3 -0
  138. package/src/console/ip-bans/routes.ts +7 -13
  139. package/src/console/observability/live.ts +2 -2
  140. package/src/console/observability/store.ts +0 -53
  141. package/src/console/providers/catalog/contracts.ts +9 -3
  142. package/src/console/providers/catalog/model-operations.ts +2 -3
  143. package/src/console/providers/catalog/provider-operations.ts +1 -1
  144. package/src/console/providers/catalog/routes.ts +3 -2
  145. package/src/console/providers/catalog/store.ts +1914 -1902
  146. package/src/console/providers/detail/routes.ts +1 -0
  147. package/src/console/providers/detail/store.ts +4 -0
  148. package/src/console/providers/oauth/callback-listener.ts +30 -11
  149. package/src/console/providers/oauth/device-egress.ts +123 -0
  150. package/src/console/providers/oauth/routes.ts +123 -16
  151. package/src/console/quota/account-quota-global.ts +14 -24
  152. package/src/console/quota/account-quota-shared.ts +49 -0
  153. package/src/console/quota/account-quota-tenant.ts +11 -23
  154. package/src/console/quota/account-test-egress.ts +2 -2
  155. package/src/console/quota/daily-growth-job.ts +1 -1
  156. package/src/console/quota/quota-view.ts +19 -3
  157. package/src/console/routing/pools/contracts.ts +1 -1
  158. package/src/console/routing/pools/operations.ts +32 -47
  159. package/src/console/routing/pools/probe-verdict.ts +2 -2
  160. package/src/console/routing/pools/relay-deploy.ts +1 -1
  161. package/src/console/routing/pools/store.ts +4 -4
  162. package/src/console/shared/errors.ts +33 -6
  163. package/src/main.ts +2 -3
  164. package/src/network/client.ts +67 -0
  165. package/src/network/egress/bidi-session.ts +322 -0
  166. package/src/network/egress/dial.ts +201 -0
  167. package/src/network/egress/factory.ts +191 -0
  168. package/src/network/{outbound-fetch.ts → egress/fetch.ts} +195 -29
  169. package/src/network/egress/tls-profile.ts +123 -0
  170. package/src/network/egress/ws.ts +175 -0
  171. package/src/network/pool/{byte-accounting.ts → accounting.ts} +3 -2
  172. package/src/network/{types.ts → pool/agent-config.ts} +1 -1
  173. package/src/network/pool/agent.ts +2 -2
  174. package/src/network/{pool-cooldown-store.ts → pool/cooldown-store.ts} +95 -20
  175. package/src/network/{pool-health-machine.ts → pool/health.ts} +205 -6
  176. package/src/network/pool/resolver.ts +10 -849
  177. package/src/network/pool/selector.ts +184 -41
  178. package/src/network/ssrf.ts +7 -7
  179. package/src/network/{retry.ts → util/retry.ts} +1 -1
  180. package/src/network/{rate-limit-verdict.ts → verdict.ts} +1 -1
  181. package/src/observability/event-log.ts +7 -361
  182. package/src/observability/performance-metrics.ts +9 -0
  183. package/src/observability/runtime-metrics.ts +14 -9
  184. package/src/observability/telemetry-buffer.ts +16 -26
  185. package/src/observability/telemetry-reconciliation.ts +9 -37
  186. package/src/observability/telemetry-row.ts +125 -0
  187. package/src/persistence/db-mode.ts +4 -1
  188. package/src/persistence/dialect.ts +18 -0
  189. package/src/persistence/migrate.ts +6 -3
  190. package/src/persistence/schema.ts +17 -0
  191. package/src/persistence/ttl-cache.ts +21 -3
  192. package/src/protocol/codecs.ts +59 -2
  193. package/src/protocol/dsml.ts +34 -86
  194. package/src/protocol/markup-stream-parser.ts +195 -0
  195. package/src/protocol/reasoning-text.ts +19 -0
  196. package/src/protocol/request/chat.ts +10 -10
  197. package/src/protocol/request/gemini.ts +8 -2
  198. package/src/protocol/request/messages.ts +34 -22
  199. package/src/protocol/response/chat.ts +12 -20
  200. package/src/protocol/response/messages.ts +34 -7
  201. package/src/protocol/response/omp-tool-call-markup.ts +43 -86
  202. package/src/protocol/response/responses.ts +18 -2
  203. package/src/protocol/stop-reason.ts +23 -1
  204. package/src/protocol/think-split.ts +112 -0
  205. package/src/protocol/translation/dialect/qwen.ts +26 -58
  206. package/src/protocol/translation/quirks.ts +15 -0
  207. package/src/protocol/upstream/send-claude-messages.ts +2 -2
  208. package/src/providers/adapters/compatible-adapter.ts +76 -12
  209. package/src/providers/authentication/oauth-client.ts +40 -6
  210. package/src/providers/authentication/oauth-device-flow.ts +105 -11
  211. package/src/providers/authentication/oauth-flow-store.ts +82 -1
  212. package/src/providers/authentication/oauth-refresh-service.ts +766 -758
  213. package/src/providers/configured-provider.ts +148 -0
  214. package/src/providers/default-registry.ts +137 -36
  215. package/src/providers/discovery/discovery-types.ts +7 -0
  216. package/src/providers/discovery/probe-phases.ts +20 -6
  217. package/src/providers/discovery/probing-service.ts +22 -2
  218. package/src/providers/integrations/alibabacp/alibabacp-models.ts +1 -2
  219. package/src/providers/integrations/{dashscope-models.ts → alibabacp/dashscope-models.ts} +2 -2
  220. package/src/providers/integrations/antigravity/antigravity-protocol.ts +16 -1
  221. package/src/providers/integrations/buddy/account.ts +969 -0
  222. package/src/providers/integrations/buddy/capabilities.ts +12 -12
  223. package/src/providers/integrations/buddy/{buddy-catalog-shared.ts → catalog.ts} +198 -136
  224. package/src/providers/integrations/buddy/{buddy-chat-shared.ts → chat.ts} +176 -20
  225. package/src/providers/integrations/buddy/codebuddy/index.ts +429 -0
  226. package/src/providers/integrations/buddy/codebuddy/shared.ts +41 -26
  227. package/src/providers/integrations/buddy/headers.ts +311 -0
  228. package/src/providers/integrations/buddy/lifecycle.ts +1018 -0
  229. package/src/providers/integrations/buddy/{buddy-media.ts → media.ts} +1 -1
  230. package/src/providers/integrations/claude/claude-quota.ts +14 -17
  231. package/src/providers/integrations/cline/cline-oauth.ts +10 -5
  232. package/src/providers/integrations/cline/cline.ts +5 -6
  233. package/src/providers/integrations/clixad/clixad-oauth.ts +98 -0
  234. package/src/providers/integrations/clixad/clixad-quota.ts +132 -0
  235. package/src/providers/integrations/clixad/provider.ts +145 -0
  236. package/src/providers/integrations/codex/codex-oauth.ts +8 -5
  237. package/src/providers/integrations/commandcode/quota.ts +22 -28
  238. package/src/providers/integrations/cursor/cursor-auth.ts +1 -9
  239. package/src/providers/integrations/cursor/cursor-exec.ts +9 -2
  240. package/src/providers/integrations/cursor/cursor-hardening.ts +279 -0
  241. package/src/providers/integrations/cursor/cursor-http2.ts +605 -6
  242. package/src/providers/integrations/cursor/cursor-request.ts +26 -12
  243. package/src/providers/integrations/cursor/cursor-shared.ts +8 -5
  244. package/src/providers/integrations/cursor/cursor.ts +574 -110
  245. package/src/providers/integrations/cursor/protocol/messages.ts +22 -29
  246. package/src/providers/integrations/cursor/protocol/protobuf-schema.ts +37 -0
  247. package/src/providers/integrations/deepai/deepai-catalog.ts +149 -0
  248. package/src/providers/integrations/deepai/deepai-common.ts +145 -0
  249. package/src/providers/integrations/deepai/deepai-oauth.ts +129 -0
  250. package/src/providers/integrations/deepai/deepai-quota.ts +97 -0
  251. package/src/providers/integrations/deepai/provider.ts +42 -0
  252. package/src/providers/integrations/devin/devin-auth.ts +7 -0
  253. package/src/providers/integrations/devin/protocol/devin-proto.ts +1 -27
  254. package/src/providers/integrations/factory/factory-oauth.ts +33 -51
  255. package/src/providers/integrations/freebuff/assets/official-system-manager.txt +88 -0
  256. package/src/providers/integrations/freebuff/assets/official-system-worker.txt +57 -0
  257. package/src/providers/integrations/freebuff/assets/official-tools.json +1070 -0
  258. package/src/providers/integrations/freebuff/freebuff-catalog.ts +120 -0
  259. package/src/providers/integrations/freebuff/freebuff-constants.ts +1233 -0
  260. package/src/providers/integrations/freebuff/freebuff-discovery.ts +108 -0
  261. package/src/providers/integrations/freebuff/freebuff-oauth.ts +240 -0
  262. package/src/providers/integrations/freebuff/freebuff-quota.ts +260 -0
  263. package/src/providers/integrations/freebuff/freebuff-virtual.ts +89 -0
  264. package/src/providers/integrations/freebuff/freebuff.ts +682 -0
  265. package/src/providers/integrations/freepi/freepi-catalog.ts +5 -0
  266. package/src/providers/integrations/freepi/freepi-discovery.ts +2 -2
  267. package/src/providers/integrations/freepi/freepi-headers.ts +2 -2
  268. package/src/providers/integrations/freepi/freepi-protocol.ts +11 -2
  269. package/src/providers/integrations/freepi/freepi-realm.ts +0 -3
  270. package/src/providers/integrations/freepi/freepi-session.ts +158 -0
  271. package/src/providers/integrations/freepi/freepi.ts +80 -54
  272. package/src/providers/integrations/github/github-discovery.ts +30 -13
  273. package/src/providers/integrations/github/github-oauth.ts +217 -44
  274. package/src/providers/integrations/github/github-quota.ts +22 -5
  275. package/src/providers/integrations/github/github.ts +40 -32
  276. package/src/providers/integrations/grok/grok-oauth.ts +52 -49
  277. package/src/providers/integrations/grok/grok-ratelimit-store.ts +10 -17
  278. package/src/providers/integrations/grok/grok-turn-index.ts +11 -16
  279. package/src/providers/integrations/hermes/hermes-oauth.ts +3 -3
  280. package/src/providers/integrations/{hermes.ts → hermes/hermes.ts} +42 -13
  281. package/src/providers/integrations/hermes/index.ts +2 -0
  282. package/src/providers/integrations/kilo/kilo-oauth.ts +4 -4
  283. package/src/providers/integrations/kilo/kilo.ts +1 -1
  284. package/src/providers/integrations/kimi/kimi-oauth.ts +3 -3
  285. package/src/providers/integrations/kiro/kiro-catalog.ts +17 -1
  286. package/src/providers/integrations/kiro/kiro-discovery.ts +10 -12
  287. package/src/providers/integrations/kiro/kiro-oauth.ts +2 -2
  288. package/src/providers/integrations/kiro/kiro-quota.ts +8 -4
  289. package/src/providers/integrations/kiro/kiro.ts +15 -19
  290. package/src/providers/integrations/muse/muse-oauth.ts +5 -5
  291. package/src/providers/integrations/ollamacloud/index.ts +2 -0
  292. package/src/providers/integrations/{ollamacloud-models.ts → ollamacloud/models.ts} +2 -2
  293. package/src/providers/integrations/{ollamacloud-quota.ts → ollamacloud/quota.ts} +3 -3
  294. package/src/providers/integrations/opencode/fingerprint.ts +1 -1
  295. package/src/providers/integrations/opencode/opencode-go-quota.ts +2 -8
  296. package/src/providers/integrations/openrouter/provider.ts +1 -1
  297. package/src/providers/integrations/perch/perch-credential.ts +25 -0
  298. package/src/providers/integrations/perch/perch-protocol.ts +0 -6
  299. package/src/providers/integrations/perch/perch-quota.ts +2 -16
  300. package/src/providers/integrations/perch/perch.ts +6 -16
  301. package/src/providers/integrations/qoder/claim-qoder-credits.ts +19 -60
  302. package/src/providers/integrations/qoder/qoder-adapter.ts +20 -125
  303. package/src/providers/integrations/qoder/qoder-auth.ts +109 -30
  304. package/src/providers/integrations/qoder/qoder-catalog.ts +21 -6
  305. package/src/providers/integrations/qoder/qoder-chat.ts +32 -29
  306. package/src/providers/integrations/qoder/qoder-checkin.ts +5 -5
  307. package/src/providers/integrations/qoder/qoder-cosy.ts +37 -9
  308. package/src/providers/integrations/qoder/qoder-oauth.ts +9 -2
  309. package/src/providers/integrations/qoder/qoder-realm.ts +13 -36
  310. package/src/providers/integrations/qoder/qoder-sse.ts +447 -68
  311. package/src/providers/integrations/qoder/qoder-types.ts +9 -0
  312. package/src/providers/integrations/qoder/qoder.ts +3 -26
  313. package/src/providers/integrations/sensenova/provider.ts +144 -0
  314. package/src/providers/integrations/trae/trae-protocol.ts +9 -5
  315. package/src/providers/integrations/trae/trae-quota.ts +21 -29
  316. package/src/providers/integrations/trae/trae-realm.ts +38 -0
  317. package/src/providers/integrations/trae/trae.ts +7 -24
  318. package/src/providers/integrations/vercel/provider.ts +117 -0
  319. package/src/providers/integrations/vercel/vercel-quota.ts +96 -0
  320. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  321. package/src/providers/integrations/zcode-start-plan/gifts.ts +1 -1
  322. package/src/providers/integrations/zcode-start-plan/oauth.ts +3 -3
  323. package/src/providers/integrations/zcode-start-plan/provider.ts +226 -23
  324. package/src/providers/integrations/zcode-start-plan/quota.ts +19 -2
  325. package/src/providers/integrations/zro/zro.ts +205 -0
  326. package/src/providers/operations/account-error-classification.ts +199 -307
  327. package/src/providers/operations/account-health-service.ts +82 -1
  328. package/src/providers/operations/account-refresh-status.ts +36 -37
  329. package/src/providers/operations/account-tier.ts +15 -16
  330. package/src/providers/operations/client-version-resolver.ts +1 -1
  331. package/src/providers/operations/client-versions.ts +100 -81
  332. package/src/providers/operations/cooldown-rules.ts +11 -16
  333. package/src/providers/operations/oauth-refresh-lead.ts +46 -22
  334. package/src/providers/operations/{model-catalog-cache.ts → provider-caches.ts} +68 -16
  335. package/src/providers/operations/provider-catalog-service.ts +1 -1
  336. package/src/providers/operations/provider-credential-service.ts +118 -51
  337. package/src/providers/operations/provider-rules/github.ts +48 -0
  338. package/src/providers/operations/provider-rules/grok.ts +33 -0
  339. package/src/providers/operations/provider-rules/inception.ts +49 -0
  340. package/src/providers/operations/provider-rules/index.ts +32 -0
  341. package/src/providers/operations/provider-rules/perch.ts +37 -0
  342. package/src/providers/operations/provider-rules/qoder.ts +70 -0
  343. package/src/providers/operations/provider-rules/trae.ts +81 -0
  344. package/src/providers/operations/session-resolution.ts +17 -1
  345. package/src/providers/provider-contracts.ts +6 -4
  346. package/src/providers/{provider-credential-resolver.ts → provider-credentials.ts} +40 -3
  347. package/src/providers/provider-metadata.ts +70 -10
  348. package/src/providers/provider-probe.ts +15 -1
  349. package/src/providers/provider-registry.ts +42 -33
  350. package/src/providers/quota/quota-contracts.ts +2 -0
  351. package/src/providers/quota/quota-limit-windows.ts +16 -5
  352. package/src/providers/quota/quota-support.ts +1 -1
  353. package/src/providers/quota/quota-window-parser.ts +90 -18
  354. package/src/providers/quota/refresh.ts +100 -21
  355. package/src/security/api-key-auth-cache.ts +1 -1
  356. package/src/security/api-key-auth.ts +6 -2
  357. package/src/security/ip-boundary.ts +1 -1
  358. package/src/transport/dispatch/attempt-finalize.ts +15 -14
  359. package/src/transport/dispatch/attempt-loop.ts +73 -19
  360. package/src/transport/dispatch/generation.ts +2 -8
  361. package/src/transport/dispatch/handler-deps.ts +1 -1
  362. package/src/transport/dispatch/leases.ts +1 -1
  363. package/src/transport/dispatch/native-shared.ts +25 -0
  364. package/src/transport/dispatch/proxy-request.ts +8 -46
  365. package/src/transport/dispatch/responses-compact.ts +2 -8
  366. package/src/transport/dispatch/retry-policy.ts +1 -1
  367. package/src/transport/dispatch/streaming/finalize.ts +10 -7
  368. package/src/transport/dispatch/streaming/stream.ts +9 -37
  369. package/src/transport/dispatch/systemone.ts +2 -8
  370. package/src/transport/dispatch/token-count.ts +2 -6
  371. package/src/transport/dispatch/upstream.ts +63 -0
  372. package/src/transport/drain-endpoint.ts +31 -4
  373. package/src/transport/failure-policy.ts +16 -30
  374. package/src/transport/guards/body-policy.ts +7 -1
  375. package/src/transport/guards/error-lifecycle.ts +13 -1
  376. package/src/transport/guards/request-context.ts +22 -14
  377. package/src/transport/request/preparer.ts +81 -71
  378. package/src/transport/routing/bounded-lru.ts +14 -0
  379. package/src/transport/routing/drain-reserve.ts +129 -0
  380. package/src/transport/routing/plan-gate.ts +7 -1
  381. package/src/transport/routing/round-robin.ts +60 -0
  382. package/src/transport/routing/route-catalog.ts +123 -111
  383. package/src/transport/routing/route-model.ts +51 -9
  384. package/src/transport/routing/router.ts +393 -32
  385. package/src/transport/shutdown-notice.ts +1 -1
  386. package/src/transport/surface/adapters.ts +11 -2
  387. package/src/transport/surface/chat/adapter.ts +2 -2
  388. package/src/transport/surface/chat/encode.ts +47 -4
  389. package/src/transport/surface/chat/parse.ts +2 -12
  390. package/src/transport/surface/completion.ts +44 -33
  391. package/src/transport/surface/content-parts.ts +21 -0
  392. package/src/transport/surface/messages/adapter.ts +7 -1
  393. package/src/transport/surface/messages/encode.ts +11 -3
  394. package/src/transport/surface/messages/parse.ts +2 -1
  395. package/src/transport/surface/messages/stream.ts +33 -17
  396. package/src/transport/surface/responses/encode.ts +22 -5
  397. package/src/transport/surface/responses/parse.ts +3 -11
  398. package/src/workers/buddy-growth-tasks.ts +8 -8
  399. package/src/workers/daily-checkin.ts +4 -4
  400. package/src/workers/quota-refresh-sweep.ts +1 -1
  401. package/src/workers/zcode-gift-claim.ts +1 -1
  402. package/dist/dashboard/assets/BannedPage-BxoG1MrL.js.gz +0 -0
  403. package/dist/dashboard/assets/CliToolDetailPage-ixwgKk53.js.gz +0 -0
  404. package/dist/dashboard/assets/CliToolsPage-BmttNV3U.js.gz +0 -0
  405. package/dist/dashboard/assets/CombosPage-BE3qwwfC.js.gz +0 -0
  406. package/dist/dashboard/assets/ConsoleLogPage-CRZdmMIX.js.gz +0 -0
  407. package/dist/dashboard/assets/CustomizationPage-Dv_FJ6Er.js.gz +0 -0
  408. package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js +0 -1
  409. package/dist/dashboard/assets/HealthEventsModal-CoVrw2sM.js.gz +0 -0
  410. package/dist/dashboard/assets/InjectSystemPromptPanel-BOoO8rpz.js.gz +0 -0
  411. package/dist/dashboard/assets/LoginPage-ChJuNNVN.js.gz +0 -0
  412. package/dist/dashboard/assets/ModelPicker-BZAJtPg1.js.gz +0 -0
  413. package/dist/dashboard/assets/OverviewPage-BE40s3u5.js.gz +0 -0
  414. package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js +0 -8
  415. package/dist/dashboard/assets/ProviderDetailPage-sfLoQtPV.js.gz +0 -0
  416. package/dist/dashboard/assets/ProviderIcon-CQ6bPUf_.js.gz +0 -0
  417. package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js +0 -1
  418. package/dist/dashboard/assets/ProvidersPage-DcepmPWo.js.gz +0 -0
  419. package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js +0 -9
  420. package/dist/dashboard/assets/ProxyPage-BJ87Pp0U.js.gz +0 -0
  421. package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js +0 -1
  422. package/dist/dashboard/assets/QuotaPage-gkSyRAKa.js.gz +0 -0
  423. package/dist/dashboard/assets/SettingsPage-C5HPWqEv.js.gz +0 -0
  424. package/dist/dashboard/assets/SetupPage-CFNcATJJ.js.gz +0 -0
  425. package/dist/dashboard/assets/StudioPage-YoD4tY5l.js.gz +0 -0
  426. package/dist/dashboard/assets/UsagePage-DxjaAhb_.js.gz +0 -0
  427. package/dist/dashboard/assets/api-keys-BTlkq_Uk.js.gz +0 -0
  428. package/dist/dashboard/assets/app-BX2nnKqs.css +0 -2
  429. package/dist/dashboard/assets/app-BX2nnKqs.css.gz +0 -0
  430. package/dist/dashboard/assets/assert-CndthXFQ.js +0 -1
  431. package/dist/dashboard/assets/assert-CndthXFQ.js.gz +0 -0
  432. package/dist/dashboard/assets/badge-DdbT_7Am.js.gz +0 -0
  433. package/dist/dashboard/assets/banner-CsGN-nbm.js.gz +0 -0
  434. package/dist/dashboard/assets/card-mgZ_TLLZ.js.gz +0 -0
  435. package/dist/dashboard/assets/cli-tools-A1-v8-03.js.gz +0 -0
  436. package/dist/dashboard/assets/clipboard-button-CJ4Zty89.js.gz +0 -0
  437. package/dist/dashboard/assets/dialog-B5L2jPQ_.js.gz +0 -0
  438. package/dist/dashboard/assets/drawer-DkjUouAj.js.gz +0 -0
  439. package/dist/dashboard/assets/entry-B-LVLV6o.js.gz +0 -0
  440. package/dist/dashboard/assets/entry-CAhdYl3B.js.gz +0 -0
  441. package/dist/dashboard/assets/entry-D2xD0Tmd.js +0 -4
  442. package/dist/dashboard/assets/entry-D2xD0Tmd.js.gz +0 -0
  443. package/dist/dashboard/assets/formatters-CrsdLVsn.js.gz +0 -0
  444. package/dist/dashboard/assets/index-BU64Lqvp.js.gz +0 -0
  445. package/dist/dashboard/assets/inline-B2aDLyyg.js.gz +0 -0
  446. package/dist/dashboard/assets/input-BCVkdR9d.js.gz +0 -0
  447. package/dist/dashboard/assets/layout-DNcAdMK-.js.gz +0 -0
  448. package/dist/dashboard/assets/list-row-DgrIH0hw.js.gz +0 -0
  449. package/dist/dashboard/assets/live-Cae01iu8.js.gz +0 -0
  450. package/dist/dashboard/assets/network-CRib7H_2.js.gz +0 -0
  451. package/dist/dashboard/assets/numbers-BKQE8Xpz.js.gz +0 -0
  452. package/dist/dashboard/assets/pagination-ecPvG_8g.js.gz +0 -0
  453. package/dist/dashboard/assets/quota-DJ1QlAOq.js +0 -1
  454. package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
  455. package/dist/dashboard/assets/routing-Ckm1UXuC.js.gz +0 -0
  456. package/dist/dashboard/assets/select-ChoFWyKz.js.gz +0 -0
  457. package/dist/dashboard/assets/settings-CKjFPlKW.js.gz +0 -0
  458. package/dist/dashboard/assets/stack-DWCwU3fh.js.gz +0 -0
  459. package/dist/dashboard/assets/state-Cg3VL5J_.js.gz +0 -0
  460. package/dist/dashboard/assets/switch-Db70BMix.js.gz +0 -0
  461. package/dist/dashboard/assets/useMutation-BqdE0LuM.js.gz +0 -0
  462. package/src/network/pool-health.ts +0 -210
  463. package/src/providers/bundled-discovery-providers.ts +0 -98
  464. package/src/providers/configured-openai-providers.ts +0 -120
  465. package/src/providers/integrations/buddy/buddy-checkin.ts +0 -521
  466. package/src/providers/integrations/buddy/buddy-cli-headers.ts +0 -76
  467. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -130
  468. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +0 -234
  469. package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -496
  470. package/src/providers/integrations/buddy/buddy-identity.ts +0 -300
  471. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +0 -341
  472. package/src/providers/integrations/buddy/buddy-quota-shared.ts +0 -417
  473. package/src/providers/integrations/buddy/buddy-server-tools.ts +0 -240
  474. package/src/providers/integrations/buddy/buddy-usage-shared.ts +0 -221
  475. package/src/providers/integrations/buddy/buddy-usage-store.ts +0 -181
  476. package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +0 -37
  477. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +0 -185
  478. package/src/providers/integrations/buddy/codebuddy/oauth.ts +0 -47
  479. package/src/providers/integrations/buddy/codebuddy/provider.ts +0 -175
  480. package/src/providers/integrations/buddy/codebuddy/quota.ts +0 -154
  481. package/src/providers/integrations/qoder/chat-proto.ts +0 -328
  482. package/src/providers/integrations/qoder/qoder-grpc.ts +0 -871
  483. package/src/providers/integrations/qoder/qoder-ide.ts +0 -588
  484. package/src/providers/operations/model-discovery-cache.ts +0 -34
  485. package/src/providers/operations/probe-fetch.ts +0 -15
  486. package/src/providers/operations/provider-version-cache.ts +0 -30
  487. package/src/providers/provider-capabilities.ts +0 -33
  488. package/src/providers/provider-credential-envelope.ts +0 -43
  489. /package/dist/dashboard/assets/{app-B7kIWFm5.js → app-C0gTXEoN.js} +0 -0
  490. /package/dist/dashboard/assets/{app-B7kIWFm5.js.gz → app-C0gTXEoN.js.gz} +0 -0
  491. /package/src/network/{http2-bidi.ts → bidi.ts} +0 -0
  492. /package/src/network/pool/{pool-scripts.ts → scripts.ts} +0 -0
  493. /package/src/network/pool/{pool-state.ts → state.ts} +0 -0
  494. /package/src/network/{backoff.ts → util/backoff.ts} +0 -0
  495. /package/src/network/{deduplication.ts → util/dedupe.ts} +0 -0
  496. /package/src/network/{ip-utils.ts → util/ip.ts} +0 -0
@@ -1,8 +1,8 @@
1
1
  // dynamic-import-ok: lazy per-realm capability map. Each buddy regional
2
2
  // product (cb/cbcn) imports its adapter + oauth + discovery on first use so a
3
3
  // deployment that only serves one realm never drags the others into memory.
4
- import type { ProviderModuleCapabilities } from "../../provider-capabilities";
5
- import { oauthCapability, quotaCapability } from "../../provider-capabilities";
4
+ import type { ProviderModuleCapabilities } from "../../provider-registry";
5
+ import { oauthCapability, quotaCapability } from "../../provider-registry";
6
6
 
7
7
  type BuddyProviderId = "cb" | "cbcn";
8
8
 
@@ -12,38 +12,38 @@ type BuddyProviderId = "cb" | "cbcn";
12
12
  */
13
13
  export const BUDDY_PROVIDER_CAPABILITIES = {
14
14
  cb: {
15
- loadAdapter: async () => (await import("./codebuddy/provider")).createCodeBuddyAdapter(),
16
- loadModels: async () => (await import("./codebuddy/provider")).CODEBUDDY_MODELS,
15
+ loadAdapter: async () => (await import("./codebuddy/index")).createCodeBuddyAdapter(),
16
+ loadModels: async () => (await import("./codebuddy/index")).CODEBUDDY_MODELS,
17
17
  loadModelDiscovery: async () => async ({ credential, fetcher }) =>
18
- (await import("./codebuddy/provider")).discoverCodeBuddyModels({
18
+ (await import("./codebuddy/index")).discoverCodeBuddyModels({
19
19
  credential,
20
20
  ...(fetcher === undefined ? {} : { fetcher }),
21
21
  }),
22
22
  loadAuthentication: oauthCapability(
23
- () => import("./codebuddy/oauth"),
23
+ () => import("./codebuddy/index"),
24
24
  "codeBuddyOAuthClient",
25
25
  { withRefresher: true },
26
26
  ),
27
27
  loadQuotaCollector: quotaCapability(
28
- () => import("./codebuddy/quota"),
28
+ () => import("./codebuddy/index"),
29
29
  "fetchCodeBuddyIntlQuota",
30
30
  ),
31
31
  },
32
32
  cbcn: {
33
- loadAdapter: async () => (await import("./codebuddy/cn-provider")).createCodeBuddyCnAdapter(),
34
- loadModels: async () => (await import("./codebuddy/cn-provider")).CODEBUDDY_CN_MODELS,
33
+ loadAdapter: async () => (await import("./codebuddy/index")).createCodeBuddyCnAdapter(),
34
+ loadModels: async () => (await import("./codebuddy/index")).CODEBUDDY_CN_MODELS,
35
35
  loadModelDiscovery: async () => async ({ credential, fetcher }) =>
36
- (await import("./codebuddy/cn-provider")).discoverCodeBuddyCnModels({
36
+ (await import("./codebuddy/index")).discoverCodeBuddyCnModels({
37
37
  credential,
38
38
  ...(fetcher === undefined ? {} : { fetcher }),
39
39
  }),
40
40
  loadAuthentication: oauthCapability(
41
- () => import("./codebuddy/oauth"),
41
+ () => import("./codebuddy/index"),
42
42
  "codeBuddyCnOAuthClient",
43
43
  { withRefresher: true },
44
44
  ),
45
45
  loadQuotaCollector: quotaCapability(
46
- () => import("./codebuddy/quota"),
46
+ () => import("./codebuddy/index"),
47
47
  "fetchCodeBuddyCnQuota",
48
48
  ),
49
49
  },
@@ -1,22 +1,11 @@
1
- /**
2
- * The buddy-family static catalog row.
3
- *
4
- * CodeBuddy (intl + CN) and WorkBuddy describe their static fallback catalogs
5
- * with the same seven-field tuple and build each row the same way, differing
6
- * only in the wire endpoint the row targets. Both had their own copy of the
7
- * tuple type and the builder, so a new column meant editing two identical
8
- * declarations.
9
- *
10
- * Only the row shape and the builder are shared. Identity headers are not:
11
- * `codebuddyHeaders` sends genuinely different bytes per realm
12
- * (`X-Product`/`X-IDE-Type`/`X-Domain` versus the CN CLI profile), and those
13
- * stay with the provider.
14
- */
15
1
  import { GatewayError } from "../../../protocol/gateway-error";
16
2
  import { defineModel } from "../../provider-model-definition";
17
3
  import type { ModelDefinition } from "../../provider-model-definition";
4
+ import { asNumber as sharedAsNumber, asRecord } from "../../../shared/coerce";
5
+ import { buddyAccountUid } from "./account";
6
+
7
+ // ── buddy-catalog-shared ──────────────────────────────────────────
18
8
 
19
- /** One static catalog row: id, display name, flags, limits, optional tool override. */
20
9
  export type BuddyRawEntry = readonly [
21
10
  string,
22
11
  string,
@@ -28,14 +17,6 @@ export type BuddyRawEntry = readonly [
28
17
  boolean?,
29
18
  ];
30
19
 
31
- /**
32
- * Realm-specific effort ladders.
33
- *
34
- * International DeepSeek Flash accepts only `high`; sending CN's `low`/`max`
35
- * is a 400. A model absent from its realm's table is not clamped. Lives here,
36
- * next to the catalog rows, so a row can carry its ladder as
37
- * `reasoningEfforts` without the catalog importing the chat hook.
38
- */
39
20
  export const BUDDY_INTL_EFFORTS: Readonly<Record<string, readonly string[]>> = {
40
21
  "deepseek-v4.1-flash": ["high"],
41
22
  "glm-5.2": ["high", "xhigh"],
@@ -44,6 +25,7 @@ export const BUDDY_INTL_EFFORTS: Readonly<Record<string, readonly string[]>> = {
44
25
  hy4: ["high"],
45
26
  hy4free: ["high"],
46
27
  };
28
+
47
29
  export const BUDDY_CN_EFFORTS: Readonly<Record<string, readonly string[]>> = {
48
30
  "deepseek-v4-flash": ["low", "high", "max"],
49
31
  "deepseek-v4-pro": ["low", "high", "xhigh"],
@@ -57,7 +39,6 @@ export const BUDDY_CN_EFFORTS: Readonly<Record<string, readonly string[]>> = {
57
39
  hy4free: ["high"],
58
40
  };
59
41
 
60
- /** The image-generation ids the international buddy providers serve. */
61
42
  const BUDDY_IMAGE_MODEL_IDS: readonly { id: string; endpoint: string; ctx: number; out: number }[] = [
62
43
  { id: "gemini-2.5-flash-image", endpoint: "/chat/completions", ctx: 1_000_000, out: 64_000 },
63
44
  { id: "gemini-3.0-pro-image", endpoint: "/chat/completions", ctx: 1_000_000, out: 64_000 },
@@ -70,16 +51,6 @@ const BUDDY_IMAGE_MODEL_IDS: readonly { id: string; endpoint: string; ctx: numbe
70
51
  { id: "hy-image-3.5", endpoint: "/chat/completions", ctx: 1_000_000, out: 64_000 },
71
52
  ];
72
53
 
73
- /**
74
- * The video-generation ids the international buddy providers serve.
75
- *
76
- * `seedance-2.5` is the text-to-video model the buddy facade exposes. It is a
77
- * distinct service kind (`videoGeneration`), not a chat or image row, so it is
78
- * built by {@link makeBuddyVideoModels} and reached through
79
- * `/videos/generations` (relative to each variant's own base) rather than a
80
- * chat wire. CodeBuddy CN is deliberately absent — it publishes a different
81
- * roster.
82
- */
83
54
  const BUDDY_VIDEO_MODEL_IDS: readonly { id: string; endpoint: string; ctx: number; out: number }[] = [
84
55
  { id: "seedance-2.5", endpoint: "/videos/generations", ctx: 1_000_000, out: 128_000 },
85
56
  // Published by /v3/config only, tagged `text-to-video` + `image-to-video`.
@@ -89,42 +60,19 @@ const BUDDY_VIDEO_MODEL_IDS: readonly { id: string; endpoint: string; ctx: numbe
89
60
  { id: "kling-video-v3", endpoint: "/videos/generations", ctx: 1_000_000, out: 128_000 },
90
61
  ];
91
62
 
92
- /**
93
- * Ids that belong to the image-generation rows rather than the chat roster.
94
- *
95
- * A caller mapping `BUDDY_SHARED_RAW` through {@link makeBuddyModel} must skip
96
- * these, or the same model id lands in the catalog twice under two service
97
- * kinds and becomes ambiguous to resolve.
98
- */
99
63
  export const BUDDY_IMAGE_MODEL_ID_SET: ReadonlySet<string> = new Set(
100
64
  BUDDY_IMAGE_MODEL_IDS.map((entry) => entry.id),
101
65
  );
102
66
 
103
- /**
104
- * The CN realm's image-generation ids.
105
- *
106
- * Separate from {@link BUDDY_IMAGE_MODEL_IDS} because the realms do not share
107
- * a roster: `hunyuan-image-alpha` (text-to-image) and
108
- * `hunyuan-image-alpha-edit` (image-to-image) are published by the CN
109
- * `/v3/config` only, and the intl image ids are not served there. Sharing one
110
- * list would either leak CN-only ids onto the international catalogs or force
111
- * a realm check into every consumer.
112
- */
113
67
  const BUDDY_CN_IMAGE_MODEL_IDS: readonly { id: string; ctx: number; out: number }[] = [
114
68
  { id: "hunyuan-image-alpha", ctx: 1_000_000, out: 64_000 },
115
69
  { id: "hunyuan-image-alpha-edit", ctx: 1_000_000, out: 64_000 },
116
70
  ];
117
71
 
118
- /** The CN analogue of {@link BUDDY_IMAGE_MODEL_ID_SET}. */
119
72
  export const BUDDY_CN_IMAGE_MODEL_ID_SET: ReadonlySet<string> = new Set(
120
73
  BUDDY_CN_IMAGE_MODEL_IDS.map((entry) => entry.id),
121
74
  );
122
75
 
123
- /**
124
- * Builds the CN image-generation rows for one buddy CN provider.
125
- *
126
- * Same shape as {@link makeBuddyImageModels}, scoped to the CN roster.
127
- */
128
76
  export function makeBuddyCnImageModels(
129
77
  providerId: string,
130
78
  endpoint: string,
@@ -145,30 +93,15 @@ export function makeBuddyCnImageModels(
145
93
  );
146
94
  }
147
95
 
148
- /**
149
- * The CN realm's video-generation ids.
150
- *
151
- * `kling-video-v3` (text-to-video + image-to-video) and
152
- * `minimax-video-h3` (text-to-video) are published by the CN `/v3/config`,
153
- * sharing the async task surface the intl video rows use.
154
- */
155
96
  const BUDDY_CN_VIDEO_MODEL_IDS: readonly { id: string; ctx: number; out: number }[] = [
156
97
  { id: "kling-video-v3", ctx: 1_000_000, out: 128_000 },
157
98
  { id: "minimax-video-h3", ctx: 1_000_000, out: 128_000 },
158
99
  ];
159
100
 
160
- /** The CN analogue of {@link BUDDY_VIDEO_MODEL_ID_SET}. */
161
101
  export const BUDDY_CN_VIDEO_MODEL_ID_SET: ReadonlySet<string> = new Set(
162
102
  BUDDY_CN_VIDEO_MODEL_IDS.map((entry) => entry.id),
163
103
  );
164
104
 
165
- /**
166
- * Builds the CN video-generation rows for one buddy CN provider.
167
- *
168
- * Same shape as {@link makeBuddyVideoModels}, scoped to the CN roster: a video
169
- * row produces `["video"]` on the `videoGeneration` surface and is reached
170
- * through the native video route, not a chat wire.
171
- */
172
105
  export function makeBuddyCnVideoModels(
173
106
  providerId: string,
174
107
  endpoint: string,
@@ -189,23 +122,6 @@ export function makeBuddyCnVideoModels(
189
122
  );
190
123
  }
191
124
 
192
- /**
193
- * Ids the buddy facade refuses on a free plan.
194
- *
195
- * The international CodeBuddy catalog shares this roster and
196
- * the same Pro-tier model classification.
197
- *
198
- * Nothing in the console directory predicts it. `credits` does not — `kimi-k3`
199
- * bills `x1.62` and is served while `gpt-5.6-luna` bills `x0.14` and is
200
- * refused — and `vendor` does not either. Only the refusal itself is a signal,
201
- * which is why this is a list and not a rule.
202
- *
203
- * Hardcoded deliberately: it is one account's tier, so it is a fact about that
204
- * plan rather than about the model. A pro account serves all six. The pill is
205
- * therefore a hint about a free account, and a dispatch is what settles it.
206
- *
207
- * @see `documentation/research/codebuddy/2026-10-19-codebuddy-chat-dispatch-headers.md`
208
- */
209
125
  export const BUDDY_PRO_ONLY_MODEL_IDS: ReadonlySet<string> = new Set([
210
126
  "primary-model",
211
127
  "gpt-5.6-terra",
@@ -227,18 +143,6 @@ export const BUDDY_PRO_ONLY_MODEL_IDS: ReadonlySet<string> = new Set([
227
143
  "claude-opus-4.7-1m",
228
144
  ]);
229
145
 
230
- /**
231
- * Builds the image-generation rows for one buddy provider.
232
- *
233
- * Shared rather than copied per provider: cb serves the same image
234
- * models from the same facade, so the roster and the declared capabilities are
235
- * one decision instead of two that drift. CodeBuddy CN is deliberately absent —
236
- * it publishes a different roster.
237
- *
238
- * `endpoint` is explicit because the realms disagree about the path their
239
- * base URL expects, and a bare `defineModel` would infer the generic default
240
- * and produce a URL the upstream rejects.
241
- */
242
146
  export function makeBuddyImageModels(
243
147
  providerId: string,
244
148
  endpoint: string,
@@ -260,15 +164,6 @@ export function makeBuddyImageModels(
260
164
  );
261
165
  }
262
166
 
263
- /**
264
- * Builds the video-generation rows for one buddy provider.
265
- *
266
- * Shared for the same reason as {@link makeBuddyImageModels}: the roster is one
267
- * decision, not one per provider that drifts. A video row produces `["video"]`
268
- * on the `videoGeneration` surface and is reached through the native video
269
- * route, not a chat wire, so `endpoint` names the upstream generation path
270
- * rather than a chat-completions path.
271
- */
272
167
  export function makeBuddyVideoModels(
273
168
  providerId: string,
274
169
  endpoint: string,
@@ -289,25 +184,10 @@ export function makeBuddyVideoModels(
289
184
  );
290
185
  }
291
186
 
292
- /**
293
- * Ids that belong to the video-generation rows rather than the chat roster.
294
- *
295
- * The video analogue of {@link BUDDY_IMAGE_MODEL_ID_SET}: a caller mapping the
296
- * shared chat tuple must skip these so `seedance-2.5` never lands in the
297
- * catalog twice under two service kinds.
298
- */
299
187
  export const BUDDY_VIDEO_MODEL_ID_SET: ReadonlySet<string> = new Set(
300
188
  BUDDY_VIDEO_MODEL_IDS.map((entry) => entry.id),
301
189
  );
302
190
 
303
- /**
304
- * Builds one buddy catalog row.
305
- *
306
- * `endpoint` is explicit rather than left to the generic `/chat/completions`
307
- * default because the family's CN base URL differs from the intl one; callers
308
- * pass the endpoint their base URL actually serves, and `undefined` for the
309
- * default.
310
- */
311
191
  export function makeBuddyModel(
312
192
  entry: BuddyRawEntry,
313
193
  providerId: string,
@@ -337,17 +217,6 @@ export function makeBuddyModel(
337
217
  });
338
218
  }
339
219
 
340
- /**
341
- * The shared model roster for the international buddy site.
342
- *
343
- * CodeBuddy intl serves the model set from the same console directory shape, so
344
- * the catalog is one hand-written list as the single source of truth, mapped
345
- * with the provider's own endpoint (`codebuddy.ts` takes the family default).
346
- *
347
- * CodeBuddy CN is deliberately NOT on this list: its console publishes a
348
- * different roster (its own `glm-5v-turbo` / `kimi-k3-1` ids and CN-specific
349
- * output ceilings), so it keeps its own table.
350
- */
351
220
  export const BUDDY_SHARED_RAW: readonly BuddyRawEntry[] = [
352
221
  ["auto", "Auto", false, true, 176_000, 24_000],
353
222
  // The three named tiers and `gpt-6-astra` are published by /v3/config and sit
@@ -400,3 +269,196 @@ export const BUDDY_SHARED_RAW: readonly BuddyRawEntry[] = [
400
269
  ["minimax-m3.1-flash", "MiniMax-M3.1 Flash", true, true, 1_000_000, 128_000],
401
270
  ["step-5-preview", "Step-5-Preview", true, true, 1_000_000, 64_000, true],
402
271
  ];
272
+
273
+ // ── buddy-discovery-shared ──────────────────────────────────────────
274
+
275
+ export const BUDDY_CN_MODELS_PATH = "/console/enterprises/personal/models" as const;
276
+
277
+ export const BUDDY_INTL_MODELS_PATH = "/v2/enterprises/personal/models" as const;
278
+
279
+ export const BUDDY_CONFIG_PATH = "/v3/config" as const;
280
+
281
+ const BUDDY_OK_CODE = 0;
282
+
283
+ interface BuddyDirectoryRow {
284
+ readonly id?: unknown;
285
+ readonly name?: unknown;
286
+ readonly disabled?: unknown;
287
+ readonly maxInputTokens?: unknown;
288
+ readonly maxOutputTokens?: unknown;
289
+ readonly supportsImages?: unknown;
290
+ readonly supportsToolCall?: unknown;
291
+ readonly supportsReasoning?: unknown;
292
+ readonly tags?: unknown;
293
+ }
294
+
295
+ function siteOrigin(baseUrl: string): string {
296
+ return baseUrl.replace(/\/+$/, "").replace(/\/v\d+$/, "");
297
+ }
298
+
299
+ function asNumber(value: unknown): number | null {
300
+ return sharedAsNumber(value) ?? null;
301
+ }
302
+
303
+ export async function fetchBuddyDirectoryModels(args: {
304
+ readonly siteUrl: string;
305
+ readonly providerId: string;
306
+ readonly credential: string;
307
+ readonly modelsPath: string;
308
+ readonly endpoint: string | undefined;
309
+ readonly signal?: AbortSignal | undefined;
310
+ readonly fetcher?: typeof fetch | undefined;
311
+ }): Promise<readonly ModelDefinition[] | null> {
312
+ const fetcher = args.fetcher ?? globalThis.fetch;
313
+ // Fetch both catalog scopes and merge them. `/v3/config` is ranked higher and
314
+ // is the primary source (matches the reference gateways), but the personal
315
+ // models path carries models the v3 response does not always publish — so a
316
+ // single-source read can silently miss models that are callable. Merging with
317
+ // dedupe by model id gives the union, mirroring the upstream codebuddy2api
318
+ // catalog aggregation. Each failure falls through to the other source, so a
319
+ // host that answers only one behaves exactly as it does today.
320
+ const v3 = await fetchBuddyDirectoryOnce(args, fetcher, BUDDY_CONFIG_PATH);
321
+ const personal = await fetchBuddyDirectoryOnce(args, fetcher, args.modelsPath);
322
+ if (v3 !== null && personal !== null) return mergeBuddyDirectories(v3, personal);
323
+ return v3 ?? personal;
324
+ }
325
+
326
+ function mergeBuddyDirectories(
327
+ primary: readonly ModelDefinition[],
328
+ supplemental: readonly ModelDefinition[],
329
+ ): readonly ModelDefinition[] {
330
+ const seen = new Set<string>();
331
+ const merged: ModelDefinition[] = [];
332
+ for (const model of primary) {
333
+ if (seen.has(model.modelId)) continue;
334
+ seen.add(model.modelId);
335
+ merged.push(model);
336
+ }
337
+ for (const model of supplemental) {
338
+ if (seen.has(model.modelId)) continue;
339
+ seen.add(model.modelId);
340
+ merged.push(model);
341
+ }
342
+ return merged;
343
+ }
344
+
345
+ async function fetchBuddyDirectoryOnce(
346
+ args: {
347
+ readonly siteUrl: string;
348
+ readonly providerId: string;
349
+ readonly credential: string;
350
+ readonly endpoint: string | undefined;
351
+ readonly signal?: AbortSignal | undefined;
352
+ },
353
+ fetcher: typeof fetch,
354
+ path: string,
355
+ ): Promise<readonly ModelDefinition[] | null> {
356
+ // The directory scores by account: an access token's `sub` is the uid. An
357
+ // opaque API key carries no identity, and the endpoint still answers for it,
358
+ // so the header is declared absent rather than guessed.
359
+ const uid = buddyAccountUid(args.credential);
360
+ let response: Response;
361
+ try {
362
+ response = await fetcher(`${siteOrigin(args.siteUrl)}${path}`, {
363
+ method: "GET",
364
+ headers: {
365
+ accept: "application/json",
366
+ authorization: `Bearer ${args.credential}`,
367
+ "x-product": "SaaS",
368
+ ...(uid === undefined ? { "x-no-user-id": "1" } : { "x-user-id": uid }),
369
+ "x-no-enterprise-id": "1",
370
+ "x-no-department-info": "1",
371
+ },
372
+ ...(args.signal === undefined ? {} : { signal: args.signal }),
373
+ });
374
+ } catch {
375
+ return null;
376
+ }
377
+ if (!response.ok) return null;
378
+ let body: unknown;
379
+ try {
380
+ body = await response.json();
381
+ } catch {
382
+ return null;
383
+ }
384
+ const envelope = asRecord(body);
385
+ if (envelope === undefined || envelope["code"] !== BUDDY_OK_CODE) return null;
386
+ const data = asRecord(envelope["data"]);
387
+ const rawModels = data?.["models"];
388
+ if (!Array.isArray(rawModels)) return null;
389
+
390
+ // The CLI agent's roster, when published, is the callable subset.
391
+ const agents = data?.["agents"];
392
+ let cliRoster: Set<string> | undefined;
393
+ if (Array.isArray(agents)) {
394
+ for (const entry of agents) {
395
+ const agent = asRecord(entry);
396
+ if (agent?.["name"] !== "cli") continue;
397
+ const listed = agent["models"];
398
+ if (Array.isArray(listed) && listed.length > 0) {
399
+ cliRoster = new Set(listed.filter((id): id is string => typeof id === "string"));
400
+ }
401
+ break;
402
+ }
403
+ }
404
+
405
+ const entries: BuddyRawEntry[] = [];
406
+ const seen = new Set<string>();
407
+ for (const entry of rawModels) {
408
+ const model = asRecord(entry) as BuddyDirectoryRow | undefined;
409
+ const id = model?.id;
410
+ if (typeof id !== "string" || id.length === 0 || seen.has(id)) continue;
411
+ if (model?.disabled === true) continue;
412
+ // Completion, NES, and codewise rows are not chat models. Listing them
413
+ // offers a route that 400s on a chat request. A declared output of 256 or
414
+ // less is the same signal: a completion model published with a chat-sized
415
+ // name. `text-to-image` is an image row, served by the image roster.
416
+ const lowerId = id.toLowerCase();
417
+ if (lowerId.startsWith("nes-") || lowerId.startsWith("completion-") || lowerId.startsWith("codewise-")) continue;
418
+ const output = asNumber(model?.maxOutputTokens);
419
+ if (output !== null && output <= 256) continue;
420
+ const tags = model?.tags;
421
+ if (Array.isArray(tags) && tags.some((tag) => typeof tag === "string" && tag.toLowerCase() === "text-to-image")) continue;
422
+ if (cliRoster !== undefined && !cliRoster.has(id)) continue;
423
+ seen.add(id);
424
+ entries.push([
425
+ id,
426
+ typeof model?.name === "string" && model.name.length > 0 ? model.name : id,
427
+ model?.supportsReasoning === true,
428
+ model?.supportsImages === true,
429
+ asNumber(model?.maxInputTokens),
430
+ asNumber(model?.maxOutputTokens),
431
+ model?.supportsToolCall === true,
432
+ ]);
433
+ }
434
+ if (entries.length === 0) return null;
435
+ return entries.map((entry) => makeBuddyModel(entry, args.providerId, args.endpoint));
436
+ }
437
+
438
+ // ── codebuddy/cn-catalog ──────────────────────────────────────────
439
+
440
+ export const CODEBUDDY_CN_RAW: readonly BuddyRawEntry[] = [
441
+ ["glm-5.1", "GLM 5.1", true, true, 200_000, 48_000],
442
+ ["glm-5.2", "GLM 5.2", true, true, 1_000_000, 64_000],
443
+ ["glm-5.3", "GLM 5.3", true, true, 1_000_000, 64_000],
444
+ ["glm-5.3-flash", "GLM 5.3 Flash", true, true, 1_000_000, 131_072],
445
+ ["glm-5v-turbo", "GLM 5v Turbo", true, true, 200_000, 64_000],
446
+ ["minimax-m3", "MiniMax M3", true, true, 512_000, 64_000],
447
+ // 1M context, reasoning always on (upstream states both); vision inherited
448
+ // from the M3 row, which is the same family.
449
+ ["minimax-m3.1-flash", "MiniMax M3.1 Flash", true, true, 1_000_000, 128_000],
450
+ ["mimo-v2.6-pro", "MiMo V2.6 Pro", true, true, 1_000_000, 128_000],
451
+ ["kimi-k2.8-preview", "Kimi K2.8 Preview", true, true, 1_000_000, 64_000],
452
+ ["kimi-k3.1-pro", "Kimi K3.1 Pro", true, true, 1_000_000, 32_000],
453
+ ["hy3", "Hy3", true, true, 192_000, 64_000],
454
+ ["hy4", "Hy4", true, true, 960_000, 64_000],
455
+ ["hy4free", "Hy4 Free", true, true, 960_000, 64_000],
456
+ ["space-bunny", "Space Bunny", true, true, 1_000_000, 128_000],
457
+ ["step-5-preview", "Step 5 Preview", true, true, 1_000_000, 64_000],
458
+ ["deepseek-v4-pro", "DeepSeek V4 Pro", true, true, 1_000_000, 128_000],
459
+ ["deepseek-v4.1-flash", "DeepSeek V4.1 Flash", true, true, 1_000_000, 128_000],
460
+ // Live on the CN roster but absent here, so a request for it resolved to
461
+ // nothing. Limits as published by /v3/config.
462
+ ["kimi-k3-1", "Kimi K3-1", true, true, 1_000_000, 32_000],
463
+ ["minimax-m2.7", "MiniMax M2.7", true, true, 200_000, 48_000],
464
+ ];