cartethyia 2.4.5 → 2.5.0

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 (415) hide show
  1. package/.env.example +4 -1
  2. package/README.md +63 -13
  3. package/dist/dashboard/assets/AccountCooldown-ChpdzxRH.js.gz +0 -0
  4. package/dist/dashboard/assets/BannedPage-9igfctfZ.js +1 -0
  5. package/dist/dashboard/assets/BannedPage-9igfctfZ.js.gz +0 -0
  6. package/dist/dashboard/assets/{CliToolDetailPage-BzGevuql.js → CliToolDetailPage-ZRr2K2sF.js} +1 -1
  7. package/dist/dashboard/assets/CliToolDetailPage-ZRr2K2sF.js.gz +0 -0
  8. package/dist/dashboard/assets/{CliToolsPage-BaRM_7We.js → CliToolsPage-D3xqZbN-.js} +1 -1
  9. package/dist/dashboard/assets/CliToolsPage-D3xqZbN-.js.gz +0 -0
  10. package/dist/dashboard/assets/CombosPage-CVnQPBBz.js +1 -0
  11. package/dist/dashboard/assets/CombosPage-CVnQPBBz.js.gz +0 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js +1 -0
  13. package/dist/dashboard/assets/ConsoleLogPage-u6W1UXSc.js.gz +0 -0
  14. package/dist/dashboard/assets/{CustomizationPage-DqUGcoH0.js → CustomizationPage-CTTpCb25.js} +1 -1
  15. package/dist/dashboard/assets/CustomizationPage-CTTpCb25.js.gz +0 -0
  16. package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js +1 -0
  17. package/dist/dashboard/assets/HealthEventsModal-C5XpWlvy.js.gz +0 -0
  18. package/dist/dashboard/assets/{LoginPage-DbhTGfhb.js → LoginPage-DHoB3Agn.js} +1 -1
  19. package/dist/dashboard/assets/LoginPage-DHoB3Agn.js.gz +0 -0
  20. package/dist/dashboard/assets/ModelPicker-oQ-SDXp8.js +1 -0
  21. package/dist/dashboard/assets/ModelPicker-oQ-SDXp8.js.gz +0 -0
  22. package/dist/dashboard/assets/OverviewPage-BrY4SgIt.js +1 -0
  23. package/dist/dashboard/assets/OverviewPage-BrY4SgIt.js.gz +0 -0
  24. package/dist/dashboard/assets/ProviderDetailPage-D9VSt7T_.js +3 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-D9VSt7T_.js.gz +0 -0
  26. package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js +1 -0
  27. package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js.gz +0 -0
  28. package/dist/dashboard/assets/ProvidersPage-Df77V5I5.js +1 -0
  29. package/dist/dashboard/assets/ProvidersPage-Df77V5I5.js.gz +0 -0
  30. package/dist/dashboard/assets/ProxyPage-CDfxP7AC.js +7 -0
  31. package/dist/dashboard/assets/ProxyPage-CDfxP7AC.js.gz +0 -0
  32. package/dist/dashboard/assets/QuotaPage-CY4o2t4p.js +1 -0
  33. package/dist/dashboard/assets/QuotaPage-CY4o2t4p.js.gz +0 -0
  34. package/dist/dashboard/assets/{SettingsPage-YxRml8AT.js → SettingsPage-CvjZxHE4.js} +1 -1
  35. package/dist/dashboard/assets/SettingsPage-CvjZxHE4.js.gz +0 -0
  36. package/dist/dashboard/assets/SetupPage-D3nza7LH.js +1 -0
  37. package/dist/dashboard/assets/SetupPage-D3nza7LH.js.gz +0 -0
  38. package/dist/dashboard/assets/{SortableList-Bol1ASmI.js → SortableList-Dtt12WT1.js} +1 -1
  39. package/dist/dashboard/assets/SortableList-Dtt12WT1.js.gz +0 -0
  40. package/dist/dashboard/assets/StudioPage-CbK3hXvU.js +31 -0
  41. package/dist/dashboard/assets/StudioPage-CbK3hXvU.js.gz +0 -0
  42. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
  43. package/dist/dashboard/assets/UsagePage-BQlWbWg2.js +56 -0
  44. package/dist/dashboard/assets/UsagePage-BQlWbWg2.js.gz +0 -0
  45. package/dist/dashboard/assets/api-keys-BmDbsior.js +1 -0
  46. package/dist/dashboard/assets/api-keys-BmDbsior.js.gz +0 -0
  47. package/dist/dashboard/assets/app-BbpSarVV.css +2 -0
  48. package/dist/dashboard/assets/app-BbpSarVV.css.gz +0 -0
  49. package/dist/dashboard/assets/{app-BDJWMThu.js → app-C-Y4oZT0.js} +3 -3
  50. package/dist/dashboard/assets/app-C-Y4oZT0.js.gz +0 -0
  51. package/dist/dashboard/assets/arrow-left-CpBxkoxI.js.gz +0 -0
  52. package/dist/dashboard/assets/arrow-right-Dl5yKnp8.js.gz +0 -0
  53. package/dist/dashboard/assets/assert-BHfaei-X.js +1 -0
  54. package/dist/dashboard/assets/assert-BHfaei-X.js.gz +0 -0
  55. package/dist/dashboard/assets/backup-file-gdKIlg8U.js.gz +0 -0
  56. package/dist/dashboard/assets/{badge-BwmwEOgA.js → badge-DpXT4Ixt.js} +1 -1
  57. package/dist/dashboard/assets/badge-DpXT4Ixt.js.gz +0 -0
  58. package/dist/dashboard/assets/{banner-BKBfKTqn.js → banner-CSAAWLJv.js} +1 -1
  59. package/dist/dashboard/assets/banner-CSAAWLJv.js.gz +0 -0
  60. package/dist/dashboard/assets/brain-Cwed_72z.js.gz +0 -0
  61. package/dist/dashboard/assets/{card-BTdbRFFg.js → card-DEhRXXw4.js} +1 -1
  62. package/dist/dashboard/assets/card-DEhRXXw4.js.gz +0 -0
  63. package/dist/dashboard/assets/check-D69FzdvC.js.gz +0 -0
  64. package/dist/dashboard/assets/chevron-right-BXIy5l3h.js.gz +0 -0
  65. package/dist/dashboard/assets/circle-alert-CntYHV5v.js.gz +0 -0
  66. package/dist/dashboard/assets/circle-check-BU3v_mFW.js.gz +0 -0
  67. package/dist/dashboard/assets/cli-tools-B0wBq-RL.js +1 -0
  68. package/dist/dashboard/assets/cli-tools-B0wBq-RL.js.gz +0 -0
  69. package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js +1 -0
  70. package/dist/dashboard/assets/clipboard-button-DOo6EU8O.js.gz +0 -0
  71. package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
  72. package/dist/dashboard/assets/copy-ngmQ9zcZ.js.gz +0 -0
  73. package/dist/dashboard/assets/{dialog-iocKA3jr.js → dialog-BvQeBMfP.js} +1 -1
  74. package/dist/dashboard/assets/dialog-BvQeBMfP.js.gz +0 -0
  75. package/dist/dashboard/assets/dialog-actions-B1axpEg7.js.gz +0 -0
  76. package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
  77. package/dist/dashboard/assets/download-dRFo5_Wu.js.gz +0 -0
  78. package/dist/dashboard/assets/{drawer-CDKOTZdY.js → drawer-CMwPXwQB.js} +1 -1
  79. package/dist/dashboard/assets/drawer-CMwPXwQB.js.gz +0 -0
  80. package/dist/dashboard/assets/entry-D4O2229X.js +1 -0
  81. package/dist/dashboard/assets/entry-D4O2229X.js.gz +0 -0
  82. package/dist/dashboard/assets/entry-DKvr5Q9K.js +1 -0
  83. package/dist/dashboard/assets/entry-DKvr5Q9K.js.gz +0 -0
  84. package/dist/dashboard/assets/entry-FQCejoDY.js +4 -0
  85. package/dist/dashboard/assets/entry-FQCejoDY.js.gz +0 -0
  86. package/dist/dashboard/assets/eye-C_hawfH4.js.gz +0 -0
  87. package/dist/dashboard/assets/eye-off-Bk5g2luF.js.gz +0 -0
  88. package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
  89. package/dist/dashboard/assets/gauge-BbIMy7MB.js.gz +0 -0
  90. package/dist/dashboard/assets/github-badge-zliLvBwr.js +1 -0
  91. package/dist/dashboard/assets/github-badge-zliLvBwr.js.gz +0 -0
  92. package/dist/dashboard/assets/image-BPaouViG.js.gz +0 -0
  93. package/dist/dashboard/assets/{index-C4hXfAMs.js → index-CXm3FIyt.js} +2 -2
  94. package/dist/dashboard/assets/index-CXm3FIyt.js.gz +0 -0
  95. package/dist/dashboard/assets/{inline-DCejSLlA.js → inline-D1IlZZ8H.js} +1 -1
  96. package/dist/dashboard/assets/inline-D1IlZZ8H.js.gz +0 -0
  97. package/dist/dashboard/assets/{input-Bn4_kNav.js → input-BpVZdrbc.js} +1 -1
  98. package/dist/dashboard/assets/input-BpVZdrbc.js.gz +0 -0
  99. package/dist/dashboard/assets/jsx-runtime-CXUMngI_.js.gz +0 -0
  100. package/dist/dashboard/assets/key-round-UkavsGxp.js.gz +0 -0
  101. package/dist/dashboard/assets/layers-2-glBbjl.js.gz +0 -0
  102. package/dist/dashboard/assets/{layout-Bv-NxqZ5.js → layout-BioLW7gN.js} +1 -1
  103. package/dist/dashboard/assets/layout-BioLW7gN.js.gz +0 -0
  104. package/dist/dashboard/assets/{list-row-BLA0sldD.js → list-row-CwVcGAIc.js} +1 -1
  105. package/dist/dashboard/assets/list-row-CwVcGAIc.js.gz +0 -0
  106. package/dist/dashboard/assets/{live-YlifPYox.js → live-yfEJFF9T.js} +1 -1
  107. package/dist/dashboard/assets/live-yfEJFF9T.js.gz +0 -0
  108. package/dist/dashboard/assets/log-in-BmRjy60c.js.gz +0 -0
  109. package/dist/dashboard/assets/message-circle-CCxGwRvv.js.gz +0 -0
  110. package/dist/dashboard/assets/model-bans-CT-TxSNX.js +1 -0
  111. package/dist/dashboard/assets/model-bans-CT-TxSNX.js.gz +0 -0
  112. package/dist/dashboard/assets/mutation-BkoLM5Ba.js +1 -0
  113. package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
  114. package/dist/dashboard/assets/numbers-CFL4_Dqc.js.gz +0 -0
  115. package/dist/dashboard/assets/pencil-768ysRAr.js.gz +0 -0
  116. package/dist/dashboard/assets/plus-DIdX_g-x.js.gz +0 -0
  117. package/dist/dashboard/assets/power-off-Yjw9GMJh.js +1 -0
  118. package/dist/dashboard/assets/power-off-Yjw9GMJh.js.gz +0 -0
  119. package/dist/dashboard/assets/privacy-mode-GM8bej85.js +1 -0
  120. package/dist/dashboard/assets/privacy-mode-GM8bej85.js.gz +0 -0
  121. package/dist/dashboard/assets/providers/agentrouter.svg.gz +0 -0
  122. package/dist/dashboard/assets/providers/aihubmix.svg.gz +0 -0
  123. package/dist/dashboard/assets/providers/alibaba-coding-plan.svg.gz +0 -0
  124. package/dist/dashboard/assets/providers/alibaba.svg.gz +0 -0
  125. package/dist/dashboard/assets/providers/antigravity.svg.gz +0 -0
  126. package/dist/dashboard/assets/providers/bai.svg.gz +0 -0
  127. package/dist/dashboard/assets/providers/blackbox.svg.gz +0 -0
  128. package/dist/dashboard/assets/providers/claude-code.svg.gz +0 -0
  129. package/dist/dashboard/assets/providers/cursor.webp +0 -0
  130. package/dist/dashboard/assets/providers/exa.svg.gz +0 -0
  131. package/dist/dashboard/assets/providers/gmi-cloud.svg.gz +0 -0
  132. package/dist/dashboard/assets/providers/inferhub.svg.gz +0 -0
  133. package/dist/dashboard/assets/providers/muse.svg.gz +0 -0
  134. package/dist/dashboard/assets/providers/nous-research.svg.gz +0 -0
  135. package/dist/dashboard/assets/providers/openai-light.svg.gz +0 -0
  136. package/dist/dashboard/assets/providers/parallel.svg.gz +0 -0
  137. package/dist/dashboard/assets/providers/tokenharbor.svg.gz +0 -0
  138. package/dist/dashboard/assets/providers/trae.webp +0 -0
  139. package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
  140. package/dist/dashboard/assets/{query-keys-ROf-g1Wi.js → query-keys-D7wX2vM5.js} +1 -1
  141. package/dist/dashboard/assets/query-keys-D7wX2vM5.js.gz +0 -0
  142. package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
  143. package/dist/dashboard/assets/refresh-cw-BqJFk4sU.js.gz +0 -0
  144. package/dist/dashboard/assets/rotate-ccw-CufcqITi.js.gz +0 -0
  145. package/dist/dashboard/assets/route-CNSNj9Zm.js.gz +0 -0
  146. package/dist/dashboard/assets/routing-Cs6jl49L.js +1 -0
  147. package/dist/dashboard/assets/routing-Cs6jl49L.js.gz +0 -0
  148. package/dist/dashboard/assets/scaling-nWE4Cx8f.js.gz +0 -0
  149. package/dist/dashboard/assets/search-JOKus9rb.js.gz +0 -0
  150. package/dist/dashboard/assets/select-C0Rer3gF.js +41 -0
  151. package/dist/dashboard/assets/select-C0Rer3gF.js.gz +0 -0
  152. package/dist/dashboard/assets/settings-CfcTcOyU.js +1 -0
  153. package/dist/dashboard/assets/settings-CfcTcOyU.js.gz +0 -0
  154. package/dist/dashboard/assets/shield-check-DVS0Foqh.js.gz +0 -0
  155. package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
  156. package/dist/dashboard/assets/{stack-C1kTcOmP.js → stack-C9_uUjaA.js} +1 -1
  157. package/dist/dashboard/assets/stack-C9_uUjaA.js.gz +0 -0
  158. package/dist/dashboard/assets/{state-DHKdg-pm.js → state-DA0B95UQ.js} +1 -1
  159. package/dist/dashboard/assets/state-DA0B95UQ.js.gz +0 -0
  160. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  161. package/dist/dashboard/assets/{switch-DIDeAiz9.js → switch-Cittxy-x.js} +1 -1
  162. package/dist/dashboard/assets/switch-Cittxy-x.js.gz +0 -0
  163. package/dist/dashboard/assets/terminal-Bd4ee8TA.js +1 -0
  164. package/dist/dashboard/assets/terminal-Bd4ee8TA.js.gz +0 -0
  165. package/dist/dashboard/assets/toast-CNt_jzO4.js +2 -0
  166. package/dist/dashboard/assets/toast-CNt_jzO4.js.gz +0 -0
  167. package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
  168. package/dist/dashboard/assets/trash-Cppn5c3R.js.gz +0 -0
  169. package/dist/dashboard/assets/use-clipboard-B0Sy03fE.js.gz +0 -0
  170. package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
  171. package/dist/dashboard/assets/use-reduced-motion-C4B0R6Sz.js.gz +0 -0
  172. package/dist/dashboard/assets/use-timeout-BwcBBRrT.js.gz +0 -0
  173. package/dist/dashboard/assets/{useMutation-DVmwOKU-.js → useMutation-BQKMcJ1H.js} +1 -1
  174. package/dist/dashboard/assets/useMutation-BQKMcJ1H.js.gz +0 -0
  175. package/dist/dashboard/assets/wrench-B6E1oEuY.js.gz +0 -0
  176. package/dist/dashboard/index.html +1 -1
  177. package/dist/dashboard/index.html.gz +0 -0
  178. package/dist/dashboard/precompressed-assets.json +122 -0
  179. package/migrations/full-postgres/0013_add_providers_tenant_id_index.sql +22 -0
  180. package/migrations/full-postgres/0014_add_provider_accounts_tenant_id_index.sql +21 -0
  181. package/migrations/full-postgres/0015_add_payload_stages.sql +18 -0
  182. package/migrations/full-postgres/0016_add_share_link_slug.sql +20 -0
  183. package/migrations/full-postgres/0017_add_models_pro_only.sql +18 -0
  184. package/migrations/full-postgres/0018_add_accounts_quota_plan.sql +18 -0
  185. package/migrations/full-postgres/0019_add_models_free_tier.sql +15 -0
  186. package/migrations/lite-sqlite3/0000_baseline.sql +4 -2
  187. package/migrations/lite-sqlite3/0013_add_providers_tenant_id_index.sql +4 -0
  188. package/migrations/lite-sqlite3/0014_add_provider_accounts_tenant_id_index.sql +4 -0
  189. package/migrations/lite-sqlite3/0015_add_payload_stages.sql +18 -0
  190. package/migrations/lite-sqlite3/0016_add_share_link_slug.sql +20 -0
  191. package/migrations/lite-sqlite3/0017_add_models_pro_only.sql +18 -0
  192. package/migrations/lite-sqlite3/0018_add_accounts_quota_plan.sql +18 -0
  193. package/migrations/lite-sqlite3/0019_add_models_free_tier.sql +15 -0
  194. package/package.json +26 -30
  195. package/scripts/cli/{carte-launcher.cjs → bin/carte.cjs} +8 -8
  196. package/scripts/cli/{cli-launcher.cjs → bin/cartethyia.cjs} +167 -134
  197. package/scripts/cli/command/admin.ts +65 -0
  198. package/scripts/cli/command/console-menu.ts +246 -0
  199. package/scripts/cli/{doctor.ts → command/doctor.ts} +257 -258
  200. package/scripts/cli/{setup.ts → command/setup.ts} +8 -12
  201. package/scripts/cli/command/start.ts +77 -0
  202. package/scripts/cli/command/tray.ts +165 -0
  203. package/scripts/cli/command/update.ts +23 -0
  204. package/scripts/cli/{runtime-state.ts → gateway/drain-token.ts} +78 -78
  205. package/scripts/cli/gateway/instance-lock.ts +105 -0
  206. package/scripts/cli/gateway/spawn.ts +173 -0
  207. package/scripts/cli/gateway/stop.ts +51 -0
  208. package/scripts/cli/main.ts +94 -0
  209. package/scripts/cli/support/bun.ts +27 -0
  210. package/scripts/cli/support/env.ts +99 -0
  211. package/scripts/cli/support/platform.ts +64 -0
  212. package/scripts/cli/support/services.ts +88 -0
  213. package/scripts/cli/support/startup-signal.ts +23 -0
  214. package/scripts/cli/{version.ts → support/version.ts} +1 -1
  215. package/scripts/cli/tray/hidden-window.vbs +28 -0
  216. package/scripts/cli/{tray.ts → tray/index.ts} +3 -3
  217. package/scripts/cli/{tray.ps1 → tray/windows.ps1} +107 -98
  218. package/scripts/cli/ui/background.ts +110 -0
  219. package/src/boot/app.ts +23 -7
  220. package/src/boot/dependencies.ts +55 -13
  221. package/src/boot/elysia-typebox-bridge.ts +37 -0
  222. package/src/boot/lifecycle.ts +2 -0
  223. package/src/config/cooldowns.ts +138 -138
  224. package/src/config/providers.ts +31 -5
  225. package/src/config/runtime.ts +19 -3
  226. package/src/config/spec.ts +20 -0
  227. package/src/console/api-keys/contracts.ts +414 -391
  228. package/src/console/api-keys/routes.ts +880 -870
  229. package/src/console/auth/account-reset-store.ts +14 -0
  230. package/src/console/auth/account-reset.ts +3 -2
  231. package/src/console/auth/setup-service.ts +6 -3
  232. package/src/console/backup/routes.ts +8 -0
  233. package/src/console/cli-tools/contracts.ts +6 -6
  234. package/src/console/console-router.ts +5 -3
  235. package/src/console/dashboard-assets.ts +81 -11
  236. package/src/console/domain-registration.ts +9 -2
  237. package/src/console/observability/contracts.ts +475 -423
  238. package/src/console/observability/routes.ts +31 -6
  239. package/src/console/observability/store.ts +1015 -912
  240. package/src/console/providers/catalog/contracts.ts +31 -0
  241. package/src/console/providers/catalog/provider-operations.ts +8 -0
  242. package/src/console/providers/catalog/public-model-store.ts +91 -60
  243. package/src/console/providers/catalog/store.ts +1532 -1521
  244. package/src/console/providers/oauth/callback-listener.ts +18 -3
  245. package/src/console/providers/oauth/routes.ts +38 -15
  246. package/src/console/quota/account-quota-tenant.ts +9 -6
  247. package/src/console/quota/refresh.ts +19 -0
  248. package/src/console/response-compression.ts +69 -2
  249. package/src/console/routing/pools/probe-verdict.ts +72 -0
  250. package/src/console/share/share-router.ts +7 -4
  251. package/src/console/share/share-stats.ts +12 -5
  252. package/src/console/shared/read-through-cache.ts +133 -7
  253. package/src/console/updates/repository-updates.ts +39 -34
  254. package/src/console/updates/routes.ts +162 -4
  255. package/src/main.ts +3 -0
  256. package/src/network/http2-bidi.ts +85 -0
  257. package/src/network/outbound-fetch.ts +87 -24
  258. package/src/network/pool/agent.ts +478 -460
  259. package/src/network/pool/resolver.ts +1104 -544
  260. package/src/network/pool-health-machine.ts +12 -5
  261. package/src/observability/event-log.ts +29 -8
  262. package/src/observability/metrics.ts +40 -13
  263. package/src/observability/payload-capture.ts +344 -324
  264. package/src/observability/runtime-metrics.ts +7 -0
  265. package/src/persistence/db-pg.ts +9 -3
  266. package/src/persistence/db-sqlite.ts +497 -495
  267. package/src/persistence/health-event-flush.ts +137 -0
  268. package/src/persistence/migrate.ts +181 -129
  269. package/src/persistence/schema.ts +1360 -1257
  270. package/src/persistence/settings-revision.ts +25 -0
  271. package/src/persistence/shared-cache.ts +217 -0
  272. package/src/persistence/stores/share-store.ts +556 -528
  273. package/src/persistence/usage-flush.ts +61 -1
  274. package/src/protocol/canonical-model.ts +23 -1
  275. package/src/protocol/response/chat.ts +143 -10
  276. package/src/protocol/response/codex.ts +9 -75
  277. package/src/protocol/response/omp-tool-call-markup.ts +221 -0
  278. package/src/protocol/tool-identity.ts +43 -9
  279. package/src/providers/authentication/jwt-validator.ts +130 -187
  280. package/src/providers/authentication/oauth-flow-store.ts +16 -9
  281. package/src/providers/default-registry.ts +177 -1
  282. package/src/providers/discovery/catalog/catalog-format.ts +20 -0
  283. package/src/providers/discovery/models-dev-catalog.ts +39 -22
  284. package/src/providers/discovery/openai-model-discovery.ts +39 -3
  285. package/src/providers/discovery/openrouter-free-roster.ts +98 -0
  286. package/src/providers/discovery/probe-wire.ts +29 -5
  287. package/src/providers/discovery/probing-service.ts +1022 -1001
  288. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +42 -2
  289. package/src/providers/integrations/buddy/buddy-chat-shared.ts +913 -914
  290. package/src/providers/integrations/buddy/buddy-cli-headers.ts +88 -0
  291. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +22 -5
  292. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +33 -1
  293. package/src/providers/integrations/buddy/buddy-identity.ts +46 -0
  294. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +37 -1
  295. package/src/providers/integrations/buddy/buddy-usage-store.ts +40 -5
  296. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +4 -0
  297. package/src/providers/integrations/buddy/codebuddy/provider.ts +180 -175
  298. package/src/providers/integrations/buddy/codebuddy/shared.ts +115 -73
  299. package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +5 -2
  300. package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -204
  301. package/src/providers/integrations/buddy/workbuddy/quota.ts +172 -159
  302. package/src/providers/integrations/buddy/workbuddy/shared.ts +200 -171
  303. package/src/providers/integrations/claude/claude.ts +606 -582
  304. package/src/providers/integrations/cline/cline-quota.ts +18 -16
  305. package/src/providers/integrations/cline/cline.ts +539 -468
  306. package/src/providers/integrations/codex/codex.ts +5 -8
  307. package/src/providers/integrations/commandcode/commandcode.ts +675 -541
  308. package/src/providers/integrations/commandcode/discovery.ts +116 -0
  309. package/src/providers/integrations/commandcode/quota.ts +160 -0
  310. package/src/providers/integrations/cursor/cursor-auth.ts +418 -0
  311. package/src/providers/integrations/cursor/cursor-catalog.ts +368 -0
  312. package/src/providers/integrations/cursor/cursor-http2.ts +300 -0
  313. package/src/providers/integrations/cursor/cursor-identity.ts +92 -0
  314. package/src/providers/integrations/cursor/cursor-request.ts +471 -0
  315. package/src/providers/integrations/cursor/cursor-session-manager.ts +281 -0
  316. package/src/providers/integrations/cursor/cursor-shared.ts +108 -0
  317. package/src/providers/integrations/cursor/cursor.ts +960 -0
  318. package/src/providers/integrations/cursor/protocol/framing.ts +129 -0
  319. package/src/providers/integrations/cursor/protocol/messages.ts +2355 -0
  320. package/src/providers/integrations/cursor/protocol/struct.ts +305 -0
  321. package/src/providers/integrations/factory/factory-oauth.ts +7 -11
  322. package/src/providers/integrations/github/github.ts +4 -4
  323. package/src/providers/integrations/hermes.ts +79 -8
  324. package/src/providers/integrations/kilo/kilo-discovery.ts +10 -1
  325. package/src/providers/integrations/kilo/kilo.ts +153 -146
  326. package/src/providers/integrations/opencode/opencode-go-quota.ts +130 -0
  327. package/src/providers/integrations/opencode/provider.ts +532 -499
  328. package/src/providers/integrations/openrouter/provider.ts +139 -281
  329. package/src/providers/integrations/qoder/qoder-catalog.ts +450 -0
  330. package/src/providers/integrations/qoder/qoder-oauth.ts +310 -263
  331. package/src/providers/integrations/qoder/qoder-realm.ts +106 -0
  332. package/src/providers/integrations/qoder/qoder-virtual.ts +77 -0
  333. package/src/providers/integrations/qoder/qoder.ts +865 -730
  334. package/src/providers/integrations/shared/install-id.ts +29 -2
  335. package/src/providers/integrations/trae/trae-catalog.ts +190 -0
  336. package/src/providers/integrations/trae/trae-headers.ts +149 -0
  337. package/src/providers/integrations/trae/trae-oauth.ts +773 -0
  338. package/src/providers/integrations/trae/trae-protocol.ts +400 -0
  339. package/src/providers/integrations/trae/trae-realm.ts +220 -0
  340. package/src/providers/integrations/trae/trae.ts +458 -0
  341. package/src/providers/operations/account-health-service.ts +107 -10
  342. package/src/providers/operations/client-versions.ts +143 -6
  343. package/src/providers/operations/model-catalog-cache.ts +18 -3
  344. package/src/providers/operations/provider-catalog-seeder.ts +95 -86
  345. package/src/providers/operations/provider-catalog-service.ts +76 -0
  346. package/src/providers/operations/provider-credential-service.ts +46 -7
  347. package/src/providers/provider-contracts.ts +76 -0
  348. package/src/providers/provider-metadata.ts +78 -6
  349. package/src/providers/provider-model-definition.ts +373 -349
  350. package/src/security/api-key-auth.ts +126 -8
  351. package/src/transport/contracts.ts +3 -0
  352. package/src/transport/dispatch/attempt-finalize.ts +39 -2
  353. package/src/transport/dispatch/attempt-loop.ts +530 -513
  354. package/src/transport/dispatch/empty-stream.ts +17 -26
  355. package/src/transport/dispatch/generation.ts +88 -21
  356. package/src/transport/dispatch/leases.ts +99 -2
  357. package/src/transport/dispatch/proxy-request.ts +60 -3
  358. package/src/transport/dispatch/streaming/finalize.ts +16 -1
  359. package/src/transport/dispatch/streaming/stream.ts +22 -2
  360. package/src/transport/dispatch/upstream.ts +19 -1
  361. package/src/transport/failure-policy.ts +20 -0
  362. package/src/transport/guards/auth-guard.ts +26 -1
  363. package/src/transport/guards/body-policy.ts +5 -4
  364. package/src/transport/request/preparer.ts +103 -0
  365. package/src/transport/request/state.ts +14 -0
  366. package/src/transport/routing/plan-gate.ts +45 -0
  367. package/src/transport/routing/route-catalog.ts +799 -738
  368. package/src/transport/routing/route-model.ts +52 -1
  369. package/src/transport/routing/router.ts +51 -0
  370. package/src/transport/surface/chat/encode.ts +18 -31
  371. package/src/transport/surface/messages/stream.ts +3 -2
  372. package/src/transport/translation/tool-repair.ts +37 -16
  373. package/src/workers/account-identity-sweep.ts +14 -12
  374. package/src/workers/daily-checkin.ts +62 -0
  375. package/src/workers/quota-refresh-sweep.ts +27 -2
  376. package/dist/dashboard/assets/BannedPage-DUrXpp-X.js +0 -1
  377. package/dist/dashboard/assets/CombosPage-B7ETkfVH.js +0 -1
  378. package/dist/dashboard/assets/ConsoleLogPage-AisQzCI1.js +0 -1
  379. package/dist/dashboard/assets/HealthEventsModal-BNflDm_f.js +0 -1
  380. package/dist/dashboard/assets/ModelPicker-CAiPR5Vd.js +0 -1
  381. package/dist/dashboard/assets/OverviewPage-C3NIzsDx.js +0 -1
  382. package/dist/dashboard/assets/ProviderDetailPage-BK8i5B5X.js +0 -3
  383. package/dist/dashboard/assets/ProviderIcon-paOCq8I0.js +0 -1
  384. package/dist/dashboard/assets/ProvidersPage-CvCVgm1e.js +0 -1
  385. package/dist/dashboard/assets/ProxyPage-DjabkuzP.js +0 -7
  386. package/dist/dashboard/assets/QuotaPage-Dxe0B0iu.js +0 -1
  387. package/dist/dashboard/assets/SetupPage-BaD4P_jW.js +0 -1
  388. package/dist/dashboard/assets/StudioPage-CLP4le3U.js +0 -31
  389. package/dist/dashboard/assets/UsagePage-Djes-Epy.js +0 -56
  390. package/dist/dashboard/assets/api-keys-CjIGQhe7.js +0 -1
  391. package/dist/dashboard/assets/app-Cjgo4-Lf.css +0 -2
  392. package/dist/dashboard/assets/assert-Bwh6DJTK.js +0 -1
  393. package/dist/dashboard/assets/cli-tools-DccaOfhX.js +0 -1
  394. package/dist/dashboard/assets/clipboard-button-DQmMikNQ.js +0 -1
  395. package/dist/dashboard/assets/entry-Cpi0rph1.js +0 -4
  396. package/dist/dashboard/assets/entry-Dm3PpDCO.js +0 -1
  397. package/dist/dashboard/assets/entry-keNDZ_Wz.js +0 -1
  398. package/dist/dashboard/assets/github-badge-BuAJr8oU.js +0 -1
  399. package/dist/dashboard/assets/model-bans-CVvHZ-qz.js +0 -1
  400. package/dist/dashboard/assets/mutation-BIizFZav.js +0 -1
  401. package/dist/dashboard/assets/privacy-mode-CQjbZ3xk.js +0 -1
  402. package/dist/dashboard/assets/routing-jntw9-Ui.js +0 -1
  403. package/dist/dashboard/assets/select-CGUuTQmj.js +0 -41
  404. package/dist/dashboard/assets/settings-BAS6QbmJ.js +0 -1
  405. package/dist/dashboard/assets/sliders-horizontal-ClG7dBeJ.js +0 -1
  406. package/dist/dashboard/assets/terminal-C9mZ4Ugm.js +0 -1
  407. package/dist/dashboard/assets/toast-DKAdP2mo.js +0 -2
  408. package/scripts/cli/cli.ts +0 -771
  409. package/scripts/operations/probe-egress.ts +0 -335
  410. package/scripts/operations/restart.ts +0 -120
  411. package/scripts/shared/env.ts +0 -269
  412. /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.ico +0 -0
  413. /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.png +0 -0
  414. /package/scripts/cli/{menu.ts → ui/prompt.ts} +0 -0
  415. /package/scripts/cli/{wordmark.ts → ui/wordmark.ts} +0 -0
@@ -1,175 +1,180 @@
1
- // CodeBuddy International adapter — exact provider contract.
2
- // Canonical provider ID: cb
3
- // Base (manifest-owned CODEBUDDY_BASE_URL) → Chat: base + /chat/completions
4
- // Auth: Authorization Bearer for both api_key and oauth
5
- // Stream: force stream=true upstream, factory reaggregates for non-stream callers
6
- // Headers: per-provider CodeBuddy headers with fresh correlation IDs per dispatch
7
- // Payload: leading CodeBuddy system prompt + typed user content, reasoning_summary auto only when reasoning_effort
8
-
9
- import { BuddyMediaAdapter } from "../buddy-media";
10
- import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderAdapter } from "../../../provider-contracts";
11
- import type { ModelDefinition } from "../../../provider-model-definition";
12
- import type { DiscoveryInput } from "../../../discovery/discovery-types";
13
- import { GatewayError } from "../../../../protocol/gateway-error";
14
- import type { CanonicalRequest } from "../../../../protocol/canonical-model";
15
- import { providerBaseUrl } from "../../../provider-metadata";
16
- import {
17
- codebuddyAdapterConfig,
18
- } from "./shared";
19
- import {
20
- BUDDY_SHARED_RAW,
21
- BUDDY_IMAGE_MODEL_ID_SET,
22
- BUDDY_VIDEO_MODEL_ID_SET,
23
- makeBuddyModel,
24
- makeBuddyImageModels,
25
- makeBuddyVideoModels,
26
- type BuddyRawEntry,
27
- } from "../buddy-catalog-shared";
28
- import { BUDDY_INTL_MODELS_PATH, fetchBuddyDirectoryModels } from "../buddy-discovery-shared";
29
- import {
30
- applyBuddySystemPrompt,
31
- buddyPrePayloadCommon,
32
- normalizeBuddyToolNames,
33
- } from "../buddy-chat-shared";
34
-
35
-
36
- // Constants — public contract
37
- export const CODEBUDDY_PROVIDER_ID = "cb" as const;
38
- export const CODEBUDDY_BASE_URL = providerBaseUrl("cb");
39
- // Upstream model translation — preserve provider mapping
40
-
41
- // Payload hook — provider intl semantics
42
- // - force stream=true
43
- // - reasoning_summary auto only when reasoning_effort requested
44
- // - upstreamId translation
45
- // - leading CodeBuddy system prompt + typed user content normalization
46
-
47
- /**
48
- * Leading system turn for this variant.
49
- *
50
- * The upstream validates that the wire *opens* with a `system` turn (code
51
- * `11128`) but does not check its text — the CN variant installs a plain
52
- * engineering-assistant sentence in the same slot and the gateway accepts it.
53
- * So this text is a product choice rather than a wire contract, and the
54
- * previous vendor-branded line ("You are CodeBuddy Code.") made every request
55
- * claim an identity the caller never chose, while also discarding whatever
56
- * system prompt the caller actually sent.
57
- *
58
- * The prompt is therefore a neutral assistant identity with an explicit
59
- * persona: pragmatic, direct, and honest — no sycophancy, no hedging, no
60
- * invented certainty.
61
- */
62
- export const CODEBUDDY_SYSTEM_PROMPT =
63
- "You are a pragmatic and direct software engineering assistant. " +
64
- "Be honest and truthful: state what you know, say plainly when you are unsure " +
65
- "or do not know, and never claim to have done something you have not done. " +
66
- "Prefer concrete answers over filler, and say so when a request is ambiguous " +
67
- "instead of guessing silently.";
68
-
69
- function codeBuddyIntlPrePayload(
70
- payload: Record<string, unknown>,
71
- request: CanonicalRequest,
72
- candidate: ProviderDispatchTarget,
73
- context?: ProviderDispatchContext,
74
- ): void {
75
- // International ladder: DeepSeek Flash and friends serve only `high`.
76
- buddyPrePayloadCommon(payload, request, "intl", context);
77
- const rawModel = payload["model"];
78
- const source =
79
- typeof rawModel === "string" && rawModel.length > 0
80
- ? rawModel
81
- : candidate.model_id;
82
- if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required");
83
- const messages = payload["messages"];
84
- if (Array.isArray(messages)) {
85
- applyBuddySystemPrompt(messages as Array<Record<string, unknown>>, CODEBUDDY_SYSTEM_PROMPT);
86
- }
87
- normalizeBuddyToolNames(payload);
88
- void request;
89
- }
90
-
91
- // Model catalog — shared CodeBuddy / WorkBuddy international roster
92
-
93
- const CODEBUDDY_INTL_RAW: readonly BuddyRawEntry[] = BUDDY_SHARED_RAW;
94
-
95
- /**
96
- * CodeBuddy's image generation rows.
97
- *
98
- * These ids also sit on the shared chat roster as ordinary `llm` rows, which is
99
- * why they were unreachable as image models: nothing downstream could tell a
100
- * chat model from one that returns an image, so `mediaGeneration` was false for
101
- * every catalog row. The roster and the declared capabilities come from
102
- * {@link makeBuddyImageModels} so cb and WorkBuddy cannot drift.
103
- */
104
- export const CODEBUDDY_IMAGE_MODELS: readonly ModelDefinition[] = makeBuddyImageModels(
105
- "cb",
106
- "/images/generations",
107
- );
108
-
109
- /**
110
- * CodeBuddy's video-generation rows (`seedance-2.5`).
111
- *
112
- * Reached through `/v1/videos/generations`, so the endpoint is the upstream
113
- * video path rather than a chat-completions path.
114
- */
115
- export const CODEBUDDY_VIDEO_MODELS: readonly ModelDefinition[] = makeBuddyVideoModels(
116
- "cb",
117
- "/videos/generations",
118
- );
119
-
120
- /**
121
- * The full cb catalog the registry loads: chat roster plus image and video rows.
122
- *
123
- * The image and video ids are filtered out of the chat pass so one id never
124
- * appears under two service kinds. Exported as a single list so
125
- * `default-registry.ts` keeps one import for this provider.
126
- */
127
- export const CODEBUDDY_MODELS: readonly ModelDefinition[] = [
128
- ...CODEBUDDY_INTL_RAW.filter(
129
- (entry) => !BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]) && !BUDDY_VIDEO_MODEL_ID_SET.has(entry[0]),
130
- ).map((entry) => makeBuddyModel(entry, "cb")),
131
- ...CODEBUDDY_IMAGE_MODELS,
132
- ...CODEBUDDY_VIDEO_MODELS,
133
- ];
134
-
135
- /**
136
- * Reads the CodeBuddy intl console directory.
137
- *
138
- * The static `CODEBUDDY_MODELS` above stays the fallback — this console is
139
- * documented to answer 500 intermittently — while discovery carries the
140
- * upstream's own limits and capability flags.
141
- */
142
- export async function discoverCodeBuddyModels(
143
- input: DiscoveryInput,
144
- ): Promise<readonly ModelDefinition[] | null> {
145
- return fetchBuddyDirectoryModels({
146
- siteUrl: CODEBUDDY_BASE_URL,
147
- providerId: CODEBUDDY_PROVIDER_ID,
148
- credential: input.credential,
149
- modelsPath: BUDDY_INTL_MODELS_PATH,
150
- endpoint: undefined,
151
- ...(input.signal ? { signal: input.signal } : {}),
152
- ...(input.fetcher ? { fetcher: input.fetcher } : {}),
153
- });
154
- }
155
-
156
- // Public factory — uses OpenAI-compatible factory but forces provider semantics
157
- // Supports both api_key and oauth via Authorization Bearer (factory handles both)
158
-
159
- export function createCodeBuddyAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
160
- return new BuddyMediaAdapter(
161
- codebuddyAdapterConfig({
162
- providerId: CODEBUDDY_PROVIDER_ID,
163
- baseUrl: CODEBUDDY_BASE_URL,
164
- variant: "IDE",
165
- prePayload: codeBuddyIntlPrePayload,
166
- ...(fetchImpl ? { fetchImpl } : {}),
167
- }),
168
- {
169
- variant: "IDE",
170
- systemPrompt: CODEBUDDY_SYSTEM_PROMPT,
171
- baseUrl: CODEBUDDY_BASE_URL,
172
- imageGenerationPath: "/images/generations",
173
- },
174
- );
175
- }
1
+ // CodeBuddy International adapter — exact provider contract.
2
+ // Canonical provider ID: cb
3
+ // Base (manifest-owned CODEBUDDY_BASE_URL) → Chat: base + /chat/completions
4
+ // Auth: Authorization Bearer for both api_key and oauth
5
+ // Stream: force stream=true upstream, factory reaggregates for non-stream callers
6
+ // Headers: per-provider CodeBuddy headers with fresh correlation IDs per dispatch
7
+ // Payload: leading CodeBuddy system prompt + typed user content, reasoning_summary auto only when reasoning_effort
8
+
9
+ import { BuddyMediaAdapter } from "../buddy-media";
10
+ import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderAdapter } from "../../../provider-contracts";
11
+ import type { ModelDefinition } from "../../../provider-model-definition";
12
+ import type { DiscoveryInput } from "../../../discovery/discovery-types";
13
+ import { GatewayError } from "../../../../protocol/gateway-error";
14
+ import type { CanonicalRequest } from "../../../../protocol/canonical-model";
15
+ import { providerBaseUrl } from "../../../provider-metadata";
16
+ import {
17
+ codebuddyAdapterConfig,
18
+ codebuddyHeaders,
19
+ } from "./shared";
20
+ import {
21
+ BUDDY_SHARED_RAW,
22
+ BUDDY_IMAGE_MODEL_ID_SET,
23
+ BUDDY_VIDEO_MODEL_ID_SET,
24
+ makeBuddyModel,
25
+ makeBuddyImageModels,
26
+ makeBuddyVideoModels,
27
+ type BuddyRawEntry,
28
+ } from "../buddy-catalog-shared";
29
+ import { BUDDY_INTL_MODELS_PATH, fetchBuddyDirectoryModels } from "../buddy-discovery-shared";
30
+ import {
31
+ applyBuddySystemPrompt,
32
+ buddyPrePayloadCommon,
33
+ normalizeBuddyToolNames,
34
+ } from "../buddy-chat-shared";
35
+
36
+
37
+ // Constants — public contract
38
+ export const CODEBUDDY_PROVIDER_ID = "cb" as const;
39
+ export const CODEBUDDY_BASE_URL = providerBaseUrl("cb");
40
+ // Upstream model translation — preserve provider mapping
41
+
42
+ // Payload hook — provider intl semantics
43
+ // - force stream=true
44
+ // - reasoning_summary auto only when reasoning_effort requested
45
+ // - upstreamId translation
46
+ // - leading CodeBuddy system prompt + typed user content normalization
47
+
48
+ /**
49
+ * Leading system turn for this variant.
50
+ *
51
+ * The upstream validates that the wire *opens* with a `system` turn (code
52
+ * `11128`) but does not check its text — the CN variant installs a plain
53
+ * engineering-assistant sentence in the same slot and the gateway accepts it.
54
+ * So this text is a product choice rather than a wire contract, and the
55
+ * previous vendor-branded line ("You are CodeBuddy Code.") made every request
56
+ * claim an identity the caller never chose, while also discarding whatever
57
+ * system prompt the caller actually sent.
58
+ *
59
+ * The prompt is therefore a neutral assistant identity with an explicit
60
+ * persona: pragmatic, direct, and honest — no sycophancy, no hedging, no
61
+ * invented certainty.
62
+ */
63
+ export const CODEBUDDY_SYSTEM_PROMPT =
64
+ "You are a pragmatic and direct software engineering assistant. " +
65
+ "Be honest and truthful: state what you know, say plainly when you are unsure " +
66
+ "or do not know, and never claim to have done something you have not done. " +
67
+ "Prefer concrete answers over filler, and say so when a request is ambiguous " +
68
+ "instead of guessing silently.";
69
+
70
+ function codeBuddyIntlPrePayload(
71
+ payload: Record<string, unknown>,
72
+ request: CanonicalRequest,
73
+ candidate: ProviderDispatchTarget,
74
+ context?: ProviderDispatchContext,
75
+ ): void {
76
+ // International ladder: DeepSeek Flash and friends serve only `high`.
77
+ buddyPrePayloadCommon(payload, request, "intl", context);
78
+ const rawModel = payload["model"];
79
+ const source =
80
+ typeof rawModel === "string" && rawModel.length > 0
81
+ ? rawModel
82
+ : candidate.model_id;
83
+ if (!source) throw new GatewayError("invalid_request", 400, "CodeBuddy model is required");
84
+ const messages = payload["messages"];
85
+ if (Array.isArray(messages)) {
86
+ applyBuddySystemPrompt(messages as Array<Record<string, unknown>>, CODEBUDDY_SYSTEM_PROMPT);
87
+ }
88
+ normalizeBuddyToolNames(payload);
89
+ void request;
90
+ }
91
+
92
+ // Model catalog — shared CodeBuddy / WorkBuddy international roster
93
+
94
+ const CODEBUDDY_INTL_RAW: readonly BuddyRawEntry[] = BUDDY_SHARED_RAW;
95
+
96
+ /**
97
+ * CodeBuddy's image generation rows.
98
+ *
99
+ * These ids also sit on the shared chat roster as ordinary `llm` rows, which is
100
+ * why they were unreachable as image models: nothing downstream could tell a
101
+ * chat model from one that returns an image, so `mediaGeneration` was false for
102
+ * every catalog row. The roster and the declared capabilities come from
103
+ * {@link makeBuddyImageModels} so cb and WorkBuddy cannot drift.
104
+ */
105
+ export const CODEBUDDY_IMAGE_MODELS: readonly ModelDefinition[] = makeBuddyImageModels(
106
+ "cb",
107
+ "/images/generations",
108
+ );
109
+
110
+ /**
111
+ * CodeBuddy's video-generation rows (`seedance-2.5`).
112
+ *
113
+ * Reached through `/videos/generations` on the `/v2` base, so the endpoint is
114
+ * the upstream video path rather than a chat-completions path.
115
+ */
116
+ export const CODEBUDDY_VIDEO_MODELS: readonly ModelDefinition[] = makeBuddyVideoModels(
117
+ "cb",
118
+ "/videos/generations",
119
+ );
120
+
121
+ /**
122
+ * The full cb catalog the registry loads: chat roster plus image and video rows.
123
+ *
124
+ * The image and video ids are filtered out of the chat pass so one id never
125
+ * appears under two service kinds. Exported as a single list so
126
+ * `default-registry.ts` keeps one import for this provider.
127
+ */
128
+ export const CODEBUDDY_MODELS: readonly ModelDefinition[] = [
129
+ ...CODEBUDDY_INTL_RAW.filter(
130
+ (entry) => !BUDDY_IMAGE_MODEL_ID_SET.has(entry[0]) && !BUDDY_VIDEO_MODEL_ID_SET.has(entry[0]),
131
+ ).map((entry) => makeBuddyModel(entry, "cb")),
132
+ ...CODEBUDDY_IMAGE_MODELS,
133
+ ...CODEBUDDY_VIDEO_MODELS,
134
+ ];
135
+
136
+ /**
137
+ * Reads the CodeBuddy intl console directory.
138
+ *
139
+ * The static `CODEBUDDY_MODELS` above stays the fallback — this console is
140
+ * documented to answer 500 intermittently — while discovery carries the
141
+ * upstream's own limits and capability flags.
142
+ */
143
+ export async function discoverCodeBuddyModels(
144
+ input: DiscoveryInput,
145
+ ): Promise<readonly ModelDefinition[] | null> {
146
+ return fetchBuddyDirectoryModels({
147
+ siteUrl: CODEBUDDY_BASE_URL,
148
+ providerId: CODEBUDDY_PROVIDER_ID,
149
+ credential: input.credential,
150
+ modelsPath: BUDDY_INTL_MODELS_PATH,
151
+ endpoint: undefined,
152
+ ...(input.signal ? { signal: input.signal } : {}),
153
+ ...(input.fetcher ? { fetcher: input.fetcher } : {}),
154
+ });
155
+ }
156
+
157
+ // Public factory — uses OpenAI-compatible factory but forces provider semantics
158
+ // Supports both api_key and oauth via Authorization Bearer (factory handles both)
159
+
160
+ export function createCodeBuddyAdapter(fetchImpl?: typeof fetch): ProviderAdapter {
161
+ return new BuddyMediaAdapter(
162
+ codebuddyAdapterConfig({
163
+ providerId: CODEBUDDY_PROVIDER_ID,
164
+ baseUrl: CODEBUDDY_BASE_URL,
165
+ variant: "IDE",
166
+ cliIdentity: true,
167
+ prePayload: codeBuddyIntlPrePayload,
168
+ ...(fetchImpl ? { fetchImpl } : {}),
169
+ }),
170
+ {
171
+ variant: "IDE",
172
+ // BuddyMediaConfig has no `cliIdentity`; the CLI identity is selected by
173
+ // supplying the builder that takes it.
174
+ buildHeaders: (context, request) => codebuddyHeaders("IDE", context, request, true),
175
+ systemPrompt: CODEBUDDY_SYSTEM_PROMPT,
176
+ baseUrl: CODEBUDDY_BASE_URL,
177
+ imageGenerationPath: "/images/generations",
178
+ },
179
+ );
180
+ }
@@ -1,73 +1,115 @@
1
- import { withBearerAuthentication, type OpenAICompatibleAdapterConfig } from "../../../adapters/compatible-adapter";
2
- import type { CanonicalRequest } from "../../../../protocol/canonical-model";
3
- import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from "../../../provider-contracts";
4
- import { resolveInboundSessionId } from "../../../operations/session-resolution";
5
- import { buddyConversationHeaders } from "../buddy-conversation-headers";
6
- import { buildCodeBuddyUserAgent } from "../../../operations/client-versions";
7
- import { readBuddyDeviceToken } from "../workbuddy/shared";
8
-
9
- /** Client identity variant behind the per-request CodeBuddy headers. */
10
- export type CodeBuddyVariant = "IDE" | "CLI";
11
-
12
- export function codebuddyDomain(variant: CodeBuddyVariant): string {
13
- return variant === "IDE" ? "www.codebuddy.ai" : "copilot.tencent.com";
14
- }
15
-
16
-
17
- /**
18
- * Per-request CodeBuddy headers — exact provider contract shared by the
19
- * international (IDE identity) and CN (CLI identity). The stable conversation
20
- * header is preserved from the client when available; request IDs rotate.
21
- */
22
- export async function codebuddyHeaders(
23
- variant: CodeBuddyVariant,
24
- context?: ProviderDispatchContext,
25
- request?: CanonicalRequest,
26
- ): Promise<Record<string, string>> {
27
- const identity = variant === "IDE" ? "IDE" : "CLI";
28
- const ua = buildCodeBuddyUserAgent(identity);
29
- const deviceToken = readBuddyDeviceToken(context);
30
- const conversationId = resolveInboundSessionId(context, request);
31
- return {
32
- accept: "text/event-stream",
33
- "User-Agent": ua,
34
- "X-Product": "SaaS",
35
- "X-IDE-Type": identity,
36
- "X-IDE-Name": identity,
37
- "X-Domain": codebuddyDomain(variant),
38
- "x-requested-with": "XMLHttpRequest",
39
- "x-codebuddy-request": "1",
40
- // Same family WorkBuddy sends: the upstream's channel check reads the
41
- // turn-level aggregation key, and a chat request without it is refused with
42
- // `400 · 11128 "conversation id missing"`.
43
- ...buddyConversationHeaders({
44
- ...(conversationId === undefined ? {} : { conversationId }),
45
- }),
46
- ...(deviceToken === undefined ? {} : { "X-Device-Token": deviceToken }),
47
- };
48
- }
49
-
50
- /**
51
- * Shared OpenAI-compatible chat-adapter config for both CodeBuddy variants:
52
- * bearer auth, chat-only wire contract, per-request identity headers, and the
53
- * variant's payload hook.
54
- */
55
- export function codebuddyAdapterConfig(args: {
56
- providerId: ProviderId;
57
- baseUrl: string;
58
- variant: CodeBuddyVariant;
59
- prePayload: (
60
- payload: Record<string, unknown>,
61
- request: CanonicalRequest,
62
- candidate: ProviderDispatchTarget,
63
- ) => void;
64
- fetchImpl?: typeof fetch;
65
- }): OpenAICompatibleAdapterConfig {
66
- return withBearerAuthentication({
67
- provider_id: args.providerId,
68
- base_url: args.baseUrl,
69
- buildExtraHeaders: (context, request) => codebuddyHeaders(args.variant, context, request),
70
- prePayload: args.prePayload,
71
- ...(args.fetchImpl ? { fetchImpl: args.fetchImpl } : {}),
72
- });
73
- }
1
+ import { withBearerAuthentication, type OpenAICompatibleAdapterConfig } from "../../../adapters/compatible-adapter";
2
+ import type { CanonicalRequest } from "../../../../protocol/canonical-model";
3
+ import type { ProviderDispatchContext, ProviderDispatchTarget, ProviderId } from "../../../provider-contracts";
4
+ import { resolveInboundSessionId } from "../../../operations/session-resolution";
5
+ import { buddyConversationHeaders } from "../buddy-conversation-headers";
6
+ import { buddyUserId, resolveBuddyIdentity } from "../buddy-identity";
7
+ import { buildCodeBuddyUserAgent, getCodeBuddyCnVersion, getCodeBuddyVersion } from "../../../operations/client-versions";
8
+ import { readBuddyDeviceToken } from "../workbuddy/shared";
9
+ import { buddyCliHeaders, buddyCliTraceHeaders } from "../buddy-cli-headers";
10
+
11
+ /** Client identity variant behind the per-request CodeBuddy headers. */
12
+ export type CodeBuddyVariant = "IDE" | "CLI";
13
+
14
+ export function codebuddyDomain(variant: CodeBuddyVariant): string {
15
+ return variant === "IDE" ? "www.codebuddy.ai" : "copilot.tencent.com";
16
+ }
17
+
18
+
19
+ /**
20
+ * Per-request CodeBuddy headers — exact provider contract shared by the
21
+ * international (IDE identity) and CN (CLI identity). The stable conversation
22
+ * header is preserved from the client when available; request IDs rotate.
23
+ *
24
+ * `cliIdentity` selects the real CLI contract rather than today's hybrid: the
25
+ * reference CLI is issued by the OpenAI Node SDK, so it carries no browser
26
+ * headers and no device token, and it adds the agent envelope. Left unset it
27
+ * keeps the current behaviour for every provider.
28
+ */
29
+ export async function codebuddyHeaders(
30
+ variant: CodeBuddyVariant,
31
+ context?: ProviderDispatchContext,
32
+ request?: CanonicalRequest,
33
+ cliIdentity?: boolean,
34
+ ): Promise<Record<string, string>> {
35
+ const identity = variant === "IDE" ? "IDE" : "CLI";
36
+ const ua = buildCodeBuddyUserAgent(identity);
37
+ const deviceToken = readBuddyDeviceToken(context);
38
+ const conversationId = resolveInboundSessionId(context, request);
39
+ const conversation = buddyConversationHeaders({
40
+ ...(conversationId === undefined ? {} : { conversationId }),
41
+ });
42
+ if (resolveBuddyIdentity(context, cliIdentity) === "cli") {
43
+ return {
44
+ // The CLI sends `Accept: application/json` and no device token. The
45
+ // browser-shaped pair (`X-Requested-With`, `x-codebuddy-request`) stays
46
+ // off this branch: a request carrying both halves is a hybrid no real
47
+ // client produces, and that is a fidelity choice, not a requirement —
48
+ // the live API answers either way.
49
+ accept: "application/json",
50
+ "User-Agent": `CLI/${getCodeBuddyVersion()} CodeBuddy/${getCodeBuddyVersion()}`,
51
+ "X-Product": "SaaS",
52
+ "X-IDE-Type": "CLI",
53
+ "X-IDE-Name": "CLI",
54
+ "X-IDE-Version": getCodeBuddyVersion(),
55
+ "X-Domain": codebuddyDomain(variant),
56
+ // The conversation purpose the reference client states. Not required —
57
+ // verified against the live API that a request succeeds without it — but
58
+ // it is part of the client's real request, and matching the client is the
59
+ // defence against a channel check tightening later.
60
+ "X-Agent-Purpose": "conversation",
61
+ ...conversation,
62
+ ...buddyCliTraceHeaders(conversation),
63
+ ...buddyCliHeaders({ userId: buddyUserId(context) }),
64
+ };
65
+ }
66
+ return {
67
+ accept: "text/event-stream",
68
+ "User-Agent": ua,
69
+ "X-Product": "SaaS",
70
+ "X-IDE-Type": identity,
71
+ "X-IDE-Name": identity,
72
+ // Every reference branch sends this, in both the desktop and the CLI
73
+ // product; its absence here is what made a CodeBuddy dispatch the only
74
+ // buddy caller with no client version on the wire.
75
+ "X-IDE-Version": identity === "CLI" ? getCodeBuddyCnVersion() : getCodeBuddyVersion(),
76
+ "X-Domain": codebuddyDomain(variant),
77
+ "x-requested-with": "XMLHttpRequest",
78
+ "x-codebuddy-request": "1",
79
+ // Same value the CLI branch sends, for the same reason: part of the
80
+ // client's real request, harmless when the channel check does not read it.
81
+ "X-Agent-Purpose": "conversation",
82
+ // Same family WorkBuddy sends: the upstream's channel check reads the
83
+ // turn-level aggregation key, and a chat request without it is refused for a
84
+ // missing conversation id.
85
+ ...conversation,
86
+ ...(deviceToken === undefined ? {} : { "X-Device-Token": deviceToken }),
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Shared OpenAI-compatible chat-adapter config for both CodeBuddy variants:
92
+ * bearer auth, chat-only wire contract, per-request identity headers, and the
93
+ * variant's payload hook.
94
+ */
95
+ export function codebuddyAdapterConfig(args: {
96
+ providerId: ProviderId;
97
+ baseUrl: string;
98
+ variant: CodeBuddyVariant;
99
+ prePayload: (
100
+ payload: Record<string, unknown>,
101
+ request: CanonicalRequest,
102
+ candidate: ProviderDispatchTarget,
103
+ ) => void;
104
+ fetchImpl?: typeof fetch;
105
+ cliIdentity?: boolean;
106
+ }): OpenAICompatibleAdapterConfig {
107
+ return withBearerAuthentication({
108
+ provider_id: args.providerId,
109
+ base_url: args.baseUrl,
110
+ buildExtraHeaders: (context, request) =>
111
+ codebuddyHeaders(args.variant, context, request, args.cliIdentity),
112
+ prePayload: args.prePayload,
113
+ ...(args.fetchImpl ? { fetchImpl: args.fetchImpl } : {}),
114
+ });
115
+ }
@@ -5,7 +5,7 @@ import type { DiscoveryInput } from "../../../discovery/discovery-types";
5
5
  import type { ModelDefinition } from "../../../provider-model-definition";
6
6
  import { providerBaseUrl } from "../../../provider-metadata";
7
7
  import { getWorkBuddyCnClientVersion } from "../../../operations/client-versions";
8
- import { BUDDY_INTL_MODELS_PATH, fetchBuddyDirectoryModels } from "../buddy-discovery-shared";
8
+ import { BUDDY_CN_MODELS_PATH, fetchBuddyDirectoryModels } from "../buddy-discovery-shared";
9
9
  import { CODEBUDDY_CN_MODELS } from "../codebuddy/cn-provider";
10
10
  import { workbuddyPrePayload, WORKBUDDY_SYSTEM_PROMPT } from "./provider";
11
11
  import { workbuddyAdapterConfig, workbuddyHeaders, WORKBUDDY_CHAT_PATH } from "./shared";
@@ -28,7 +28,10 @@ export async function discoverWorkBuddyCnModels(
28
28
  siteUrl: WORKBUDDY_CN_BASE_URL,
29
29
  providerId: WORKBUDDY_CN_PROVIDER_ID,
30
30
  credential: input.credential,
31
- modelsPath: BUDDY_INTL_MODELS_PATH,
31
+ // The CN host answers the `/console/…` directory, exactly like the CodeBuddy
32
+ // CN host does; the international path was inherited from the intl provider
33
+ // and the CN edge answers it with a 500 rather than a 404.
34
+ modelsPath: BUDDY_CN_MODELS_PATH,
32
35
  endpoint: WORKBUDDY_CHAT_PATH,
33
36
  ...(input.signal ? { signal: input.signal } : {}),
34
37
  ...(input.fetcher ? { fetcher: input.fetcher } : {}),