cartethyia 2.7.3 → 2.7.5

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 (625) hide show
  1. package/.env.example +2 -0
  2. package/README.md +17 -5
  3. package/dist/dashboard/assets/{BannedPage-2TJD37Hb.js → BannedPage-Cj15GsMp.js} +1 -1
  4. package/dist/dashboard/assets/BannedPage-Cj15GsMp.js.gz +0 -0
  5. package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js +1 -0
  6. package/dist/dashboard/assets/ClaimGiftsButton-D83pBJ6J.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolDetailPage-xefJNRmJ.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
  8. package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
  9. package/dist/dashboard/assets/{CliToolsPage-Rj9iHQ3F.js → CliToolsPage-BIccZmeL.js} +1 -1
  10. package/dist/dashboard/assets/CliToolsPage-BIccZmeL.js.gz +0 -0
  11. package/dist/dashboard/assets/CombosPage-DEEKkYD-.js +1 -0
  12. package/dist/dashboard/assets/CombosPage-DEEKkYD-.js.gz +0 -0
  13. package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js +1 -0
  14. package/dist/dashboard/assets/ConsoleLogPage-D5rol2j2.js.gz +0 -0
  15. package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js +1 -0
  16. package/dist/dashboard/assets/CustomizationPage-BKj_r0rp.js.gz +0 -0
  17. package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js +656 -0
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-B5nZvmf0.js.gz +0 -0
  19. package/dist/dashboard/assets/{LoginPage-C4w7vea-.js → LoginPage-DkXb6dx-.js} +1 -1
  20. package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-BtPcAfot.js → ModelPicker-DnQPSIA8.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-DnQPSIA8.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-Ci2wQKUz.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js +5 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-odlgYrOg.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-EfeloBn4.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-CqFBQEB8.js.gz +0 -0
  31. package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js +9 -0
  32. package/dist/dashboard/assets/ProxyPage-5SnUSy3j.js.gz +0 -0
  33. package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js +1 -0
  34. package/dist/dashboard/assets/QuotaPage-CmnMDzhP.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-BJtRZ4qD.js.gz +0 -0
  37. package/dist/dashboard/assets/{SetupPage-BQS0Rx_u.js → SetupPage-WTa0sktC.js} +1 -1
  38. package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-TP7voAQ0.js → StudioPage-BfAb5-o_.js} +3 -3
  40. package/dist/dashboard/assets/StudioPage-BfAb5-o_.js.gz +0 -0
  41. package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js +56 -0
  42. package/dist/dashboard/assets/UsagePage-BNzeZ2Vk.js.gz +0 -0
  43. package/dist/dashboard/assets/api-keys-l29JROPv.js +1 -0
  44. package/dist/dashboard/assets/api-keys-l29JROPv.js.gz +0 -0
  45. package/dist/dashboard/assets/app--PJWq8_C.css +2 -0
  46. package/dist/dashboard/assets/app--PJWq8_C.css.gz +0 -0
  47. package/dist/dashboard/assets/{assert-C0YYuZJ4.js → assert-C0K-c4eo.js} +1 -1
  48. package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-B_DMpMJN.js → badge-DfbhQU4k.js} +1 -1
  50. package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
  51. package/dist/dashboard/assets/{banner-DMrMPmth.js → banner-BllT4LcF.js} +1 -1
  52. package/dist/dashboard/assets/banner-BllT4LcF.js.gz +0 -0
  53. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  54. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  55. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  56. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  57. package/dist/dashboard/assets/{card-Be5Uzamx.js → card-CtkX66Wd.js} +1 -1
  58. package/dist/dashboard/assets/card-CtkX66Wd.js.gz +0 -0
  59. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
  60. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
  61. package/dist/dashboard/assets/{cli-tools-muFRphDu.js → cli-tools-CQXVMn4P.js} +1 -1
  62. package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
  63. package/dist/dashboard/assets/{clipboard-button-DOfrVmsi.js → clipboard-button-BQqBQd2n.js} +1 -1
  64. package/dist/dashboard/assets/clipboard-button-BQqBQd2n.js.gz +0 -0
  65. package/dist/dashboard/assets/{dialog-C9omdjQt.js → dialog-BEK7KP0H.js} +1 -1
  66. package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
  67. package/dist/dashboard/assets/{drawer-Bm8WKaGY.js → drawer-BrTEZ8zu.js} +1 -1
  68. package/dist/dashboard/assets/drawer-BrTEZ8zu.js.gz +0 -0
  69. package/dist/dashboard/assets/entry-CHWxbS56.js +1 -0
  70. package/dist/dashboard/assets/entry-CHWxbS56.js.gz +0 -0
  71. package/dist/dashboard/assets/{entry-q5HwZ8nN.js → entry-EBHJ3DrE.js} +1 -1
  72. package/dist/dashboard/assets/entry-EBHJ3DrE.js.gz +0 -0
  73. package/dist/dashboard/assets/entry-LCS85hiq.js +4 -0
  74. package/dist/dashboard/assets/entry-LCS85hiq.js.gz +0 -0
  75. package/dist/dashboard/assets/{formatters-BTScrQpe.js → formatters-BAACA727.js} +1 -1
  76. package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
  77. package/dist/dashboard/assets/{github-badge-Orjuzemr.js → github-badge-YSCE4UC2.js} +1 -1
  78. package/dist/dashboard/assets/github-badge-YSCE4UC2.js.gz +0 -0
  79. package/dist/dashboard/assets/{index-cPrX5vn6.js → index-FQlj0HUT.js} +2 -2
  80. package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
  81. package/dist/dashboard/assets/{inline-Dvux8w-0.js → inline-C4gU5iOL.js} +1 -1
  82. package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
  83. package/dist/dashboard/assets/{input-CU1Rgf3p.js → input-BHHX_Tmm.js} +1 -1
  84. package/dist/dashboard/assets/input-BHHX_Tmm.js.gz +0 -0
  85. package/dist/dashboard/assets/{layout-C_7A6H55.js → layout-CajrYUnD.js} +1 -1
  86. package/dist/dashboard/assets/{layout-C_7A6H55.js.gz → layout-CajrYUnD.js.gz} +0 -0
  87. package/dist/dashboard/assets/{list-row-CzFvogbj.js → list-row-Bx2I7XUe.js} +1 -1
  88. package/dist/dashboard/assets/list-row-Bx2I7XUe.js.gz +0 -0
  89. package/dist/dashboard/assets/live-DNNqRbj2.js +1 -0
  90. package/dist/dashboard/assets/live-DNNqRbj2.js.gz +0 -0
  91. package/dist/dashboard/assets/minimize-2-BTmMTK4o.js +1 -0
  92. package/dist/dashboard/assets/minimize-2-BTmMTK4o.js.gz +0 -0
  93. package/dist/dashboard/assets/{mutation-JJGQm8TD.js → mutation-Rr0TIvcj.js} +1 -1
  94. package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
  95. package/dist/dashboard/assets/network-C5UBACrJ.js +1 -0
  96. package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
  97. package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
  98. package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
  99. package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
  100. package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
  101. package/dist/dashboard/assets/{query-keys-CLaNz8Xz.js → query-keys-BloKtaXJ.js} +1 -1
  102. package/dist/dashboard/assets/query-keys-BloKtaXJ.js.gz +0 -0
  103. package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
  104. package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
  105. package/dist/dashboard/assets/{routing-BEH32QOC.js → routing-in0f_IfK.js} +1 -1
  106. package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
  107. package/dist/dashboard/assets/{select-B3iTetHN.js → select-BLULNqTp.js} +2 -2
  108. package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
  109. package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
  110. package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
  111. package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
  112. package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
  113. package/dist/dashboard/assets/{stack-KrOrm7JZ.js → stack-D2lIR0tg.js} +1 -1
  114. package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
  115. package/dist/dashboard/assets/{state-DLS7IDMy.js → state-DTARjfiW.js} +1 -1
  116. package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
  117. package/dist/dashboard/assets/{switch-42ItvbAs.js → switch-c0oPSnqW.js} +1 -1
  118. package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
  119. package/dist/dashboard/assets/{useMutation-Dmnfh1Ue.js → useMutation-m8WGNPrz.js} +1 -1
  120. package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
  121. package/dist/dashboard/console-backgrounds.jpg +0 -0
  122. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  123. package/dist/dashboard/index.html +2 -2
  124. package/dist/dashboard/index.html.gz +0 -0
  125. package/dist/dashboard/precompressed-assets.json +59 -57
  126. package/migrations/full-postgres/0027_qoder_identity_genuine_seed.sql +9 -10
  127. package/migrations/full-postgres/0032_add_provider_pool_accounts.sql +53 -0
  128. package/migrations/full-postgres/0033_add_api_key_ban.sql +9 -0
  129. package/migrations/full-postgres/0034_add_api_key_ban_until.sql +7 -0
  130. package/migrations/full-postgres/0035_align_pool_account_status_enum.sql +21 -0
  131. package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
  132. package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
  133. package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
  134. package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
  135. package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
  136. package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
  137. package/migrations/lite-sqlite3/0027_qoder_identity_genuine_seed.sql +9 -10
  138. package/migrations/lite-sqlite3/0032_add_provider_pool_accounts.sql +44 -0
  139. package/migrations/lite-sqlite3/0033_add_api_key_ban.sql +8 -0
  140. package/migrations/lite-sqlite3/0034_add_api_key_ban_until.sql +5 -0
  141. package/migrations/lite-sqlite3/0035_align_pool_account_status_enum.sql +6 -0
  142. package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
  143. package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
  144. package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
  145. package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
  146. package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
  147. package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
  148. package/package.json +4 -5
  149. package/scripts/cli/update.ts +15 -41
  150. package/src/boot/app.ts +67 -10
  151. package/src/boot/dependencies.ts +786 -732
  152. package/src/boot/lifecycle.ts +11 -12
  153. package/src/config/cooldowns.ts +34 -55
  154. package/src/config/network.ts +8 -4
  155. package/src/config/package-paths.ts +1 -1
  156. package/src/config/providers.ts +13 -14
  157. package/src/config/resources.ts +0 -5
  158. package/src/config/runtime.ts +2 -5
  159. package/src/config/spec.ts +26 -6
  160. package/src/console/api-keys/ban-constants.ts +38 -0
  161. package/src/console/api-keys/contracts.ts +92 -31
  162. package/src/console/api-keys/routes.ts +131 -6
  163. package/src/console/audit/routes.ts +3 -3
  164. package/src/console/auth/access.ts +4 -4
  165. package/src/console/auth/account-reset.ts +5 -5
  166. package/src/console/auth/audit-recorder.ts +1 -1
  167. package/src/console/auth/lockout.ts +7 -3
  168. package/src/console/auth/row-coercion.ts +57 -12
  169. package/src/console/auth/session-resolver.ts +1 -1
  170. package/src/console/auth/session-service.ts +8 -2
  171. package/src/console/auth/session.ts +40 -34
  172. package/src/console/auth/setup-service.ts +4 -3
  173. package/src/console/auth/user-store.ts +1 -1
  174. package/src/console/backup/9router-map.ts +0 -3
  175. package/src/console/backup/contracts.ts +11 -9
  176. package/src/console/backup/export-endpoint.ts +11 -12
  177. package/src/console/backup/nine-router.ts +1 -7
  178. package/src/console/backup/routes.ts +32 -36
  179. package/src/console/backup/service.ts +468 -468
  180. package/src/console/backup/store.ts +47 -29
  181. package/src/console/backup/validate.ts +11 -1
  182. package/src/console/cli-tools/contracts.ts +7 -7
  183. package/src/console/cli-tools/injectors/cline.ts +110 -110
  184. package/src/console/cli-tools/injectors/codex.ts +181 -181
  185. package/src/console/cli-tools/injectors/copilot.ts +108 -108
  186. package/src/console/cli-tools/injectors/driver.ts +247 -247
  187. package/src/console/cli-tools/injectors/jcode.ts +115 -115
  188. package/src/console/cli-tools/injectors/openclaw.ts +161 -161
  189. package/src/console/cli-tools/injectors/opencode.ts +153 -153
  190. package/src/console/cli-tools/routes.ts +4 -4
  191. package/src/console/cli-tools/service.ts +1 -1
  192. package/src/console/cli-tools/store.ts +2 -2
  193. package/src/console/console-router-guards.ts +2 -2
  194. package/src/console/console-router.ts +36 -4
  195. package/src/console/dashboard-assets.ts +9 -9
  196. package/src/console/data-management/routes.ts +3 -3
  197. package/src/console/domain-registration.ts +18 -4
  198. package/src/console/inferhub/client.ts +0 -7
  199. package/src/console/inferhub/key-store.ts +1 -1
  200. package/src/console/inferhub/normalize.ts +2 -2
  201. package/src/console/inferhub/routes.ts +1 -1
  202. package/src/console/inferhub/types.ts +1 -1
  203. package/src/console/observability/contracts.ts +5 -1
  204. package/src/console/observability/live.ts +34 -21
  205. package/src/console/observability/logs.ts +4 -4
  206. package/src/console/observability/performance.ts +3 -3
  207. package/src/console/observability/routes.ts +3 -3
  208. package/src/console/observability/sse.ts +62 -8
  209. package/src/console/observability/store.ts +36 -20
  210. package/src/console/providers/catalog/catalog-projections.ts +1 -1
  211. package/src/console/providers/catalog/contracts.ts +82 -22
  212. package/src/console/providers/catalog/model-operations.ts +1 -1
  213. package/src/console/providers/catalog/provider-operations.ts +110 -17
  214. package/src/console/providers/catalog/public-model-store.ts +0 -0
  215. package/src/console/providers/catalog/routes.ts +30 -6
  216. package/src/console/providers/catalog/store-helpers.ts +349 -326
  217. package/src/console/providers/catalog/store.ts +1662 -1292
  218. package/src/console/providers/detail/routes.ts +4 -4
  219. package/src/console/providers/oauth/callback-listener.ts +100 -18
  220. package/src/console/providers/oauth/routes.ts +95 -16
  221. package/src/console/quota/account-quota-global.ts +41 -3
  222. package/src/console/quota/account-quota-shared.ts +10 -3
  223. package/src/console/quota/account-quota-tenant.ts +285 -67
  224. package/src/console/quota/account-test-egress.ts +4 -4
  225. package/src/console/quota/daily-growth-job.ts +308 -0
  226. package/src/console/quota/native-identity.ts +2 -2
  227. package/src/console/quota/quota-view.ts +1 -1
  228. package/src/console/remote-support/routes.ts +1 -1
  229. package/src/console/remote-support/service.ts +2 -2
  230. package/src/console/routing/model/contracts.ts +1 -1
  231. package/src/console/routing/model/routes.ts +3 -3
  232. package/src/console/routing/pools/contracts.ts +13 -10
  233. package/src/console/routing/pools/import-parse.ts +3 -3
  234. package/src/console/routing/pools/operations.ts +14 -7
  235. package/src/console/routing/pools/probe-verdict.ts +8 -3
  236. package/src/console/routing/pools/relay-deploy.ts +12 -12
  237. package/src/console/routing/pools/routes.ts +3 -3
  238. package/src/console/routing/pools/store.ts +21 -1
  239. package/src/console/settings/contracts.ts +29 -2
  240. package/src/console/settings/routes.ts +3 -3
  241. package/src/console/settings/store.ts +20 -0
  242. package/src/console/share/share-router.ts +112 -44
  243. package/src/console/share/share-stats.ts +109 -39
  244. package/src/console/share/share-usage.ts +1 -1
  245. package/src/console/shared/errors.ts +2 -2
  246. package/src/console/shared/object.ts +18 -0
  247. package/src/console/shared/read-through-cache.ts +42 -6
  248. package/src/console/shared/transaction.ts +14 -0
  249. package/src/console/system-prompt/contracts.ts +89 -12
  250. package/src/console/system-prompt/routes.ts +98 -45
  251. package/src/console/updates/apply-update.ts +244 -0
  252. package/src/console/updates/routes.ts +256 -98
  253. package/src/main.ts +11 -5
  254. package/src/network/http2-bidi.ts +1 -1
  255. package/src/network/ip-utils.ts +298 -0
  256. package/src/network/outbound-fetch.ts +76 -5
  257. package/src/network/pool/agent.ts +7 -6
  258. package/src/network/pool/byte-accounting.ts +1 -1
  259. package/src/network/pool/resolver.ts +55 -51
  260. package/src/network/pool/selector.ts +150 -136
  261. package/src/network/pool-cooldown-store.ts +71 -16
  262. package/src/network/pool-health-machine.ts +22 -2
  263. package/src/network/rate-limit-verdict.ts +68 -0
  264. package/src/network/retry.ts +1 -1
  265. package/src/network/ssrf.ts +24 -75
  266. package/src/observability/event-log.ts +2 -2
  267. package/src/observability/event-query.ts +286 -214
  268. package/src/observability/log-sanitize.ts +1 -1
  269. package/src/observability/metrics.ts +4 -4
  270. package/src/observability/payload-capture.ts +6 -5
  271. package/src/observability/payload-store.ts +1 -1
  272. package/src/observability/runtime-metrics.ts +1 -1
  273. package/src/observability/telemetry-buffer.ts +12 -3
  274. package/src/observability/telemetry-reconciliation.ts +3 -3
  275. package/src/observability/telemetry-status.ts +1 -1
  276. package/src/observability/token-speed.ts +1 -1
  277. package/src/persistence/connection-url.ts +1 -1
  278. package/src/persistence/db-handle.ts +1 -1
  279. package/src/persistence/db-pg.ts +2 -2
  280. package/src/persistence/db-sqlite.ts +10 -5
  281. package/src/persistence/dialect.ts +5 -1
  282. package/src/persistence/readiness.ts +19 -7
  283. package/src/persistence/redis.ts +1 -1
  284. package/src/persistence/schema.ts +177 -45
  285. package/src/persistence/shared-cache.ts +2 -2
  286. package/src/persistence/sort-order.ts +1 -1
  287. package/src/persistence/stores/api-key-store.ts +109 -4
  288. package/src/persistence/stores/share-store.ts +20 -8
  289. package/src/persistence/stores/telemetry-store.ts +1 -1
  290. package/src/persistence/system-prompt-store.ts +63 -18
  291. package/src/persistence/tenant-preferences.ts +1 -1
  292. package/src/persistence/ttl-cache.ts +3 -3
  293. package/src/persistence/usage-flush.ts +7 -2
  294. package/src/protocol/canonical-model.ts +1 -1
  295. package/src/protocol/codecs.ts +12 -16
  296. package/src/protocol/dsml.ts +3 -49
  297. package/src/protocol/gateway-error.ts +6 -3
  298. package/src/protocol/image-clamp.ts +2 -2
  299. package/src/protocol/image-generation.ts +2 -2
  300. package/src/protocol/reasoning-text.ts +1 -1
  301. package/src/protocol/reasoning.ts +7 -52
  302. package/src/protocol/registry.ts +50 -15
  303. package/src/protocol/request/chat.ts +46 -19
  304. package/src/protocol/request/codex.ts +1 -1
  305. package/src/protocol/request/messages.ts +46 -14
  306. package/src/protocol/request/responses.ts +19 -10
  307. package/src/protocol/response/chat.ts +27 -12
  308. package/src/protocol/response/codex.ts +2 -2
  309. package/src/protocol/response/gemini.ts +1 -1
  310. package/src/protocol/response/messages.ts +6 -6
  311. package/src/protocol/response/omp-tool-call-markup.ts +1 -1
  312. package/src/protocol/response/responses.ts +3 -3
  313. package/src/protocol/sse-decoder.ts +64 -4
  314. package/src/protocol/stop-reason.ts +2 -2
  315. package/src/protocol/think-split.ts +347 -0
  316. package/src/protocol/translation/attachment-integrity.ts +3 -3
  317. package/src/protocol/translation/cache-controls.ts +8 -20
  318. package/src/protocol/translation/capabilities.ts +8 -8
  319. package/src/protocol/translation/dialect/deepseek.ts +10 -0
  320. package/src/protocol/translation/dialect/inband.ts +39 -0
  321. package/src/protocol/translation/dialect/model-thinking.ts +89 -0
  322. package/src/protocol/translation/dialect/qwen.ts +114 -0
  323. package/src/protocol/translation/dialect/resolver.ts +83 -0
  324. package/src/protocol/translation/dialect/rules.ts +93 -0
  325. package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
  326. package/src/protocol/translation/dialect/types.ts +58 -0
  327. package/src/protocol/translation/quirks.ts +18 -4
  328. package/src/protocol/translation/thinking.ts +12 -252
  329. package/src/protocol/translation/tool-id.ts +3 -3
  330. package/src/protocol/translation/tool-repair.ts +1 -1
  331. package/src/protocol/upstream/post-json.ts +6 -1
  332. package/src/protocol/upstream/send-claude-messages.ts +3 -3
  333. package/src/providers/adapters/base-adapter.ts +1 -1
  334. package/src/providers/adapters/compatible-adapter.ts +44 -5
  335. package/src/providers/authentication/jwt-validator.ts +0 -5
  336. package/src/providers/authentication/oauth-client.ts +254 -253
  337. package/src/providers/authentication/oauth-flow-store.ts +42 -7
  338. package/src/providers/authentication/oauth-refresh-service.ts +2 -2
  339. package/src/providers/bundled-discovery-providers.ts +6 -30
  340. package/src/providers/configured-openai-providers.ts +82 -97
  341. package/src/providers/configured-provider.ts +1 -1
  342. package/src/providers/default-registry.ts +23 -35
  343. package/src/providers/discovery/catalog/catalog-format.ts +13 -2
  344. package/src/providers/discovery/discovery-types.ts +0 -1
  345. package/src/providers/discovery/openai-model-discovery.ts +2 -2
  346. package/src/providers/discovery/probe-phases.ts +50 -15
  347. package/src/providers/discovery/probing-service.ts +18 -20
  348. package/src/providers/integrations/agentrouter/agentrouter.ts +14 -5
  349. package/src/providers/integrations/alibabacp/alibabacp.ts +2 -2
  350. package/src/providers/integrations/anthropic.ts +4 -11
  351. package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
  352. package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
  353. package/src/providers/integrations/antigravity/antigravity.ts +15 -26
  354. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +2 -2
  355. package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
  356. package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
  357. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +37 -6
  358. package/src/providers/integrations/buddy/buddy-identity.ts +108 -1
  359. package/src/providers/integrations/buddy/buddy-media.ts +16 -16
  360. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
  361. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
  362. package/src/providers/integrations/buddy/codebuddy/provider.ts +5 -16
  363. package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
  364. package/src/providers/integrations/buddy/workbuddy/provider.ts +6 -10
  365. package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
  366. package/src/providers/integrations/claude/claude-betas.ts +1 -1
  367. package/src/providers/integrations/claude/claude-cch.ts +148 -148
  368. package/src/providers/integrations/claude/claude-credentials.ts +1 -1
  369. package/src/providers/integrations/claude/claude-slow-lane-retry.ts +1 -1
  370. package/src/providers/integrations/claude/claude.ts +3 -10
  371. package/src/providers/integrations/claude/fallback-credit.ts +3 -7
  372. package/src/providers/integrations/cline/cline.ts +2 -2
  373. package/src/providers/integrations/cloudflareai/cloudflareai.ts +4 -7
  374. package/src/providers/integrations/codex/codex-device-code.ts +101 -101
  375. package/src/providers/integrations/codex/codex-errors.ts +1 -1
  376. package/src/providers/integrations/codex/codex-oauth.ts +0 -1
  377. package/src/providers/integrations/codex/codex.ts +14 -15
  378. package/src/providers/integrations/commandcode/commandcode.ts +76 -116
  379. package/src/providers/integrations/commandcode/quota.ts +132 -48
  380. package/src/providers/integrations/cursor/cursor-http2.ts +11 -14
  381. package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
  382. package/src/providers/integrations/cursor/cursor-request.ts +0 -87
  383. package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
  384. package/src/providers/integrations/cursor/cursor.ts +53 -20
  385. package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
  386. package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
  387. package/src/providers/integrations/factory/factory.ts +13 -13
  388. package/src/providers/integrations/gemini.ts +11 -11
  389. package/src/providers/integrations/github/github-discovery.ts +55 -10
  390. package/src/providers/integrations/github/github-oauth.ts +6 -5
  391. package/src/providers/integrations/github/github.ts +47 -20
  392. package/src/providers/integrations/grok/grok-oauth.ts +261 -261
  393. package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
  394. package/src/providers/integrations/grok/grok-quota.ts +16 -7
  395. package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
  396. package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
  397. package/src/providers/integrations/grok/grok.ts +88 -42
  398. package/src/providers/integrations/inferhub.ts +4 -11
  399. package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
  400. package/src/providers/integrations/kimi/kimi.ts +4 -11
  401. package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
  402. package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
  403. package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
  404. package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
  405. package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
  406. package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
  407. package/src/providers/integrations/kiro/kiro-request.ts +8 -11
  408. package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
  409. package/src/providers/integrations/kiro/kiro.ts +91 -78
  410. package/src/providers/integrations/muse/muse-oauth.ts +0 -1
  411. package/src/providers/integrations/muse/muse-quota.ts +0 -4
  412. package/src/providers/integrations/muse/muse.ts +6 -9
  413. package/src/providers/integrations/opencode/fingerprint.ts +7 -5
  414. package/src/providers/integrations/opencode/provider.ts +17 -24
  415. package/src/providers/integrations/perplexity.ts +2 -2
  416. package/src/providers/integrations/qoder/qoder-catalog.ts +132 -17
  417. package/src/providers/integrations/qoder/qoder-checkin.ts +26 -8
  418. package/src/providers/integrations/qoder/qoder-native-identity-store.ts +9 -8
  419. package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
  420. package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
  421. package/src/providers/integrations/qoder/qoder-realm.ts +22 -28
  422. package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
  423. package/src/providers/integrations/qoder/qoder-umid.ts +33 -38
  424. package/src/providers/integrations/qoder/qoder-virtual.ts +14 -2
  425. package/src/providers/integrations/qoder/qoder.ts +521 -63
  426. package/src/providers/integrations/shared/connect.ts +0 -54
  427. package/src/providers/integrations/shared/hash.ts +15 -0
  428. package/src/providers/integrations/shared/session-cache.ts +136 -0
  429. package/src/providers/integrations/tokenharbor.ts +2 -2
  430. package/src/providers/integrations/trae/trae-cache.ts +7 -87
  431. package/src/providers/integrations/trae/trae-catalog.ts +1 -6
  432. package/src/providers/integrations/trae/trae-protocol.ts +17 -8
  433. package/src/providers/integrations/trae/trae-realm.ts +0 -7
  434. package/src/providers/integrations/trae/trae.ts +59 -19
  435. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  436. package/src/providers/integrations/zcode/oauth.ts +1 -1
  437. package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
  438. package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
  439. package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
  440. package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
  441. package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
  442. package/src/providers/operations/account-error-classification.ts +131 -116
  443. package/src/providers/operations/account-health-service.ts +31 -39
  444. package/src/providers/operations/account-reset-service.ts +58 -1
  445. package/src/providers/operations/cli-platform.ts +31 -5
  446. package/src/providers/operations/client-version-resolver.ts +4 -6
  447. package/src/providers/operations/client-versions.ts +10 -7
  448. package/src/providers/operations/provider-catalog-seeder.ts +2 -0
  449. package/src/providers/operations/provider-catalog-service.ts +22 -6
  450. package/src/providers/operations/provider-credential-service.ts +35 -6
  451. package/src/providers/operations/upstream-deadline.ts +3 -3
  452. package/src/providers/provider-contracts.ts +65 -10
  453. package/src/providers/provider-credential-resolver.ts +1 -1
  454. package/src/providers/provider-metadata.ts +17 -2
  455. package/src/providers/provider-model-definition.ts +22 -1
  456. package/src/providers/provider-probe.ts +4 -2
  457. package/src/providers/provider-registry.ts +4 -4
  458. package/src/providers/provider-usage.ts +81 -16
  459. package/src/providers/quota/cache.ts +29 -0
  460. package/src/providers/quota/quota-contracts.ts +28 -10
  461. package/src/providers/quota/refresh.ts +29 -6
  462. package/src/providers/quota/snapshot.ts +94 -0
  463. package/src/providers/search/search-provider.ts +6 -8
  464. package/src/providers/search/search-providers.ts +2 -1
  465. package/src/security/abuse.ts +8 -8
  466. package/src/security/admission/reasons.ts +17 -17
  467. package/src/security/admission/service.ts +2 -2
  468. package/src/security/admission/ttl.ts +61 -61
  469. package/src/security/api-key-auth.ts +20 -8
  470. package/src/security/client-router-fingerprint.ts +4 -4
  471. package/src/security/credential-codec.ts +3 -3
  472. package/src/security/csrf.ts +2 -2
  473. package/src/security/ip-boundary.ts +16 -189
  474. package/src/security/model-access-rule.ts +1 -1
  475. package/src/security/outbound-headers.ts +18 -0
  476. package/src/shared/coerce.ts +19 -0
  477. package/src/shared/invoke-guard.ts +47 -0
  478. package/src/transport/contracts.ts +13 -4
  479. package/src/transport/dispatch/attempt-finalize.ts +5 -4
  480. package/src/transport/dispatch/attempt-loop.ts +10 -7
  481. package/src/transport/dispatch/capture-policy.ts +34 -37
  482. package/src/transport/dispatch/empty-stream.ts +28 -25
  483. package/src/transport/dispatch/generation.ts +33 -53
  484. package/src/transport/dispatch/leases.ts +8 -8
  485. package/src/transport/dispatch/native-shared.ts +127 -0
  486. package/src/transport/dispatch/proxy-request.ts +10 -8
  487. package/src/transport/dispatch/responses-compact.ts +35 -56
  488. package/src/transport/dispatch/retry-policy.ts +4 -67
  489. package/src/transport/dispatch/stream-bridge.ts +1 -1
  490. package/src/transport/dispatch/streaming/encoder.ts +18 -72
  491. package/src/transport/dispatch/streaming/finalize.ts +11 -10
  492. package/src/transport/dispatch/streaming/stream.ts +7 -3
  493. package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
  494. package/src/transport/dispatch/systemone.ts +27 -55
  495. package/src/transport/dispatch/token-count.ts +49 -46
  496. package/src/transport/dispatch/websearch.ts +24 -50
  497. package/src/transport/drain-endpoint.ts +3 -3
  498. package/src/transport/failure-policy.ts +19 -6
  499. package/src/transport/guards/auth-guard.ts +6 -11
  500. package/src/transport/guards/body-policy.ts +7 -7
  501. package/src/transport/guards/error-lifecycle.ts +18 -3
  502. package/src/transport/guards/guard-errors.ts +7 -3
  503. package/src/transport/guards/headroom-guard.ts +2 -2
  504. package/src/transport/guards/pipeline.ts +7 -7
  505. package/src/transport/guards/readiness-guard.ts +16 -2
  506. package/src/transport/guards/request-context.ts +15 -20
  507. package/src/transport/request/preparer.ts +306 -27
  508. package/src/transport/request/rtk/compress-request.ts +3 -3
  509. package/src/transport/request/rtk/rtk-constants.ts +2 -2
  510. package/src/transport/request/rtk/rtk-filters.ts +8 -8
  511. package/src/transport/request/state.ts +5 -20
  512. package/src/transport/request/system-prompt-injection.ts +74 -11
  513. package/src/transport/request/tenant-preferences.ts +22 -0
  514. package/src/transport/routing/candidate-index.ts +2 -2
  515. package/src/transport/routing/round-robin.ts +1 -1
  516. package/src/transport/routing/route-catalog.ts +113 -19
  517. package/src/transport/routing/route-model.ts +131 -38
  518. package/src/transport/routing/router.ts +154 -39
  519. package/src/transport/shutdown-notice.ts +21 -9
  520. package/src/transport/surface/adapters.ts +3 -3
  521. package/src/transport/surface/chat/encode.ts +7 -7
  522. package/src/transport/surface/chat/parse.ts +7 -7
  523. package/src/transport/surface/completion.ts +3 -3
  524. package/src/transport/surface/content-parts.ts +1 -1
  525. package/src/transport/surface/dialects.ts +2 -2
  526. package/src/transport/surface/messages/encode.ts +1 -1
  527. package/src/transport/surface/messages/parse.ts +3 -3
  528. package/src/transport/surface/responses/adapter.ts +1 -1
  529. package/src/transport/surface/responses/errors.ts +0 -9
  530. package/src/transport/vision-handoff-cache.ts +58 -0
  531. package/src/transport/vision-handoff.ts +376 -0
  532. package/src/workers/account-identity-sweep.ts +2 -2
  533. package/src/workers/buddy-growth-tasks.ts +392 -346
  534. package/src/workers/daily-checkin.ts +102 -49
  535. package/src/workers/maintenance-lease.ts +2 -35
  536. package/src/workers/oauth-refresh-sweep.ts +8 -1
  537. package/src/workers/quota-refresh-sweep.ts +120 -82
  538. package/src/workers/scheduler.ts +67 -4
  539. package/src/workers/sweep-runner.ts +24 -5
  540. package/src/workers/zcode-gift-claim.ts +108 -0
  541. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
  542. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
  543. package/dist/dashboard/assets/BannedPage-2TJD37Hb.js.gz +0 -0
  544. package/dist/dashboard/assets/CliToolDetailPage-xefJNRmJ.js.gz +0 -0
  545. package/dist/dashboard/assets/CliToolsPage-Rj9iHQ3F.js.gz +0 -0
  546. package/dist/dashboard/assets/CombosPage-JEbYJFxw.js +0 -1
  547. package/dist/dashboard/assets/CombosPage-JEbYJFxw.js.gz +0 -0
  548. package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js +0 -1
  549. package/dist/dashboard/assets/ConsoleLogPage-C3xx_inM.js.gz +0 -0
  550. package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js +0 -1
  551. package/dist/dashboard/assets/CustomizationPage-Dw306gJU.js.gz +0 -0
  552. package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js +0 -1
  553. package/dist/dashboard/assets/HealthEventsModal-jaBo1TWV.js.gz +0 -0
  554. package/dist/dashboard/assets/LoginPage-C4w7vea-.js.gz +0 -0
  555. package/dist/dashboard/assets/ModelPicker-BtPcAfot.js.gz +0 -0
  556. package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js +0 -1
  557. package/dist/dashboard/assets/OverviewPage-CGC5gNs1.js.gz +0 -0
  558. package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js +0 -4
  559. package/dist/dashboard/assets/ProviderDetailPage-DQcthNGt.js.gz +0 -0
  560. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
  561. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  562. package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js +0 -1
  563. package/dist/dashboard/assets/ProvidersPage-0OsXRGXe.js.gz +0 -0
  564. package/dist/dashboard/assets/ProxyPage-DdPc8slb.js +0 -9
  565. package/dist/dashboard/assets/ProxyPage-DdPc8slb.js.gz +0 -0
  566. package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js +0 -1
  567. package/dist/dashboard/assets/QuotaPage-Ci5O4BnH.js.gz +0 -0
  568. package/dist/dashboard/assets/SettingsPage-CDZjTt87.js +0 -1
  569. package/dist/dashboard/assets/SettingsPage-CDZjTt87.js.gz +0 -0
  570. package/dist/dashboard/assets/SetupPage-BQS0Rx_u.js.gz +0 -0
  571. package/dist/dashboard/assets/SortableList-BAL5npBC.js +0 -1
  572. package/dist/dashboard/assets/SortableList-BAL5npBC.js.gz +0 -0
  573. package/dist/dashboard/assets/StudioPage-TP7voAQ0.js.gz +0 -0
  574. package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js +0 -56
  575. package/dist/dashboard/assets/UsagePage-Cj_fEzhg.js.gz +0 -0
  576. package/dist/dashboard/assets/api-keys-MbI7e7rt.js +0 -1
  577. package/dist/dashboard/assets/api-keys-MbI7e7rt.js.gz +0 -0
  578. package/dist/dashboard/assets/app-B2vyPoII.css +0 -2
  579. package/dist/dashboard/assets/app-B2vyPoII.css.gz +0 -0
  580. package/dist/dashboard/assets/assert-C0YYuZJ4.js.gz +0 -0
  581. package/dist/dashboard/assets/badge-B_DMpMJN.js.gz +0 -0
  582. package/dist/dashboard/assets/banner-DMrMPmth.js.gz +0 -0
  583. package/dist/dashboard/assets/card-Be5Uzamx.js.gz +0 -0
  584. package/dist/dashboard/assets/cli-tools-muFRphDu.js.gz +0 -0
  585. package/dist/dashboard/assets/clipboard-button-DOfrVmsi.js.gz +0 -0
  586. package/dist/dashboard/assets/dialog-C9omdjQt.js.gz +0 -0
  587. package/dist/dashboard/assets/drawer-Bm8WKaGY.js.gz +0 -0
  588. package/dist/dashboard/assets/entry-DS90gUks.js +0 -1
  589. package/dist/dashboard/assets/entry-DS90gUks.js.gz +0 -0
  590. package/dist/dashboard/assets/entry-j40LJotO.js +0 -4
  591. package/dist/dashboard/assets/entry-j40LJotO.js.gz +0 -0
  592. package/dist/dashboard/assets/entry-q5HwZ8nN.js.gz +0 -0
  593. package/dist/dashboard/assets/formatters-BTScrQpe.js.gz +0 -0
  594. package/dist/dashboard/assets/github-badge-Orjuzemr.js.gz +0 -0
  595. package/dist/dashboard/assets/index-cPrX5vn6.js.gz +0 -0
  596. package/dist/dashboard/assets/inline-Dvux8w-0.js.gz +0 -0
  597. package/dist/dashboard/assets/input-CU1Rgf3p.js.gz +0 -0
  598. package/dist/dashboard/assets/list-row-CzFvogbj.js.gz +0 -0
  599. package/dist/dashboard/assets/live-KaG15HLQ.js +0 -1
  600. package/dist/dashboard/assets/live-KaG15HLQ.js.gz +0 -0
  601. package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +0 -1
  602. package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
  603. package/dist/dashboard/assets/mutation-JJGQm8TD.js.gz +0 -0
  604. package/dist/dashboard/assets/numbers-BNDZnsUE.js +0 -2
  605. package/dist/dashboard/assets/numbers-BNDZnsUE.js.gz +0 -0
  606. package/dist/dashboard/assets/query-keys-CLaNz8Xz.js.gz +0 -0
  607. package/dist/dashboard/assets/quota-DZGyp0N5.js +0 -1
  608. package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
  609. package/dist/dashboard/assets/routing-BEH32QOC.js.gz +0 -0
  610. package/dist/dashboard/assets/select-B3iTetHN.js.gz +0 -0
  611. package/dist/dashboard/assets/settings-Dt3Eqbnq.js +0 -1
  612. package/dist/dashboard/assets/settings-Dt3Eqbnq.js.gz +0 -0
  613. package/dist/dashboard/assets/stack-KrOrm7JZ.js.gz +0 -0
  614. package/dist/dashboard/assets/state-DLS7IDMy.js.gz +0 -0
  615. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
  616. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  617. package/dist/dashboard/assets/switch-42ItvbAs.js.gz +0 -0
  618. package/dist/dashboard/assets/useMutation-Dmnfh1Ue.js.gz +0 -0
  619. package/src/network/response-headers.ts +0 -39
  620. package/src/protocol/response/dsml.ts +0 -38
  621. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
  622. /package/dist/dashboard/assets/{app-wvwCi4Eh.js → app-Bgd3zANQ.js} +0 -0
  623. /package/dist/dashboard/assets/{app-wvwCi4Eh.js.gz → app-Bgd3zANQ.js.gz} +0 -0
  624. /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
  625. /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
@@ -1,148 +1,148 @@
1
- import { createHash } from "node:crypto";
2
-
3
- const MASK = 0xffffffffffffffffn;
4
- const PRIME1 = 0x9e3779b185ebca87n;
5
- const PRIME2 = 0xc2b2ae3d27d4eb4fn;
6
- const PRIME3 = 0x165667b19e3779f9n;
7
- const PRIME4 = 0x85ebca77c2b2ae63n;
8
- const PRIME5 = 0x27d4eb2f165667c5n;
9
- const CCH_SEED = 0x4d659218e32a3268n;
10
- const PLACEHOLDER = "cch=00000";
11
- const encoder = new TextEncoder();
12
-
13
- function round(acc: bigint, input: bigint): bigint {
14
- let value = (acc + input * PRIME2) & MASK;
15
- value = ((value << 31n) | (value >> 33n)) & MASK;
16
- return (value * PRIME1) & MASK;
17
- }
18
-
19
- function mergeRound(acc: bigint, value: bigint): bigint {
20
- let result = acc ^ round(0n, value);
21
- return (result * PRIME1 + PRIME4) & MASK;
22
- }
23
-
24
- function read32(bytes: Uint8Array, offset: number): bigint {
25
- return (
26
- BigInt(bytes[offset] ?? 0) |
27
- (BigInt(bytes[offset + 1] ?? 0) << 8n) |
28
- (BigInt(bytes[offset + 2] ?? 0) << 16n) |
29
- (BigInt(bytes[offset + 3] ?? 0) << 24n)
30
- );
31
- }
32
-
33
- function read64(bytes: Uint8Array, offset: number): bigint {
34
- let value = 0n;
35
- for (let index = 0; index < 8; index += 1)
36
- value |= BigInt(bytes[offset + index] ?? 0) << BigInt(index * 8);
37
- return value;
38
- }
39
-
40
- function xxHash64(bytes: Uint8Array, seed: bigint): bigint {
41
- let offset = 0;
42
- let hash: bigint;
43
- if (bytes.length >= 32) {
44
- let v1 = (seed + PRIME1 + PRIME2) & MASK;
45
- let v2 = (seed + PRIME2) & MASK;
46
- let v3 = seed & MASK;
47
- let v4 = (seed - PRIME1) & MASK;
48
- while (offset <= bytes.length - 32) {
49
- v1 = round(v1, read64(bytes, offset));
50
- v2 = round(v2, read64(bytes, offset + 8));
51
- v3 = round(v3, read64(bytes, offset + 16));
52
- v4 = round(v4, read64(bytes, offset + 24));
53
- offset += 32;
54
- }
55
- hash =
56
- (((v1 << 1n) | (v1 >> 63n)) +
57
- ((v2 << 7n) | (v2 >> 57n)) +
58
- ((v3 << 12n) | (v3 >> 52n)) +
59
- ((v4 << 18n) | (v4 >> 46n))) &
60
- MASK;
61
- hash = mergeRound(hash, v1);
62
- hash = mergeRound(hash, v2);
63
- hash = mergeRound(hash, v3);
64
- hash = mergeRound(hash, v4);
65
- } else hash = (seed + PRIME5) & MASK;
66
- hash = (hash + BigInt(bytes.length)) & MASK;
67
- while (offset <= bytes.length - 8) {
68
- const value = round(0n, read64(bytes, offset));
69
- hash ^= value;
70
- hash = (((hash << 27n) | (hash >> 37n)) * PRIME1 + PRIME4) & MASK;
71
- offset += 8;
72
- }
73
- if (offset <= bytes.length - 4) {
74
- hash ^= (read32(bytes, offset) * PRIME1) & MASK;
75
- hash = (((hash << 23n) | (hash >> 41n)) * PRIME2 + PRIME3) & MASK;
76
- offset += 4;
77
- }
78
- while (offset < bytes.length) {
79
- hash ^= (BigInt(bytes[offset] ?? 0) * PRIME5) & MASK;
80
- hash = (((hash << 11n) | (hash >> 53n)) * PRIME1) & MASK;
81
- offset += 1;
82
- }
83
- hash ^= hash >> 33n;
84
- hash = (hash * PRIME2) & MASK;
85
- hash ^= hash >> 29n;
86
- hash = (hash * PRIME3) & MASK;
87
- return (hash ^ (hash >> 32n)) & MASK;
88
- }
89
-
90
- /** Computes Claude Code's five-hex-digit CCH from the exact outgoing body bytes. */
91
- export function computeClaudeCch(body: Uint8Array): string {
92
- return (xxHash64(body, CCH_SEED) & 0xfffffn).toString(16).padStart(5, "0");
93
- }
94
-
95
- /** Replaces the anchored Claude billing placeholder in a mutable body before sending. */
96
- export function patchClaudeCch(body: Uint8Array): boolean {
97
- const marker = encoder.encode('"system":[{"type":"text","text":"x-anthropic-billing-header:');
98
- const placeholder = encoder.encode(PLACEHOLDER);
99
- let markerIndex = -1;
100
- outer: for (let index = 0; index <= body.length - marker.length; index += 1) {
101
- for (let j = 0; j < marker.length; j += 1) if (body[index + j] !== marker[j]) continue outer;
102
- markerIndex = index;
103
- break;
104
- }
105
- if (markerIndex < 0) return false;
106
- const start = markerIndex + marker.length;
107
- const end = Math.min(body.length - placeholder.length, start + 150);
108
- for (let index = start; index <= end; index += 1) {
109
- let found = true;
110
- for (let j = 0; j < placeholder.length; j += 1)
111
- if (body[index + j] !== placeholder[j]) {
112
- found = false;
113
- break;
114
- }
115
- if (!found) continue;
116
- const cch = encoder.encode(computeClaudeCch(body));
117
- body.set(cch, index + 4);
118
- return true;
119
- }
120
- return false;
121
- }
122
-
123
- /** Harness identity instruction, sent on OAuth dispatch. */
124
- export const CLAUDE_CODE_SYSTEM_INSTRUCTION =
125
- "You are Claude Code, Anthropic's official CLI for Claude.";
126
-
127
- /**
128
- * Builds the billing header text with the captured version suffix:
129
- * `cc_version={ver}.{sha256("59cf53e54c78" + chars + ver)[0:3]}` where
130
- * chars are the 5th/8th/21st chars of the first user text (or "0" when
131
- * absent). `cc_entrypoint=cli` matches the harness UA `(external, cli)`;
132
- * an older snapshot used `claude-desktop`, which is unverified from local
133
- * evidence, so cli is kept with this note.
134
- */
135
- export function createClaudeBillingText(userText: string, version: string): string {
136
- const chars = [4, 7, 20].map((index) => userText[index] ?? "0").join("");
137
- const suffix = createHash("sha256")
138
- .update(`59cf53e54c78${chars}${version}`)
139
- .digest("hex")
140
- .slice(0, 3);
141
- return `x-anthropic-billing-header: cc_version=${version}.${suffix}; cc_entrypoint=cli; cch=00000;`;
142
- }
143
-
144
- /** Patches a string request body and returns its encoded bytes, or undefined when no billing block exists. */
145
- export function patchClaudeCchBody(body: string): Uint8Array | undefined {
146
- const bytes = encoder.encode(body);
147
- return patchClaudeCch(bytes) ? bytes : undefined;
148
- }
1
+ import { createHash } from "node:crypto";
2
+
3
+ const MASK = 0xffffffffffffffffn;
4
+ const PRIME1 = 0x9e3779b185ebca87n;
5
+ const PRIME2 = 0xc2b2ae3d27d4eb4fn;
6
+ const PRIME3 = 0x165667b19e3779f9n;
7
+ const PRIME4 = 0x85ebca77c2b2ae63n;
8
+ const PRIME5 = 0x27d4eb2f165667c5n;
9
+ const CCH_SEED = 0x4d659218e32a3268n;
10
+ const PLACEHOLDER = "cch=00000";
11
+ const encoder = new TextEncoder();
12
+
13
+ function round(acc: bigint, input: bigint): bigint {
14
+ let value = (acc + input * PRIME2) & MASK;
15
+ value = ((value << 31n) | (value >> 33n)) & MASK;
16
+ return (value * PRIME1) & MASK;
17
+ }
18
+
19
+ function mergeRound(acc: bigint, value: bigint): bigint {
20
+ let result = acc ^ round(0n, value);
21
+ return (result * PRIME1 + PRIME4) & MASK;
22
+ }
23
+
24
+ function read32(bytes: Uint8Array, offset: number): bigint {
25
+ return (
26
+ BigInt(bytes[offset] ?? 0) |
27
+ (BigInt(bytes[offset + 1] ?? 0) << 8n) |
28
+ (BigInt(bytes[offset + 2] ?? 0) << 16n) |
29
+ (BigInt(bytes[offset + 3] ?? 0) << 24n)
30
+ );
31
+ }
32
+
33
+ function read64(bytes: Uint8Array, offset: number): bigint {
34
+ let value = 0n;
35
+ for (let index = 0; index < 8; index += 1)
36
+ value |= BigInt(bytes[offset + index] ?? 0) << BigInt(index * 8);
37
+ return value;
38
+ }
39
+
40
+ function xxHash64(bytes: Uint8Array, seed: bigint): bigint {
41
+ let offset = 0;
42
+ let hash: bigint;
43
+ if (bytes.length >= 32) {
44
+ let v1 = (seed + PRIME1 + PRIME2) & MASK;
45
+ let v2 = (seed + PRIME2) & MASK;
46
+ let v3 = seed & MASK;
47
+ let v4 = (seed - PRIME1) & MASK;
48
+ while (offset <= bytes.length - 32) {
49
+ v1 = round(v1, read64(bytes, offset));
50
+ v2 = round(v2, read64(bytes, offset + 8));
51
+ v3 = round(v3, read64(bytes, offset + 16));
52
+ v4 = round(v4, read64(bytes, offset + 24));
53
+ offset += 32;
54
+ }
55
+ hash =
56
+ (((v1 << 1n) | (v1 >> 63n)) +
57
+ ((v2 << 7n) | (v2 >> 57n)) +
58
+ ((v3 << 12n) | (v3 >> 52n)) +
59
+ ((v4 << 18n) | (v4 >> 46n))) &
60
+ MASK;
61
+ hash = mergeRound(hash, v1);
62
+ hash = mergeRound(hash, v2);
63
+ hash = mergeRound(hash, v3);
64
+ hash = mergeRound(hash, v4);
65
+ } else hash = (seed + PRIME5) & MASK;
66
+ hash = (hash + BigInt(bytes.length)) & MASK;
67
+ while (offset <= bytes.length - 8) {
68
+ const value = round(0n, read64(bytes, offset));
69
+ hash ^= value;
70
+ hash = (((hash << 27n) | (hash >> 37n)) * PRIME1 + PRIME4) & MASK;
71
+ offset += 8;
72
+ }
73
+ if (offset <= bytes.length - 4) {
74
+ hash ^= (read32(bytes, offset) * PRIME1) & MASK;
75
+ hash = (((hash << 23n) | (hash >> 41n)) * PRIME2 + PRIME3) & MASK;
76
+ offset += 4;
77
+ }
78
+ while (offset < bytes.length) {
79
+ hash ^= (BigInt(bytes[offset] ?? 0) * PRIME5) & MASK;
80
+ hash = (((hash << 11n) | (hash >> 53n)) * PRIME1) & MASK;
81
+ offset += 1;
82
+ }
83
+ hash ^= hash >> 33n;
84
+ hash = (hash * PRIME2) & MASK;
85
+ hash ^= hash >> 29n;
86
+ hash = (hash * PRIME3) & MASK;
87
+ return (hash ^ (hash >> 32n)) & MASK;
88
+ }
89
+
90
+ /** Computes Claude Code's five-hex-digit CCH from the exact outgoing body bytes. */
91
+ export function computeClaudeCch(body: Uint8Array): string {
92
+ return (xxHash64(body, CCH_SEED) & 0xfffffn).toString(16).padStart(5, "0");
93
+ }
94
+
95
+ /** Replaces the anchored Claude billing placeholder in a mutable body before sending. */
96
+ export function patchClaudeCch(body: Uint8Array): boolean {
97
+ const marker = encoder.encode('"system":[{"type":"text","text":"x-anthropic-billing-header:');
98
+ const placeholder = encoder.encode(PLACEHOLDER);
99
+ let markerIndex = -1;
100
+ outer: for (let index = 0; index <= body.length - marker.length; index += 1) {
101
+ for (let j = 0; j < marker.length; j += 1) if (body[index + j] !== marker[j]) continue outer;
102
+ markerIndex = index;
103
+ break;
104
+ }
105
+ if (markerIndex < 0) return false;
106
+ const start = markerIndex + marker.length;
107
+ const end = Math.min(body.length - placeholder.length, start + 150);
108
+ for (let index = start; index <= end; index += 1) {
109
+ let found = true;
110
+ for (let j = 0; j < placeholder.length; j += 1)
111
+ if (body[index + j] !== placeholder[j]) {
112
+ found = false;
113
+ break;
114
+ }
115
+ if (!found) continue;
116
+ const cch = encoder.encode(computeClaudeCch(body));
117
+ body.set(cch, index + 4);
118
+ return true;
119
+ }
120
+ return false;
121
+ }
122
+
123
+ /** Harness identity instruction, sent on OAuth dispatch. */
124
+ export const CLAUDE_CODE_SYSTEM_INSTRUCTION =
125
+ "You are Claude Code, Anthropic's official CLI for Claude.";
126
+
127
+ /**
128
+ * Builds the billing header text with the captured version suffix:
129
+ * `cc_version={ver}.{sha256("59cf53e54c78" + chars + ver)[0:3]}` where
130
+ * chars are the 5th/8th/21st chars of the first user text (or "0" when
131
+ * absent). `cc_entrypoint=cli` matches the harness UA `(external, cli)`;
132
+ * an older snapshot used `claude-desktop`, which is unverified from local
133
+ * evidence, so cli is kept with this note.
134
+ */
135
+ export function createClaudeBillingText(userText: string, version: string): string {
136
+ const chars = [4, 7, 20].map((index) => userText[index] ?? "0").join("");
137
+ const suffix = createHash("sha256")
138
+ .update(`59cf53e54c78${chars}${version}`)
139
+ .digest("hex")
140
+ .slice(0, 3);
141
+ return `x-anthropic-billing-header: cc_version=${version}.${suffix}; cc_entrypoint=cli; cch=00000;`;
142
+ }
143
+
144
+ /** Patches a string request body and returns its encoded bytes, or undefined when no billing block exists. */
145
+ export function patchClaudeCchBody(body: string): Uint8Array | undefined {
146
+ const bytes = encoder.encode(body);
147
+ return patchClaudeCch(bytes) ? bytes : undefined;
148
+ }
@@ -10,7 +10,7 @@ function invalidHeader(
10
10
  message: string,
11
11
  details: Readonly<Record<string, unknown>> = {},
12
12
  ): GatewayError {
13
- return new GatewayError("invalid_request", 400, message, details);
13
+ return new GatewayError("invalid_request", 400, `${message} (request {requestId}). Check the shape of what you sent — then resend 🪞`, details);
14
14
  }
15
15
 
16
16
  function decodeSecret(secret: Uint8Array | undefined): string | undefined {
@@ -96,5 +96,5 @@ export function planSlowLaneRetry(
96
96
 
97
97
  /** Typed error for a caller-aborted wait, so it is never read as a failure. */
98
98
  export function slowLaneAborted(): GatewayError {
99
- return new GatewayError("transport_closed", 499, "Aborted during slow-lane capacity wait");
99
+ return new GatewayError("transport_closed", 499, "The request was cancelled during the slow-lane capacity wait (request {requestId}). Send it again whenever ready 🙃");
100
100
  }
@@ -61,6 +61,7 @@ import {
61
61
  refusalCreditToken,
62
62
  sharedFallbackCreditCache,
63
63
  } from "./fallback-credit";
64
+ import { assertCredentialKind, assertWireFamily } from "../../provider-contracts";
64
65
  import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext } from "../../provider-contracts";
65
66
  import { defineModel } from "../../provider-model-definition";
66
67
  import type { ModelDefinition } from "../../provider-model-definition";
@@ -185,21 +186,13 @@ export class ClaudeAdapter implements ProviderAdapter {
185
186
  context: ProviderDispatchContext,
186
187
  ): AsyncIterable<CanonicalEvent> {
187
188
  if (candidate.wire_family !== "messages") {
188
- throw new GatewayError(
189
- "capability_unsupported",
190
- 400,
191
- "claude supports messages only",
192
- );
189
+ assertWireFamily(candidate, "messages", "claude");
193
190
  }
194
191
  if (
195
192
  context.credential.credential_kind !== "oauth" &&
196
193
  context.credential.credential_kind !== "scoped_access_token"
197
194
  ) {
198
- throw new GatewayError(
199
- "invalid_request",
200
- 400,
201
- `claude: the assistant OAuth credential required (got credential_kind=${context.credential.credential_kind})`,
202
- );
195
+ assertCredentialKind(context.credential, ["oauth", "scoped_access_token"], "claude");
203
196
  }
204
197
  const customHeaders = filterClaudeCustomHeaders({
205
198
  ...this.customHeaders,
@@ -27,6 +27,7 @@
27
27
  */
28
28
 
29
29
  import { GatewayError } from "../../../protocol/gateway-error";
30
+ import { fnv1a32 } from "../shared/hash";
30
31
 
31
32
  const CREDIT_TTL_MS = 5 * 60 * 1000; // 5 minutes
32
33
  const MAX_CACHE_SIZE = 64;
@@ -122,15 +123,10 @@ export class FallbackCreditCache {
122
123
 
123
124
  /**
124
125
  * Compute a simple hash of the request body for cache keying.
125
- * Uses FNV-1a — fast, deterministic, sufficient for cache identity.
126
+ * FNV-1a — fast, deterministic, sufficient for cache identity.
126
127
  */
127
128
  export function hashBody(body: string): string {
128
- let hash = 0x811c9dc5;
129
- for (let i = 0; i < body.length; i++) {
130
- hash ^= body.charCodeAt(i);
131
- hash = Math.imul(hash, 0x01000193);
132
- }
133
- return (hash >>> 0).toString(36);
129
+ return fnv1a32(body).toString(36);
134
130
  }
135
131
 
136
132
  // Shared process-wide cache instance
@@ -28,7 +28,7 @@ const CLINE_MODELS_CATALOG_PATH = "/ai/cline/models" as const;
28
28
 
29
29
 
30
30
 
31
- export function workosToken(token: string): string {
31
+ function workosToken(token: string): string {
32
32
  return token.startsWith("workos:") ? token : `workos:${token}`;
33
33
  }
34
34
 
@@ -150,7 +150,7 @@ function clinePrePayload(
150
150
  const cur = typeof payload["max_tokens"] === "number" ? (payload["max_tokens"] as number) : 0;
151
151
  payload["max_tokens"] = Math.max(cur, 256);
152
152
  // keep GatewayError reachable
153
- if (!model) throw new GatewayError("invalid_request", 400, "Cline model is required");
153
+ if (!model) throw new GatewayError("invalid_request", 400, "Cline model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
154
154
  }
155
155
  }
156
156
 
@@ -16,6 +16,7 @@
16
16
  * protocol at the `/anthropic` path suffix, including `thinking_delta`
17
17
  * blocks, so the Messages leg is built directly.
18
18
  */
19
+ import { assertWireFamily } from "../../provider-contracts";
19
20
  import type {
20
21
  ProviderAdapter,
21
22
  ProviderDispatchContext,
@@ -57,7 +58,7 @@ function cloudflareEnvelope(context: ProviderDispatchContext): {
57
58
  } {
58
59
  const secret = context.credential.secret;
59
60
  if (secret === undefined || secret.length === 0) {
60
- throw new GatewayError("invalid_request", 400, "cloudflareai: credential is missing a secret value");
61
+ throw new GatewayError("invalid_request", 400, "cloudflareai: credential is missing a secret value (request {requestId}). Wrong key, right door — check the credential 🔑");
61
62
  }
62
63
  let envelope: ReturnType<typeof decodeCloudflareAiGatewayCredential>;
63
64
  try {
@@ -66,7 +67,7 @@ function cloudflareEnvelope(context: ProviderDispatchContext): {
66
67
  throw new GatewayError(
67
68
  "invalid_request",
68
69
  400,
69
- `cloudflareai: ${error instanceof Error ? error.message : "stored credential is not a Cloudflare envelope"}`,
70
+ `cloudflareai: ${error instanceof Error ? error.message : "stored credential is not a Cloudflare envelope"} (request {requestId}). Wrong key, right door — check the credential 🔑`,
70
71
  );
71
72
  }
72
73
  return { token: envelope.token, baseUrl: cloudflareBaseUrl(envelope.accountId, envelope.gatewayId) };
@@ -93,11 +94,7 @@ class CloudflareAiGatewayAdapter implements ProviderAdapter {
93
94
  context: ProviderDispatchContext,
94
95
  ): AsyncIterable<CanonicalEvent> {
95
96
  if (candidate.wire_family !== "messages") {
96
- throw new GatewayError(
97
- "capability_unsupported",
98
- 400,
99
- `cloudflareai supports messages only, got ${candidate.wire_family}`,
100
- );
97
+ assertWireFamily(candidate, "messages", "cloudflareai");
101
98
  }
102
99
  const { token, baseUrl } = cloudflareEnvelope(context);
103
100
  const outbound = buildClaudeMessagesRequest({
@@ -1,101 +1,101 @@
1
- import type { FetchLike } from "../../authentication/oauth-client";
2
-
3
- export const CODEX_DEVICE_USERCODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
4
- export const CODEX_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
5
-
6
- /**
7
- * Lifetime of one device authorization, in seconds.
8
- *
9
- * The Codex device endpoint states no expiry, so the flow bounds itself: this
10
- * is both what `startDeviceAuth` reports to the dashboard (its own countdown)
11
- * and what the poll checks before spending a request on a dead authorization.
12
- */
13
- export const CODEX_DEVICE_TTL_SECONDS = 900;
14
-
15
- interface CodexDeviceStart {
16
- readonly deviceAuthId: string;
17
- readonly userCode: string;
18
- readonly intervalSeconds: number;
19
- }
20
-
21
- interface CodexDeviceAuthorization {
22
- readonly authorizationCode: string;
23
- readonly codeVerifier: string;
24
- }
25
-
26
- /** Validates persisted provider-private device state read back from the flow store. */
27
- export function parseCodexDeviceStart(value: Record<string, unknown>): CodexDeviceStart | undefined {
28
- const { deviceAuthId, userCode, intervalSeconds } = value;
29
- if (typeof deviceAuthId !== "string" || typeof userCode !== "string") return undefined;
30
- if (typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds)) return undefined;
31
- return { deviceAuthId, userCode, intervalSeconds: Math.max(0, intervalSeconds) };
32
- }
33
-
34
- interface DeviceUserCodeResponse {
35
- device_auth_id?: unknown;
36
- user_code?: unknown;
37
- interval?: unknown;
38
- }
39
- interface DeviceTokenResponse {
40
- authorization_code?: unknown;
41
- code_verifier?: unknown;
42
- }
43
-
44
- function jsonHeaders(): HeadersInit {
45
- return { "content-type": "application/json", accept: "application/json" };
46
- }
47
-
48
- export async function startCodexDeviceAuth(
49
- clientId: string,
50
- fetchFn: FetchLike = globalThis.fetch,
51
- ): Promise<CodexDeviceStart> {
52
- const response = await fetchFn(CODEX_DEVICE_USERCODE_URL, {
53
- method: "POST",
54
- headers: jsonHeaders(),
55
- body: JSON.stringify({ client_id: clientId }),
56
- });
57
- if (!response.ok) throw new Error(`Codex device authorization failed (${response.status})`);
58
- const body = (await response.json()) as DeviceUserCodeResponse;
59
- if (typeof body.device_auth_id !== "string" || typeof body.user_code !== "string")
60
- throw new Error("Codex device authorization returned an invalid response");
61
- const interval =
62
- typeof body.interval === "number" && Number.isFinite(body.interval)
63
- ? Math.max(0, body.interval)
64
- : 5;
65
- return { deviceAuthId: body.device_auth_id, userCode: body.user_code, intervalSeconds: interval };
66
- }
67
-
68
- /**
69
- * One device-token poll attempt.
70
- *
71
- * Returns `undefined` while the user has not approved yet (the endpoint answers
72
- * 403/404) and the parsed PKCE pair once it has. Deliberately a single request:
73
- * the dashboard owns the polling cadence, so the console route returns
74
- * `pending` between attempts instead of holding one HTTP request open for the
75
- * whole authorization window. A blocking loop here occupied a console worker
76
- * for up to the full TTL and made the dialog's own interval meaningless.
77
- */
78
- export async function pollCodexDeviceAuth(
79
- device: CodexDeviceStart,
80
- fetchFn: FetchLike = globalThis.fetch,
81
- ): Promise<CodexDeviceAuthorization | undefined> {
82
- let response: Response;
83
- try {
84
- response = await fetchFn(CODEX_DEVICE_TOKEN_URL, {
85
- method: "POST",
86
- headers: jsonHeaders(),
87
- body: JSON.stringify({ device_auth_id: device.deviceAuthId, user_code: device.userCode }),
88
- });
89
- } catch (error) {
90
- // A network failure is not "not approved yet": surface it so the caller
91
- // can return a failed verdict instead of polling to expiry.
92
- throw new Error(`Codex device polling failed: ${error instanceof Error ? error.message : String(error)}`);
93
- }
94
- // 403/404 are the endpoint's "not approved yet" answers, not failures.
95
- if (response.status === 403 || response.status === 404) return undefined;
96
- if (!response.ok) throw new Error(`Codex device polling failed (${response.status})`);
97
- const body = (await response.json()) as DeviceTokenResponse;
98
- if (typeof body.authorization_code === "string" && typeof body.code_verifier === "string")
99
- return { authorizationCode: body.authorization_code, codeVerifier: body.code_verifier };
100
- return undefined;
101
- }
1
+ import type { FetchLike } from "../../authentication/oauth-client";
2
+
3
+ export const CODEX_DEVICE_USERCODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
4
+ export const CODEX_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
5
+
6
+ /**
7
+ * Lifetime of one device authorization, in seconds.
8
+ *
9
+ * The Codex device endpoint states no expiry, so the flow bounds itself: this
10
+ * is both what `startDeviceAuth` reports to the dashboard (its own countdown)
11
+ * and what the poll checks before spending a request on a dead authorization.
12
+ */
13
+ export const CODEX_DEVICE_TTL_SECONDS = 900;
14
+
15
+ interface CodexDeviceStart {
16
+ readonly deviceAuthId: string;
17
+ readonly userCode: string;
18
+ readonly intervalSeconds: number;
19
+ }
20
+
21
+ interface CodexDeviceAuthorization {
22
+ readonly authorizationCode: string;
23
+ readonly codeVerifier: string;
24
+ }
25
+
26
+ /** Validates persisted provider-private device state read back from the flow store. */
27
+ export function parseCodexDeviceStart(value: Record<string, unknown>): CodexDeviceStart | undefined {
28
+ const { deviceAuthId, userCode, intervalSeconds } = value;
29
+ if (typeof deviceAuthId !== "string" || typeof userCode !== "string") return undefined;
30
+ if (typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds)) return undefined;
31
+ return { deviceAuthId, userCode, intervalSeconds: Math.max(0, intervalSeconds) };
32
+ }
33
+
34
+ interface DeviceUserCodeResponse {
35
+ device_auth_id?: unknown;
36
+ user_code?: unknown;
37
+ interval?: unknown;
38
+ }
39
+ interface DeviceTokenResponse {
40
+ authorization_code?: unknown;
41
+ code_verifier?: unknown;
42
+ }
43
+
44
+ function jsonHeaders(): HeadersInit {
45
+ return { "content-type": "application/json", accept: "application/json" };
46
+ }
47
+
48
+ export async function startCodexDeviceAuth(
49
+ clientId: string,
50
+ fetchFn: FetchLike = globalThis.fetch,
51
+ ): Promise<CodexDeviceStart> {
52
+ const response = await fetchFn(CODEX_DEVICE_USERCODE_URL, {
53
+ method: "POST",
54
+ headers: jsonHeaders(),
55
+ body: JSON.stringify({ client_id: clientId }),
56
+ });
57
+ if (!response.ok) throw new Error(`Codex device authorization failed (${response.status})`);
58
+ const body = (await response.json()) as DeviceUserCodeResponse;
59
+ if (typeof body.device_auth_id !== "string" || typeof body.user_code !== "string")
60
+ throw new Error("Codex device authorization returned an invalid response");
61
+ const interval =
62
+ typeof body.interval === "number" && Number.isFinite(body.interval)
63
+ ? Math.max(0, body.interval)
64
+ : 5;
65
+ return { deviceAuthId: body.device_auth_id, userCode: body.user_code, intervalSeconds: interval };
66
+ }
67
+
68
+ /**
69
+ * One device-token poll attempt.
70
+ *
71
+ * Returns `undefined` while the user has not approved yet (the endpoint answers
72
+ * 403/404) and the parsed PKCE pair once it has. Deliberately a single request:
73
+ * the dashboard owns the polling cadence, so the console route returns
74
+ * `pending` between attempts instead of holding one HTTP request open for the
75
+ * whole authorization window. A blocking loop here occupied a console worker
76
+ * for up to the full TTL and made the dialog's own interval meaningless.
77
+ */
78
+ export async function pollCodexDeviceAuth(
79
+ device: CodexDeviceStart,
80
+ fetchFn: FetchLike = globalThis.fetch,
81
+ ): Promise<CodexDeviceAuthorization | undefined> {
82
+ let response: Response;
83
+ try {
84
+ response = await fetchFn(CODEX_DEVICE_TOKEN_URL, {
85
+ method: "POST",
86
+ headers: jsonHeaders(),
87
+ body: JSON.stringify({ device_auth_id: device.deviceAuthId, user_code: device.userCode }),
88
+ });
89
+ } catch (error) {
90
+ // A network failure is not "not approved yet": surface it so the caller
91
+ // can return a failed verdict instead of polling to expiry.
92
+ throw new Error(`Codex device polling failed: ${error instanceof Error ? error.message : String(error)}`);
93
+ }
94
+ // 403/404 are the endpoint's "not approved yet" answers, not failures.
95
+ if (response.status === 403 || response.status === 404) return undefined;
96
+ if (!response.ok) throw new Error(`Codex device polling failed (${response.status})`);
97
+ const body = (await response.json()) as DeviceTokenResponse;
98
+ if (typeof body.authorization_code === "string" && typeof body.code_verifier === "string")
99
+ return { authorizationCode: body.authorization_code, codeVerifier: body.code_verifier };
100
+ return undefined;
101
+ }
@@ -167,7 +167,7 @@ export async function mapCodexErrorResponse(res: Response): Promise<never> {
167
167
  throw new GatewayError(
168
168
  classification.code,
169
169
  classification.status,
170
- friendlyMessage ?? sanitized,
170
+ `${friendlyMessage ?? sanitized} (request {requestId}). The upstream came back empty-handed — retry 🌙`,
171
171
  details,
172
172
  classification.origin,
173
173
  );
@@ -272,4 +272,3 @@ export class CodexOAuthClient extends OAuthDeviceFlow {
272
272
  }
273
273
 
274
274
  export const codexOAuthClient = new CodexOAuthClient();
275
- export { exchangeCodeForToken };