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
@@ -21,15 +21,16 @@ import { createHash } from "node:crypto";
21
21
  import { completeRequiredSchema } from "../../../protocol/codecs";
22
22
  import type { CanonicalRequest } from "../../../protocol/canonical-model";
23
23
  import { isRecord } from "../../../protocol/codecs";
24
+ import { GatewayError } from "../../../protocol/gateway-error";
24
25
  import { applyDeepSeekReasoning, applyOpenAIReasoning, backfillDeepSeekReasoningContent, clampedEffortOutputFloor, ensureChatReasoningReplayPresence } from "../../../protocol/reasoning";
25
- import { BUDDY_CN_EFFORTS, BUDDY_INTL_EFFORTS, BUDDY_SHARED_RAW } from "./buddy-catalog-shared";
26
+ import { BUDDY_CN_EFFORTS, BUDDY_INTL_EFFORTS, BUDDY_SHARED_RAW } from "./catalog";
26
27
  // Imported for the CN roster only: a CN-only id has no row in the shared
27
28
  // table, and without one `raiseOutputForRaisedEffort` silently no-ops, so a
28
29
  // raised effort still answers inside a budget sized for the lower one. It is
29
30
  // read inside the function below — never at module init — so the cycle with
30
31
  // cn-provider (which imports this module) resolves before any call.
31
- import { CODEBUDDY_CN_RAW } from "./codebuddy/cn-catalog";
32
- import { buddyAccountUid } from "./buddy-oauth-shared";
32
+ import { CODEBUDDY_CN_RAW } from "./catalog";
33
+ import { buddyAccountUid } from "./account";
33
34
  import { SYSTEM_PROMPT_WRAPPER_PREFIX, SYSTEM_PROMPT_WRAPPER_SUFFIX } from "../../../console/system-prompt/contracts";
34
35
  import type { ProviderDispatchContext } from "../../provider-contracts";
35
36
 
@@ -55,6 +56,123 @@ function normalizedToolName(value: string, index: number, used: Set<string>): st
55
56
  return uniqueToolName(base || `tool_${index + 1}`, used);
56
57
  }
57
58
 
59
+ /**
60
+ * Schema keywords whose values are schemas (recursed as schema objects).
61
+ * Mirrors the donor gateway's `upstream_compat._SCHEMA_MAPS/_ARRAYS/CHILDREN`.
62
+ */
63
+ const RE2_SCHEMA_MAPS: ReadonlySet<string> = new Set([
64
+ "properties",
65
+ "patternProperties",
66
+ "$defs",
67
+ "definitions",
68
+ "dependentSchemas",
69
+ "dependencies",
70
+ ]);
71
+ const RE2_SCHEMA_ARRAYS: ReadonlySet<string> = new Set([
72
+ "allOf",
73
+ "anyOf",
74
+ "oneOf",
75
+ "prefixItems",
76
+ "items",
77
+ ]);
78
+ const RE2_SCHEMA_CHILDREN: ReadonlySet<string> = new Set([
79
+ "items",
80
+ "additionalItems",
81
+ "contains",
82
+ "unevaluatedItems",
83
+ "additionalProperties",
84
+ "unevaluatedProperties",
85
+ "propertyNames",
86
+ "not",
87
+ "if",
88
+ "then",
89
+ "else",
90
+ "contentSchema",
91
+ ]);
92
+
93
+ /**
94
+ * Removes unescaped backslashes before underscores in one regex pattern. The
95
+ * CodeBuddy upstream validates tool schemas with RE2, which does not support
96
+ * `\_` escapes — a client schema that serializes `\_` (a common JSON
97
+ * representation of a literal underscore) is rejected with a 400. The donor
98
+ * gateway normalizes this before dispatch; a backslash that escapes a
99
+ * backslash is preserved.
100
+ */
101
+ function normalizeRe2Pattern(value: string): string {
102
+ let out = "";
103
+ for (let i = 0; i < value.length; i++) {
104
+ const char = value[i];
105
+ if (char === "\\" && value[i + 1] === "\\") {
106
+ // Escaped backslash: keep the pair so a following `_` stays escaped.
107
+ out += "\\\\";
108
+ i += 1;
109
+ continue;
110
+ }
111
+ if (char === "\\" && value[i + 1] === "_") {
112
+ // `\_` — the upstream's RE2 rejects it; drop the backslash.
113
+ out += "_";
114
+ i += 1;
115
+ continue;
116
+ }
117
+ out += char;
118
+ }
119
+ return out;
120
+ }
121
+
122
+ /** Normalizes RE2-incompatible underscore escapes in schema pattern positions. */
123
+ function normalizeRe2SchemaPatterns(schema: unknown): void {
124
+ if (!isRecord(schema)) return;
125
+ const pattern = schema["pattern"];
126
+ if (typeof pattern === "string") schema["pattern"] = normalizeRe2Pattern(pattern);
127
+ const patternProperties = schema["patternProperties"];
128
+ if (isRecord(patternProperties)) {
129
+ const normalized: Record<string, unknown> = {};
130
+ for (const [key, value] of Object.entries(patternProperties)) {
131
+ const key2 = normalizeRe2Pattern(key);
132
+ if (key2 in normalized) {
133
+ normalized[key2] = { allOf: [normalized[key2], value] };
134
+ } else {
135
+ normalized[key2] = value;
136
+ }
137
+ }
138
+ schema["patternProperties"] = normalized;
139
+ }
140
+ for (const key of RE2_SCHEMA_MAPS) {
141
+ const map = schema[key];
142
+ if (!isRecord(map)) continue;
143
+ for (const child of Object.values(map)) normalizeRe2SchemaPatterns(child);
144
+ }
145
+ for (const key of RE2_SCHEMA_ARRAYS) {
146
+ const list = schema[key];
147
+ if (!Array.isArray(list)) continue;
148
+ for (const child of list) normalizeRe2SchemaPatterns(child);
149
+ }
150
+ for (const key of RE2_SCHEMA_CHILDREN) {
151
+ normalizeRe2SchemaPatterns(schema[key]);
152
+ }
153
+ }
154
+
155
+ /** JSON-serializes a value to cheaply detect a backslash-before-underscore. */
156
+ function hasUnderscoreEscape(value: unknown): boolean {
157
+ try {
158
+ return JSON.stringify(value).includes("\\_");
159
+ } catch {
160
+ return true;
161
+ }
162
+ }
163
+
164
+ /** Returns the declaration with RE2-safe schema patterns, or the same object. */
165
+ function normalizeRe2Declaration(declaration: Record<string, unknown>): Record<string, unknown> {
166
+ const parameters = declaration["parameters"];
167
+ if (!hasUnderscoreEscape(parameters)) return declaration;
168
+ // Deep-copy only when a rewrite is needed; the shared object must not be
169
+ // mutated for every dispatch.
170
+ const out: Record<string, unknown> = { ...declaration };
171
+ out["parameters"] = structuredClone(parameters);
172
+ normalizeRe2SchemaPatterns(out["parameters"]);
173
+ return out;
174
+ }
175
+
58
176
  /**
59
177
  * Buddy's Chat Completions wire has no `web_search_preview` hosted tool; its
60
178
  * search is an ordinary function named `web_search` with a `{query}` schema.
@@ -102,29 +220,28 @@ export function normalizeBuddyToolNames(payload: Record<string, unknown>): void
102
220
  const name = normalizedToolName(sourceName, index, used);
103
221
  used.add(name);
104
222
  if (!replacements.has(sourceName)) replacements.set(sourceName, name);
105
- if (fn !== undefined)
106
- return {
107
- ...rawTool,
108
- function: {
109
- ...fn,
110
- name,
111
- ...(fn["parameters"] === undefined ? {} : { parameters: completeRequiredSchema(fn["parameters"]) }),
112
- },
223
+ if (fn !== undefined) {
224
+ const fnOut = {
225
+ ...fn,
226
+ name,
227
+ ...(fn["parameters"] === undefined ? {} : { parameters: completeRequiredSchema(fn["parameters"]) }),
113
228
  };
114
- if (custom !== undefined)
115
- return {
116
- ...rawTool,
117
- custom: {
118
- ...custom,
119
- name,
120
- ...(custom["format"] === undefined ? {} : { format: completeRequiredSchema(custom["format"]) }),
121
- },
229
+ return { ...rawTool, function: normalizeRe2Declaration(fnOut) };
230
+ }
231
+ if (custom !== undefined) {
232
+ const customOut = {
233
+ ...custom,
234
+ name,
235
+ ...(custom["format"] === undefined ? {} : { format: completeRequiredSchema(custom["format"]) }),
122
236
  };
123
- return {
237
+ return { ...rawTool, custom: normalizeRe2Declaration(customOut) };
238
+ }
239
+ const bareOut = {
124
240
  ...rawTool,
125
241
  name,
126
242
  ...(rawTool["parameters"] === undefined ? {} : { parameters: completeRequiredSchema(rawTool["parameters"]) }),
127
243
  };
244
+ return { ...bareOut, ...normalizeRe2Declaration(bareOut) };
128
245
  });
129
246
  const messages = payload["messages"];
130
247
  if (Array.isArray(messages)) {
@@ -138,6 +255,13 @@ export function normalizeBuddyToolNames(payload: Record<string, unknown>): void
138
255
  }
139
256
  }
140
257
  }
258
+ const responseFormat = payload["response_format"];
259
+ if (isRecord(responseFormat) && hasUnderscoreEscape(responseFormat)) {
260
+ const copied = structuredClone(responseFormat) as Record<string, unknown>;
261
+ const jsonSchema = copied["json_schema"];
262
+ if (isRecord(jsonSchema)) normalizeRe2SchemaPatterns(jsonSchema["schema"]);
263
+ payload["response_format"] = copied;
264
+ }
141
265
  const choice = payload["tool_choice"];
142
266
  if (!isRecord(choice)) return;
143
267
  if (choice["type"] === "allowed_tools" && Array.isArray(choice["tools"])) {
@@ -477,6 +601,10 @@ export function buddyPrePayloadCommon(
477
601
  normalizeBuddyImageUrl(payload);
478
602
  // developer role → system (buddy whitelist rejects developer, 11128)
479
603
  normalizeBuddyRoles(payload);
604
+ // Validate the *caller's* thinking controls before the DeepSeek contract may
605
+ // inject its own `thinking` (an injected `{type:"enabled"}` has no budget and
606
+ // must not be rejected as a malformed client shape).
607
+ validateBuddyThinking(payload);
480
608
  applyOpenAIReasoning(payload, request);
481
609
  applyDeepSeekReasoning(payload);
482
610
  // sol family defaults to high reasoning like reference thinking.go defaultDeepSeekEffort — sol without effort gets 500/invoke error otherwise
@@ -516,6 +644,34 @@ export function buddyPrePayloadCommon(
516
644
  delete payload["agent_prompt"];
517
645
  }
518
646
 
647
+ /**
648
+ * Validates the reasoning controls the CodeBuddy Chat wire accepts, mirroring
649
+ * the donor gateway's `map_reasoning_controls`. The upstream rejects the whole
650
+ * request for shapes it does not model, so a client that sends an unsupported
651
+ * `thinking` shape is failed here with a 400 that names the field — instead of
652
+ * an opaque upstream error.
653
+ */
654
+ function validateBuddyThinking(payload: Record<string, unknown>): void {
655
+ const thinking = isRecord(payload["thinking"]) ? payload["thinking"] : undefined;
656
+ if (thinking === undefined) return;
657
+ const mode = typeof thinking["type"] === "string" ? (thinking["type"] as string) : "";
658
+ if (mode !== "enabled" && mode !== "adaptive" && mode !== "disabled") {
659
+ throw new GatewayError("invalid_request", 400, `CodeBuddy thinking.type must be enabled, adaptive or disabled (got ${JSON.stringify(mode)}) (request {requestId}). Check the shape of what you sent — then resend 🪞`);
660
+ }
661
+ if (mode === "enabled") {
662
+ const budget = thinking["budget_tokens"];
663
+ if (typeof budget !== "number" || !Number.isInteger(budget) || budget < 1024) {
664
+ throw new GatewayError("invalid_request", 400, "CodeBuddy thinking.budget_tokens must be an integer >= 1024 (request {requestId}). Check the shape of what you sent — then resend 🪞");
665
+ }
666
+ } else if (thinking["budget_tokens"] !== undefined) {
667
+ throw new GatewayError("invalid_request", 400, "CodeBuddy thinking.budget_tokens requires thinking.type=enabled (request {requestId}). Check the shape of what you sent — then resend 🪞");
668
+ }
669
+ const display = thinking["display"];
670
+ if (display !== undefined && display !== null && display !== "summarized") {
671
+ throw new GatewayError("invalid_request", 400, "CodeBuddy thinking.display supports only summarized (request {requestId}). Check the shape of what you sent — then resend 🪞");
672
+ }
673
+ }
674
+
519
675
  function injectSolReasoningDefault(payload: Record<string, unknown>): void {
520
676
  const model = typeof payload["model"] === "string" ? (payload["model"] as string) : "";
521
677
  const isSol = model.toLowerCase().includes("sol");
@@ -0,0 +1,429 @@
1
+ import { BuddyMediaAdapter } from "../media";
2
+ import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderAdapter } from "../../../provider-contracts";
3
+ import type { ModelDefinition } from "../../../provider-model-definition";
4
+ import type { DiscoveryInput } from "../../../discovery/discovery-types";
5
+ import { GatewayError } from "../../../../protocol/gateway-error";
6
+ import type { CanonicalRequest } from "../../../../protocol/canonical-model";
7
+ import { providerBaseUrl } from "../../../provider-metadata";
8
+ import { ensurePayloadModel } from "../../../configured-provider";
9
+ import { codebuddyAdapterConfig, codebuddyDomain, codebuddyHeaders } from "./shared";
10
+ import {
11
+ BUDDY_SHARED_RAW,
12
+ BUDDY_IMAGE_MODEL_ID_SET,
13
+ BUDDY_VIDEO_MODEL_ID_SET,
14
+ BUDDY_INTL_MODELS_PATH,
15
+ BUDDY_CN_MODELS_PATH,
16
+ BUDDY_CN_IMAGE_MODEL_ID_SET,
17
+ BUDDY_CN_VIDEO_MODEL_ID_SET,
18
+ CODEBUDDY_CN_RAW,
19
+ type BuddyRawEntry,
20
+ makeBuddyModel,
21
+ makeBuddyImageModels,
22
+ makeBuddyVideoModels,
23
+ makeBuddyCnImageModels,
24
+ makeBuddyCnVideoModels,
25
+ fetchBuddyDirectoryModels,
26
+ } from "../catalog";
27
+ import {
28
+ applyBuddySystemPrompt,
29
+ buddyPrePayloadCommon,
30
+ finalizeBuddyMessages,
31
+ injectBuddyParallelToolCalls,
32
+ normalizeBuddyToolNames,
33
+ } from "../chat";
34
+ import {
35
+ BuddyOAuthClient,
36
+ type BuddyOAuthVariant,
37
+ strictResponseCode,
38
+ fetchTencentBillingQuota,
39
+ fetchBuddyRequestUsage,
40
+ type BuddyUsageResult,
41
+ } from "../account";
42
+ import { buildCodeBuddyUserAgent } from "../../../operations/client-versions";
43
+ import type { FetchLike, ProviderQuotaResult } from "../../../quota/quota-contracts";
44
+
45
+ // ── codebuddy/provider ──────────────────────────────────────────
46
+
47
+ export const CODEBUDDY_PROVIDER_ID = "cb" as const;
48
+
49
+ export const CODEBUDDY_BASE_URL = providerBaseUrl("cb");
50
+
51
+ export const CODEBUDDY_SYSTEM_PROMPT = "You are a helpful assistant.";
52
+
53
+ function codeBuddyIntlPrePayload(
54
+ payload: Record<string, unknown>,
55
+ request: CanonicalRequest,
56
+ candidate: ProviderDispatchTarget,
57
+ context?: ProviderDispatchContext,
58
+ ): void {
59
+ // International ladder: DeepSeek Flash and friends serve only `high`.
60
+ buddyPrePayloadCommon(payload, request, "intl", context);
61
+ const rawModel = payload["model"];
62
+ const source =
63
+ typeof rawModel === "string" && rawModel.length > 0
64
+ ? rawModel
65
+ : candidate.model_id;
66
+ if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
67
+ const messages = payload["messages"];
68
+ if (Array.isArray(messages)) {
69
+ applyBuddySystemPrompt(
70
+ messages as Array<Record<string, unknown>>,
71
+ CODEBUDDY_SYSTEM_PROMPT,
72
+ context?.tenant_system_prompt,
73
+ );
74
+ }
75
+ normalizeBuddyToolNames(payload);
76
+ injectBuddyParallelToolCalls(payload, request);
77
+ void request;
78
+ }
79
+
80
+ const CODEBUDDY_INTL_RAW: readonly BuddyRawEntry[] = BUDDY_SHARED_RAW;
81
+
82
+ export const CODEBUDDY_IMAGE_MODELS: readonly ModelDefinition[] = makeBuddyImageModels(
83
+ "cb",
84
+ "/images/generations",
85
+ );
86
+
87
+ export const CODEBUDDY_VIDEO_MODELS: readonly ModelDefinition[] = makeBuddyVideoModels(
88
+ "cb",
89
+ "/videos/generations",
90
+ );
91
+
92
+ export const CODEBUDDY_MODELS: readonly ModelDefinition[] = [
93
+ ...CODEBUDDY_INTL_RAW.filter(
94
+ (entry) => !BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]) && !BUDDY_VIDEO_MODEL_ID_SET.has(entry[0]),
95
+ ).map((entry) => makeBuddyModel(entry, "cb")),
96
+ ...CODEBUDDY_IMAGE_MODELS,
97
+ ...CODEBUDDY_VIDEO_MODELS,
98
+ ];
99
+
100
+ export async function discoverCodeBuddyModels(
101
+ input: DiscoveryInput,
102
+ ): Promise<readonly ModelDefinition[] | null> {
103
+ return fetchBuddyDirectoryModels({
104
+ siteUrl: CODEBUDDY_BASE_URL,
105
+ providerId: CODEBUDDY_PROVIDER_ID,
106
+ credential: input.credential,
107
+ modelsPath: BUDDY_INTL_MODELS_PATH,
108
+ endpoint: undefined,
109
+ ...(input.signal ? { signal: input.signal } : {}),
110
+ ...(input.fetcher ? { fetcher: input.fetcher } : {}),
111
+ });
112
+ }
113
+
114
+ export function createCodeBuddyAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
115
+ return new BuddyMediaAdapter(
116
+ codebuddyAdapterConfig({
117
+ providerId: CODEBUDDY_PROVIDER_ID,
118
+ baseUrl: CODEBUDDY_BASE_URL,
119
+ variant: "IDE",
120
+ cliIdentity: true,
121
+ prePayload: codeBuddyIntlPrePayload,
122
+ // The intl CLI profile gzips the chat body and recovers a channel-check
123
+ // 400 by retrying once on the console chat endpoint (donor behavior).
124
+ requestCompression: "gzip",
125
+ channelFallbackPath: "/console/chat/completions",
126
+ ...(fetchImpl ? { fetchImpl } : {}),
127
+ }),
128
+ {
129
+ variant: "IDE",
130
+ // BuddyMediaConfig has no `cliIdentity`; the CLI identity is selected by
131
+ // supplying the builder that takes it.
132
+ buildHeaders: (context, request) => codebuddyHeaders("IDE", context, request, true),
133
+ systemPrompt: CODEBUDDY_SYSTEM_PROMPT,
134
+ baseUrl: CODEBUDDY_BASE_URL,
135
+ imageGenerationPath: "/images/generations",
136
+ },
137
+ );
138
+ }
139
+
140
+ // ── codebuddy/cn-provider ──────────────────────────────────────────
141
+
142
+ export const CODEBUDDY_CN_PROVIDER_ID = "cbcn" as const;
143
+
144
+ export const CODEBUDDY_CN_BASE_URL = providerBaseUrl("cbcn");
145
+
146
+ function isAgentPromptText(text: string): boolean {
147
+ return /you are claude code|claude.?code.+official.+cli|anthropic.+official.+cli|anxthxropic.+official.+cli|you are (?:cursor|windsurf|cline|aider|continue|copilot|cody)|you are an? (?:ai )?(?:coding |code )?agent|cc_entrypoint\s*=\s*(?:cli|vscode|jetbrains|gui)|claude.?code.+issues|give feedback.+claude.?code|you are .{0,30}(?:powerful )?ai agent|orchestration capabilities|OhMyOpenCode|<agent-identity>|<Role>|<Behavior_Instructions>/i.test(
148
+ text,
149
+ );
150
+ }
151
+
152
+ const CODEBUDDY_CN_NEUTRAL_PROMPT = "You are a helpful assistant.";
153
+
154
+ function flattenContent(content: unknown): string {
155
+ if (typeof content === "string") return content;
156
+ if (!Array.isArray(content)) return "";
157
+ return content
158
+ .map((part) =>
159
+ part !== null && typeof part === "object" && "text" in part
160
+ ? String((part as Record<string, unknown>)["text"] ?? "")
161
+ : "",
162
+ )
163
+ .join("\n");
164
+ }
165
+
166
+ function neutralizeCnMessages(messages: Array<Record<string, unknown>>): void {
167
+ for (let index = 0; index < messages.length; index += 1) {
168
+ const message = messages[index];
169
+ if (!message || message["role"] !== "system") continue;
170
+ const content = message["content"];
171
+ const text = flattenContent(content);
172
+ if (text.length <= 2_000 && !isAgentPromptText(text)) continue;
173
+ messages[index] =
174
+ typeof content === "string"
175
+ ? { ...message, content: CODEBUDDY_CN_NEUTRAL_PROMPT }
176
+ : {
177
+ ...message,
178
+ content: [{ type: "text", text: CODEBUDDY_CN_NEUTRAL_PROMPT }],
179
+ };
180
+ }
181
+ }
182
+
183
+ export function codeBuddyCnPrePayload(
184
+ payload: Record<string, unknown>,
185
+ request: CanonicalRequest,
186
+ candidate: ProviderDispatchTarget,
187
+ context?: ProviderDispatchContext,
188
+ ): void {
189
+ // CN ladder: the CN backend serves `low`/`max` levels the international one
190
+ // rejects, so the realm must be named rather than left to default to intl.
191
+ buddyPrePayloadCommon(payload, request, "cn", context);
192
+ if (Array.isArray(payload["messages"])) {
193
+ const messages = payload["messages"] as Array<Record<string, unknown>>;
194
+ neutralizeCnMessages(messages);
195
+ finalizeBuddyMessages(messages, { leadPrompt: CODEBUDDY_CN_NEUTRAL_PROMPT });
196
+ }
197
+ ensurePayloadModel(payload, candidate, "CodeBuddy CN");
198
+ normalizeBuddyToolNames(payload);
199
+ injectBuddyParallelToolCalls(payload, request);
200
+ void request;
201
+ }
202
+
203
+ export { CODEBUDDY_CN_RAW };
204
+
205
+ export const CODEBUDDY_CN_IMAGE_MODELS: readonly ModelDefinition[] = makeBuddyCnImageModels(
206
+ CODEBUDDY_CN_PROVIDER_ID,
207
+ "/images/generations",
208
+ );
209
+
210
+ export const CODEBUDDY_CN_VIDEO_MODELS: readonly ModelDefinition[] = makeBuddyCnVideoModels(
211
+ CODEBUDDY_CN_PROVIDER_ID,
212
+ "/videos/generations",
213
+ );
214
+
215
+ export const CODEBUDDY_CN_MODELS: readonly ModelDefinition[] = [
216
+ ...CODEBUDDY_CN_RAW.filter(
217
+ (entry) =>
218
+ !BUDDY_CN_IMAGE_MODEL_ID_SET.has(entry[0]) &&
219
+ !BUDDY_CN_VIDEO_MODEL_ID_SET.has(entry[0]),
220
+ ).map((entry) =>
221
+ makeBuddyModel(entry, CODEBUDDY_CN_PROVIDER_ID, undefined, "cn"),
222
+ ),
223
+ ...CODEBUDDY_CN_IMAGE_MODELS,
224
+ ...CODEBUDDY_CN_VIDEO_MODELS,
225
+ ];
226
+
227
+ export async function discoverCodeBuddyCnModels(
228
+ input: DiscoveryInput,
229
+ ): Promise<readonly ModelDefinition[] | null> {
230
+ return fetchBuddyDirectoryModels({
231
+ siteUrl: CODEBUDDY_CN_BASE_URL,
232
+ providerId: CODEBUDDY_CN_PROVIDER_ID,
233
+ credential: input.credential,
234
+ modelsPath: BUDDY_CN_MODELS_PATH,
235
+ endpoint: undefined,
236
+ ...(input.signal ? { signal: input.signal } : {}),
237
+ ...(input.fetcher ? { fetcher: input.fetcher } : {}),
238
+ });
239
+ }
240
+
241
+ export function createCodeBuddyCnAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
242
+ // BuddyMediaAdapter, not OpenAICompatibleAdapter: the CN realm publishes an
243
+ // image-generation row, and the plain compatible adapter has no image path,
244
+ // so `hunyuan-image-alpha` would route to /chat/completions and fail.
245
+ return new BuddyMediaAdapter(
246
+ codebuddyAdapterConfig({
247
+ providerId: CODEBUDDY_CN_PROVIDER_ID,
248
+ baseUrl: CODEBUDDY_CN_BASE_URL,
249
+ variant: "CLI",
250
+ prePayload: codeBuddyCnPrePayload,
251
+ // The CN CLI profile gzips the chat body (donor behavior). The console
252
+ // channel fallback is an intl-only recovery; CN has no second endpoint.
253
+ requestCompression: "gzip",
254
+ ...(fetchImpl ? { fetchImpl } : {}),
255
+ }),
256
+ {
257
+ variant: "CLI",
258
+ // The CN realm has no separate system prompt of its own; the neutral CN
259
+ // prompt is applied by `codeBuddyCnPrePayload`, so the media config
260
+ // reuses the intl one purely to satisfy the required field. Image
261
+ // generation sends a prompt, not a conversation, so this turn is
262
+ // discarded by the image path in every case.
263
+ systemPrompt: CODEBUDDY_SYSTEM_PROMPT,
264
+ baseUrl: CODEBUDDY_CN_BASE_URL,
265
+ imageGenerationPath: "/images/generations",
266
+ },
267
+ );
268
+ }
269
+
270
+ // ── codebuddy/oauth ──────────────────────────────────────────
271
+
272
+ const CODEBUDDY_INTL_DEVICE_START_URL = `${providerBaseUrl("cb")}/plugin/auth/state`;
273
+
274
+ const CODEBUDDY_INTL_DEVICE_POLL_URL = `${providerBaseUrl("cb")}/plugin/auth/token`;
275
+
276
+ const CODEBUDDY_INTL_REFRESH_URL = `${providerBaseUrl("cb")}/plugin/auth/token/refresh`;
277
+
278
+ const CODEBUDDY_CN_DEVICE_START_URL = `${providerBaseUrl("cbcn")}/plugin/auth/state`;
279
+
280
+ const CODEBUDDY_CN_DEVICE_POLL_URL = `${providerBaseUrl("cbcn")}/plugin/auth/token`;
281
+
282
+ const CODEBUDDY_CN_REFRESH_URL = `${providerBaseUrl("cbcn")}/plugin/auth/token/refresh`;
283
+
284
+ export const CODEBUDDY_INTL_VARIANT: BuddyOAuthVariant = {
285
+ providerId: "cb",
286
+ providerLabel: "CodeBuddy",
287
+ domain: "www.codebuddy.ai",
288
+ platform: "ide",
289
+ userAgent: async () => {
290
+ return buildCodeBuddyUserAgent("IDE");
291
+ },
292
+ deviceStartUrl: CODEBUDDY_INTL_DEVICE_START_URL,
293
+ devicePollUrl: CODEBUDDY_INTL_DEVICE_POLL_URL,
294
+ refreshUrl: CODEBUDDY_INTL_REFRESH_URL,
295
+ responseCode: strictResponseCode,
296
+ };
297
+
298
+ export const CODEBUDDY_CN_VARIANT: BuddyOAuthVariant = {
299
+ providerId: "cbcn",
300
+ providerLabel: "CodeBuddy",
301
+ domain: "copilot.tencent.com",
302
+ platform: "CLI",
303
+ userAgent: async () => {
304
+ return buildCodeBuddyUserAgent("CLI");
305
+ },
306
+ deviceStartUrl: CODEBUDDY_CN_DEVICE_START_URL,
307
+ devicePollUrl: CODEBUDDY_CN_DEVICE_POLL_URL,
308
+ refreshUrl: CODEBUDDY_CN_REFRESH_URL,
309
+ responseCode: strictResponseCode,
310
+ };
311
+
312
+ export const codeBuddyOAuthClient = new BuddyOAuthClient(CODEBUDDY_INTL_VARIANT);
313
+
314
+ export const codeBuddyCnOAuthClient = new BuddyOAuthClient(CODEBUDDY_CN_VARIANT);
315
+
316
+ // ── codebuddy/quota ──────────────────────────────────────────
317
+
318
+ export const CODEBUDDY_CN_USAGE_URL =
319
+ `${providerBaseUrl("cbcn")}/billing/meter/get-user-resource`;
320
+
321
+ export const CODEBUDDY_INTL_USAGE_URL =
322
+ `${providerBaseUrl("cb")}/billing/meter/get-user-resource`;
323
+
324
+ const CODEBUDDY_CN_REQUEST_USAGE_URL =
325
+ `${providerBaseUrl("cbcn")}/billing/meter/get-user-request-usage`;
326
+
327
+ const CODEBUDDY_INTL_REQUEST_USAGE_URL =
328
+ `${providerBaseUrl("cb")}/billing/meter/get-user-request-usage`;
329
+
330
+ type CodeBuddyProviderId = "cb" | "cbcn";
331
+
332
+ async function cnHeaders(enterpriseId?: string): Promise<Record<string, string>> {
333
+ return {
334
+ "User-Agent": buildCodeBuddyUserAgent("CLI"),
335
+ "X-Product": "SaaS",
336
+ "X-IDE-Type": "CLI",
337
+ "X-IDE-Name": "CLI",
338
+ "X-Domain": codebuddyDomain("CLI"),
339
+ "x-requested-with": "XMLHttpRequest",
340
+ "x-codebuddy-request": "1",
341
+ ...(enterpriseId === undefined || enterpriseId.length === 0
342
+ ? {}
343
+ : { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
344
+ };
345
+ }
346
+
347
+ async function intlHeaders(enterpriseId?: string): Promise<Record<string, string>> {
348
+ return {
349
+ "User-Agent": buildCodeBuddyUserAgent("IDE"),
350
+ "X-Product": "SaaS",
351
+ "X-IDE-Type": "IDE",
352
+ "X-IDE-Name": "IDE",
353
+ "X-Domain": codebuddyDomain("IDE"),
354
+ "x-requested-with": "XMLHttpRequest",
355
+ "x-codebuddy-request": "1",
356
+ ...(enterpriseId === undefined || enterpriseId.length === 0
357
+ ? {}
358
+ : { "X-Tenant-Id": enterpriseId, "X-Enterprise-Id": enterpriseId }),
359
+ };
360
+ }
361
+
362
+ function parseProviderId(providerId: string): CodeBuddyProviderId {
363
+ const value = providerId.trim().toLowerCase();
364
+ if (value === "cb") return "cb";
365
+ if (value === "cbcn") return "cbcn";
366
+ throw new Error(`Unsupported CodeBuddy provider ${providerId}`);
367
+ }
368
+
369
+ async function providerConfig(
370
+ providerId: CodeBuddyProviderId,
371
+ enterpriseId?: string,
372
+ ): Promise<{
373
+ url: string;
374
+ headers: Record<string, string>;
375
+ display: string;
376
+ }> {
377
+ if (providerId === "cb") {
378
+ return { url: CODEBUDDY_INTL_USAGE_URL, headers: await intlHeaders(enterpriseId), display: "CodeBuddy" };
379
+ }
380
+ return { url: CODEBUDDY_CN_USAGE_URL, headers: await cnHeaders(enterpriseId), display: "CodeBuddy CN" };
381
+ }
382
+
383
+ export async function fetchCodeBuddyQuota(
384
+ credential: string,
385
+ fetcher: FetchLike,
386
+ providerId: string = "cbcn",
387
+ enterpriseId?: string,
388
+ ): Promise<ProviderQuotaResult> {
389
+ const source = parseProviderId(providerId);
390
+ const cfg = await providerConfig(source, enterpriseId);
391
+ return fetchTencentBillingQuota({
392
+ source,
393
+ display: cfg.display,
394
+ url: cfg.url,
395
+ headers: cfg.headers,
396
+ credential,
397
+ fetcher,
398
+ defaultPlan: "CodeBuddy",
399
+ });
400
+ }
401
+
402
+ export const fetchCodeBuddyCnQuota = (
403
+ credential: string,
404
+ fetcher: FetchLike,
405
+ ): Promise<ProviderQuotaResult> => fetchCodeBuddyQuota(credential, fetcher, "cbcn");
406
+
407
+ export const fetchCodeBuddyIntlQuota = (
408
+ credential: string,
409
+ fetcher: FetchLike,
410
+ ): Promise<ProviderQuotaResult> => fetchCodeBuddyQuota(credential, fetcher, "cb");
411
+
412
+ export async function fetchCodeBuddyRequestUsage(
413
+ credential: string,
414
+ fetcher: FetchLike,
415
+ providerId: string = "cbcn",
416
+ days: number = 30,
417
+ enterpriseId?: string,
418
+ ): Promise<BuddyUsageResult> {
419
+ const source = parseProviderId(providerId);
420
+ const cfg = await providerConfig(source, enterpriseId);
421
+ return fetchBuddyRequestUsage({
422
+ url:
423
+ source === "cb" ? CODEBUDDY_INTL_REQUEST_USAGE_URL : CODEBUDDY_CN_REQUEST_USAGE_URL,
424
+ headers: cfg.headers,
425
+ credential,
426
+ fetcher,
427
+ days,
428
+ });
429
+ }