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
@@ -24,7 +24,7 @@ export interface DsmlToolCall {
24
24
  readonly arguments: string;
25
25
  }
26
26
 
27
- export interface DsmlRecovery {
27
+ interface DsmlRecovery {
28
28
  readonly calls: readonly DsmlToolCall[];
29
29
  readonly clean: string;
30
30
  }
@@ -63,7 +63,7 @@ const DEFAULT_MAX_BLOCK_BYTES = 256 * 1024;
63
63
  const TOOL_NAME = /^[A-Za-z0-9_][A-Za-z0-9_.:-]{0,63}$/;
64
64
 
65
65
  /** Escapes regex metacharacters so a `|` separator is literal, not alternation. */
66
- export function escapeRegExp(value: string): string {
66
+ function escapeRegExp(value: string): string {
67
67
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
68
68
  }
69
69
 
@@ -79,7 +79,7 @@ function uuidId(_call: { readonly name: string }, _index: number, _seq: number):
79
79
  return `call_${randomUUID().replace(/-/g, "").slice(0, 16)}`;
80
80
  }
81
81
 
82
- export interface DsmlParseResult {
82
+ interface DsmlParseResult {
83
83
  readonly text: string;
84
84
  readonly calls: readonly DsmlToolCall[];
85
85
  }
@@ -306,15 +306,6 @@ function parseFuzzyDsml(text: string, options: DsmlParseOptions): DsmlRecovery {
306
306
  return { calls, clean };
307
307
  }
308
308
 
309
- /**
310
- * Recovers DSML tool calls from one plain-text string using the Qoder fuzzy
311
- * dialect. Always returns `{ calls, clean }` — no-DSML input returns the text
312
- * unchanged with no calls.
313
- */
314
- export function parseFuzzyDsmlToolCalls(text: string): DsmlRecovery {
315
- return parseFuzzyDsml(text, {});
316
- }
317
-
318
309
  /**
319
310
  * Recovers DSML tool calls from one plain-text string. The dialect is chosen
320
311
  * by `options.fuzzy`; each dialect keeps its exact public shape:
@@ -338,40 +329,3 @@ export function parseDsmlToolCalls(
338
329
  const recovered = [...first.calls, ...last.calls];
339
330
  return recovered.length === 0 ? undefined : { text: `${first.text}${last.text}`.trim(), calls: recovered };
340
331
  }
341
-
342
- /**
343
- * The holdable tail of a content chunk: a short suffix that looks like the
344
- * start of a DSML tag and may finish in the next frame. Empty when there is
345
- * nothing worth holding. Mirrors `_dsml_tail_hold` in the reference bridge.
346
- */
347
- export function dsmlTailHold(text: string): string {
348
- const at = text.lastIndexOf("<");
349
- if (at < 0 || text.length - at > 24) return "";
350
- const tail = text.slice(at);
351
- // A complete tag already — nothing to wait for.
352
- if (tail.includes(">")) return "";
353
- const body = tail.replace(/\uFF5C/g, "|").toUpperCase().slice(1).replace(/^\//, "");
354
- if (body.length === 0) return tail; // bare "<" or "</"
355
- if (!body.startsWith("|")) return "";
356
- const rest = body.slice(1);
357
- if (rest.length === 0) return tail;
358
- if ("DSML".startsWith(rest) || rest.startsWith("DSML")) return tail;
359
- return "";
360
- }
361
-
362
- const DSML_CLOSE_TAG_RE = /<\/(?:[^>]*DSML[^>]*|parameter|invoke|calls|tool_calls|function_calls)\s*>\s*$/i;
363
-
364
- /**
365
- * Removes leftover DSML closing tags from the tail of a text. Anchored to the
366
- * end and looped, so several trailing tags come off one per pass; a closing
367
- * tag in the middle of a text is not residue and is preserved.
368
- */
369
- export function stripDsmlCloseTags(text: string): string {
370
- let previous: string | null = null;
371
- let out = text.trimEnd();
372
- while (previous !== out) {
373
- previous = out;
374
- out = out.replace(DSML_CLOSE_TAG_RE, "").trimEnd();
375
- }
376
- return out;
377
- }
@@ -6,12 +6,14 @@ export type GatewayErrorCode =
6
6
  | "capability_unsupported"
7
7
  | "ambiguous_model"
8
8
  | "model_not_found"
9
+ | "model_not_allowed"
9
10
  | "upstream_not_found"
10
11
  | "context_length_exceeded"
11
12
  | "request_too_large"
12
13
  | "accounts_unavailable"
13
14
  | "accounts_rate_limited"
14
15
  | "capacity_exhausted"
16
+ | "upstream_overloaded"
15
17
  | "provider_capacity_exhausted"
16
18
  | "upstream_queued"
17
19
  | "proxy_pool_capacity_exceeded"
@@ -22,8 +24,10 @@ export type GatewayErrorCode =
22
24
  | "proxy_pool_unhealthy"
23
25
  | "invalid_pool_limits"
24
26
  | "admission_unavailable"
27
+ | "route_unavailable"
25
28
  | "slug_reserved"
26
29
  | "quota_exceeded"
30
+ | "rate_limited"
27
31
  | "authentication_failed"
28
32
  | "policy_rejected"
29
33
  | "invalid_request"
@@ -52,8 +56,7 @@ export type GatewayErrorCode =
52
56
  | "proxy_unreachable"
53
57
  | "tool_call_loop_detected"
54
58
  | "client_router_denied"
55
- | "shutting_down"
56
- | "restart_for_update";
59
+ | "shutting_down";
57
60
 
58
61
  /** Identifies which boundary produced a safe public error. */
59
62
  export type GatewayErrorOrigin = "cartethyia" | "upstream" | "network";
@@ -226,7 +229,7 @@ export function capabilityUnsupported(
226
229
  return new GatewayError(
227
230
  "capability_unsupported",
228
231
  400,
229
- `The selected route does not support capability: ${capability}`,
232
+ `The selected route does not support capability: ${capability} (request {requestId}). Drop the ${capability} part of the request, or route to a model that accepts it. Know your tools — this one just isn't in the box 🧰`,
230
233
  { capability, ...details },
231
234
  );
232
235
  }
@@ -69,7 +69,7 @@ export interface ImageClampInput {
69
69
  readonly maxBytesOverride?: number;
70
70
  }
71
71
 
72
- export interface ImageClampDecision {
72
+ interface ImageClampDecision {
73
73
  readonly action: ImageClampAction;
74
74
  readonly reason: ImageClampReason;
75
75
  /** Longest edge allowed for this image, given how many the request carries. */
@@ -96,7 +96,7 @@ export function base64DecodedByteLength(data: string): number {
96
96
  }
97
97
 
98
98
  /** The per-image longest-edge ceiling for a request carrying `imageCount` images. */
99
- export function imageClampMaxDimensionPx(imageCount: number): number {
99
+ function imageClampMaxDimensionPx(imageCount: number): number {
100
100
  return imageCount > IMAGE_CLAMP_MANY_IMAGE_COUNT
101
101
  ? IMAGE_CLAMP_MANY_IMAGE_MAX_DIMENSION_PX
102
102
  : IMAGE_CLAMP_MAX_DIMENSION_PX;
@@ -22,7 +22,7 @@ const OPENAI_ASPECT_RATIOS: Readonly<Record<string, string>> = {
22
22
  export function imagePrompt(body: Record<string, unknown>): string {
23
23
  if (typeof body.prompt === "string" && body.prompt.trim().length > 0) return body.prompt;
24
24
  if (!Array.isArray(body.messages)) {
25
- throw new GatewayError("invalid_request", 400, "prompt is required");
25
+ throw new GatewayError("invalid_request", 400, "prompt is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
26
26
  }
27
27
  const texts: string[] = [];
28
28
  for (const message of body.messages) {
@@ -41,7 +41,7 @@ export function imagePrompt(body: Record<string, unknown>): string {
41
41
  }
42
42
  }
43
43
  const prompt = texts.join("\n").trim();
44
- if (prompt.length === 0) throw new GatewayError("invalid_request", 400, "prompt is required");
44
+ if (prompt.length === 0) throw new GatewayError("invalid_request", 400, "prompt is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
45
45
  return prompt;
46
46
  }
47
47
 
@@ -1,6 +1,6 @@
1
1
  /** The reasoning-shaped part this reads. Structural, so any reasoning part —
2
2
  * including a `ContentPart` narrowed to `kind: "reasoning"` — is accepted. */
3
- export interface ReasoningTextSource {
3
+ interface ReasoningTextSource {
4
4
  readonly payload?: unknown;
5
5
  readonly summary?: string;
6
6
  readonly opaque?: boolean;
@@ -1,6 +1,7 @@
1
1
  import type { CanonicalRequest, ReasoningEffort, ReasoningIntent } from "./canonical-model";
2
2
  import { budgetToLevel } from "./translation/thinking";
3
3
  import { isRecord } from "./codecs";
4
+ import { DEEPSEEK_DEFAULT_EFFORT } from "./translation/dialect/thinking-ladder";
4
5
 
5
6
  /**
6
7
  * The effective reasoning effort for a canonical intent, deriving one from an
@@ -47,7 +48,7 @@ export function applyDeepSeekReasoning(payload: Record<string, unknown>): void {
47
48
  if (thinking === undefined) payload["thinking"] = { type: "enabled" };
48
49
  else if (type.length === 0) thinking["type"] = "enabled";
49
50
  if (typeof payload["reasoning_effort"] !== "string" || payload["reasoning_effort"].length === 0)
50
- payload["reasoning_effort"] = "high";
51
+ payload["reasoning_effort"] = DEEPSEEK_DEFAULT_EFFORT;
51
52
  }
52
53
 
53
54
  /**
@@ -151,59 +152,13 @@ export function geminiThinkingOutputFloor(reasoning: CanonicalRequest["reasoning
151
152
 
152
153
  /**
153
154
  * Minimum output budget for a caller whose requested effort the ladder could
154
- * not serve as asked.
155
+ * not serve as asked. See the module doc for why both clamp directions need it.
156
+ * Only ever raises, and only to the model's own catalog limit.
155
157
  *
156
- * A wire ladder can only serve levels the upstream accepts, so a request for
157
- * `low` may be clamped up to whatever that model offers — `hy4-preview-f`
158
- * serves `high` and nothing else — and a request for `max` may be clamped down
159
- * to it. Either way the caller sized `max_tokens` for the effort it asked for,
160
- * and effort is not free: the applied level spends its budget on reasoning
161
- * before it writes the answer, so an answer that fit in 2048 tokens of visible
162
- * text no longer fits once the reasoning share is taken out of the same 2048.
163
- *
164
- * Both directions need the floor, because the mismatch is what costs tokens,
165
- * not its sign. A caller who asked for `max` with a 2048-token answer in mind
166
- * is owed the same headroom as one who asked for `low`: the applied level is
167
- * `high` either way, and `high` reasons out of that 2048 regardless.
168
- *
169
- * The symptom this removes is a truncated answer that an agent retries from
170
- * the top — reading as a loop ("let me do / let me go / let me do it") rather
171
- * than as a short limit.
172
- *
173
- * Only ever raises, and only to the model's own catalog limit: a caller whose
174
- * effort was served exactly as asked keeps its number, and no provider is
175
- * asked for more output than it declares.
158
+ * Re-exported from `translation/dialect/model-thinking` (the canonical helper);
159
+ * this shim keeps existing importers (e.g. buddy-chat-shared) stable.
176
160
  */
177
- export function clampedEffortOutputFloor(
178
- requested: string | undefined,
179
- applied: string | undefined,
180
- modelOutputLimit: number | undefined,
181
- ): number | undefined {
182
- if (requested === undefined || applied === undefined) return undefined;
183
- const from = BUDDY_LEVEL_RANK[requested.trim().toLowerCase()];
184
- const to = BUDDY_LEVEL_RANK[applied.trim().toLowerCase()];
185
- if (from === undefined || to === undefined || from === to) return undefined;
186
- if (modelOutputLimit === undefined || !Number.isFinite(modelOutputLimit) || modelOutputLimit <= 0)
187
- return undefined;
188
- // Leave headroom instead of claiming the whole catalog limit: the caller's
189
- // number was a real preference about answer size, and the goal is to stop
190
- // truncating, not to spend the model's ceiling on every turn.
191
- return Math.max(CLAMPED_EFFORT_MIN_OUTPUT_TOKENS, Math.floor(modelOutputLimit / 2));
192
- }
193
-
194
- const CLAMPED_EFFORT_MIN_OUTPUT_TOKENS = 16_384;
195
-
196
- const BUDDY_LEVEL_RANK: Readonly<Record<string, number>> = {
197
- off: 0,
198
- none: 0,
199
- instant: 1,
200
- minimal: 2,
201
- low: 3,
202
- medium: 4,
203
- high: 5,
204
- xhigh: 6,
205
- max: 7,
206
- };
161
+ export { outputFloorFor as clampedEffortOutputFloor } from "./translation/dialect/model-thinking";
207
162
 
208
163
  /** Builds the Anthropic thinking block from canonical reasoning intent. */
209
164
  export function buildAnthropicThinkingPayload(reasoning: ReasoningIntent): Record<string, unknown> {
@@ -1,6 +1,8 @@
1
1
  import type { CanonicalEvent, CanonicalRequest, WireFamily } from "./canonical-model";
2
+ import type { DialectPolicy } from "./translation/dialect/types";
3
+ import type { ThinkingConfig } from "./translation/dialect/thinking-ladder";
2
4
 
3
- export interface CodecContext {
5
+ interface CodecContext {
4
6
  readonly isOAuth?: boolean;
5
7
  readonly sessionId?: string;
6
8
  readonly supportsPromptCaching?: boolean;
@@ -13,6 +15,16 @@ export interface CodecContext {
13
15
  * deployment default; only wire encoders that clamp images read it.
14
16
  */
15
17
  readonly maxBytesOverride?: number;
18
+ /**
19
+ * Resolved wire dialect (see `translation/dialect`). Absent = the codec's
20
+ * own default behavior (today's exact bytes).
21
+ */
22
+ readonly dialectPolicy?: DialectPolicy;
23
+ /**
24
+ * Resolved thinking config (see `translation/dialect/thinking-ladder`).
25
+ * Absent = the codec's own default behavior (today's exact clamp/ladder).
26
+ */
27
+ readonly thinking?: ThinkingConfig;
16
28
  }
17
29
 
18
30
  /**
@@ -27,7 +39,13 @@ type CodecModule =
27
39
  readonly family: "messages";
28
40
  readonly encodeWireRequest: (
29
41
  request: CanonicalRequest,
30
- options?: { isOAuth?: boolean },
42
+ options?: {
43
+ readonly isOAuth?: boolean;
44
+ readonly maxBytesOverride?: number;
45
+ readonly dialectPolicy?: DialectPolicy;
46
+ readonly thinking?: ThinkingConfig;
47
+ readonly maxOutputTokens?: number;
48
+ },
31
49
  ) => Record<string, unknown>;
32
50
  readonly decodeWireResponse: (
33
51
  json: Record<string, unknown>,
@@ -48,6 +66,8 @@ type CodecModule =
48
66
  readonly supportsPromptCaching?: boolean;
49
67
  readonly tokenLimitField?: "max_tokens" | "max_completion_tokens";
50
68
  readonly promptCacheKey?: string;
69
+ readonly dialectPolicy?: DialectPolicy;
70
+ readonly thinking?: ThinkingConfig;
51
71
  },
52
72
  ) => Record<string, unknown>;
53
73
  readonly decodeWireResponse: (
@@ -58,6 +78,7 @@ type CodecModule =
58
78
  body: ReadableStream<Uint8Array>,
59
79
  request: CanonicalRequest,
60
80
  signal?: AbortSignal,
81
+ options?: { readonly dialectPolicy?: DialectPolicy },
61
82
  ) => AsyncIterable<CanonicalEvent>;
62
83
  }
63
84
  | {
@@ -67,6 +88,9 @@ type CodecModule =
67
88
  options?: {
68
89
  readonly supportsPromptCaching?: boolean;
69
90
  readonly promptCacheKey?: string;
91
+ readonly dialectPolicy?: DialectPolicy;
92
+ readonly thinking?: ThinkingConfig;
93
+ readonly maxOutputTokens?: number;
70
94
  },
71
95
  ) => Record<string, unknown>;
72
96
  readonly decodeWireResponse: (
@@ -89,8 +113,10 @@ type CodecModule =
89
113
  *
90
114
  * The dynamic import is awaited by the caller. Wire encoding happens before the
91
115
  * upstream request is issued, so the cost is paid once, on the first request,
92
- * and is subsequently free. `preloadCodecs()` warms it during boot to remove
93
- * even that first-request delay.
116
+ * The cost is paid once, on the first request for that family, because wire
117
+ * encoding happens before the upstream request is issued. There is no preload
118
+ * at boot: no family is knowable then, and eagerly loading all three codecs
119
+ * would defeat the ~50 MiB of resident memory this indirection removes.
94
120
  */
95
121
  const codecCache = new Map<WireFamily, Promise<CodecModule>>();
96
122
 
@@ -103,8 +129,8 @@ const codecCache = new Map<WireFamily, Promise<CodecModule>>();
103
129
  * a gateway instance only ever serves one family.
104
130
  *
105
131
  * The cost is paid once, on the first request for that family, because wire
106
- * encoding happens before the upstream request is issued. `preloadCodec()`
107
- * warms it during boot so even that first-request delay disappears.
132
+ * encoding happens before the upstream request is issued. No boot-time preload
133
+ * exists — see the note on `codecCache` above.
108
134
  */
109
135
  async function loadCodec(wireFamily: WireFamily): Promise<CodecModule> {
110
136
  const cached = codecCache.get(wireFamily);
@@ -127,15 +153,6 @@ async function loadCodec(wireFamily: WireFamily): Promise<CodecModule> {
127
153
  return promise;
128
154
  }
129
155
 
130
- /**
131
- * Warms the codec module for a wire family during boot so the first request
132
- * does not pay the dynamic-import cost. Safe to call concurrently; the cache
133
- * deduplicates.
134
- */
135
- export function preloadCodec(wireFamily: WireFamily): Promise<void> {
136
- return loadCodec(wireFamily).then(() => undefined);
137
- }
138
-
139
156
  export async function encodeWireRequest(
140
157
  wireFamily: WireFamily,
141
158
  request: CanonicalRequest,
@@ -148,6 +165,11 @@ export async function encodeWireRequest(
148
165
  ...(context?.maxBytesOverride === undefined
149
166
  ? {}
150
167
  : { maxBytesOverride: context.maxBytesOverride }),
168
+ ...(context?.maxOutputTokens === undefined
169
+ ? {}
170
+ : { maxOutputTokens: context.maxOutputTokens }),
171
+ ...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
172
+ ...(context?.thinking === undefined ? {} : { thinking: context.thinking }),
151
173
  });
152
174
  }
153
175
  if (codec.family === "chat") {
@@ -164,6 +186,8 @@ export async function encodeWireRequest(
164
186
  ...(context?.promptCacheKey === undefined
165
187
  ? {}
166
188
  : { promptCacheKey: context.promptCacheKey }),
189
+ ...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
190
+ ...(context?.thinking === undefined ? {} : { thinking: context.thinking }),
167
191
  });
168
192
  }
169
193
  return codec.encodeWireRequest(request, {
@@ -173,6 +197,11 @@ export async function encodeWireRequest(
173
197
  ...(context?.promptCacheKey === undefined
174
198
  ? {}
175
199
  : { promptCacheKey: context.promptCacheKey }),
200
+ ...(context?.maxOutputTokens === undefined
201
+ ? {}
202
+ : { maxOutputTokens: context.maxOutputTokens }),
203
+ ...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
204
+ ...(context?.thinking === undefined ? {} : { thinking: context.thinking }),
176
205
  });
177
206
  }
178
207
 
@@ -206,6 +235,12 @@ export function decodeWireStream(
206
235
  yield* codec.decodeWireStream(body, context?.signal, context?.isOAuth ?? false);
207
236
  return;
208
237
  }
238
+ if (codec.family === "chat") {
239
+ yield* codec.decodeWireStream(body, request, context?.signal, {
240
+ ...(context?.dialectPolicy === undefined ? {} : { dialectPolicy: context.dialectPolicy }),
241
+ });
242
+ return;
243
+ }
209
244
  yield* codec.decodeWireStream(body, request, context?.signal);
210
245
  }
211
246
  return decode();
@@ -8,15 +8,19 @@ import { isWebSearchTool } from "../../protocol/translation/search";
8
8
  import { pickWireSupportedControls } from "../../protocol/translation/capabilities";
9
9
  import { normalizeWireMaxTokens } from "../../protocol/translation/normalize";
10
10
  import { resolveWireMaxTokens } from "../../protocol/translation/quirks";
11
- import {
12
- clampReasoningEffort,
13
- resolveSupportedReasoningEfforts,
14
- } from "../../protocol/translation/thinking";
11
+ import { DEFAULT_DIALECT_POLICIES } from "../../protocol/translation/dialect/rules";
12
+ import type { DialectPolicy } from "../../protocol/translation/dialect/types";
13
+ import type { ThinkingConfig } from "../../protocol/translation/dialect/thinking-ladder";
14
+ import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
15
+ import { clampThinkingLevelForModel } from "../../protocol/translation/dialect/model-thinking";
15
16
  import { isClaudeBillingHeaderText, resolveImageSource } from "../codecs";
16
17
  import { resolvePromptCacheKey } from "../../providers/operations/session-resolution";
17
18
  import { reasoningEffortFromIntent } from "../../protocol/reasoning";
18
19
  import { parseChatResponseToEvents, decodeChatSseStream } from "../response/chat";
19
20
 
21
+ /** Fallback when no resolved policy is supplied — today's exact behavior. */
22
+ const DEFAULT_CHAT_DIALECT_POLICY: DialectPolicy = DEFAULT_DIALECT_POLICIES.openai;
23
+
20
24
  /**
21
25
  * OpenAI `input_audio.format` accepts only the discrete ids `wav`/`mp3`, never a
22
26
  * MIME type. The canonical `audio` part carries a `media_type`; map it here and
@@ -182,15 +186,31 @@ export function canonicalToChatPayload(
182
186
  readonly tokenLimitField?: "max_tokens" | "max_completion_tokens";
183
187
  readonly maxOutputTokens?: number;
184
188
  readonly promptCacheKey?: string;
189
+ readonly dialectPolicy?: DialectPolicy;
190
+ readonly thinking?: ThinkingConfig;
185
191
  } = {},
186
192
  ): Record<string, unknown> {
193
+ const policy = options.dialectPolicy ?? DEFAULT_CHAT_DIALECT_POLICY;
194
+ const resolvedThinking = options.thinking ?? resolveThinkingForModel(request.model, "", "chat");
187
195
  const supportsPromptCaching = options.supportsPromptCaching ?? true;
188
- const tokenLimitField = options.tokenLimitField ?? "max_tokens";
196
+ const tokenLimitField = options.tokenLimitField ?? policy.maxTokensField;
197
+ const reasoningField = policy.reasoningContentField;
198
+ const carryReasoning = (has: boolean, text: string): Record<string, unknown> =>
199
+ has && reasoningField !== undefined ? { [reasoningField]: text } : {};
189
200
  const messages: Array<Record<string, unknown>> = [];
201
+ const systemTexts: string[] = [];
190
202
  if (request.system?.length) {
191
203
  for (const p of request.system) {
192
- if (p.kind === "text" && !isClaudeBillingHeaderText(p.text))
193
- messages.push({ role: "system", content: p.text });
204
+ if (p.kind === "text" && !isClaudeBillingHeaderText(p.text)) systemTexts.push(p.text);
205
+ }
206
+ }
207
+ if (systemTexts.length > 0) {
208
+ if (policy.supportsMultipleSystemMessages) {
209
+ for (const text of systemTexts) messages.push({ role: "system", content: text });
210
+ } else {
211
+ // Strict chat templates (Qwen Portal / Alibaba / MiniMax) accept a single
212
+ // system message; join the canonical system parts into one.
213
+ messages.push({ role: "system", content: systemTexts.join("\n") });
194
214
  }
195
215
  }
196
216
  if (request.instructions?.length) {
@@ -217,6 +237,12 @@ export function canonicalToChatPayload(
217
237
  (c): c is Extract<typeof c, { kind: "text" }> => c.kind === "text",
218
238
  );
219
239
  const content = textParts.length ? textParts.map((c) => c.text).join("\n") : null;
240
+ // DeepSeek V4 requires the assistant content field to be present on a
241
+ // tool-call turn; a null content would be rejected verbatim.
242
+ const effectiveContent =
243
+ policy.requiresAssistantContentForToolCalls && (content === null || content.length === 0)
244
+ ? ""
245
+ : content;
220
246
  // Reasoning must survive on a tool-call turn, not just on plain assistant
221
247
  // turns. Providers in thinking mode require the previous turn's reasoning
222
248
  // to be replayed, and the tool-call turn is exactly where a thinking
@@ -237,9 +263,9 @@ export function canonicalToChatPayload(
237
263
  const hasReasoning = m.content.some((c) => c.kind === "reasoning");
238
264
  messages.push({
239
265
  role: "assistant",
240
- content,
266
+ content: effectiveContent,
241
267
  tool_calls: toolCalls,
242
- ...(hasReasoning ? { reasoning_content: reasoningContent } : {}),
268
+ ...carryReasoning(hasReasoning, reasoningContent),
243
269
  });
244
270
  } else if (m.role === "tool") {
245
271
  for (const p of m.content) {
@@ -332,9 +358,7 @@ export function canonicalToChatPayload(
332
358
  messages.push({
333
359
  role: m.role,
334
360
  content: parts,
335
- ...(m.role === "assistant" && hasReasoning
336
- ? { reasoning_content: reasoningContent }
337
- : {}),
361
+ ...carryReasoning(m.role === "assistant" && hasReasoning, reasoningContent),
338
362
  });
339
363
  } else {
340
364
  // A user turn whose toolResult parts were all folded out above has
@@ -374,7 +398,7 @@ export function canonicalToChatPayload(
374
398
  messages.push({
375
399
  role: "assistant",
376
400
  content: "",
377
- reasoning_content: reasoningContent,
401
+ ...carryReasoning(true, reasoningContent),
378
402
  });
379
403
  continue;
380
404
  }
@@ -401,9 +425,7 @@ export function canonicalToChatPayload(
401
425
  messages.push({
402
426
  role: m.role,
403
427
  content,
404
- ...(m.role === "assistant" && hasReasoning
405
- ? { reasoning_content: reasoningContent }
406
- : {}),
428
+ ...carryReasoning(m.role === "assistant" && hasReasoning, reasoningContent),
407
429
  });
408
430
  }
409
431
  }
@@ -458,7 +480,7 @@ export function canonicalToChatPayload(
458
480
  };
459
481
  });
460
482
  }
461
- if (request.tool_choice) {
483
+ if (request.tool_choice && policy.supportsToolChoice) {
462
484
  if (typeof request.tool_choice === "object" && request.tool_choice.type === "allowed_tools") {
463
485
  payload["tool_choice"] = {
464
486
  type: "allowed_tools",
@@ -484,11 +506,16 @@ export function canonicalToChatPayload(
484
506
  // is what the Codex encoder already uses); deriving it here instead of in
485
507
  // each codec is what keeps a translated request from silently losing it.
486
508
  if (request.reasoning !== undefined) {
487
- const effort = clampReasoningEffort(
509
+ const effort = clampThinkingLevelForModel(
510
+ resolvedThinking,
488
511
  reasoningEffortFromIntent(request.reasoning),
489
- resolveSupportedReasoningEfforts(request.model, "chat"),
490
512
  );
491
513
  if (effort !== undefined) payload["reasoning_effort"] = effort;
514
+ // Qwen chat templates select thinking with `enable_thinking` (plus optional
515
+ // `thinking_budget`) instead of `reasoning_effort`.
516
+ if (policy.thinkingFormat === "qwen" && effort !== undefined) {
517
+ payload["enable_thinking"] = true;
518
+ }
492
519
  }
493
520
  // Stream controls the caller asked for are forwarded upstream so a
494
521
  // pass-through provider can honor them (the local encoder honors them too).
@@ -27,7 +27,7 @@ import {
27
27
  * `provider_options` key that opts one request into the Daybreak
28
28
  * `access_programs.cyber` member. See the UNCONFIRMED note at its use site.
29
29
  */
30
- export const CODEX_ACCESS_PROGRAMS_CYBER_OPTION = "codex_access_programs_cyber";
30
+ const CODEX_ACCESS_PROGRAMS_CYBER_OPTION = "codex_access_programs_cyber";
31
31
 
32
32
  /**
33
33
  * Removes `access_programs` from an already-built Codex Responses payload.