cartethyia 2.7.4 → 2.7.6

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 (595) hide show
  1. package/.env.example +5 -0
  2. package/README.md +18 -6
  3. package/dist/dashboard/assets/BannedPage-B1N603cM.js +1 -0
  4. package/dist/dashboard/assets/BannedPage-B1N603cM.js.gz +0 -0
  5. package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js +3 -0
  6. package/dist/dashboard/assets/CliToolDetailPage-9q4_4NoK.js.gz +0 -0
  7. package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js +1 -0
  8. package/dist/dashboard/assets/CliToolsPage-DwshGtK-.js.gz +0 -0
  9. package/dist/dashboard/assets/CombosPage-D762MIkp.js +1 -0
  10. package/dist/dashboard/assets/CombosPage-D762MIkp.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-KRYjHZsX.js.gz +0 -0
  13. package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js +1 -0
  14. package/dist/dashboard/assets/CustomizationPage-DXsxk5uM.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-BEjAjD4F.js.gz +0 -0
  17. package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js +899 -0
  18. package/dist/dashboard/assets/InjectSystemPromptPanel-d5v3K_Yc.js.gz +0 -0
  19. package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js +1 -0
  20. package/dist/dashboard/assets/LoginPage-Ccv4tjNS.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.js → ModelPicker-C6WlpU5E.js} +1 -1
  22. package/dist/dashboard/assets/ModelPicker-C6WlpU5E.js.gz +0 -0
  23. package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js +1 -0
  24. package/dist/dashboard/assets/OverviewPage-DN9fYNWA.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js +5 -0
  26. package/dist/dashboard/assets/ProviderDetailPage-BY0ieUgz.js.gz +0 -0
  27. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js +1 -0
  28. package/dist/dashboard/assets/ProviderIcon-jjqXJDA3.js.gz +0 -0
  29. package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js +1 -0
  30. package/dist/dashboard/assets/ProvidersPage-DNsbfea2.js.gz +0 -0
  31. package/dist/dashboard/assets/{ProxyPage-lsrx7NYg.js → ProxyPage-DxjvUzSD.js} +1 -1
  32. package/dist/dashboard/assets/ProxyPage-DxjvUzSD.js.gz +0 -0
  33. package/dist/dashboard/assets/QuotaPage-OaHScjpX.js +1 -0
  34. package/dist/dashboard/assets/QuotaPage-OaHScjpX.js.gz +0 -0
  35. package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js +1 -0
  36. package/dist/dashboard/assets/SettingsPage-BW4AKj2H.js.gz +0 -0
  37. package/dist/dashboard/assets/SetupPage-44BZrxFC.js +1 -0
  38. package/dist/dashboard/assets/SetupPage-44BZrxFC.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.js → StudioPage-DRPavCdU.js} +4 -4
  40. package/dist/dashboard/assets/StudioPage-DRPavCdU.js.gz +0 -0
  41. package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js +1 -0
  42. package/dist/dashboard/assets/ToolIcon-CfeLA-Z_.js.gz +0 -0
  43. package/dist/dashboard/assets/UsagePage-B7M7LvMM.js +56 -0
  44. package/dist/dashboard/assets/UsagePage-B7M7LvMM.js.gz +0 -0
  45. package/dist/dashboard/assets/api-keys-KvX83mRe.js +1 -0
  46. package/dist/dashboard/assets/api-keys-KvX83mRe.js.gz +0 -0
  47. package/dist/dashboard/assets/app-DRnQLhsc.js +9 -0
  48. package/dist/dashboard/assets/app-DRnQLhsc.js.gz +0 -0
  49. package/dist/dashboard/assets/app-mweRcsKp.css +2 -0
  50. package/dist/dashboard/assets/app-mweRcsKp.css.gz +0 -0
  51. package/dist/dashboard/assets/assert-CidQVoNo.js +1 -0
  52. package/dist/dashboard/assets/assert-CidQVoNo.js.gz +0 -0
  53. package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-BaX2GTrn.js} +1 -1
  54. package/dist/dashboard/assets/badge-BaX2GTrn.js.gz +0 -0
  55. package/dist/dashboard/assets/{banner-DympBNq4.js → banner-DFH4Bkte.js} +1 -1
  56. package/dist/dashboard/assets/banner-DFH4Bkte.js.gz +0 -0
  57. package/dist/dashboard/assets/brand/login_register.jpg +0 -0
  58. package/dist/dashboard/assets/brand/login_register_initial.jpg +0 -0
  59. package/dist/dashboard/assets/brand/og_bansos.jpg +0 -0
  60. package/dist/dashboard/assets/brand/og_image.jpg +0 -0
  61. package/dist/dashboard/assets/{card-ibRWU_uT.js → card-CxDw0lK6.js} +1 -1
  62. package/dist/dashboard/assets/card-CxDw0lK6.js.gz +0 -0
  63. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js +1 -0
  64. package/dist/dashboard/assets/chevron-left-Bf6CaTSJ.js.gz +0 -0
  65. package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js +1 -0
  66. package/dist/dashboard/assets/circle-question-mark-Cz4un8sH.js.gz +0 -0
  67. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js +1 -0
  68. package/dist/dashboard/assets/cli-tools-Bwv5-zGZ.js.gz +0 -0
  69. package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.js → clipboard-button-DfS1ntiq.js} +1 -1
  70. package/dist/dashboard/assets/clipboard-button-DfS1ntiq.js.gz +0 -0
  71. package/dist/dashboard/assets/dialog-BK-NRr5u.js +1 -0
  72. package/dist/dashboard/assets/dialog-BK-NRr5u.js.gz +0 -0
  73. package/dist/dashboard/assets/{drawer-CqGYeOrd.js → drawer-QqPul6sC.js} +1 -1
  74. package/dist/dashboard/assets/drawer-QqPul6sC.js.gz +0 -0
  75. package/dist/dashboard/assets/entry-BMlYJVFj.js +1 -0
  76. package/dist/dashboard/assets/entry-BMlYJVFj.js.gz +0 -0
  77. package/dist/dashboard/assets/entry-D6WvojeD.js +4 -0
  78. package/dist/dashboard/assets/entry-D6WvojeD.js.gz +0 -0
  79. package/dist/dashboard/assets/entry-Dmx7gBiN.js +1 -0
  80. package/dist/dashboard/assets/entry-Dmx7gBiN.js.gz +0 -0
  81. package/dist/dashboard/assets/{formatters-D-MTJxMr.js → formatters-u7JPB5BX.js} +1 -1
  82. package/dist/dashboard/assets/formatters-u7JPB5BX.js.gz +0 -0
  83. package/dist/dashboard/assets/house-h9AZlJuT.js +1 -0
  84. package/dist/dashboard/assets/house-h9AZlJuT.js.gz +0 -0
  85. package/dist/dashboard/assets/{index-DBNPOfhV.js → index-Ko4dLRnV.js} +2 -2
  86. package/dist/dashboard/assets/index-Ko4dLRnV.js.gz +0 -0
  87. package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-CHJQwxLa.js} +1 -1
  88. package/dist/dashboard/assets/inline-CHJQwxLa.js.gz +0 -0
  89. package/dist/dashboard/assets/{input-Da2ZViWg.js → input-BlmlizVV.js} +1 -1
  90. package/dist/dashboard/assets/input-BlmlizVV.js.gz +0 -0
  91. package/dist/dashboard/assets/{layout-BXNeLw6M.js → layout-Bz93I-yE.js} +1 -1
  92. package/dist/dashboard/assets/layout-Bz93I-yE.js.gz +0 -0
  93. package/dist/dashboard/assets/{list-row-BycOrrIV.js → list-row-Ml16KCfu.js} +1 -1
  94. package/dist/dashboard/assets/list-row-Ml16KCfu.js.gz +0 -0
  95. package/dist/dashboard/assets/live-7_QpnYGu.js +1 -0
  96. package/dist/dashboard/assets/live-7_QpnYGu.js.gz +0 -0
  97. package/dist/dashboard/assets/{mutation-Rr0TIvcj.js → mutation-GU7XdEjz.js} +1 -1
  98. package/dist/dashboard/assets/mutation-GU7XdEjz.js.gz +0 -0
  99. package/dist/dashboard/assets/network-CuMDaTzT.js +1 -0
  100. package/dist/dashboard/assets/network-CuMDaTzT.js.gz +0 -0
  101. package/dist/dashboard/assets/numbers-CoqpaDMx.js +2 -0
  102. package/dist/dashboard/assets/numbers-CoqpaDMx.js.gz +0 -0
  103. package/dist/dashboard/assets/pagination-B5aOoweZ.js +1 -0
  104. package/dist/dashboard/assets/pagination-B5aOoweZ.js.gz +0 -0
  105. package/dist/dashboard/assets/providers/zai.webp +0 -0
  106. package/dist/dashboard/assets/providers/zcode.webp +0 -0
  107. package/dist/dashboard/assets/{query-keys-BloKtaXJ.js → query-keys-YSoQOUh6.js} +1 -1
  108. package/dist/dashboard/assets/{query-keys-BloKtaXJ.js.gz → query-keys-YSoQOUh6.js.gz} +0 -0
  109. package/dist/dashboard/assets/quota-DJ1QlAOq.js +1 -0
  110. package/dist/dashboard/assets/quota-DJ1QlAOq.js.gz +0 -0
  111. package/dist/dashboard/assets/routing-fnCsxgNO.js +1 -0
  112. package/dist/dashboard/assets/routing-fnCsxgNO.js.gz +0 -0
  113. package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BHqpd-bg.js} +2 -2
  114. package/dist/dashboard/assets/select-BHqpd-bg.js.gz +0 -0
  115. package/dist/dashboard/assets/settings-BxslsErn.js +1 -0
  116. package/dist/dashboard/assets/settings-BxslsErn.js.gz +0 -0
  117. package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
  118. package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
  119. package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-j7cXjgYX.js} +1 -1
  120. package/dist/dashboard/assets/stack-j7cXjgYX.js.gz +0 -0
  121. package/dist/dashboard/assets/{state-CkfdYWel.js → state-DHmEnLa2.js} +1 -1
  122. package/dist/dashboard/assets/state-DHmEnLa2.js.gz +0 -0
  123. package/dist/dashboard/assets/{switch-SYm237HG.js → switch-DmZcyTIC.js} +1 -1
  124. package/dist/dashboard/assets/switch-DmZcyTIC.js.gz +0 -0
  125. package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-CbCP4w1o.js} +1 -1
  126. package/dist/dashboard/assets/useMutation-CbCP4w1o.js.gz +0 -0
  127. package/dist/dashboard/console-backgrounds.jpg +0 -0
  128. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  129. package/dist/dashboard/index.html +2 -2
  130. package/dist/dashboard/index.html.gz +0 -0
  131. package/dist/dashboard/precompressed-assets.json +60 -59
  132. package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
  133. package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
  134. package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
  135. package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
  136. package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
  137. package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
  138. package/migrations/full-postgres/0042_add_telemetry_degenerate_stop.sql +14 -0
  139. package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
  140. package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
  141. package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
  142. package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
  143. package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
  144. package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
  145. package/migrations/lite-sqlite3/0042_add_telemetry_degenerate_stop.sql +12 -0
  146. package/package.json +4 -6
  147. package/scripts/cli/update.ts +15 -41
  148. package/src/boot/app.ts +58 -2
  149. package/src/boot/dependencies.ts +794 -732
  150. package/src/boot/lifecycle.ts +11 -12
  151. package/src/config/cooldowns.ts +34 -55
  152. package/src/config/network.ts +1 -1
  153. package/src/config/package-paths.ts +1 -1
  154. package/src/config/providers.ts +19 -14
  155. package/src/config/resources.ts +0 -5
  156. package/src/config/runtime.ts +2 -5
  157. package/src/config/spec.ts +33 -6
  158. package/src/config/usage.ts +27 -0
  159. package/src/console/api-keys/ban-constants.ts +38 -0
  160. package/src/console/api-keys/contracts.ts +71 -62
  161. package/src/console/api-keys/routes.ts +56 -24
  162. package/src/console/auth/access.ts +4 -4
  163. package/src/console/auth/account-reset.ts +1 -1
  164. package/src/console/auth/audit-recorder.ts +1 -1
  165. package/src/console/auth/lockout.ts +7 -3
  166. package/src/console/auth/row-coercion.ts +57 -12
  167. package/src/console/auth/session-resolver.ts +1 -1
  168. package/src/console/auth/session-service.ts +8 -2
  169. package/src/console/auth/session.ts +37 -31
  170. package/src/console/auth/setup-service.ts +4 -3
  171. package/src/console/auth/user-store.ts +1 -1
  172. package/src/console/backup/9router-map.ts +0 -3
  173. package/src/console/backup/contracts.ts +9 -9
  174. package/src/console/backup/export-endpoint.ts +5 -6
  175. package/src/console/backup/nine-router.ts +1 -7
  176. package/src/console/backup/routes.ts +29 -33
  177. package/src/console/backup/service.ts +468 -468
  178. package/src/console/backup/store.ts +47 -29
  179. package/src/console/backup/validate.ts +11 -1
  180. package/src/console/cli-tools/contracts.ts +43 -299
  181. package/src/console/cli-tools/fs-ops.ts +29 -0
  182. package/src/console/cli-tools/injectors/claude.ts +3 -3
  183. package/src/console/cli-tools/injectors/codex.ts +181 -181
  184. package/src/console/cli-tools/injectors/driver.ts +150 -247
  185. package/src/console/cli-tools/injectors/kilo.ts +146 -21
  186. package/src/console/cli-tools/injectors/opencode.ts +176 -153
  187. package/src/console/cli-tools/routes.ts +7 -1
  188. package/src/console/cli-tools/service.ts +8 -7
  189. package/src/console/cli-tools/store.ts +2 -2
  190. package/src/console/console-router.ts +32 -0
  191. package/src/console/dashboard-assets.ts +9 -9
  192. package/src/console/domain-registration.ts +16 -2
  193. package/src/console/inferhub/client.ts +0 -7
  194. package/src/console/inferhub/key-store.ts +1 -1
  195. package/src/console/inferhub/normalize.ts +2 -2
  196. package/src/console/inferhub/routes.ts +1 -1
  197. package/src/console/inferhub/types.ts +1 -1
  198. package/src/console/observability/contracts.ts +7 -1
  199. package/src/console/observability/live.ts +31 -18
  200. package/src/console/observability/logs.ts +1 -1
  201. package/src/console/observability/sse.ts +62 -8
  202. package/src/console/observability/store.ts +23 -4
  203. package/src/console/providers/catalog/catalog-projections.ts +1 -1
  204. package/src/console/providers/catalog/contracts.ts +39 -0
  205. package/src/console/providers/catalog/model-operations.ts +1 -1
  206. package/src/console/providers/catalog/provider-operations.ts +95 -17
  207. package/src/console/providers/catalog/public-model-store.ts +0 -0
  208. package/src/console/providers/catalog/routes.ts +27 -3
  209. package/src/console/providers/catalog/store.ts +147 -8
  210. package/src/console/providers/detail/routes.ts +1 -1
  211. package/src/console/providers/oauth/callback-listener.ts +100 -18
  212. package/src/console/providers/oauth/routes.ts +92 -13
  213. package/src/console/quota/account-quota-global.ts +41 -3
  214. package/src/console/quota/account-quota-shared.ts +10 -3
  215. package/src/console/quota/account-quota-tenant.ts +259 -66
  216. package/src/console/quota/daily-growth-job.ts +308 -0
  217. package/src/console/quota/native-identity.ts +2 -2
  218. package/src/console/quota/quota-view.ts +1 -1
  219. package/src/console/remote-support/routes.ts +1 -1
  220. package/src/console/remote-support/service.ts +2 -2
  221. package/src/console/routing/model/contracts.ts +1 -1
  222. package/src/console/routing/pools/contracts.ts +2 -2
  223. package/src/console/routing/pools/import-parse.ts +3 -3
  224. package/src/console/routing/pools/relay-deploy.ts +3 -3
  225. package/src/console/settings/contracts.ts +29 -2
  226. package/src/console/settings/store.ts +20 -0
  227. package/src/console/share/share-router.ts +100 -32
  228. package/src/console/share/share-stats.ts +11 -13
  229. package/src/console/share/share-usage.ts +1 -1
  230. package/src/console/shared/errors.ts +2 -2
  231. package/src/console/shared/object.ts +18 -0
  232. package/src/console/shared/read-through-cache.ts +4 -4
  233. package/src/console/shared/transaction.ts +14 -0
  234. package/src/console/system-prompt/contracts.ts +89 -12
  235. package/src/console/system-prompt/routes.ts +98 -45
  236. package/src/console/updates/apply-update.ts +244 -0
  237. package/src/console/updates/routes.ts +252 -97
  238. package/src/main.ts +11 -5
  239. package/src/network/http2-bidi.ts +1 -1
  240. package/src/network/ip-utils.ts +298 -0
  241. package/src/network/outbound-fetch.ts +1 -1
  242. package/src/network/pool/agent.ts +7 -6
  243. package/src/network/pool/byte-accounting.ts +1 -1
  244. package/src/network/pool/resolver.ts +16 -12
  245. package/src/network/pool/selector.ts +150 -136
  246. package/src/network/pool-health-machine.ts +1 -1
  247. package/src/network/rate-limit-verdict.ts +1 -1
  248. package/src/network/retry.ts +1 -1
  249. package/src/network/ssrf.ts +20 -71
  250. package/src/observability/event-log.ts +9 -2
  251. package/src/observability/event-query.ts +61 -291
  252. package/src/observability/log-sanitize.ts +1 -1
  253. package/src/observability/metrics.ts +4 -4
  254. package/src/observability/payload-capture.ts +6 -5
  255. package/src/observability/payload-store.ts +1 -1
  256. package/src/observability/runtime-metrics.ts +1 -1
  257. package/src/observability/telemetry-buffer.ts +19 -3
  258. package/src/observability/telemetry-reconciliation.ts +3 -3
  259. package/src/observability/token-speed.ts +1 -1
  260. package/src/persistence/connection-url.ts +1 -1
  261. package/src/persistence/db-handle.ts +1 -1
  262. package/src/persistence/db-pg.ts +2 -2
  263. package/src/persistence/db-sqlite.ts +3 -3
  264. package/src/persistence/dialect.ts +5 -1
  265. package/src/persistence/readiness.ts +1 -1
  266. package/src/persistence/redis.ts +1 -1
  267. package/src/persistence/schema.ts +121 -40
  268. package/src/persistence/shared-cache.ts +2 -2
  269. package/src/persistence/sort-order.ts +1 -1
  270. package/src/persistence/stores/api-key-store.ts +29 -2
  271. package/src/persistence/stores/share-store.ts +20 -8
  272. package/src/persistence/system-prompt-store.ts +63 -18
  273. package/src/persistence/tenant-preferences.ts +1 -1
  274. package/src/persistence/ttl-cache.ts +3 -3
  275. package/src/persistence/usage-flush.ts +7 -2
  276. package/src/protocol/canonical-model.ts +1 -1
  277. package/src/protocol/codecs.ts +6 -10
  278. package/src/protocol/dsml.ts +8 -125
  279. package/src/protocol/image-clamp.ts +2 -2
  280. package/src/protocol/reasoning-text.ts +1 -1
  281. package/src/protocol/reasoning.ts +7 -52
  282. package/src/protocol/registry.ts +50 -15
  283. package/src/protocol/request/chat.ts +46 -19
  284. package/src/protocol/request/codex.ts +1 -1
  285. package/src/protocol/request/messages.ts +46 -14
  286. package/src/protocol/request/responses.ts +19 -10
  287. package/src/protocol/response/chat.ts +25 -10
  288. package/src/protocol/response/codex.ts +1 -1
  289. package/src/protocol/response/messages.ts +1 -1
  290. package/src/protocol/response/omp-tool-call-markup.ts +1 -1
  291. package/src/protocol/response/responses.ts +1 -1
  292. package/src/protocol/sse-decoder.ts +50 -1
  293. package/src/protocol/stop-reason.ts +2 -2
  294. package/src/protocol/think-split.ts +347 -0
  295. package/src/protocol/translation/attachment-integrity.ts +3 -3
  296. package/src/protocol/translation/cache-controls.ts +8 -20
  297. package/src/protocol/translation/capabilities.ts +6 -6
  298. package/src/protocol/translation/dialect/deepseek.ts +10 -0
  299. package/src/protocol/translation/dialect/inband.ts +39 -0
  300. package/src/protocol/translation/dialect/model-thinking.ts +89 -0
  301. package/src/protocol/translation/dialect/qwen.ts +114 -0
  302. package/src/protocol/translation/dialect/resolver.ts +83 -0
  303. package/src/protocol/translation/dialect/rules.ts +93 -0
  304. package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
  305. package/src/protocol/translation/dialect/types.ts +58 -0
  306. package/src/protocol/translation/quirks.ts +18 -4
  307. package/src/protocol/translation/thinking.ts +12 -252
  308. package/src/protocol/translation/tool-id.ts +3 -3
  309. package/src/protocol/translation/tool-repair.ts +1 -1
  310. package/src/protocol/upstream/post-json.ts +6 -1
  311. package/src/providers/adapters/compatible-adapter.ts +71 -4
  312. package/src/providers/authentication/jwt-validator.ts +0 -5
  313. package/src/providers/authentication/oauth-client.ts +254 -253
  314. package/src/providers/authentication/oauth-flow-store.ts +42 -7
  315. package/src/providers/bundled-discovery-providers.ts +6 -30
  316. package/src/providers/configured-openai-providers.ts +82 -97
  317. package/src/providers/default-registry.ts +35 -37
  318. package/src/providers/discovery/catalog/catalog-format.ts +13 -2
  319. package/src/providers/discovery/discovery-types.ts +0 -1
  320. package/src/providers/discovery/openai-model-discovery.ts +2 -2
  321. package/src/providers/discovery/probe-phases.ts +48 -13
  322. package/src/providers/discovery/probing-service.ts +6 -8
  323. package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
  324. package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
  325. package/src/providers/integrations/antigravity/antigravity-protocol.ts +88 -28
  326. package/src/providers/integrations/antigravity/antigravity-quota.ts +18 -6
  327. package/src/providers/integrations/antigravity/antigravity.ts +22 -13
  328. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
  329. package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
  330. package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
  331. package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
  332. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
  333. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
  334. package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
  335. package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
  336. package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
  337. package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
  338. package/src/providers/integrations/claude/claude-cch.ts +148 -148
  339. package/src/providers/integrations/claude/fallback-credit.ts +3 -7
  340. package/src/providers/integrations/cline/cline.ts +1 -1
  341. package/src/providers/integrations/codex/codex-device-code.ts +101 -101
  342. package/src/providers/integrations/codex/codex-oauth.ts +0 -1
  343. package/src/providers/integrations/commandcode/commandcode.ts +75 -115
  344. package/src/providers/integrations/commandcode/quota.ts +131 -51
  345. package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
  346. package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
  347. package/src/providers/integrations/cursor/cursor-request.ts +0 -87
  348. package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
  349. package/src/providers/integrations/cursor/cursor.ts +35 -3
  350. package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
  351. package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
  352. package/src/providers/integrations/factory/factory.ts +9 -9
  353. package/src/providers/integrations/github/github-discovery.ts +70 -12
  354. package/src/providers/integrations/github/github-oauth.ts +184 -14
  355. package/src/providers/integrations/github/github.ts +134 -26
  356. package/src/providers/integrations/grok/grok-oauth.ts +261 -261
  357. package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
  358. package/src/providers/integrations/grok/grok-quota.ts +16 -7
  359. package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
  360. package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
  361. package/src/providers/integrations/grok/grok.ts +86 -36
  362. package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
  363. package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
  364. package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
  365. package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
  366. package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
  367. package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
  368. package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
  369. package/src/providers/integrations/kiro/kiro-request.ts +8 -11
  370. package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
  371. package/src/providers/integrations/kiro/kiro.ts +80 -68
  372. package/src/providers/integrations/muse/muse-oauth.ts +0 -1
  373. package/src/providers/integrations/muse/muse-quota.ts +0 -4
  374. package/src/providers/integrations/opencode/fingerprint.ts +7 -5
  375. package/src/providers/integrations/opencode/provider.ts +17 -24
  376. package/src/providers/integrations/qoder/qoder-catalog.ts +94 -11
  377. package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
  378. package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
  379. package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
  380. package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
  381. package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
  382. package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
  383. package/src/providers/integrations/qoder/qoder.ts +422 -71
  384. package/src/providers/integrations/shared/connect.ts +0 -54
  385. package/src/providers/integrations/shared/hash.ts +15 -0
  386. package/src/providers/integrations/shared/session-cache.ts +136 -0
  387. package/src/providers/integrations/trae/trae-cache.ts +7 -87
  388. package/src/providers/integrations/trae/trae-catalog.ts +1 -6
  389. package/src/providers/integrations/trae/trae-protocol.ts +17 -8
  390. package/src/providers/integrations/trae/trae-realm.ts +0 -7
  391. package/src/providers/integrations/trae/trae.ts +51 -8
  392. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  393. package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
  394. package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
  395. package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
  396. package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
  397. package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
  398. package/src/providers/operations/account-error-classification.ts +198 -133
  399. package/src/providers/operations/account-health-service.ts +31 -39
  400. package/src/providers/operations/account-reset-service.ts +58 -1
  401. package/src/providers/operations/byok-wire-profile.ts +19 -15
  402. package/src/providers/operations/cli-platform.ts +31 -5
  403. package/src/providers/operations/client-version-resolver.ts +4 -6
  404. package/src/providers/operations/client-versions.ts +10 -7
  405. package/src/providers/operations/provider-catalog-seeder.ts +2 -0
  406. package/src/providers/operations/provider-catalog-service.ts +18 -2
  407. package/src/providers/operations/provider-credential-service.ts +19 -2
  408. package/src/providers/provider-contracts.ts +18 -7
  409. package/src/providers/provider-metadata.ts +17 -2
  410. package/src/providers/provider-model-definition.ts +22 -1
  411. package/src/providers/provider-probe.ts +4 -2
  412. package/src/providers/provider-usage.ts +50 -19
  413. package/src/providers/quota/cache.ts +29 -0
  414. package/src/providers/quota/quota-contracts.ts +4 -0
  415. package/src/providers/quota/refresh.ts +27 -4
  416. package/src/providers/quota/snapshot.ts +94 -0
  417. package/src/providers/search/search-provider.ts +1 -3
  418. package/src/providers/search/search-providers.ts +2 -1
  419. package/src/security/abuse.ts +4 -4
  420. package/src/security/admission/service.ts +13 -6
  421. package/src/security/admission/ttl.ts +61 -61
  422. package/src/security/api-key-auth.ts +17 -3
  423. package/src/security/client-router-fingerprint.ts +4 -4
  424. package/src/security/credential-codec.ts +3 -3
  425. package/src/security/csrf.ts +2 -2
  426. package/src/security/ip-boundary.ts +16 -189
  427. package/src/security/model-access-rule.ts +1 -1
  428. package/src/security/outbound-headers.ts +18 -0
  429. package/src/shared/invoke-guard.ts +47 -0
  430. package/src/transport/contracts.ts +13 -4
  431. package/src/transport/dispatch/attempt-finalize.ts +70 -22
  432. package/src/transport/dispatch/attempt-loop.ts +22 -0
  433. package/src/transport/dispatch/capture-policy.ts +34 -37
  434. package/src/transport/dispatch/empty-stream.ts +23 -20
  435. package/src/transport/dispatch/generation.ts +25 -45
  436. package/src/transport/dispatch/native-shared.ts +127 -0
  437. package/src/transport/dispatch/proxy-request.ts +3 -1
  438. package/src/transport/dispatch/responses-compact.ts +25 -46
  439. package/src/transport/dispatch/streaming/encoder.ts +18 -72
  440. package/src/transport/dispatch/streaming/finalize.ts +2 -2
  441. package/src/transport/dispatch/streaming/stream.ts +7 -3
  442. package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
  443. package/src/transport/dispatch/systemone.ts +20 -48
  444. package/src/transport/dispatch/token-count.ts +41 -38
  445. package/src/transport/dispatch/websearch.ts +19 -45
  446. package/src/transport/drain-endpoint.ts +1 -1
  447. package/src/transport/failure-policy.ts +21 -1
  448. package/src/transport/guards/auth-guard.ts +0 -6
  449. package/src/transport/guards/body-policy.ts +3 -3
  450. package/src/transport/guards/error-lifecycle.ts +4 -0
  451. package/src/transport/guards/headroom-guard.ts +1 -1
  452. package/src/transport/guards/pipeline.ts +1 -1
  453. package/src/transport/guards/request-context.ts +12 -17
  454. package/src/transport/request/preparer.ts +286 -7
  455. package/src/transport/request/rtk/compress-request.ts +3 -3
  456. package/src/transport/request/rtk/rtk-constants.ts +2 -2
  457. package/src/transport/request/rtk/rtk-filters.ts +8 -8
  458. package/src/transport/request/state.ts +7 -13
  459. package/src/transport/request/system-prompt-injection.ts +74 -11
  460. package/src/transport/request/tenant-preferences.ts +22 -0
  461. package/src/transport/routing/candidate-index.ts +2 -2
  462. package/src/transport/routing/round-robin.ts +1 -1
  463. package/src/transport/routing/route-catalog.ts +17 -18
  464. package/src/transport/routing/route-model.ts +126 -33
  465. package/src/transport/routing/router.ts +159 -37
  466. package/src/transport/shutdown-notice.ts +2 -2
  467. package/src/transport/surface/adapters.ts +3 -3
  468. package/src/transport/surface/chat/encode.ts +7 -7
  469. package/src/transport/surface/chat/parse.ts +7 -7
  470. package/src/transport/surface/completion.ts +2 -2
  471. package/src/transport/surface/content-parts.ts +1 -1
  472. package/src/transport/surface/dialects.ts +2 -2
  473. package/src/transport/surface/messages/parse.ts +3 -3
  474. package/src/transport/surface/reasoning-summary.ts +9 -14
  475. package/src/transport/surface/responses/adapter.ts +1 -1
  476. package/src/transport/surface/responses/errors.ts +0 -9
  477. package/src/transport/vision-handoff-cache.ts +58 -0
  478. package/src/transport/vision-handoff.ts +431 -0
  479. package/src/workers/account-identity-sweep.ts +2 -2
  480. package/src/workers/buddy-growth-tasks.ts +392 -346
  481. package/src/workers/daily-checkin.ts +102 -49
  482. package/src/workers/maintenance-lease.ts +2 -35
  483. package/src/workers/oauth-refresh-sweep.ts +8 -1
  484. package/src/workers/quota-refresh-sweep.ts +120 -82
  485. package/src/workers/scheduler.ts +67 -4
  486. package/src/workers/sweep-runner.ts +24 -5
  487. package/src/workers/zcode-gift-claim.ts +108 -0
  488. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
  489. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
  490. package/dist/dashboard/assets/BannedPage-ChG5svFb.js +0 -1
  491. package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
  492. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js +0 -1
  493. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
  494. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js +0 -1
  495. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
  496. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
  497. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
  498. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
  499. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
  500. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js +0 -1
  501. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
  502. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
  503. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
  504. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js +0 -1
  505. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
  506. package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
  507. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
  508. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
  509. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
  510. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
  511. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
  512. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  513. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
  514. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
  515. package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
  516. package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
  517. package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
  518. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
  519. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
  520. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js +0 -1
  521. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
  522. package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
  523. package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
  524. package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
  525. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js +0 -1
  526. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
  527. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
  528. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
  529. package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
  530. package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
  531. package/dist/dashboard/assets/app-BayTTy01.js +0 -9
  532. package/dist/dashboard/assets/app-BayTTy01.js.gz +0 -0
  533. package/dist/dashboard/assets/app-a159k0ub.css +0 -2
  534. package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
  535. package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
  536. package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
  537. package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
  538. package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
  539. package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
  540. package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
  541. package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
  542. package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
  543. package/dist/dashboard/assets/dialog-8fiE6tec.js +0 -1
  544. package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
  545. package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
  546. package/dist/dashboard/assets/entry-BSAsYsmV.js +0 -1
  547. package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
  548. package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
  549. package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
  550. package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
  551. package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
  552. package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
  553. package/dist/dashboard/assets/github-badge-CPK47xQx.js +0 -1
  554. package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
  555. package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
  556. package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
  557. package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
  558. package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
  559. package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
  560. package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
  561. package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
  562. package/dist/dashboard/assets/mutation-Rr0TIvcj.js.gz +0 -0
  563. package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
  564. package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
  565. package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
  566. package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
  567. package/dist/dashboard/assets/providers/zai-coding-plan.svg +0 -6
  568. package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
  569. package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
  570. package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
  571. package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
  572. package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
  573. package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
  574. package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
  575. package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
  576. package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
  577. package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
  578. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
  579. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  580. package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
  581. package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
  582. package/src/console/cli-tools/injectors/cline.ts +0 -110
  583. package/src/console/cli-tools/injectors/copilot.ts +0 -108
  584. package/src/console/cli-tools/injectors/cowork.ts +0 -64
  585. package/src/console/cli-tools/injectors/deepseek-tui.ts +0 -85
  586. package/src/console/cli-tools/injectors/droid.ts +0 -96
  587. package/src/console/cli-tools/injectors/grok-build.ts +0 -70
  588. package/src/console/cli-tools/injectors/hermes.ts +0 -101
  589. package/src/console/cli-tools/injectors/jcode.ts +0 -115
  590. package/src/console/cli-tools/injectors/openclaw.ts +0 -161
  591. package/src/network/response-headers.ts +0 -39
  592. package/src/protocol/response/dsml.ts +0 -38
  593. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
  594. /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
  595. /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
@@ -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
+ }
@@ -272,4 +272,3 @@ export class CodexOAuthClient extends OAuthDeviceFlow {
272
272
  }
273
273
 
274
274
  export const codexOAuthClient = new CodexOAuthClient();
275
- export { exchangeCodeForToken };
@@ -6,20 +6,22 @@ import { canContainToolResult, joinTextParts, toolCallParts, toolResultParts } f
6
6
  import {
7
7
  classifyUpstreamError,
8
8
  extractUpstreamMessage,
9
+ mapUpstreamHttpError,
9
10
  upstreamErrorIdentifier,
10
11
  } from "../../../transport/failure-policy";
11
- import { createApiKeyAdapter } from "../../configured-provider";
12
- import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason, ContentPart } from "../../../protocol/canonical-model";
12
+ import { postUpstreamJson } from "../../../protocol/upstream/post-json";
13
+ import type { CanonicalEvent, CanonicalRequest, CanonicalStopReason, ContentPart, UsageRecord } from "../../../protocol/canonical-model";
13
14
  import { isRecord, readNumber, readString, resolveImageSource, splitDataUrl } from "../../../protocol/codecs";
14
15
  import { usageFromProvider } from "../../provider-usage";
15
16
  import { readCredentialSecret, type ProviderDispatchTarget, type ProviderAdapter, type ProviderDispatchContext } from "../../provider-contracts";
17
+ import { abortGatewayError } from "../../operations/upstream-deadline";
16
18
  import { providerBaseUrl } from "../../provider-metadata";
17
19
  import { defineModel } from "../../provider-model-definition";
18
20
  import type { ModelDefinition } from "../../provider-model-definition";
19
21
  import {
20
22
  getCommandCodeVersion,
21
23
  } from "../../operations/client-versions";
22
- import { MimoThinkSplitter } from "../xiaomi-mimo/think-stream";
24
+ import { ThinkSplitter } from "../../../protocol/think-split";
23
25
  export const COMMANDCODE_PROVIDER_ID = "commandcode" as const;
24
26
  export const COMMANDCODE_BASE_URL = providerBaseUrl("commandcode");
25
27
  /**
@@ -37,10 +39,6 @@ export const COMMANDCODE_HOST = "https://api.commandcode.ai" as const;
37
39
  * generate.
38
40
  */
39
41
  export const COMMANDCODE_GENERATE_PATH = "/alpha/generate" as const;
40
- /** The three routes the Provider API serves, one per wire family. */
41
- export const COMMANDCODE_CHAT_PATH = "/chat/completions" as const;
42
- export const COMMANDCODE_RESPONSES_PATH = "/responses" as const;
43
- export const COMMANDCODE_MESSAGES_PATH = "/messages" as const;
44
42
 
45
43
  /**
46
44
  * Command Code's roster, as the Provider API publishes it.
@@ -426,7 +424,7 @@ export async function headers(sessionId: string, token: string): Promise<Record<
426
424
  }
427
425
 
428
426
 
429
- type StreamState = { toolIndexById: Map<string, number>; nextToolIndex: number; finishReason: string | undefined; usage: Record<string, unknown> | undefined; think: MimoThinkSplitter };
427
+ type StreamState = { toolIndexById: Map<string, number>; nextToolIndex: number; finishReason: string | undefined; usage: Record<string, unknown> | undefined; think: ThinkSplitter };
430
428
 
431
429
  export function ccMapFinishReason(reason: string): CanonicalStopReason {
432
430
  return reason === "length" ? "length" : reason === "tool_calls" ? "tool_use" : reason === "content_filter" ? "content_filter" : "stop";
@@ -450,7 +448,7 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
450
448
  if (!text) return [];
451
449
  const split = state.think.push(text);
452
450
  const events: CanonicalEvent[] = [];
453
- if (split.reasoning) events.push({ type: "content_delta", sequence_number: seqBase, content: { kind: "reasoning", payload: null, summary: split.reasoning } } as CanonicalEvent);
451
+ if (split.reasoning) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "reasoning", payload: null, summary: split.reasoning } } as CanonicalEvent);
454
452
  if (split.text) events.push({ type: "content_delta", sequence_number: seqBase, content: { kind: "text", text: split.text } } as CanonicalEvent);
455
453
  return events;
456
454
  }
@@ -485,9 +483,11 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
485
483
  if (type === "finish") {
486
484
  const reason = state.finishReason ?? readString(event, "finishReason") ?? "stop";
487
485
  const canonicalReason = ccMapFinishReason(reason);
488
- const events: CanonicalEvent[] = [
489
- { type: "terminal", sequence_number: seqBase, state: "complete", stop_reason: canonicalReason, provider_stop_reason: reason } as CanonicalEvent,
490
- ];
486
+ const rest = state.think.flush();
487
+ const events: CanonicalEvent[] = [];
488
+ if (rest.reasoning) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } });
489
+ if (rest.text) events.push({ type: "content_delta", sequence_number: seqBase++, content: { kind: "text", text: rest.text } });
490
+ let usage: UsageRecord | undefined;
491
491
  if (state.usage) {
492
492
  const prompt = readNumber(state.usage, "promptTokens") ?? readNumber(state.usage, "inputTokens") ?? 0;
493
493
  const completion = readNumber(state.usage, "completionTokens") ?? readNumber(state.usage, "outputTokens") ?? 0;
@@ -500,9 +500,9 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
500
500
  cached_tokens: cached,
501
501
  cache_creation_input_tokens: readNumber(state.usage, "cacheWriteTokens") ?? undefined,
502
502
  } as unknown as Record<string, unknown>);
503
- // Append usage to terminal
504
- (events[0] as unknown as Record<string, unknown>)["usage"] = usageRecord;
503
+ usage = usageRecord;
505
504
  }
505
+ events.push({ type: "terminal", sequence_number: seqBase, state: "complete", stop_reason: canonicalReason, provider_stop_reason: reason, ...(usage === undefined ? {} : { usage }) });
506
506
  return events;
507
507
  }
508
508
  if (type === "error") {
@@ -546,30 +546,29 @@ export function transformLine(line: string, state: StreamState, seqBase: number)
546
546
  return [];
547
547
  }
548
548
 
549
- /** NDJSON transform — beta-style simple loop + signal-aware read for abort/timeout propagation. */
550
- export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal: AbortSignal): AsyncIterable<CanonicalEvent> {
549
+ /** NDJSON decoding uses the request signal after the opening deadline is released. */
550
+ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal: AbortSignal, model: string): AsyncIterable<CanonicalEvent> {
551
551
  const reader = body.getReader();
552
552
  const decoder = new TextDecoder();
553
- const state: StreamState = { toolIndexById: new Map(), nextToolIndex: 0, finishReason: undefined, usage: undefined, think: new MimoThinkSplitter() };
553
+ const state: StreamState = { toolIndexById: new Map(), nextToolIndex: 0, finishReason: undefined, usage: undefined, think: new ThinkSplitter() };
554
554
  let buffer = "";
555
- let hasTerminal = false;
556
555
  let seq = 1;
557
- // initial response_start
558
- yield { type: "response_start", sequence_number: seq++, model: "commandcode" } as CanonicalEvent;
559
556
 
560
- const readWithAbort = (): Promise<{ done: boolean; value?: Uint8Array }> => {
561
- if (signal.aborted) throw new GatewayError("transport_closed", 499, "Command Code stream aborted (request {requestId}). Send it again whenever ready 🙃");
562
- const { promise, resolve, reject } = Promise.withResolvers<{ done: boolean; value?: Uint8Array }>() as unknown as { promise: Promise<{ done: boolean; value?: Uint8Array }>; resolve: (v: unknown) => void; reject: (e: unknown) => void };
563
- const onAbort = (): void => {
564
- if (signal.aborted) reject(new GatewayError("transport_closed", 499, "Command Code stream aborted (request {requestId}). Send it again whenever ready 🙃"));
565
- else reject(new GatewayError("platform_unavailable", 502, "Command Code stream error (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream"));
566
- };
557
+ const readWithAbort = async (): Promise<{ readonly done: boolean; readonly value?: Uint8Array | undefined }> => {
558
+ if (signal.aborted) throw signal.reason;
559
+ const { promise, resolve, reject } = Promise.withResolvers<{ readonly done: boolean; readonly value?: Uint8Array | undefined }>();
560
+ const onAbort = (): void => reject(signal.reason);
567
561
  signal.addEventListener("abort", onAbort, { once: true });
568
- void reader.read().then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
569
- return promise;
562
+ void reader.read().then(resolve, reject);
563
+ try {
564
+ return await promise;
565
+ } finally {
566
+ signal.removeEventListener("abort", onAbort);
567
+ }
570
568
  };
571
569
 
572
570
  try {
571
+ yield { type: "response_start", sequence_number: seq++, model };
573
572
  while (true) {
574
573
  const { done, value } = await readWithAbort();
575
574
  if (done) break;
@@ -579,20 +578,11 @@ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal:
579
578
  const line = buffer.slice(0, nl).trim();
580
579
  buffer = buffer.slice(nl + 1);
581
580
  if (line) {
582
- let evs: CanonicalEvent[] = [];
583
- try {
584
- evs = transformLine(line, state, seq);
585
- } catch (e) {
586
- throw e;
587
- }
588
- for (const ev of evs) {
589
- // Strictly increasing per line, in emission order: the Responses
590
- // surface throws on any non-monotonic sequence mid-stream, after
591
- // partial bytes are already flushed. No special-casing for
592
- // dual-event lines — order is order.
593
- (ev as unknown as Record<string, unknown>)["sequence_number"] = seq++;
594
- if (ev.type === "terminal") hasTerminal = true;
595
- yield ev;
581
+ const events = transformLine(line, state, seq);
582
+ seq += events.length;
583
+ for (const event of events) {
584
+ yield event;
585
+ if (event.type === "terminal") return;
596
586
  }
597
587
  }
598
588
  nl = buffer.indexOf("\n");
@@ -601,101 +591,71 @@ export async function* transformNdjson(body: ReadableStream<Uint8Array>, signal:
601
591
  buffer += decoder.decode();
602
592
  const tail = buffer.trim();
603
593
  if (tail) {
604
- for (const ev of transformLine(tail, state, seq)) {
605
- if (ev.type === "terminal") hasTerminal = true;
606
- (ev as unknown as Record<string, unknown>)["sequence_number"] = seq++;
607
- yield ev;
594
+ const events = transformLine(tail, state, seq);
595
+ seq += events.length;
596
+ for (const event of events) {
597
+ yield event;
598
+ if (event.type === "terminal") return;
608
599
  }
609
600
  }
610
601
  const rest = state.think.flush();
611
- if (rest.reasoning) yield { type: "content_delta", sequence_number: seq++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } } as CanonicalEvent;
612
- if (rest.text) yield { type: "content_delta", sequence_number: seq++, content: { kind: "text", text: rest.text } } as CanonicalEvent;
613
- if (!hasTerminal) {
614
- // NDJSON ended with no terminal envelope: truncated, never complete.
615
- yield { type: "terminal", sequence_number: seq++, state: "failed", stop_reason: ccMapFinishReason(state.finishReason ?? "stop"), provider_stop_reason: state.finishReason ?? "stop" } as CanonicalEvent;
616
- }
602
+ if (rest.reasoning) yield { type: "content_delta", sequence_number: seq++, content: { kind: "reasoning", payload: null, summary: rest.reasoning } };
603
+ if (rest.text) yield { type: "content_delta", sequence_number: seq++, content: { kind: "text", text: rest.text } };
604
+ // NDJSON ended with no terminal envelope: truncated, never complete.
605
+ yield { type: "terminal", sequence_number: seq++, state: "failed", stop_reason: ccMapFinishReason(state.finishReason ?? "stop"), provider_stop_reason: state.finishReason ?? "stop" };
617
606
  } finally {
618
- try {
619
- reader.releaseLock?.();
620
- } catch {
621
- // Best-effort reader unlock during stream cleanup.
622
- }
623
- void reader.cancel().catch(() => {});
607
+ void reader.cancel(signal.reason).catch(() => {});
608
+ reader.releaseLock();
624
609
  }
625
610
  }
626
611
 
627
- // CommandCode model catalog.
628
-
629
-
630
-
631
- // ProviderAdapter — the Provider API serves three wires, so dispatch is the
632
- // shared OpenAI-compatible adapter rather than one bespoke NDJSON reader.
633
- //
634
- // Generation goes to `/alpha/generate` for every model: that is the CLI's own
635
- // surface and the one the reference client calls, and it does not vary the path
636
- // by the wire a model row declares. `/provider/v1` is the catalog surface — it
637
- // answers `GET /models`, which discovery still uses — so a completion posted to
638
- // `/provider/v1/<wire>` was reaching a surface the CLI never calls to
639
- // generate. The wire family still decides how the body is shaped; only the
640
- // endpoint is shared.
612
+ // The CLI generation surface takes a proprietary envelope and returns NDJSON
613
+ // regardless of the catalog row's wire family.
641
614
 
642
615
  interface CommandCodeAdapterOptions {
643
616
  readonly fetch?: typeof fetch;
644
617
  }
645
618
 
646
- function commandCodeIdentityHeaders(_token: string): Record<string, string> {
647
- return {
648
- "x-command-code-version": getCommandCodeVersion(),
649
- "x-cli-environment": "production",
650
- "x-taste-learning": "true",
651
- "x-project-slug": "cartethyia",
652
- "user-agent": "cli",
653
- // Per-request, as the CLI client sends it. The upstream expects a session
654
- // id on every generate call and the reference client mints a fresh UUID
655
- // for each one; sending a constant correlated requests that had nothing
656
- // to do with each other.
657
- "x-session-id": randomUUID(),
658
- };
659
- }
660
-
661
- function providerApiAdapter(options: CommandCodeAdapterOptions): ProviderAdapter {
662
- return createApiKeyAdapter(
663
- {
664
- provider_id: COMMANDCODE_PROVIDER_ID,
665
- // The host, not the `/provider/v1` base: generation is a sibling
666
- // surface, so every wire resolves under the host and the path below
667
- // supplies the CLI endpoint. Nesting it under `/provider/v1` produced a
668
- // URL that is neither surface.
669
- base_url: COMMANDCODE_HOST,
670
- endpoint_paths_by_wire_family: {
671
- // Every wire, not one per family: the reference client sends all
672
- // generation to `/alpha/generate` regardless of the row's declared
673
- // wire, so dispatch must not fan out across three paths.
674
- chat: COMMANDCODE_GENERATE_PATH,
675
- responses: COMMANDCODE_GENERATE_PATH,
676
- messages: COMMANDCODE_GENERATE_PATH,
677
- },
678
- buildExtraHeaders: async (context: ProviderDispatchContext) =>
679
- commandCodeIdentityHeaders(await readCredentialSecret(context.credential, "Command Code bearer token is required")),
680
- },
681
- options.fetch,
682
- );
683
- }
684
619
 
685
620
  class CommandCodeAdapter implements ProviderAdapter {
686
621
  readonly provider_id = COMMANDCODE_PROVIDER_ID;
687
- private readonly inner: ProviderAdapter;
622
+ private readonly fetchFn: typeof fetch;
688
623
 
689
624
  constructor(options: CommandCodeAdapterOptions = {}) {
690
- this.inner = providerApiAdapter(options);
625
+ this.fetchFn = options.fetch ?? globalThis.fetch;
691
626
  }
692
627
 
693
- dispatch(
628
+ async *dispatch(
694
629
  request: CanonicalRequest,
695
630
  candidate: ProviderDispatchTarget,
696
631
  context: ProviderDispatchContext,
697
632
  ): AsyncIterable<CanonicalEvent> {
698
- return this.inner.dispatch(request, candidate, context);
633
+ const token = readCredentialSecret(context.credential, "Command Code bearer token is required");
634
+ const sessionId = randomUUID();
635
+ const payload = buildRequest(candidate.model_id, {
636
+ messages: request.messages,
637
+ tools: (request.tools ?? []).map(({ name, description, jsonSchema }) => ({ name, description, jsonSchema })),
638
+ maxOutputTokens: request.generation_controls.max_output_tokens ?? request.generation_controls.max_tokens ?? request.generation_controls.max_completion_tokens ?? null,
639
+ temperature: request.generation_controls.temperature ?? null,
640
+ topP: request.generation_controls.top_p ?? null,
641
+ reasoningEffort: request.reasoning?.effort ?? null,
642
+ }, sessionId, [request.system, request.instructions].map((parts) => joinTextParts(parts ?? [])).filter(Boolean).join("\n"));
643
+ const { res, release } = await postUpstreamJson(
644
+ `${COMMANDCODE_HOST}${COMMANDCODE_GENERATE_PATH}`,
645
+ await headers(sessionId, token),
646
+ payload,
647
+ context,
648
+ context.outbound_fetch ?? this.fetchFn,
649
+ );
650
+ release();
651
+ try {
652
+ if (!res.ok) throw await mapUpstreamHttpError(res, COMMANDCODE_PROVIDER_ID);
653
+ if (!res.body) throw new GatewayError("platform_unavailable", 502, "Command Code returned an empty stream (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
654
+ // NDJSON carries no model identity; use the selected model, not the provider id.
655
+ yield* transformNdjson(res.body, context.abort_signal, candidate.model_id);
656
+ } catch (error: unknown) {
657
+ throw abortGatewayError({ signal: context.abort_signal, release }, error) ?? error;
658
+ }
699
659
  }
700
660
  }
701
661