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
@@ -32,7 +32,7 @@ export interface ParamQuirk {
32
32
  }
33
33
 
34
34
  /** Per-wire output-token policy, in one table instead of per-builder branches. */
35
- export interface WireTokenBound {
35
+ interface WireTokenBound {
36
36
  /** Default when the caller sent no limit (undefined = leave absent). */
37
37
  readonly defaultMaxTokens?: number;
38
38
  /** Floor applied to any positive caller value below it (wire minimum). */
@@ -66,6 +66,13 @@ const DEFAULT_OUTPUT_TOKENS = 32_000;
66
66
  * Output-token bounds per wire family. Chat has no global ceiling: a model's
67
67
  * catalog output limit is the ceiling, and an unknown model passes the
68
68
  * caller's value through. Messages keeps its Anthropic floors and OAuth cap.
69
+ *
70
+ * The ceiling only ever comes from `options.maxOutputTokens` (the model's
71
+ * catalog output limit, supplied by the compatible adapter from
72
+ * `candidate.output_limit`). When it is omitted there is nothing to clamp to,
73
+ * which is intentional pass-through: a direct codec caller without a catalog
74
+ * limit is unbounded, and an unknown model passes the caller's value through by
75
+ * design — the bound table supplies floors/defaults, never an invented ceiling.
69
76
  */
70
77
  export const WIRE_TOKEN_BOUNDS: Readonly<Record<string, WireTokenBound>> = {
71
78
  chat: { minTokens: 16, defaultMaxTokens: DEFAULT_OUTPUT_TOKENS },
@@ -73,7 +80,14 @@ export const WIRE_TOKEN_BOUNDS: Readonly<Record<string, WireTokenBound>> = {
73
80
  responses: { minTokens: 16, defaultMaxTokens: DEFAULT_OUTPUT_TOKENS },
74
81
  };
75
82
 
76
- /** Resolves the output-token value for one wire from caller controls. */
83
+ /**
84
+ * Resolves the output-token value for one wire from caller controls.
85
+ *
86
+ * Clamping to a ceiling happens only when `options.maxOutputTokens` (the
87
+ * model's catalog limit) is present. An omitted `maxOutputTokens` means
88
+ * pass-through by design: a direct codec caller without a catalog limit is
89
+ * unbounded, and this function never fabricates a ceiling on its own.
90
+ */
77
91
  export function resolveWireMaxTokens(
78
92
  wire: string,
79
93
  controls: { max_tokens?: number | undefined },
@@ -120,7 +134,7 @@ function modelGeneration(modelId: string): { family: string; major: number; mino
120
134
  }
121
135
 
122
136
  /** True when the model rejects `temperature`/`top_p`/`top_k` at any thinking setting. */
123
- export function rejectsSamplingParams(modelId: string): boolean {
137
+ function rejectsSamplingParams(modelId: string): boolean {
124
138
  const generation = modelGeneration(modelId);
125
139
  if (generation === undefined) return false;
126
140
  // Opus turns strict at 4.7; the other families at 5.0.
@@ -157,7 +171,7 @@ const PARAM_QUIRKS: readonly ParamQuirk[] = [
157
171
  ];
158
172
 
159
173
  /** Finds the first quirk matching the provider/model pair, or undefined. */
160
- export function findParamQuirk(
174
+ function findParamQuirk(
161
175
  providerId: string,
162
176
  modelId: string,
163
177
  ): ParamQuirk | undefined {
@@ -5,7 +5,9 @@
5
5
  // so the native config (`thinking_type` + `budget_tokens`) is dropped while the
6
6
  // request-level effort intent (OpenAI `reasoning_effort`) survives — that field
7
7
  // is a property of the request, not of the turn.
8
- import type { CanonicalRequest, ReasoningIntent, WireFamily } from "../canonical-model";
8
+ import type { CanonicalRequest, ReasoningIntent } from "../canonical-model";
9
+ import type { ThinkingConfig } from "./dialect/thinking-ladder";
10
+ import { clampThinkingLevelForModel } from "./dialect/model-thinking";
9
11
 
10
12
  /**
11
13
  * Canonical reasoning effort ladder, ordered least to most intensive.
@@ -41,7 +43,7 @@ export type ThinkingSuffixIntent =
41
43
  * A parsed model name: the bare id the router and upstream must see, plus the
42
44
  * thinking level the caller asked for (or null when they asked for none).
43
45
  */
44
- export interface ParsedThinkingSuffix {
46
+ interface ParsedThinkingSuffix {
45
47
  readonly model: string;
46
48
  readonly intent: ThinkingSuffixIntent | null;
47
49
  }
@@ -200,248 +202,11 @@ export function withThinkingSuffixIntent(
200
202
  }
201
203
 
202
204
  /** Standard OpenAI Responses wire supported efforts (OpenAI, OpenCode, Azure). Responses API has no 'max' tier. */
203
- export const RESPONSES_WIRE_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
204
- "minimal",
205
- "low",
206
- "medium",
207
- "high",
208
- "xhigh",
209
- ];
210
-
211
- /** Full 6-tier effort scale for models that support 'max' (Claude, MiMo, Kimi, DeepSeek). */
212
- export const EXTENDED_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
213
- "minimal",
214
- "low",
215
- "medium",
216
- "high",
217
- "xhigh",
218
- "max",
219
- ];
220
-
221
- /** Standard 4-tier effort scale (Gemini, Qwen). */
222
- export const BASE_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
223
- "minimal",
224
- "low",
225
- "medium",
226
- "high",
227
- ];
228
-
229
- /**
230
- * The `mimo-v2.6` family rejects every effort outside this set.
231
- *
232
- * Verified live against OpenCode's `/zen/v1` on 2026-09-22: `minimal`, `xhigh`,
233
- * and `max` each answer `500 {"type":"error","error":{"message":"Internal server
234
- * error"}}` — an opaque failure that names nothing, so the caller sees a dead
235
- * request rather than a bad parameter — while `low`/`medium`/`high` and an
236
- * omitted field answer `200`. Its siblings on the very same endpoint
237
- * (`mimo-v2.5-free`, `nemotron-3-ultra-free`, `big-pickle`) accept the full
238
- * ladder, so this is a property of the model rather than of the route.
239
- *
240
- * Narrowing is the safe direction: every level here is accepted by all hosts of
241
- * the id, so the worst case for a host that would also take `xhigh` is that the
242
- * request runs one tier below what the caller asked for instead of failing.
243
- */
244
- const MIMO_V26_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = ["low", "medium", "high"];
245
-
246
- /**
247
- * Mercury (Inception Labs) — the chat ladder is `{instant, low, medium,
248
- * high}`: `minimal`, `xhigh`, and `max` each answer a 400
249
- * `reasoning_effort must be one of: 'instant', 'low', 'medium', 'high'`.
250
- * `instant` is not on the canonical ladder, so it can only appear here; the
251
- * clamp steps down to `high` for any higher request.
252
- */
253
- const INCEPTION_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
254
- "instant",
255
- "low",
256
- "medium",
257
- "high",
258
- ];
259
205
 
260
- /**
261
- * `low..max`: the OpenAI 5.6/6/daybreak generation and the new-gen Claude
262
- * adaptive models (`fable`/`mythos`/`opus-5`/`sonnet-5`/`opus-4-7`/`opus-4-8`)
263
- * all serve `max`, and none of them advertises `minimal`.
264
- */
265
- const LOW_TO_MAX_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
266
- "low",
267
- "medium",
268
- "high",
269
- "xhigh",
270
- "max",
271
- ];
272
-
273
- /** `gpt-5.5` rows: neither `minimal` nor `max`. */
274
- const GPT55_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
275
- "low",
276
- "medium",
277
- "high",
278
- "xhigh",
279
- ];
280
-
281
- /** Claude adaptive 4.6 pair: `low..high`, no `xhigh`/`max`. */
282
- const CLAUDE_ADAPTIVE_46_SUPPORTED_EFFORTS: readonly ReasoningEffortLevel[] = [
283
- "low",
284
- "medium",
285
- "high",
286
- ];
287
-
288
- /**
289
- * Resolves the valid reasoning effort levels for a given model and wire family.
290
- *
291
- * Priority order:
292
- * 1. Explicit model-declared `reasoningEfforts` from the catalog.
293
- * 2. Wire family constraint: the Responses wire API (`/v1/responses`) does not
294
- * support 'max' (capped at 'xhigh') unless the model's published ladder
295
- * includes it.
296
- * 3. Model family heuristics, matching each family's published ladder:
297
- * - Muse Spark (Meta on OpenCode / Fireworks): `["minimal", "low", "medium", "high", "xhigh"]`
298
- * - Gemini: `["minimal", "low", "medium", "high"]`
299
- * - Claude: per-generation — 4.6 adaptive stops at `high`, budget-era 4.5/4.1
300
- * tops out at `xhigh`, new-gen adaptive is `low..max`.
301
- * - DeepSeek, Kimi, MiMo: full extended ladder including 'max'
302
- * - Default: extended ladder.
303
- */
304
- export function resolveSupportedReasoningEfforts(
305
- modelId?: string,
306
- wireFamily?: WireFamily,
307
- declaredEfforts?: readonly string[],
308
- ): readonly ReasoningEffortLevel[] {
309
- if (declaredEfforts !== undefined && declaredEfforts.length > 0) {
310
- const filtered = declaredEfforts.filter((e): e is ReasoningEffortLevel =>
311
- REASONING_EFFORT_LADDER.includes(e as ReasoningEffortLevel),
312
- );
313
- if (filtered.length > 0) return filtered;
314
- }
315
-
316
- const id = (modelId ?? "").toLowerCase();
317
-
318
- if (wireFamily === "responses") {
319
- // Catalog ladders for the ChatGPT/OpenAI generations: `gpt-5.5`
320
- // is the one row that stops at `xhigh`.
321
- if (id.includes("gpt-5.5")) return GPT55_SUPPORTED_EFFORTS;
322
- if (id.includes("gpt-5.6") || id.includes("gpt-6") || id.includes("daybreak")) {
323
- return LOW_TO_MAX_SUPPORTED_EFFORTS;
324
- }
325
- return RESPONSES_WIRE_SUPPORTED_EFFORTS;
326
- }
327
-
328
- if (id.includes("muse")) {
329
- return RESPONSES_WIRE_SUPPORTED_EFFORTS;
330
- }
331
- if (id.includes("gemini")) {
332
- return BASE_SUPPORTED_EFFORTS;
333
- }
334
- // Checked before the generic default, which would hand this family `xhigh`
335
- // and `max` — both of which it answers with an opaque 500.
336
- if (id.includes("mimo-v2.6")) {
337
- return MIMO_V26_SUPPORTED_EFFORTS;
338
- }
339
- // Checked before the generic default: Mercury's chat endpoint answers every
340
- // effort outside {instant, low, medium, high} with a 400 that names the
341
- // field (recorded live from request 40b60777).
342
- if (id.includes("mercury") && wireFamily === "chat") {
343
- return INCEPTION_SUPPORTED_EFFORTS;
344
- }
345
- // Claude catalog ladders: `output_config.effort` rides the
346
- // Messages wire, so an out-of-ladder tier is an upstream rejection risk.
347
- // Dot-tolerant (`cb/claude-opus-4.6`) because gateway-prefixed ids keep the
348
- // upstream separator.
349
- if (id.includes("claude")) {
350
- const claudeId = id.replaceAll(".", "-");
351
- if (claudeId.includes("opus-4-6") || claudeId.includes("sonnet-4-6")) {
352
- return CLAUDE_ADAPTIVE_46_SUPPORTED_EFFORTS;
353
- }
354
- if (
355
- claudeId.includes("fable") ||
356
- claudeId.includes("mythos") ||
357
- claudeId.includes("opus-5") ||
358
- claudeId.includes("sonnet-5") ||
359
- claudeId.includes("opus-4-7") ||
360
- claudeId.includes("opus-4-8")
361
- ) {
362
- return LOW_TO_MAX_SUPPORTED_EFFORTS;
363
- }
364
- if (
365
- claudeId.includes("opus-4-5") ||
366
- claudeId.includes("sonnet-4-5") ||
367
- claudeId.includes("haiku-4-5") ||
368
- claudeId.includes("opus-4-1") ||
369
- claudeId.includes("opus-4-0") ||
370
- claudeId.includes("sonnet-4-0")
371
- ) {
372
- // Budget-mode rows: `minimal..xhigh`, no `max` — same shape as the
373
- // responses-wire default.
374
- return RESPONSES_WIRE_SUPPORTED_EFFORTS;
375
- }
376
- }
377
-
378
- return EXTENDED_SUPPORTED_EFFORTS;
379
- }
380
-
381
- /**
382
- * Whether a Claude model wants *adaptive* thinking (`thinking.type: "adaptive"`
383
- * + `output_config.effort`) or *budget* thinking (`thinking.type: "enabled"` +
384
- * `budget_tokens`).
385
- *
386
- * The two generations reject each other's shape: an adaptive-era model answers
387
- * a budget block with `thinking.budget_tokens: Extra inputs are not permitted`,
388
- * and a budget-era model answers an adaptive block with `adaptive thinking is
389
- * not supported on this model` (verified live against the Anthropic OAuth
390
- * route — opus-4-5/sonnet-4-5/haiku-4-5 400 on adaptive, while
391
- * opus-4-6+/sonnet-4-6+/5-series accept it).
392
- *
393
- * Adaptive era, per the reference catalog: Opus 4.6+, Sonnet 4.6+, and the
394
- * 5-series (fable/mythos/opus-5/sonnet-5). Everything older is budget era.
395
- * The rule is stated once here so the Messages codec and the effort ladder
396
- * cannot disagree about which generation a model belongs to.
397
- */
398
- export function claudeUsesAdaptiveThinking(modelId: string): boolean {
399
- const id = modelId.toLowerCase().replaceAll(".", "-");
400
- if (id.includes("fable") || id.includes("mythos")) return true;
401
- if (id.includes("opus-5") || id.includes("sonnet-5")) return true;
402
- if (id.includes("opus-4-6") || id.includes("sonnet-4-6")) return true;
403
- if (id.includes("opus-4-7") || id.includes("opus-4-8")) return true;
404
- return false;
405
- }
406
-
407
- /**
408
- * Clamps a requested reasoning effort against a target model/wire's supported ladder.
409
- *
410
- * If the requested effort is not in the supported list, it gracefully steps down to the
411
- * highest supported level that is less than or equal to the requested index in the canonical ladder.
412
- * Synonyms are normalized: 'ultra' -> 'max', 'off' -> 'none'.
413
- * Returns undefined for 'none' / unrequested.
414
- */
415
- export function clampReasoningEffort(
416
- requested: string | undefined,
417
- supported: readonly ReasoningEffortLevel[],
418
- ): ReasoningEffortLevel | undefined {
419
- if (!requested || typeof requested !== "string") return undefined;
420
- const raw = requested.toLowerCase().trim();
421
- const normalized = raw === "ultra" ? "max" : raw === "off" ? "none" : raw;
422
- if (normalized === "none") return undefined;
423
-
424
- const reqLevel = normalized as ReasoningEffortLevel;
425
- // Don't clamp if provider declares it supports the level but we haven't updated constants yet.
426
- // Fall through to direct return for any ladder member the caller asked for.
427
- if (supported.includes(reqLevel)) return reqLevel;
428
- // Unknown string → drop, don't invent a fallback.
429
- const requestedIndex = REASONING_EFFORT_LADDER.indexOf(reqLevel);
430
- if (requestedIndex === -1) return undefined;
431
-
432
- let clamped: ReasoningEffortLevel | undefined;
433
- for (const level of supported) {
434
- if (REASONING_EFFORT_LADDER.indexOf(level) > requestedIndex) break;
435
- clamped = level;
436
- }
437
- // No smaller supported level exists (caller asked below floor): use floor rather than max.
438
- return clamped ?? supported[0];
439
- }
440
206
 
441
- export interface ThinkingNormalizationOptions {
442
- readonly wireFamily?: WireFamily;
443
- readonly modelId?: string;
444
- readonly supportedEfforts?: readonly string[];
207
+ interface ThinkingNormalizationOptions {
208
+ /** Resolved thinking config (from `resolveThinkingForModel`). Absent = no clamp. */
209
+ readonly thinking?: ThinkingConfig;
445
210
  }
446
211
 
447
212
  /**
@@ -459,7 +224,7 @@ function isLastMessageFromUser(request: CanonicalRequest): boolean {
459
224
  * `thinking` config is also present, so a config drop must never leave them
460
225
  * orphaned.
461
226
  */
462
- export function hasReplayedThinkingBlocks(request: CanonicalRequest): boolean {
227
+ function hasReplayedThinkingBlocks(request: CanonicalRequest): boolean {
463
228
  for (const message of request.messages) {
464
229
  for (const part of message.content) {
465
230
  if (part.kind !== "reasoning") continue;
@@ -504,15 +269,10 @@ export function normalizeThinkingConfig(
504
269
  }
505
270
  }
506
271
 
507
- // Only clamp when caller actually set an effort AND provider declares a ladder.
508
- // If provider doesn't declare supportedEfforts, don't invent a 32k clamp — pass through.
509
- if (reasoning?.effort !== undefined && options?.supportedEfforts !== undefined && options.supportedEfforts.length > 0) {
510
- const supported = resolveSupportedReasoningEfforts(
511
- options?.modelId ?? request.model,
512
- options?.wireFamily,
513
- options?.supportedEfforts,
514
- );
515
- const clamped = clampReasoningEffort(reasoning.effort, supported);
272
+ // Only clamp when caller actually set an effort AND a thinking config is
273
+ // resolved (ladder known). Without one, don't invent a clamp — pass through.
274
+ if (reasoning?.effort !== undefined && options?.thinking !== undefined) {
275
+ const clamped = clampThinkingLevelForModel(options.thinking, reasoning.effort);
516
276
  if (clamped !== reasoning.effort) {
517
277
  reasoning = { ...reasoning };
518
278
  if (clamped === undefined) delete reasoning.effort;
@@ -9,7 +9,7 @@
9
9
  import type { CanonicalRequest } from "../canonical-model";
10
10
 
11
11
  /** Anthropic tool ID contract: alphanumerics, underscore, hyphen only. */
12
- export const TOOL_ID_PATTERN: RegExp = /^[a-zA-Z0-9_-]+$/;
12
+ const TOOL_ID_PATTERN: RegExp = /^[a-zA-Z0-9_-]+$/;
13
13
 
14
14
  const INVALID_TOOL_ID_CHARS = /[^a-zA-Z0-9_-]/g;
15
15
 
@@ -21,7 +21,7 @@ const INVALID_TOOL_ID_CHARS = /[^a-zA-Z0-9_-]/g;
21
21
  * input is not a non-empty string or nothing valid remains, so callers can
22
22
  * fall back to a deterministic generated ID.
23
23
  */
24
- export function sanitizeToolId(id: unknown): string | null {
24
+ function sanitizeToolId(id: unknown): string | null {
25
25
  if (typeof id !== "string" || id.length === 0) return null;
26
26
  const base = id.includes("|") ? (id.split("|")[0] ?? id) : id;
27
27
  const sanitized = base.replace(INVALID_TOOL_ID_CHARS, "");
@@ -33,7 +33,7 @@ export function sanitizeToolId(id: unknown): string | null {
33
33
  * identical histories produce byte-identical requests — cache-friendly and
34
34
  * directly testable.
35
35
  */
36
- export function generateToolCallId(msgIndex = 0, tcIndex = 0, toolName?: string): string {
36
+ function generateToolCallId(msgIndex = 0, tcIndex = 0, toolName?: string): string {
37
37
  const name = toolName ? `_${toolName.replace(INVALID_TOOL_ID_CHARS, "")}` : "";
38
38
  return `call_msg${msgIndex}_tc${tcIndex}${name}`;
39
39
  }
@@ -211,7 +211,7 @@ function toolCallIdsIn(message: CanonicalMessage): string[] {
211
211
  * and is repaired by synthesizing a result (`repairMissingToolResponses`), not
212
212
  * by deleting the call — the model should see that the tool was interrupted.
213
213
  */
214
- export function dropOrphanToolResults(
214
+ function dropOrphanToolResults(
215
215
  messages: readonly CanonicalMessage[],
216
216
  ): CanonicalMessage[] {
217
217
  const callIds = new Set<string>();
@@ -1,6 +1,10 @@
1
1
  /**
2
2
  * Shared upstream JSON executor for [OpenAI]-compatible adapters: POSTs a payload
3
3
  * with deadline/abort wiring and returns the response plus a release hook.
4
+ *
5
+ * `bodyEncoder` lets a provider send the same body with non-JSON encoding
6
+ * (e.g. zstd, which the Grok Build CLI does). When omitted, the JSON string is
7
+ * sent as-is.
4
8
  */
5
9
  import type { ProviderDispatchContext, ValidatedOutboundFetch } from "../../providers/provider-contracts";
6
10
  import { abortGatewayError, createUpstreamDeadlineLifecycle } from "../../providers/operations/upstream-deadline";
@@ -11,13 +15,14 @@ export async function postUpstreamJson(
11
15
  payload: Record<string, unknown>,
12
16
  context: ProviderDispatchContext,
13
17
  outboundFetch: ValidatedOutboundFetch,
18
+ bodyEncoder?: (payload: Record<string, unknown>) => string | Uint8Array<ArrayBuffer>,
14
19
  ): Promise<{ res: Response; signal: AbortSignal; release: () => void }> {
15
20
  const lifecycle = createUpstreamDeadlineLifecycle(context);
16
21
  try {
17
22
  const res = await outboundFetch(fetchUrl, {
18
23
  method: "POST",
19
24
  headers,
20
- body: JSON.stringify(payload),
25
+ body: bodyEncoder ? bodyEncoder(payload) : JSON.stringify(payload),
21
26
  signal: lifecycle.signal,
22
27
  });
23
28
  return {
@@ -13,6 +13,9 @@ import {
13
13
  import { applyRouteUserAgent, type ProviderDispatchTarget, type ProviderId, type ProviderDispatchContext } from "../provider-contracts";
14
14
  import { BaseProviderAdapter } from "./base-adapter";
15
15
  import { encodeWireRequest, decodeWireResponse, decodeWireStream } from "../../protocol/registry";
16
+ import { resolveDialect } from "../../protocol/translation/dialect/resolver";
17
+ import { resolveThinkingForModel } from "../../protocol/translation/dialect/thinking-ladder";
18
+ import type { DialectPolicy } from "../../protocol/translation/dialect/types";
16
19
  import { postUpstreamJson } from "../../protocol/upstream/post-json";
17
20
  import { GATEWAY_USER_AGENT } from "../operations/gateway-user-agent";
18
21
  import { resolvePromptCacheKey } from "../operations/session-resolution";
@@ -25,6 +28,19 @@ import {
25
28
  } from "../../protocol/codecs";
26
29
  const TEXT_DECODER = new TextDecoder("utf-8", { fatal: false });
27
30
 
31
+ /**
32
+ * Provider ids that understand the OpenAI-style `service_tier` control. Only
33
+ * these upstreams accept the field; every other OpenAI-compatible provider
34
+ * either ignores it or rejects the whole request with `unsupported_value`
35
+ * (measured: GitHub Copilot returns 400). `service_tier` is advisory on the
36
+ * providers that do support it, so dropping it elsewhere is lossless.
37
+ */
38
+ const SERVICE_TIER_SUPPORTED_PROVIDERS: ReadonlySet<string> = new Set([
39
+ "openai",
40
+ "codex",
41
+ "anthropic",
42
+ ]);
43
+
28
44
  /**
29
45
  * The subset of a canonical request a native-service header hook may read.
30
46
  *
@@ -89,6 +105,14 @@ export interface OpenAICompatibleAdapterConfig {
89
105
  * this is the enforcement boundary, not account-creation validation.
90
106
  */
91
107
  readonly credential_forwarding?: "account" | "never";
108
+ /**
109
+ * Body encoding for the upstream POST. `"json"` (default) sends the plain
110
+ * JSON string. `"zstd"` compresses the JSON with `Bun.zstdCompressSync` and
111
+ * stamps `Content-Encoding: zstd` — the Grok Build CLI does this via its
112
+ * sampler (`request_compression.rs`), and the proxy accepts it (verified
113
+ * live 2026-11-02). Falls back to plain JSON if the runtime lacks zstd.
114
+ */
115
+ readonly request_compression?: "json" | "zstd";
92
116
  /**
93
117
  * Stamps `user-agent: Cartethyia/<version>` on every dispatch. Explicit
94
118
  * opt-in per provider spec — never a default — so first-party cloaking
@@ -188,6 +212,10 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
188
212
  // serving the stale pinned fallback on the first dispatch.
189
213
  Object.assign(headers, await this.config.buildExtraHeaders(context, request, candidate));
190
214
  }
215
+ // The compression header must match the body actually sent. It is stamped
216
+ // here — alongside the other request headers — so auth/proxy layers see the
217
+ // final shape before the transport runs.
218
+ if (this.config.request_compression === "zstd") headers["content-encoding"] = "zstd";
191
219
  Object.assign(headers, filterProviderCustomHeaders(context.credential.custom_headers));
192
220
  applyRouteUserAgent(headers, context.credential, context.user_agent);
193
221
  return headers;
@@ -201,6 +229,17 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
201
229
  const wireFamily = candidate.wire_family;
202
230
  const effectiveRequest = this.config.prepareRequest?.(request) ?? request;
203
231
  const promptCacheKey = resolvePromptCacheKey(effectiveRequest, context);
232
+ const dialectPolicy: DialectPolicy = resolveDialect(
233
+ candidate.model_id,
234
+ candidate.provider_id,
235
+ wireFamily,
236
+ candidate.dialect,
237
+ );
238
+ const thinking = resolveThinkingForModel(
239
+ candidate.model_id,
240
+ candidate.provider_id,
241
+ wireFamily,
242
+ );
204
243
  const payload = await encodeWireRequest(wireFamily, effectiveRequest, {
205
244
  supportsPromptCaching: this.config.supports_prompt_caching !== false,
206
245
  ...(promptCacheKey === undefined ? {} : { promptCacheKey }),
@@ -211,6 +250,8 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
211
250
  ...(context.image_clamp_max_bytes === undefined
212
251
  ? {}
213
252
  : { maxBytesOverride: context.image_clamp_max_bytes }),
253
+ dialectPolicy,
254
+ thinking,
214
255
  });
215
256
  if (
216
257
  wireFamily !== "messages" &&
@@ -251,6 +292,18 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
251
292
  }
252
293
  }
253
294
  this.config.prePayload?.(payload, effectiveRequest, candidate, context);
295
+ // `service_tier` is an OpenAI-style control that only a small set of
296
+ // upstreams understand. Every other OpenAI-compatible provider either
297
+ // ignores it silently or rejects the whole request with
298
+ // `unsupported_value` (measured: GitHub Copilot returns 400). Since the
299
+ // field is purely advisory on the providers that support it, dropping it
300
+ // everywhere else is safe and prevents avoidable upstream 400s.
301
+ if (
302
+ payload["service_tier"] !== undefined &&
303
+ !SERVICE_TIER_SUPPORTED_PROVIDERS.has(candidate.provider_id)
304
+ ) {
305
+ delete payload["service_tier"];
306
+ }
254
307
  return payload;
255
308
  }
256
309
 
@@ -283,6 +336,11 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
283
336
  payload as Record<string, unknown>,
284
337
  context,
285
338
  outboundFetch,
339
+ // zstd body encoding: matches the Grok Build CLI's
340
+ // `request_compression` (zstd with a JSON fallback when unavailable).
341
+ this.config.request_compression === "zstd" && typeof Bun?.zstdCompressSync === "function"
342
+ ? (p) => Bun.zstdCompressSync(Buffer.from(JSON.stringify(p))) as Uint8Array<ArrayBuffer>
343
+ : undefined,
286
344
  );
287
345
  upstream.release();
288
346
  return upstream.res;
@@ -300,8 +358,11 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
300
358
  * the caller (the route handler validates only the trust boundary), so this
301
359
  * method only stamps headers and posts.
302
360
  *
303
- * `systemone` is kept as a named alias because the `/v1/systemone` route
304
- * reads it directly; both names are the same behavior.
361
+ * `systemone` is kept as a named alias because both names are live: the
362
+ * transport dispatch handler for `POST /v1/systemone`
363
+ * (transport/dispatch/systemone.ts) and the discovery probing service
364
+ * (discovery/probing-service.ts) read it directly; both names are the same
365
+ * behavior.
305
366
  */
306
367
  async dispatchNativeService(
307
368
  body: Record<string, unknown>,
@@ -356,7 +417,10 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
356
417
  "upstream",
357
418
  );
358
419
  }
359
- yield* decodeWireStream(wireFamily, res.body, request, { signal: context.abort_signal });
420
+ yield* decodeWireStream(wireFamily, res.body, request, {
421
+ signal: context.abort_signal,
422
+ dialectPolicy: resolveDialect(candidate.model_id, candidate.provider_id, wireFamily, candidate.dialect),
423
+ });
360
424
  } else {
361
425
  // A streaming request answered with a non-SSE body is a provider
362
426
  // protocol violation, and the body is often an error envelope or a
@@ -390,12 +454,15 @@ export class OpenAICompatibleAdapter extends BaseProviderAdapter {
390
454
  // the absence of every completion shape so a provider that merely
391
455
  // echoes an `error` field alongside real output is not misread.
392
456
  const envelopeError = json["error"];
457
+ const startPlanError = this.provider_id === "zcode-start" &&
458
+ (json["success"] === false || (json["code"] !== undefined &&
459
+ ![0, 200, "0", "200"].includes(json["code"] as string | number)));
393
460
  const hasCompletionShape =
394
461
  json["choices"] !== undefined ||
395
462
  json["output"] !== undefined ||
396
463
  json["content"] !== undefined ||
397
464
  json["candidates"] !== undefined;
398
- if (envelopeError !== undefined && envelopeError !== null && !hasCompletionShape) {
465
+ if (((envelopeError !== undefined && envelopeError !== null) || startPlanError) && !hasCompletionShape) {
399
466
  const errorObject = isRecord(envelopeError) ? envelopeError : json;
400
467
  const identifier = upstreamErrorIdentifier(json);
401
468
  const providerStatus = [
@@ -340,11 +340,6 @@ export function jwksVerifierFor(
340
340
  return verifier;
341
341
  }
342
342
 
343
- /** Test hook: forgets cached JWKS verifiers. */
344
- export function resetJwksVerifiersForTests(): void {
345
- jwksVerifiers.clear();
346
- }
347
-
348
343
  interface IssuedTokenValidation {
349
344
  readonly jwksUrl?: string;
350
345
  readonly issuer?: string | readonly string[];