cartethyia 2.5.2 → 2.5.4

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 (277) hide show
  1. package/dist/dashboard/assets/{BannedPage-MsQaeQTs.js → BannedPage-C2orBsI2.js} +1 -1
  2. package/dist/dashboard/assets/BannedPage-C2orBsI2.js.gz +0 -0
  3. package/dist/dashboard/assets/CliToolDetailPage-DUcZ6pMB.js +1 -0
  4. package/dist/dashboard/assets/CliToolDetailPage-DUcZ6pMB.js.gz +0 -0
  5. package/dist/dashboard/assets/{CliToolsPage-DfWHTJ7v.js → CliToolsPage-BV6pxVQo.js} +1 -1
  6. package/dist/dashboard/assets/CliToolsPage-BV6pxVQo.js.gz +0 -0
  7. package/dist/dashboard/assets/{CombosPage-BrCBQDAc.js → CombosPage-Bsan4679.js} +1 -1
  8. package/dist/dashboard/assets/CombosPage-Bsan4679.js.gz +0 -0
  9. package/dist/dashboard/assets/{ConsoleLogPage-C6Uh33er.js → ConsoleLogPage-CW-wPmJ6.js} +1 -1
  10. package/dist/dashboard/assets/ConsoleLogPage-CW-wPmJ6.js.gz +0 -0
  11. package/dist/dashboard/assets/{CustomizationPage-8aS9hyJu.js → CustomizationPage-0p8uX7vB.js} +1 -1
  12. package/dist/dashboard/assets/CustomizationPage-0p8uX7vB.js.gz +0 -0
  13. package/dist/dashboard/assets/HealthEventsModal-BjqSMfko.js +1 -0
  14. package/dist/dashboard/assets/HealthEventsModal-BjqSMfko.js.gz +0 -0
  15. package/dist/dashboard/assets/{LoginPage-C8hKyXBe.js → LoginPage-BvzCx8Kr.js} +1 -1
  16. package/dist/dashboard/assets/LoginPage-BvzCx8Kr.js.gz +0 -0
  17. package/dist/dashboard/assets/{ModelPicker-CWkTUtpX.js → ModelPicker-BY1aKEkP.js} +1 -1
  18. package/dist/dashboard/assets/ModelPicker-BY1aKEkP.js.gz +0 -0
  19. package/dist/dashboard/assets/OverviewPage-DOQpy1y0.js +1 -0
  20. package/dist/dashboard/assets/OverviewPage-DOQpy1y0.js.gz +0 -0
  21. package/dist/dashboard/assets/ProviderDetailPage-ecxyUMzt.js +3 -0
  22. package/dist/dashboard/assets/ProviderDetailPage-ecxyUMzt.js.gz +0 -0
  23. package/dist/dashboard/assets/ProvidersPage-Js9jUPSb.js +1 -0
  24. package/dist/dashboard/assets/ProvidersPage-Js9jUPSb.js.gz +0 -0
  25. package/dist/dashboard/assets/ProxyPage-J3TBi3Kx.js +7 -0
  26. package/dist/dashboard/assets/ProxyPage-J3TBi3Kx.js.gz +0 -0
  27. package/dist/dashboard/assets/QuotaPage-C1gZS6xr.js +1 -0
  28. package/dist/dashboard/assets/QuotaPage-C1gZS6xr.js.gz +0 -0
  29. package/dist/dashboard/assets/SettingsPage-CS86ho5X.js +1 -0
  30. package/dist/dashboard/assets/SettingsPage-CS86ho5X.js.gz +0 -0
  31. package/dist/dashboard/assets/{SetupPage-CXjUlfqr.js → SetupPage-DDbMQsoo.js} +1 -1
  32. package/dist/dashboard/assets/SetupPage-DDbMQsoo.js.gz +0 -0
  33. package/dist/dashboard/assets/{SortableList-C-_oD3F2.js → SortableList-CB3Z7VTf.js} +1 -1
  34. package/dist/dashboard/assets/SortableList-CB3Z7VTf.js.gz +0 -0
  35. package/dist/dashboard/assets/{StudioPage-u9IxmYOI.js → StudioPage-D95UCPHI.js} +3 -3
  36. package/dist/dashboard/assets/StudioPage-D95UCPHI.js.gz +0 -0
  37. package/dist/dashboard/assets/{UsagePage-BEVLVrwP.js → UsagePage-Cnae9SWA.js} +13 -13
  38. package/dist/dashboard/assets/UsagePage-Cnae9SWA.js.gz +0 -0
  39. package/dist/dashboard/assets/{api-keys-uNywYlfv.js → api-keys-VY68Mhd1.js} +1 -1
  40. package/dist/dashboard/assets/api-keys-VY68Mhd1.js.gz +0 -0
  41. package/dist/dashboard/assets/app-COlK95oi.css +2 -0
  42. package/dist/dashboard/assets/app-COlK95oi.css.gz +0 -0
  43. package/dist/dashboard/assets/{assert-NHwYq95t.js → assert-Chi7pCnt.js} +1 -1
  44. package/dist/dashboard/assets/assert-Chi7pCnt.js.gz +0 -0
  45. package/dist/dashboard/assets/{badge-6uzDDvqs.js → badge-D4pQapKj.js} +1 -1
  46. package/dist/dashboard/assets/badge-D4pQapKj.js.gz +0 -0
  47. package/dist/dashboard/assets/{banner-4_WNg2WZ.js → banner-DH6cg-_B.js} +1 -1
  48. package/dist/dashboard/assets/banner-DH6cg-_B.js.gz +0 -0
  49. package/dist/dashboard/assets/{card--AtFedAq.js → card-BKqlUOe4.js} +1 -1
  50. package/dist/dashboard/assets/card-BKqlUOe4.js.gz +0 -0
  51. package/dist/dashboard/assets/{cli-tools-B3e7dx3N.js → cli-tools-fTgljTGA.js} +1 -1
  52. package/dist/dashboard/assets/cli-tools-fTgljTGA.js.gz +0 -0
  53. package/dist/dashboard/assets/{clipboard-button-NreUx6c8.js → clipboard-button-D5Ys_sM0.js} +1 -1
  54. package/dist/dashboard/assets/clipboard-button-D5Ys_sM0.js.gz +0 -0
  55. package/dist/dashboard/assets/database-Dz9N3zGd.js +1 -0
  56. package/dist/dashboard/assets/database-Dz9N3zGd.js.gz +0 -0
  57. package/dist/dashboard/assets/{dialog-BtpsJU98.js → dialog-BYj-8WuK.js} +1 -1
  58. package/dist/dashboard/assets/dialog-BYj-8WuK.js.gz +0 -0
  59. package/dist/dashboard/assets/{drawer-WwwtzihF.js → drawer-CmXIZ6H1.js} +1 -1
  60. package/dist/dashboard/assets/drawer-CmXIZ6H1.js.gz +0 -0
  61. package/dist/dashboard/assets/entry-CBg5zeu8.js +1 -0
  62. package/dist/dashboard/assets/entry-CBg5zeu8.js.gz +0 -0
  63. package/dist/dashboard/assets/entry-CQBr6U9c.js +1 -0
  64. package/dist/dashboard/assets/entry-CQBr6U9c.js.gz +0 -0
  65. package/dist/dashboard/assets/entry-CgdSAzEV.js +4 -0
  66. package/dist/dashboard/assets/entry-CgdSAzEV.js.gz +0 -0
  67. package/dist/dashboard/assets/{github-badge-D_eM3IgG.js → github-badge-BlptL8Uf.js} +1 -1
  68. package/dist/dashboard/assets/github-badge-BlptL8Uf.js.gz +0 -0
  69. package/dist/dashboard/assets/{index-DCBtROoK.js → index-js6TJvdr.js} +2 -2
  70. package/dist/dashboard/assets/index-js6TJvdr.js.gz +0 -0
  71. package/dist/dashboard/assets/{inline-BcNGF8Gr.js → inline-DUWDSmDV.js} +1 -1
  72. package/dist/dashboard/assets/inline-DUWDSmDV.js.gz +0 -0
  73. package/dist/dashboard/assets/{input-BG41et9G.js → input-LVjgZq4f.js} +1 -1
  74. package/dist/dashboard/assets/input-LVjgZq4f.js.gz +0 -0
  75. package/dist/dashboard/assets/{layout-C8mer_Ak.js → layout-CPfxpsfy.js} +1 -1
  76. package/dist/dashboard/assets/layout-CPfxpsfy.js.gz +0 -0
  77. package/dist/dashboard/assets/{list-row-Gh_W4OR_.js → list-row-DupvLfDx.js} +1 -1
  78. package/dist/dashboard/assets/list-row-DupvLfDx.js.gz +0 -0
  79. package/dist/dashboard/assets/{live-BJGYRBnR.js → live-C4pEJUqI.js} +1 -1
  80. package/dist/dashboard/assets/live-C4pEJUqI.js.gz +0 -0
  81. package/dist/dashboard/assets/model-bans-BRiuufkB.js +1 -0
  82. package/dist/dashboard/assets/model-bans-BRiuufkB.js.gz +0 -0
  83. package/dist/dashboard/assets/{mutation-BkoLM5Ba.js → mutation-B4ROwk8L.js} +1 -1
  84. package/dist/dashboard/assets/mutation-B4ROwk8L.js.gz +0 -0
  85. package/dist/dashboard/assets/numbers-YNcHvRY7.js +2 -0
  86. package/dist/dashboard/assets/numbers-YNcHvRY7.js.gz +0 -0
  87. package/dist/dashboard/assets/{query-keys-D7wX2vM5.js → query-keys-gmjzC3RS.js} +1 -1
  88. package/dist/dashboard/assets/{query-keys-D7wX2vM5.js.gz → query-keys-gmjzC3RS.js.gz} +0 -0
  89. package/dist/dashboard/assets/{routing-CcusqXA7.js → routing-C7tBT5o-.js} +1 -1
  90. package/dist/dashboard/assets/routing-C7tBT5o-.js.gz +0 -0
  91. package/dist/dashboard/assets/{select-DsX5QT8K.js → select-WUCXorXw.js} +2 -2
  92. package/dist/dashboard/assets/select-WUCXorXw.js.gz +0 -0
  93. package/dist/dashboard/assets/{settings-mpmXTgUa.js → settings-C_zKl1GS.js} +1 -1
  94. package/dist/dashboard/assets/settings-C_zKl1GS.js.gz +0 -0
  95. package/dist/dashboard/assets/{stack-DwLmjUFK.js → stack-_3O0F8Xn.js} +1 -1
  96. package/dist/dashboard/assets/stack-_3O0F8Xn.js.gz +0 -0
  97. package/dist/dashboard/assets/{state-DYdQmdAl.js → state-BgTxHcJS.js} +1 -1
  98. package/dist/dashboard/assets/state-BgTxHcJS.js.gz +0 -0
  99. package/dist/dashboard/assets/switch-DEjTtOWf.js +1 -0
  100. package/dist/dashboard/assets/switch-DEjTtOWf.js.gz +0 -0
  101. package/dist/dashboard/assets/terminal-0_IjPWTk.js +1 -0
  102. package/dist/dashboard/assets/terminal-0_IjPWTk.js.gz +0 -0
  103. package/dist/dashboard/assets/{useMutation-w4u4CVue.js → useMutation-BWSC0UAS.js} +1 -1
  104. package/dist/dashboard/assets/useMutation-BWSC0UAS.js.gz +0 -0
  105. package/dist/dashboard/assets/zap-C4EeVW4q.js +1 -0
  106. package/dist/dashboard/assets/zap-C4EeVW4q.js.gz +0 -0
  107. package/dist/dashboard/donation/qris-risun-marke.png +0 -0
  108. package/dist/dashboard/index.html +1 -1
  109. package/dist/dashboard/index.html.gz +0 -0
  110. package/dist/dashboard/precompressed-assets.json +54 -54
  111. package/package.json +1 -1
  112. package/scripts/cli/autostart.ts +237 -0
  113. package/scripts/cli/command/console-menu.ts +244 -246
  114. package/scripts/cli/command/tray.ts +208 -204
  115. package/scripts/cli/command/update.ts +27 -10
  116. package/scripts/cli/main.ts +28 -1
  117. package/src/boot/app.ts +693 -693
  118. package/src/boot/dependencies.ts +646 -616
  119. package/src/config/spec.ts +81 -2
  120. package/src/config/telemetry.ts +46 -0
  121. package/src/console/api-keys/bucket-spend.ts +15 -4
  122. package/src/console/backup/contracts.ts +15 -2
  123. package/src/console/backup/routes.ts +52 -1
  124. package/src/console/backup/service.ts +60 -4
  125. package/src/console/console-router.ts +8 -0
  126. package/src/console/data-management/contracts.ts +93 -0
  127. package/src/console/data-management/operations.ts +229 -0
  128. package/src/console/data-management/routes.ts +104 -0
  129. package/src/console/domain-registration.ts +39 -0
  130. package/src/console/observability/contracts.ts +524 -485
  131. package/src/console/observability/store.ts +1115 -1018
  132. package/src/console/providers/catalog/contracts.ts +6 -0
  133. package/src/console/providers/catalog/provider-operations.ts +20 -0
  134. package/src/console/providers/catalog/routes.ts +7 -0
  135. package/src/console/providers/catalog/store.ts +22 -1
  136. package/src/console/quota/account-quota-shared.ts +52 -39
  137. package/src/console/quota/refresh.ts +441 -429
  138. package/src/console/routing/pools/import-parse.ts +206 -0
  139. package/src/console/routing/pools/operations.ts +543 -501
  140. package/src/console/routing/pools/routes.ts +181 -164
  141. package/src/console/settings/contracts.ts +37 -0
  142. package/src/console/settings/store.ts +51 -0
  143. package/src/console/share/share-router.ts +6 -9
  144. package/src/console/updates/routes.ts +16 -0
  145. package/src/main.ts +10 -0
  146. package/src/observability/event-compaction.ts +315 -0
  147. package/src/observability/event-day-index.ts +442 -0
  148. package/src/observability/event-log.ts +152 -3
  149. package/src/observability/payload-capture.ts +373 -344
  150. package/src/observability/payload-store.ts +440 -366
  151. package/src/observability/telemetry-status.ts +28 -16
  152. package/src/persistence/health-event-flush.ts +36 -0
  153. package/src/persistence/schema.ts +1402 -1360
  154. package/src/persistence/stores/api-key-store.ts +6 -0
  155. package/src/persistence/stores/share-store.ts +583 -556
  156. package/src/persistence/stores/telemetry-store.ts +237 -214
  157. package/src/protocol/codecs.ts +1 -2
  158. package/src/protocol/image-clamp.ts +19 -1
  159. package/src/protocol/registry.ts +8 -0
  160. package/src/protocol/request/gemini.ts +9 -2
  161. package/src/protocol/request/messages.ts +14 -2
  162. package/src/protocol/response/gemini.ts +18 -4
  163. package/src/providers/adapters/compatible-adapter.ts +3 -0
  164. package/src/providers/bundled-discovery-providers.ts +122 -119
  165. package/src/providers/configured-openai-providers.ts +136 -134
  166. package/src/providers/default-registry.ts +5 -4
  167. package/src/providers/discovery/openai-model-discovery.ts +5 -0
  168. package/src/providers/discovery/openrouter-free-roster.ts +15 -17
  169. package/src/providers/integrations/antigravity/antigravity-quota.ts +11 -3
  170. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +4 -4
  171. package/src/providers/integrations/buddy/workbuddy/shared.ts +201 -200
  172. package/src/providers/integrations/cline/cline-quota.ts +132 -128
  173. package/src/providers/integrations/codex/codex-headers.ts +25 -39
  174. package/src/providers/integrations/codex/codex.ts +2 -29
  175. package/src/providers/integrations/cursor/cursor-quota.ts +310 -0
  176. package/src/providers/integrations/cursor/cursor-request.ts +616 -471
  177. package/src/providers/integrations/cursor/cursor-session-manager.ts +319 -281
  178. package/src/providers/integrations/cursor/cursor.ts +1485 -960
  179. package/src/providers/integrations/cursor/protocol/messages.ts +25 -0
  180. package/src/providers/integrations/factory/factory.ts +8 -1
  181. package/src/providers/integrations/gemini.ts +6 -1
  182. package/src/providers/integrations/grok/grok-quota.ts +279 -177
  183. package/src/providers/integrations/grok/grok-ratelimit-store.ts +73 -0
  184. package/src/providers/integrations/grok/grok-ratelimit.ts +218 -0
  185. package/src/providers/integrations/opencode/provider.ts +531 -532
  186. package/src/providers/integrations/qoder/qoder-quota.ts +192 -0
  187. package/src/providers/integrations/tokenharbor.ts +2 -2
  188. package/src/providers/integrations/trae/trae-catalog.ts +5 -3
  189. package/src/providers/integrations/trae/trae-quota.ts +384 -0
  190. package/src/providers/operations/account-health-service.ts +1523 -1457
  191. package/src/providers/operations/client-versions.ts +9 -2
  192. package/src/providers/provider-contracts.ts +7 -0
  193. package/src/providers/provider-metadata.ts +13 -1
  194. package/src/providers/quota/quota-support.ts +8 -0
  195. package/src/security/api-key-auth.ts +504 -494
  196. package/src/transport/dispatch/attempt-finalize.ts +46 -5
  197. package/src/transport/dispatch/generation.ts +6 -0
  198. package/src/transport/dispatch/proxy-request.ts +33 -1
  199. package/src/transport/dispatch/ratelimit-capture.ts +37 -0
  200. package/src/transport/dispatch/streaming/stream.ts +30 -2
  201. package/src/transport/dispatch/upstream.ts +9 -0
  202. package/src/transport/request/preparer.ts +7 -6
  203. package/src/transport/request/state.ts +9 -0
  204. package/src/transport/request/tenant-preferences.ts +60 -0
  205. package/src/transport/routing/route-catalog.ts +854 -799
  206. package/dist/dashboard/assets/BannedPage-MsQaeQTs.js.gz +0 -0
  207. package/dist/dashboard/assets/CliToolDetailPage-BO9nKg9w.js +0 -1
  208. package/dist/dashboard/assets/CliToolDetailPage-BO9nKg9w.js.gz +0 -0
  209. package/dist/dashboard/assets/CliToolsPage-DfWHTJ7v.js.gz +0 -0
  210. package/dist/dashboard/assets/CombosPage-BrCBQDAc.js.gz +0 -0
  211. package/dist/dashboard/assets/ConsoleLogPage-C6Uh33er.js.gz +0 -0
  212. package/dist/dashboard/assets/CustomizationPage-8aS9hyJu.js.gz +0 -0
  213. package/dist/dashboard/assets/HealthEventsModal-qomXThxX.js +0 -1
  214. package/dist/dashboard/assets/HealthEventsModal-qomXThxX.js.gz +0 -0
  215. package/dist/dashboard/assets/LoginPage-C8hKyXBe.js.gz +0 -0
  216. package/dist/dashboard/assets/ModelPicker-CWkTUtpX.js.gz +0 -0
  217. package/dist/dashboard/assets/OverviewPage-C-ExCy1V.js +0 -1
  218. package/dist/dashboard/assets/OverviewPage-C-ExCy1V.js.gz +0 -0
  219. package/dist/dashboard/assets/ProviderDetailPage-tr811uaF.js +0 -3
  220. package/dist/dashboard/assets/ProviderDetailPage-tr811uaF.js.gz +0 -0
  221. package/dist/dashboard/assets/ProvidersPage-BS9IEpvv.js +0 -1
  222. package/dist/dashboard/assets/ProvidersPage-BS9IEpvv.js.gz +0 -0
  223. package/dist/dashboard/assets/ProxyPage-Rn_qXScb.js +0 -7
  224. package/dist/dashboard/assets/ProxyPage-Rn_qXScb.js.gz +0 -0
  225. package/dist/dashboard/assets/QuotaPage-BihkgQSq.js +0 -1
  226. package/dist/dashboard/assets/QuotaPage-BihkgQSq.js.gz +0 -0
  227. package/dist/dashboard/assets/SettingsPage-DhiEjm6T.js +0 -1
  228. package/dist/dashboard/assets/SettingsPage-DhiEjm6T.js.gz +0 -0
  229. package/dist/dashboard/assets/SetupPage-CXjUlfqr.js.gz +0 -0
  230. package/dist/dashboard/assets/SortableList-C-_oD3F2.js.gz +0 -0
  231. package/dist/dashboard/assets/StudioPage-u9IxmYOI.js.gz +0 -0
  232. package/dist/dashboard/assets/UsagePage-BEVLVrwP.js.gz +0 -0
  233. package/dist/dashboard/assets/api-keys-uNywYlfv.js.gz +0 -0
  234. package/dist/dashboard/assets/app-DxivpfYG.css +0 -2
  235. package/dist/dashboard/assets/app-DxivpfYG.css.gz +0 -0
  236. package/dist/dashboard/assets/assert-NHwYq95t.js.gz +0 -0
  237. package/dist/dashboard/assets/badge-6uzDDvqs.js.gz +0 -0
  238. package/dist/dashboard/assets/banner-4_WNg2WZ.js.gz +0 -0
  239. package/dist/dashboard/assets/card--AtFedAq.js.gz +0 -0
  240. package/dist/dashboard/assets/cli-tools-B3e7dx3N.js.gz +0 -0
  241. package/dist/dashboard/assets/clipboard-button-NreUx6c8.js.gz +0 -0
  242. package/dist/dashboard/assets/dialog-BtpsJU98.js.gz +0 -0
  243. package/dist/dashboard/assets/download-A0SW9OCW.js +0 -1
  244. package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
  245. package/dist/dashboard/assets/drawer-WwwtzihF.js.gz +0 -0
  246. package/dist/dashboard/assets/entry-Dj9AR0gY.js +0 -4
  247. package/dist/dashboard/assets/entry-Dj9AR0gY.js.gz +0 -0
  248. package/dist/dashboard/assets/entry-TJIye_jT.js +0 -1
  249. package/dist/dashboard/assets/entry-TJIye_jT.js.gz +0 -0
  250. package/dist/dashboard/assets/entry-jy9_4-Ke.js +0 -1
  251. package/dist/dashboard/assets/entry-jy9_4-Ke.js.gz +0 -0
  252. package/dist/dashboard/assets/github-badge-D_eM3IgG.js.gz +0 -0
  253. package/dist/dashboard/assets/index-DCBtROoK.js.gz +0 -0
  254. package/dist/dashboard/assets/inline-BcNGF8Gr.js.gz +0 -0
  255. package/dist/dashboard/assets/input-BG41et9G.js.gz +0 -0
  256. package/dist/dashboard/assets/layout-C8mer_Ak.js.gz +0 -0
  257. package/dist/dashboard/assets/list-row-Gh_W4OR_.js.gz +0 -0
  258. package/dist/dashboard/assets/live-BJGYRBnR.js.gz +0 -0
  259. package/dist/dashboard/assets/model-bans-DeVLDA7I.js +0 -1
  260. package/dist/dashboard/assets/model-bans-DeVLDA7I.js.gz +0 -0
  261. package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
  262. package/dist/dashboard/assets/numbers-Bs4LOOuf.js +0 -2
  263. package/dist/dashboard/assets/numbers-Bs4LOOuf.js.gz +0 -0
  264. package/dist/dashboard/assets/routing-CcusqXA7.js.gz +0 -0
  265. package/dist/dashboard/assets/select-DsX5QT8K.js.gz +0 -0
  266. package/dist/dashboard/assets/settings-mpmXTgUa.js.gz +0 -0
  267. package/dist/dashboard/assets/sparkles-BRaRUxAU.js +0 -1
  268. package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
  269. package/dist/dashboard/assets/stack-DwLmjUFK.js.gz +0 -0
  270. package/dist/dashboard/assets/state-DYdQmdAl.js.gz +0 -0
  271. package/dist/dashboard/assets/switch-CidSfbG7.js +0 -1
  272. package/dist/dashboard/assets/switch-CidSfbG7.js.gz +0 -0
  273. package/dist/dashboard/assets/terminal-Bd4ee8TA.js +0 -1
  274. package/dist/dashboard/assets/terminal-Bd4ee8TA.js.gz +0 -0
  275. package/dist/dashboard/assets/useMutation-w4u4CVue.js.gz +0 -0
  276. /package/dist/dashboard/assets/{app-CafWtVXA.js → app-DCQZRmHY.js} +0 -0
  277. /package/dist/dashboard/assets/{app-CafWtVXA.js.gz → app-DCQZRmHY.js.gz} +0 -0
@@ -1,128 +1,132 @@
1
- import type { FetchLike, ProviderQuotaResult, ProviderQuotaWindow } from "../../quota/quota-contracts";
2
- import { authCredential, getJson, record, text } from "../../quota/quota-contracts";
3
- import { parseLimitWindows } from "../../quota/quota-limit-windows";
4
- import { probeApiKeyConnectivity } from "../../quota/quota-support";
5
- import { getClineCliVersion, getClineSdkVersion } from "../../operations/client-versions";
6
- import { clinePlatform, clinePlatformVersion } from "../../operations/cli-platform";
7
-
8
- /**
9
- * Quota headers always carry the currently resolved CLI version.
10
- *
11
- * The two version headers are two different versions and must stay that way.
12
- * `x-client-version` is the Cline CLI the operator is running (`cline` on npm),
13
- * from the shared pooler. `x-core-version` is the `@cline/sdk` version — a
14
- * separate npm package with its own release line, though one the CLI pins as a
15
- * dependency. This used to send the *client* version in both slots, so the
16
- * billing surface was told our core was `4.1.23`, a vscode extension version
17
- * that `@cline/sdk` never published.
18
- *
19
- * Both surfaces now send the same pairing (`cliVersion` / `sdkVersion`) and the
20
- * same `cline-cli` client type. A header the upstream can validate is not
21
- * cosmetic: an implausible core version is exactly what a "please update and
22
- * re-authenticate" refusal is shaped like, and it is indistinguishable from a
23
- * dead credential from the response alone.
24
- *
25
- * Header identity is not what gates these endpoints: probing `/users/me`,
26
- * `/users/me/plan` and `/users/me/plan/usage-limits` with no identity headers,
27
- * the SDK identity and the CLI identity all returned identical responses. The
28
- * 404 from the plan routes is "no plan history found for user", i.e. account
29
- * state, not a rejected client.
30
- */
31
- function clineQuotaHeaders(): Record<string, string> {
32
- const version = getClineCliVersion();
33
- return {
34
- accept: "application/json",
35
- "content-type": "application/json",
36
- "user-agent": `Cline/${version}`,
37
- "x-platform": clinePlatform(),
38
- "x-platform-version": clinePlatformVersion(),
39
- "x-client-type": "cline-cli",
40
- "x-client-version": version,
41
- "x-core-version": getClineSdkVersion(),
42
- "x-is-multiroot": "false",
43
- };
44
- }
45
-
46
- const CLINE_WINDOW_LABELS: Readonly<Record<string, string>> = {
47
- five_hour: "5 Hour",
48
- weekly: "7 Day",
49
- monthly: "30 Day",
50
- };
51
-
52
- /** Reads Cline's `limits[]` array — one entry per billing window. */
53
- function usageWindows(value: unknown): readonly ProviderQuotaWindow[] {
54
- return [
55
- ...parseLimitWindows(value, {
56
- kindPaths: ["type"],
57
- percentPaths: ["percentUsed"],
58
- resetPaths: ["resetsAt"],
59
- limitPaths: ["limit", "entitlement", "total"],
60
- usedPaths: ["used", "usedCredits"],
61
- // Cline reports a percentage and a ceiling but no absolute used value,
62
- // so the absolute is derived rather than left null.
63
- deriveUsed: (_entry, usedPercent, limit) =>
64
- usedPercent !== null && limit !== null ? (limit * usedPercent) / 100 : null,
65
- labelFor: (kind) => CLINE_WINDOW_LABELS[kind] ?? null,
66
- fallbackLabel: (kind) => kind,
67
- }),
68
- ];
69
- }
70
-
71
- function isMissingPlanHistory(reason: unknown): boolean {
72
- const message =
73
- reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "";
74
- return /\b404\b|\bno plan history\b/i.test(message);
75
- }
76
-
77
- const CLINE_PROVIDER_ID = "cline" as const;
78
- /** Envelope marking a resolved secret as an api key rather than an OAuth grant. */
79
- export const CLINE_API_KEY_PREFIX = "cline-api-key:" as const;
80
-
81
- /** Wraps a resolved api_key secret so the collector can route it to /models. */
82
- export function markClineApiKeyCredential(credential: string): string {
83
- return credential.startsWith(CLINE_API_KEY_PREFIX) ? credential : `${CLINE_API_KEY_PREFIX}${credential}`;
84
- }
85
-
86
- export async function fetchClineQuota(
87
- credential: string,
88
- fetcher: FetchLike,
89
- ): Promise<ProviderQuotaResult> {
90
- // API-key accounts carry no OAuth envelope and upstream exposes no quota
91
- // surface for them, so an api key must never reach the OAuth-only
92
- // users/me endpoint (a 401 there is not dispatchable either). The account
93
- // test for keys is plain validity via /models.
94
- if (credential.startsWith(CLINE_API_KEY_PREFIX)) {
95
- return probeApiKeyConnectivity(
96
- CLINE_PROVIDER_ID,
97
- credential.slice(CLINE_API_KEY_PREFIX.length),
98
- fetcher,
99
- );
100
- }
101
- const fields = authCredential(credential);
102
- const access = text(fields.accessToken);
103
- if (!access) throw new Error("Cline credential has no access token.");
104
- const headers = {
105
- ...clineQuotaHeaders(),
106
- authorization: `Bearer ${access.startsWith("workos:") ? access : `workos:${access}`}`,
107
- };
108
- const me = record(await getJson("https://api.cline.bot/api/v1/users/me", headers, fetcher));
109
- const userId = text(me?.id);
110
- if (!userId) throw new Error("Cline account response has no user id.");
111
- const [planRaw, limitsRaw] = await Promise.allSettled([
112
- getJson("https://api.cline.bot/api/v1/users/me/plan", headers, fetcher),
113
- getJson("https://api.cline.bot/api/v1/users/me/plan/usage-limits", headers, fetcher),
114
- ]);
115
- const plan = record(planRaw.status === "fulfilled" ? planRaw.value : null);
116
- const limitsFailed = limitsRaw.status === "rejected";
117
- const windows = usageWindows(limitsRaw.status === "fulfilled" ? limitsRaw.value : null);
118
- const error =
119
- limitsFailed && !isMissingPlanHistory(limitsRaw.reason)
120
- ? "Failed to fetch quota limits."
121
- : null;
122
- return {
123
- source: "cline",
124
- plan: text(record(plan?.plan)?.displayName) ?? text(plan?.displayName) ?? "Cline",
125
- windows,
126
- error,
127
- };
128
- }
1
+ import type { FetchLike, ProviderQuotaResult, ProviderQuotaWindow } from "../../quota/quota-contracts";
2
+ import { authCredential, getJson, record, text } from "../../quota/quota-contracts";
3
+ import { parseLimitWindows } from "../../quota/quota-limit-windows";
4
+ import { getClineCliVersion, getClineSdkVersion } from "../../operations/client-versions";
5
+ import { clinePlatform, clinePlatformVersion } from "../../operations/cli-platform";
6
+
7
+ /**
8
+ * Quota headers always carry the currently resolved CLI version.
9
+ *
10
+ * The two version headers are two different versions and must stay that way.
11
+ * `x-client-version` is the Cline CLI the operator is running (`cline` on npm),
12
+ * from the shared pooler. `x-core-version` is the `@cline/sdk` version — a
13
+ * separate npm package with its own release line, though one the CLI pins as a
14
+ * dependency. This used to send the *client* version in both slots, so the
15
+ * billing surface was told our core was `4.1.23`, a vscode extension version
16
+ * that `@cline/sdk` never published.
17
+ *
18
+ * Both surfaces now send the same pairing (`cliVersion` / `sdkVersion`) and the
19
+ * same `cline-cli` client type. A header the upstream can validate is not
20
+ * cosmetic: an implausible core version is exactly what a "please update and
21
+ * re-authenticate" refusal is shaped like, and it is indistinguishable from a
22
+ * dead credential from the response alone.
23
+ *
24
+ * Header identity is not what gates these endpoints: probing `/users/me`,
25
+ * `/users/me/plan` and `/users/me/plan/usage-limits` with no identity headers,
26
+ * the SDK identity and the CLI identity all returned identical responses. The
27
+ * 404 from the plan routes is "no plan history found for user", i.e. account
28
+ * state, not a rejected client.
29
+ */
30
+ function clineQuotaHeaders(): Record<string, string> {
31
+ const version = getClineCliVersion();
32
+ return {
33
+ accept: "application/json",
34
+ "content-type": "application/json",
35
+ "user-agent": `Cline/${version}`,
36
+ "x-platform": clinePlatform(),
37
+ "x-platform-version": clinePlatformVersion(),
38
+ "x-client-type": "cline-cli",
39
+ "x-client-version": version,
40
+ "x-core-version": getClineSdkVersion(),
41
+ "x-is-multiroot": "false",
42
+ };
43
+ }
44
+
45
+ const CLINE_WINDOW_LABELS: Readonly<Record<string, string>> = {
46
+ five_hour: "5 Hour",
47
+ weekly: "7 Day",
48
+ monthly: "30 Day",
49
+ };
50
+
51
+ /** Reads Cline's `limits[]` array — one entry per billing window. */
52
+ function usageWindows(value: unknown): readonly ProviderQuotaWindow[] {
53
+ return [
54
+ ...parseLimitWindows(value, {
55
+ kindPaths: ["type"],
56
+ percentPaths: ["percentUsed"],
57
+ resetPaths: ["resetsAt"],
58
+ limitPaths: ["limit", "entitlement", "total"],
59
+ usedPaths: ["used", "usedCredits"],
60
+ // Cline reports a percentage and a ceiling but no absolute used value,
61
+ // so the absolute is derived rather than left null.
62
+ deriveUsed: (_entry, usedPercent, limit) =>
63
+ usedPercent !== null && limit !== null ? (limit * usedPercent) / 100 : null,
64
+ labelFor: (kind) => CLINE_WINDOW_LABELS[kind] ?? null,
65
+ fallbackLabel: (kind) => kind,
66
+ }),
67
+ ];
68
+ }
69
+
70
+ function isMissingPlanHistory(reason: unknown): boolean {
71
+ const message =
72
+ reason instanceof Error ? reason.message : typeof reason === "string" ? reason : "";
73
+ return /\b404\b|\bno plan history\b/i.test(message);
74
+ }
75
+
76
+ /** Envelope marking a resolved secret as an api key rather than an OAuth grant. */
77
+ export const CLINE_API_KEY_PREFIX = "cline-api-key:" as const;
78
+
79
+ /** Wraps a resolved api_key secret so the collector can route it to /models. */
80
+ export function markClineApiKeyCredential(credential: string): string {
81
+ return credential.startsWith(CLINE_API_KEY_PREFIX) ? credential : `${CLINE_API_KEY_PREFIX}${credential}`;
82
+ }
83
+
84
+ export async function fetchClineQuota(
85
+ credential: string,
86
+ fetcher: FetchLike,
87
+ ): Promise<ProviderQuotaResult> {
88
+ const isApiKey = credential.startsWith(CLINE_API_KEY_PREFIX);
89
+ const bearer = isApiKey ? credential.slice(CLINE_API_KEY_PREFIX.length) : null;
90
+
91
+ let headers: Record<string, string>;
92
+ if (isApiKey && bearer) {
93
+ // An api key is its own bearer token: `Authorization: Bearer sk_...`, with
94
+ // no `workos:` prefix.
95
+ //
96
+ // Prefixing it is what produced "Unauthorized: please make sure you're
97
+ // using the latest version of Cline and re-authenticate" — verified against
98
+ // a live key, where the same key returned 200 on `/users/me` bare and 401
99
+ // once `workos:` was prepended. The message names a version problem, so it
100
+ // reads as a client the upstream refuses rather than a malformed header,
101
+ // which is why it went unrecognised for so long.
102
+ headers = { ...clineQuotaHeaders(), authorization: `Bearer ${bearer}` };
103
+ } else {
104
+ const fields = authCredential(credential);
105
+ const access = text(fields.accessToken);
106
+ if (!access) throw new Error("Cline credential has no access token.");
107
+ headers = {
108
+ ...clineQuotaHeaders(),
109
+ authorization: `Bearer ${access.startsWith("workos:") ? access : `workos:${access}`}`,
110
+ };
111
+ }
112
+ const me = record(await getJson("https://api.cline.bot/api/v1/users/me", headers, fetcher));
113
+ const userId = text(me?.id);
114
+ if (!userId) throw new Error("Cline account response has no user id.");
115
+ const [planRaw, limitsRaw] = await Promise.allSettled([
116
+ getJson("https://api.cline.bot/api/v1/users/me/plan", headers, fetcher),
117
+ getJson("https://api.cline.bot/api/v1/users/me/plan/usage-limits", headers, fetcher),
118
+ ]);
119
+ const plan = record(planRaw.status === "fulfilled" ? planRaw.value : null);
120
+ const limitsFailed = limitsRaw.status === "rejected";
121
+ const windows = usageWindows(limitsRaw.status === "fulfilled" ? limitsRaw.value : null);
122
+ const error =
123
+ limitsFailed && !isMissingPlanHistory(limitsRaw.reason)
124
+ ? "Failed to fetch quota limits."
125
+ : null;
126
+ return {
127
+ source: "cline",
128
+ plan: text(record(plan?.plan)?.displayName) ?? text(plan?.displayName) ?? "Cline",
129
+ windows,
130
+ error,
131
+ };
132
+ }
@@ -16,31 +16,38 @@ interface CodexIdentityHeadersOptions {
16
16
  readonly sessionId?: string | undefined;
17
17
  readonly threadId?: string | undefined;
18
18
  readonly windowId?: string | undefined;
19
- readonly turnId?: string | undefined;
20
- readonly parentTurnId?: string | undefined;
21
- readonly conversationId?: string | undefined;
22
- readonly installationId?: string | undefined;
23
19
  readonly turnMetadataJson?: string | undefined;
24
20
  readonly betaFeatures?: string | undefined;
25
21
  readonly subAgent?: string | undefined;
26
22
  readonly responsesLite?: boolean | undefined;
27
23
  readonly turnState?: string | undefined;
28
- readonly modelsEtag?: string | undefined;
29
- /**
30
- * `x-codex-routing-hint: model=<slug>[;tier=<service_tier>]` — codex-rs
31
- * sends this on every ChatGPT-OAuth Responses/compaction/WebSocket
32
- * request. Callers compute the value; absent/empty omits the header.
33
- */
34
- readonly routingHint?: string | undefined;
35
24
  }
36
25
 
26
+ /**
27
+ * Assembles the request headers the reference ChatGPT-OAuth Responses
28
+ * dispatch sends (`codex-rs` rust-v0.160.0):
29
+ *
30
+ * - default client headers (`default_headers`): `originator`, `user-agent`
31
+ * (no `version` header at this tag);
32
+ * - auth (`add_auth_headers`): `authorization`, `chatgpt-account-id`;
33
+ * - per-request extras (`build_responses_options`): `x-codex-beta-features`?,
34
+ * `x-codex-turn-state`?, `x-oai-attestation`?, lite header when Responses
35
+ * Lite, the compatibility projection (`x-codex-window-id`,
36
+ * `x-codex-turn-metadata`, `x-codex-parent-thread-id`?, `x-openai-subagent`?);
37
+ * - transport options (`ApiResponsesOptions` + stream wrapper):
38
+ * `x-client-request-id` / `session-id` / `thread-id` / `x-openai-subagent`?.
39
+ *
40
+ * Identity values that moved into the body (`client_metadata` — installation,
41
+ * turn id, parent turn id) are absent here by design. `conversation-id`,
42
+ * `turn-id`, `parent-turn-id` direct headers and `x-codex-routing-hint`
43
+ * (WebSocket-only at this tag) are not emitted.
44
+ */
37
45
  export function buildCodexIdentityHeaders(
38
46
  options: CodexIdentityHeadersOptions,
39
47
  ): Record<string, string> {
40
48
  const headers: Record<string, string> = {};
41
49
  headers["user-agent"] = buildCodexUserAgent(options.version);
42
50
  headers["originator"] = "codex_cli_rs";
43
- headers["version"] = options.version;
44
51
  const token =
45
52
  options.credential.secret === undefined
46
53
  ? undefined
@@ -50,37 +57,19 @@ export function buildCodexIdentityHeaders(
50
57
  (token === undefined ? undefined : getCodexAccountId(token));
51
58
  if (accountId !== undefined && accountId.length > 0)
52
59
  headers["chatgpt-account-id"] = accountId;
53
- headers["OpenAI-Beta"] = "responses=experimental";
54
60
  if (options.attestation !== undefined && options.attestation.length > 0)
55
61
  headers["x-oai-attestation"] = options.attestation;
56
62
  if (options.residency !== undefined && options.residency.length > 0)
57
63
  headers["x-openai-internal-codex-residency"] = options.residency;
58
64
  if (options.sessionId !== undefined && options.sessionId.length > 0) {
59
65
  headers["session-id"] = options.sessionId;
60
- headers["x-client-request-id"] = options.sessionId;
61
- if (
62
- options.conversationId === undefined ||
63
- options.conversationId.length === 0
64
- ) {
65
- headers["conversation-id"] = options.sessionId;
66
- }
67
66
  }
68
- if (options.threadId !== undefined && options.threadId.length > 0)
67
+ if (options.threadId !== undefined && options.threadId.length > 0) {
69
68
  headers["thread-id"] = options.threadId;
69
+ headers["x-client-request-id"] = options.threadId;
70
+ }
70
71
  if (options.windowId !== undefined && options.windowId.length > 0)
71
72
  headers["x-codex-window-id"] = options.windowId;
72
- if (options.turnId !== undefined && options.turnId.length > 0)
73
- headers["turn-id"] = options.turnId;
74
- if (options.parentTurnId !== undefined && options.parentTurnId.length > 0)
75
- headers["parent-turn-id"] = options.parentTurnId;
76
- if (options.conversationId !== undefined && options.conversationId.length > 0)
77
- headers["conversation-id"] = options.conversationId;
78
- if (
79
- options.installationId !== undefined &&
80
- options.installationId.length > 0
81
- ) {
82
- headers["x-codex-installation-id"] = options.installationId;
83
- }
84
73
  if (
85
74
  options.turnMetadataJson !== undefined &&
86
75
  options.turnMetadataJson.length > 0
@@ -99,12 +88,6 @@ export function buildCodexIdentityHeaders(
99
88
  if (options.turnState !== undefined && options.turnState.length > 0) {
100
89
  headers["x-codex-turn-state"] = options.turnState;
101
90
  }
102
- if (options.modelsEtag !== undefined && options.modelsEtag.length > 0) {
103
- headers["x-models-etag"] = options.modelsEtag;
104
- }
105
- if (options.routingHint !== undefined && options.routingHint.length > 0) {
106
- headers["x-codex-routing-hint"] = options.routingHint;
107
- }
108
91
  return headers;
109
92
  }
110
93
 
@@ -118,6 +101,7 @@ export function createCodexRequestMetadata(args: {
118
101
  windowId: string;
119
102
  turnId: string;
120
103
  parentTurnId?: string;
104
+ subAgent?: string;
121
105
  requestKind?: string;
122
106
  turnStartedAtUnixMs?: number;
123
107
  compaction?: Record<string, unknown>;
@@ -150,6 +134,8 @@ export function createCodexRequestMetadata(args: {
150
134
  };
151
135
  if (args.parentTurnId !== undefined && args.parentTurnId.length > 0)
152
136
  clientMetadata["parent_turn_id"] = args.parentTurnId;
137
+ if (args.subAgent !== undefined && args.subAgent.length > 0)
138
+ clientMetadata["x-openai-subagent"] = args.subAgent;
153
139
  clientMetadata["x-codex-turn-metadata"] = turnMetadataJson;
154
140
  return { clientMetadata, turnMetadataJson };
155
141
  }
@@ -551,8 +551,8 @@ export function createCodexAdapter(
551
551
  const subAgent = config.subagent;
552
552
  const installationOverride = config.installation_id_override;
553
553
 
554
- // Per-session state for sticky routing (x-codex-turn-state / x-models-etag)
555
- // and identity reuse. Bounded LRU + TTL: an unbounded map would leak
554
+ // Per-session state for sticky routing (x-codex-turn-state) and identity
555
+ // reuse. Bounded LRU + TTL: an unbounded map would leak
556
556
  // memory forever under a long-running process serving many distinct
557
557
  // Codex sessions.
558
558
  const sessionStates = new Map<
@@ -639,16 +639,13 @@ export function createCodexAdapter(
639
639
  const state = getSessionState(sessionId);
640
640
  if (state === undefined) return;
641
641
  let turnState: string | null = null;
642
- let modelsEtag: string | null = null;
643
642
  if (headers instanceof Headers) {
644
643
  turnState = headers.get("x-codex-turn-state");
645
- modelsEtag = headers.get("x-models-etag");
646
644
  } else if (typeof headers === "object") {
647
645
  const rec = headers as Record<string, string>;
648
646
  for (const [k, v] of Object.entries(rec)) {
649
647
  const lower = k.toLowerCase();
650
648
  if (lower === "x-codex-turn-state") turnState = v;
651
- if (lower === "x-models-etag") modelsEtag = v;
652
649
  }
653
650
  }
654
651
  if (
@@ -658,9 +655,6 @@ export function createCodexAdapter(
658
655
  ) {
659
656
  state.turnState = turnState;
660
657
  }
661
- if (modelsEtag !== null && modelsEtag.length > 0) {
662
- state.modelsEtag = modelsEtag;
663
- }
664
658
  }
665
659
 
666
660
  return {
@@ -700,13 +694,10 @@ export function createCodexAdapter(
700
694
  sessionId: identity.session_id,
701
695
  threadId: identity.thread_id,
702
696
  windowId: identity.window_id,
703
- turnId: identity.turn_id,
704
- installationId,
705
697
  turnMetadataJson,
706
698
  betaFeatures: betaRemoteCompaction
707
699
  ? "remote_compaction_v2"
708
700
  : undefined,
709
- routingHint: `model=${body["model"] as string}`,
710
701
  }),
711
702
  };
712
703
  const { res, release } = await postUpstreamJson(
@@ -919,7 +910,6 @@ export function createCodexAdapter(
919
910
  let rawWindowId = nonEmpty(request.window_id);
920
911
  let rawTurnId = nonEmpty(request.turn_id);
921
912
  const rawParentTurnId = nonEmpty(request.parent_turn_id);
922
- const rawConversationId = nonEmpty(request.conversation_id);
923
913
 
924
914
  const installationId = await getInstallationIdCached();
925
915
 
@@ -970,9 +960,6 @@ export function createCodexAdapter(
970
960
  const turnStartedAtUnixMs = Date.now();
971
961
  sessionState.turnStartedAtUnixMs = turnStartedAtUnixMs;
972
962
 
973
- // If conversation_id not supplied, mirror session_id (reference behavior).
974
- const conversationId = rawConversationId ?? effectiveSessionId;
975
-
976
963
  const token =
977
964
  context.credential.secret === undefined
978
965
  ? undefined
@@ -998,12 +985,6 @@ export function createCodexAdapter(
998
985
  const betaFeatures = betaRemoteCompaction
999
986
  ? "remote_compaction_v2"
1000
987
  : undefined;
1001
- // `x-codex-routing-hint` mirrors codex-rs (`codexRoutingHint`): the
1002
- // Codex adapter is OAuth-family only, so the hint is always emitted.
1003
- const serviceTier = request.generation_controls.service_tier;
1004
- const routingHint = serviceTier
1005
- ? `model=${request.model};tier=${serviceTier}`
1006
- : `model=${request.model}`;
1007
988
 
1008
989
  const headers: Record<string, string> = {
1009
990
  "content-type": "application/json",
@@ -1020,19 +1001,11 @@ export function createCodexAdapter(
1020
1001
  sessionId: effectiveSessionId,
1021
1002
  threadId,
1022
1003
  windowId,
1023
- turnId,
1024
- ...(rawParentTurnId === undefined
1025
- ? {}
1026
- : { parentTurnId: rawParentTurnId }),
1027
- conversationId,
1028
- installationId,
1029
1004
  turnMetadataJson,
1030
1005
  betaFeatures,
1031
1006
  subAgent,
1032
1007
  responsesLite,
1033
1008
  turnState: sessionState.turnState,
1034
- modelsEtag: sessionState.modelsEtag,
1035
- routingHint,
1036
1009
  }),
1037
1010
  );
1038
1011
  const outboundFetch = context.outbound_fetch ?? fetchFn;