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
@@ -5,24 +5,6 @@
5
5
  // end-of-stream trailer. Compression and trailer semantics stay at the call
6
6
  // sites; this module owns only the envelope arithmetic.
7
7
 
8
- /** Payload is gzip-compressed. */
9
- export const CONNECT_COMPRESSED_FLAG = 0x01;
10
- /** Frame carries the end-of-stream trailer rather than a message. */
11
- export const CONNECT_END_STREAM_FLAG = 0x02;
12
-
13
- /** One decoded Connect envelope. */
14
- interface ConnectFrame {
15
- readonly flags: number;
16
- readonly payload: Uint8Array;
17
- }
18
-
19
- interface ConsumeConnectFramesOptions {
20
- /** Reject frames whose declared payload exceeds this many bytes. */
21
- readonly maxPayloadBytes?: number;
22
- /** Builds the error thrown for an oversized frame; defaults to a plain `Error`. */
23
- readonly oversizeError?: (declaredLength: number) => Error;
24
- }
25
-
26
8
  /** Initial allocation for a frame buffer that has not received a chunk yet. */
27
9
  const FRAME_BUFFER_MIN_BYTES = 4096;
28
10
  /** Ceiling on the spare capacity kept above the live length when growing. */
@@ -84,39 +66,3 @@ export class FrameBuffer {
84
66
  this.start = 0;
85
67
  }
86
68
  }
87
-
88
- /** Wraps `payload` in a 5-byte Connect envelope. */
89
- export function frameConnectMessage(payload: Uint8Array, flags = 0) {
90
- const frame = Buffer.alloc(5 + payload.length);
91
- frame.writeUInt8(flags, 0);
92
- frame.writeUInt32BE(payload.length, 1);
93
- frame.set(payload, 5);
94
- return frame;
95
- }
96
-
97
- /**
98
- * Splits every complete Connect frame out of `buffer`, in order. Returns the
99
- * trailing bytes that do not yet form a complete frame so a streaming caller
100
- * can prepend them to the next chunk and call again.
101
- */
102
- export function consumeConnectFrames(
103
- buffer: Buffer,
104
- options: ConsumeConnectFramesOptions = {},
105
- ): { frames: ConnectFrame[]; rest: Buffer } {
106
- const frames: ConnectFrame[] = [];
107
- let pending = buffer;
108
- while (pending.length >= 5) {
109
- const flags = pending[0] ?? 0;
110
- const length = pending.readUInt32BE(1);
111
- if (options.maxPayloadBytes !== undefined && length > options.maxPayloadBytes) {
112
- throw (
113
- options.oversizeError?.(length) ??
114
- new Error(`Connect frame length ${length} exceeds cap`)
115
- );
116
- }
117
- if (pending.length < 5 + length) break;
118
- frames.push({ flags, payload: pending.subarray(5, 5 + length) });
119
- pending = pending.subarray(5 + length);
120
- }
121
- return { frames, rest: pending };
122
- }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 32-bit FNV-1a hash.
3
+ *
4
+ * Single source for the two former inline copies (claude `hashBody`,
5
+ * cursor `cursorAccountTag`). Fast, deterministic, sufficient for cache
6
+ * identity / short display tags — not a cryptographic hash.
7
+ */
8
+ export function fnv1a32(input: string): number {
9
+ let hash = 0x811c9dc5;
10
+ for (let index = 0; index < input.length; index += 1) {
11
+ hash ^= input.charCodeAt(index);
12
+ hash = Math.imul(hash, 0x01000193) >>> 0;
13
+ }
14
+ return hash >>> 0;
15
+ }
@@ -0,0 +1,136 @@
1
+ // Shared session-cache estimation factory.
2
+ //
3
+ // The Kiro and Trae adapters both need to ESTIMATE prompt-cache hits locally
4
+ // because their upstream surfaces never report them. Their logic is
5
+ // byte-identical modulo the provider header comment, so it lives here once —
6
+ // but the state must stay per-provider: a factory call creates a private Map
7
+ // per integration, so cross-provider session-id collisions can never
8
+ // contaminate each other's estimates. Call each provider's wrapper
9
+ // (kiro-cache.ts / trae-cache.ts); do not import this module directly.
10
+
11
+ import { createHash } from "node:crypto";
12
+ import type { CanonicalMessage, UsageRecord } from "../../../protocol/canonical-model";
13
+
14
+ /** Bounded in-memory tracker: one entry per session, oldest evicted first. */
15
+ export const SESSION_CACHE_MAX_SESSIONS = 512;
16
+
17
+ interface SessionCacheEntry {
18
+ /** hash(full messages) -> reported input tokens for that exact list. */
19
+ readonly seen: Map<string, number>;
20
+ /** Insertion order for bounded eviction. */
21
+ readonly order: string[];
22
+ }
23
+
24
+ export interface SessionCache {
25
+ estimate(
26
+ record: UsageRecord,
27
+ sessionId: string | undefined,
28
+ messages: readonly CanonicalMessage[] | undefined,
29
+ ): UsageRecord;
30
+ resetForTesting(): void;
31
+ }
32
+
33
+ function hashOf(messages: readonly CanonicalMessage[]): string {
34
+ return createHash("sha256").update(JSON.stringify(messages)).digest("hex");
35
+ }
36
+
37
+ /**
38
+ * Creates an isolated session-cache estimator: its own private session Map,
39
+ * bounded at SESSION_CACHE_MAX_SESSIONS with per-entry oldest-first eviction.
40
+ */
41
+ export function createSessionCache(): SessionCache {
42
+ const sessions = new Map<string, SessionCacheEntry>();
43
+
44
+ function sessionFor(sessionId: string): SessionCacheEntry {
45
+ let entry = sessions.get(sessionId);
46
+ if (!entry) {
47
+ entry = { seen: new Map(), order: [] };
48
+ sessions.set(sessionId, entry);
49
+ }
50
+ return entry;
51
+ }
52
+
53
+ function remember(sessionId: string, fullHash: string, inputTokens: number): void {
54
+ const entry = sessionFor(sessionId);
55
+ if (!entry.seen.has(fullHash)) {
56
+ entry.order.push(fullHash);
57
+ if (entry.order.length > SESSION_CACHE_MAX_SESSIONS) {
58
+ const oldest = entry.order.shift();
59
+ if (oldest !== undefined) entry.seen.delete(oldest);
60
+ }
61
+ }
62
+ entry.seen.set(fullHash, inputTokens);
63
+ if (sessions.size > SESSION_CACHE_MAX_SESSIONS) {
64
+ const oldestSession = sessions.keys().next().value;
65
+ if (oldestSession !== undefined) sessions.delete(oldestSession);
66
+ }
67
+ }
68
+
69
+ return {
70
+ estimate(record, sessionId, messages) {
71
+ if (!sessionId || !messages || messages.length === 0) return record;
72
+ const upstreamReported =
73
+ typeof record.cached_input_tokens === "number" && record.cached_input_tokens > 0;
74
+ if (upstreamReported) return record;
75
+
76
+ const fullHash = hashOf(messages);
77
+ const entry = sessions.get(sessionId);
78
+
79
+ if (entry) {
80
+ // Longest prefix that matches a previously sent complete request.
81
+ for (let len = messages.length; len >= 1; len -= 1) {
82
+ const prefix = messages.slice(0, len);
83
+ const tokens = entry.seen.get(hashOf(prefix));
84
+ if (tokens === undefined) continue;
85
+ if (len === messages.length) {
86
+ // Byte-identical request: the whole input came from cache.
87
+ return {
88
+ ...record,
89
+ cached_input_tokens: record.input_tokens,
90
+ uncached_input_tokens: 0,
91
+ };
92
+ }
93
+ const cached = Math.min(tokens, record.input_tokens);
94
+ return {
95
+ ...record,
96
+ cached_input_tokens: cached,
97
+ uncached_input_tokens: Math.max(0, record.input_tokens - cached),
98
+ };
99
+ }
100
+ }
101
+
102
+ remember(sessionId, fullHash, record.input_tokens);
103
+ return record;
104
+ },
105
+
106
+ resetForTesting() {
107
+ sessions.clear();
108
+ },
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Estimates how much of this request's input was served from cache.
114
+ *
115
+ * The longest prefix of `messages` that was ever sent as a complete request in
116
+ * this session is considered cached, and its recorded token count is the
117
+ * cached portion — if that prefix is the whole request, everything was cached.
118
+ * This models how upstream prompt caching actually behaves (byte-identical
119
+ * prefix reuse) without trusting a counter the upstream never reports.
120
+ *
121
+ * Returns the record unchanged when there is nothing to estimate (no session,
122
+ * no history, or upstream already reported a real hit).
123
+ */
124
+ export function estimateSessionCache(
125
+ cache: SessionCache,
126
+ record: UsageRecord,
127
+ sessionId: string | undefined,
128
+ messages: readonly CanonicalMessage[] | undefined,
129
+ ): UsageRecord {
130
+ return cache.estimate(record, sessionId, messages);
131
+ }
132
+
133
+ /** Drops all tracked sessions in this cache. Test-only. */
134
+ export function resetSessionCacheForTesting(cache: SessionCache): void {
135
+ cache.resetForTesting();
136
+ }
@@ -71,11 +71,11 @@ export const TOKENHARBOR_FALLBACK_MODELS: readonly ModelDefinition[] = [
71
71
  function tokenharborPrePayload(payload: Record<string, unknown>): void {
72
72
  const model = payload["model"];
73
73
  if (typeof model !== "string" || model.length === 0) {
74
- throw new GatewayError("invalid_request", 400, "TokenHarbor model is required");
74
+ throw new GatewayError("invalid_request", 400, "TokenHarbor model is required (request {requestId}). Check the shape of what you sent — then resend 🪞");
75
75
  }
76
76
  // Strip accidental query-string smuggling (mirrors the factory's own guard)
77
77
  if (model.includes("?")) {
78
- throw new GatewayError("invalid_request", 400, "TokenHarbor model must not contain query string");
78
+ throw new GatewayError("invalid_request", 400, "TokenHarbor model must not contain query string (request {requestId}). Check the shape of what you sent — then resend 🪞");
79
79
  }
80
80
  }
81
81
 
@@ -7,104 +7,24 @@
7
7
  // conversation we ESTIMATE the hit locally. This only fills the gap when
8
8
  // upstream reports nothing (0 or unavailable); a genuine upstream report (>0)
9
9
  // is trusted and left untouched.
10
+ //
11
+ // The state lives in a factory-created instance, so Trae's sessions are fully
12
+ // isolated from Kiro's (and any other consumer of the shared factory).
10
13
 
11
- import { createHash } from "node:crypto";
12
14
  import type { CanonicalMessage, UsageRecord } from "../../../protocol/canonical-model";
15
+ import { createSessionCache, estimateSessionCache, resetSessionCacheForTesting } from "../shared/session-cache";
13
16
 
14
- /** Bounded in-memory tracker: one entry per session, oldest evicted first. */
15
- const MAX_SESSIONS = 512;
16
-
17
- interface TraeSessionCacheEntry {
18
- /** hash(full messages) -> reported input tokens for that exact list. */
19
- readonly seen: Map<string, number>;
20
- /** Insertion order for bounded eviction. */
21
- readonly order: string[];
22
- }
23
-
24
- const sessions = new Map<string, TraeSessionCacheEntry>();
17
+ const cache = createSessionCache();
25
18
 
26
- function hashOf(messages: readonly CanonicalMessage[]): string {
27
- return createHash("sha256").update(JSON.stringify(messages)).digest("hex");
28
- }
29
-
30
- function sessionFor(sessionId: string): TraeSessionCacheEntry {
31
- let entry = sessions.get(sessionId);
32
- if (!entry) {
33
- entry = { seen: new Map(), order: [] };
34
- sessions.set(sessionId, entry);
35
- }
36
- return entry;
37
- }
38
-
39
- function remember(sessionId: string, fullHash: string, inputTokens: number): void {
40
- const entry = sessionFor(sessionId);
41
- if (!entry.seen.has(fullHash)) {
42
- entry.order.push(fullHash);
43
- if (entry.order.length > MAX_SESSIONS) {
44
- const oldest = entry.order.shift();
45
- if (oldest !== undefined) entry.seen.delete(oldest);
46
- }
47
- }
48
- entry.seen.set(fullHash, inputTokens);
49
- if (sessions.size > MAX_SESSIONS) {
50
- const oldestSession = sessions.keys().next().value;
51
- if (oldestSession !== undefined) sessions.delete(oldestSession);
52
- }
53
- }
54
-
55
- /**
56
- * Estimates how much of this request's input was served from cache.
57
- *
58
- * The longest prefix of `messages` that was ever sent as a complete request in
59
- * this session is considered cached, and its recorded token count is the
60
- * cached portion — if that prefix is the whole request, everything was cached.
61
- * This models how upstream prompt caching actually behaves (byte-identical
62
- * prefix reuse) without trusting a counter the upstream never reports.
63
- *
64
- * Returns the record unchanged when there is nothing to estimate (no session,
65
- * no history, or upstream already reported a real hit).
66
- */
67
19
  export function estimateTraeSessionCache(
68
20
  record: UsageRecord,
69
21
  sessionId: string | undefined,
70
22
  messages: readonly CanonicalMessage[] | undefined,
71
23
  ): UsageRecord {
72
- if (!sessionId || !messages || messages.length === 0) return record;
73
- const upstreamReported =
74
- typeof record.cached_input_tokens === "number" && record.cached_input_tokens > 0;
75
- if (upstreamReported) return record;
76
-
77
- const fullHash = hashOf(messages);
78
- const entry = sessions.get(sessionId);
79
-
80
- if (entry) {
81
- // Longest prefix that matches a previously sent complete request.
82
- for (let len = messages.length; len >= 1; len -= 1) {
83
- const prefix = messages.slice(0, len);
84
- const tokens = entry.seen.get(hashOf(prefix));
85
- if (tokens === undefined) continue;
86
- if (len === messages.length) {
87
- // Byte-identical request: the whole input came from cache.
88
- return {
89
- ...record,
90
- cached_input_tokens: record.input_tokens,
91
- uncached_input_tokens: 0,
92
- };
93
- }
94
- const cached = Math.min(tokens, record.input_tokens);
95
- return {
96
- ...record,
97
- cached_input_tokens: cached,
98
- uncached_input_tokens: Math.max(0, record.input_tokens - cached),
99
- };
100
- }
101
- }
102
-
103
- remember(sessionId, fullHash, record.input_tokens);
104
- return record;
24
+ return estimateSessionCache(cache, record, sessionId, messages);
105
25
  }
106
26
 
107
27
  /** Drops all tracked sessions. Test-only. */
108
28
  export function resetTraeSessionCacheForTesting(): void {
109
- sessions.clear();
29
+ resetSessionCacheForTesting(cache);
110
30
  }
@@ -12,7 +12,7 @@
12
12
  // intl stays on its static roster and says so via `modelListSupported`.
13
13
 
14
14
  import { defineModel, type ModelDefinition } from "../../provider-model-definition";
15
- import { TRAE_AGENT_CHAT_PATH, TRAE_CHAT_PATH, type TraeRealm } from "./trae-realm";
15
+ import { TRAE_AGENT_CHAT_PATH, TRAE_CHAT_PATH } from "./trae-realm";
16
16
 
17
17
  /** One roster row, as upstream describes it. */
18
18
  export interface TraeModelRow {
@@ -135,11 +135,6 @@ function traeModels(rows: readonly TraeModelRow[], providerId: string): readonly
135
135
  export const TRAE_CN_MODELS: readonly ModelDefinition[] = traeModels(TRAE_CN_ROWS, "traecn");
136
136
  export const TRAE_INTL_MODELS: readonly ModelDefinition[] = traeModels(TRAE_INTL_ROWS, "trae");
137
137
 
138
- /** Roster for a realm. */
139
- export function traeStaticModels(realm: TraeRealm): readonly ModelDefinition[] {
140
- return realm === "cn" ? TRAE_CN_MODELS : TRAE_INTL_MODELS;
141
- }
142
-
143
138
  /**
144
139
  * Reads the largest context window out of one upstream model object.
145
140
  *
@@ -13,11 +13,11 @@
13
13
  // `iter_events` in `trae_client.py`).
14
14
 
15
15
  import type { CanonicalRequest, ContentPart } from "../../../protocol/canonical-model";
16
+ import { resolveWireMaxTokens } from "../../../protocol/translation/quirks";
16
17
  import {
17
18
  TRAE_AGENT_CHAT_PATH,
18
19
  TRAE_AGENT_FUNCTION,
19
20
  TRAE_CHAT_PATH,
20
- TRAE_MODEL_LIST_PATH,
21
21
  TRAE_REALMS,
22
22
  type TraeRealm,
23
23
  } from "./trae-realm";
@@ -161,6 +161,7 @@ export function buildTraeChatBody(
161
161
  request: CanonicalRequest,
162
162
  realm: TraeRealm,
163
163
  sessionId?: string,
164
+ maxOutputTokens?: number,
164
165
  ): TraeChatBody {
165
166
  if (modelId.length === 0) throw new Error("trae model name is required");
166
167
 
@@ -257,13 +258,26 @@ export function buildTraeChatBody(
257
258
  },
258
259
  }));
259
260
  }
261
+ const requestedMaxTokens =
262
+ typeof controls.max_tokens === "number" && Number.isFinite(controls.max_tokens)
263
+ ? controls.max_tokens
264
+ : undefined;
260
265
  const options: Record<string, unknown> = {
261
266
  temperature: controls.temperature,
262
267
  top_p: controls.top_p,
263
- max_tokens: controls.max_tokens,
264
268
  stop: controls.stop,
265
-
266
269
  };
270
+ // Route a numeric `max_tokens` through the shared chat-wire bound so it is
271
+ // floored to the wire minimum and clamped to the model's roster output limit
272
+ // — it must never balloon unboundedly (the roster's `out` is the ceiling).
273
+ // Non-numeric values keep the previous verbatim passthrough, and an absent
274
+ // value still omits the field (the chat bound must not invent a default here).
275
+ options["max_tokens"] =
276
+ requestedMaxTokens === undefined
277
+ ? controls.max_tokens
278
+ : resolveWireMaxTokens("chat", { max_tokens: requestedMaxTokens }, {
279
+ ...(maxOutputTokens === undefined ? {} : { maxOutputTokens }),
280
+ });
267
281
  for (const key of PASSTHROUGH_OPTIONS) {
268
282
  const value = options[key];
269
283
  if (value !== undefined && value !== null) body[key] = value;
@@ -272,13 +286,8 @@ export function buildTraeChatBody(
272
286
  }
273
287
 
274
288
  /** Body for the live model list. Upstream requires a body even to list. */
275
- export function buildTraeModelListBody(): Record<string, unknown> {
276
- return { type: "chat" };
277
- }
278
-
279
289
  export const TRAE_CHAT_ENDPOINT = TRAE_CHAT_PATH;
280
290
  export const TRAE_AGENT_ENDPOINT = TRAE_AGENT_CHAT_PATH;
281
- export const TRAE_MODEL_LIST_ENDPOINT = TRAE_MODEL_LIST_PATH;
282
291
 
283
292
  /**
284
293
  * Rewrites a chat-surface body into the agent surface's shape.
@@ -88,7 +88,6 @@ export const TRAE_AUTH_CODE_EXCHANGE_PATHS: readonly string[] = [
88
88
  "/trae/api/v3/oauth/ExchangeToken",
89
89
  "/cloudide/api/v3/public/oauth/ExchangeToken",
90
90
  ];
91
- export const TRAE_TEMP_TOKEN_PATH = "/cloudide/api/v3/trae/GenerateTempToken";
92
91
  export const TRAE_GET_USER_INFO_PATH = "/cloudide/api/v3/trae/GetUserInfo";
93
92
 
94
93
  /** Browser-login path on the host `GetLoginGuidance` names. */
@@ -123,13 +122,7 @@ export const TRAE_LOGIN_GUIDANCE_URLS: readonly string[] = [
123
122
 
124
123
  /** Usage / entitlement paths, relative to the realm's `pay` host. */
125
124
  export const TRAE_SESSION_USAGE_PATH = "/api/v1/commercial/get_session_usage";
126
- export const TRAE_ACTIVITY_PATH = "/api/v1/commercial/get_user_activity";
127
125
  export const TRAE_ENT_USAGE_PATH = "/trae/api/v1/pay/ide_user_ent_usage";
128
- export const TRAE_PAY_STATUS_PATH = "/trae/api/v1/pay/ide_user_pay_status";
129
-
130
- /** Growth paths, relative to the realm's `ug` host. CN-only upstream. */
131
- export const TRAE_CHECKIN_STATUS_PATH = "/trae/api/v2/ug/checkin_credits/status";
132
- export const TRAE_CHECKIN_CLAIM_PATH = "/trae/api/v2/ug/checkin_credits/claim";
133
126
 
134
127
  /**
135
128
  * Realm → deployment.
@@ -7,9 +7,10 @@
7
7
  import { GatewayError } from "../../../protocol/gateway-error";
8
8
  import type { CanonicalEvent, CanonicalMessage, CanonicalRequest, CanonicalStopReason } from "../../../protocol/canonical-model";
9
9
  import type { UsageRecord } from "../../../protocol/canonical-model";
10
- import { usageFromProvider } from "../../provider-usage";
10
+ import { applyCacheMode, usageFromProvider } from "../../provider-usage";
11
11
  import {
12
12
  readCredentialSecret,
13
+ assertWireFamily,
13
14
  type ProviderAdapter,
14
15
  type ProviderDispatchContext,
15
16
  type ProviderDispatchTarget,
@@ -67,7 +68,7 @@ const STOP_REASONS: Readonly<Record<string, CanonicalStopReason>> = {
67
68
  function traeAuth(secret: string, accountId: string | undefined): TraeAuth {
68
69
  const token = extractToken(secret);
69
70
  if (token === undefined) {
70
- throw new GatewayError("authentication_failed", 401, "Trae credential has no access token", {}, "upstream");
71
+ throw new GatewayError("authentication_failed", 401, "Trae credential has no access token (request {requestId}). Wrong key, right door — check the credential 🔑", {}, "upstream");
71
72
  }
72
73
  return { token, uid: accountId ?? "" };
73
74
  }
@@ -102,7 +103,11 @@ function extractToken(secret: string): string | undefined {
102
103
  * `quota_exceeded` 429, not a platform fault.
103
104
  * - Everything else is a platform fault (`platform_unavailable`).
104
105
  */
105
- function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
106
+ function throwTraeUpstreamError(
107
+ codeRaw: unknown,
108
+ messageRaw: unknown,
109
+ providerId?: string,
110
+ ): never {
106
111
  const code =
107
112
  typeof codeRaw === "number" || typeof codeRaw === "string" ? String(codeRaw) : undefined;
108
113
  const message =
@@ -116,8 +121,13 @@ function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
116
121
  throw new GatewayError(
117
122
  "authentication_failed",
118
123
  401,
119
- `Trae could not authenticate the account (upstream code 1001): ${message}`,
120
- { providerCode: "1001", providerStatus: 1001, credentialEvidence: true },
124
+ `Trae could not authenticate the account (upstream code 1001): ${message} (request {requestId}). Wrong key, right door — check the credential 🔑`,
125
+ {
126
+ providerCode: "1001",
127
+ providerStatus: 1001,
128
+ credentialEvidence: true,
129
+ ...(providerId ? { providerId } : {}),
130
+ },
121
131
  "upstream",
122
132
  );
123
133
  }
@@ -127,13 +137,39 @@ function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
127
137
  throw new GatewayError(
128
138
  "quota_exceeded",
129
139
  429,
130
- `Trae quota exceeded (upstream code ${code ?? "unknown"}): ${message}`,
131
- { providerCode: code ?? "4008", providerStatus: code === "4008" ? 4008 : 429 },
140
+ `Trae quota exceeded (upstream code ${code ?? "unknown"}): ${message} (request {requestId}). You've maxed this window — pace yourself ⏳`,
141
+ {
142
+ providerCode: code ?? "4008",
143
+ providerStatus: code === "4008" ? 4008 : 429,
144
+ ...(providerId ? { providerId } : {}),
145
+ },
132
146
  "upstream",
133
147
  );
134
148
  }
135
149
 
136
- throw new GatewayError("platform_unavailable", 502, message, {}, "upstream");
150
+ // Trae answers `4013 "AI service is not available in the current region now."`
151
+ // when the upstream does not serve the account's region. That is a durable
152
+ // verdict, not a transient transport fault: the account reproduces it on
153
+ // every request until the region opens, so it must cool hard rather than be
154
+ // re-dialled every thirty seconds. The classifier scopes this to the account
155
+ // (`trae-region-unavailable`) — never the proxy pool.
156
+ if (code === "4013" || lower.includes("not available in the current region")) {
157
+ throw new GatewayError(
158
+ "platform_unavailable",
159
+ 502,
160
+ message,
161
+ { providerCode: "4013", ...(providerId ? { providerId } : {}) },
162
+ "upstream",
163
+ );
164
+ }
165
+
166
+ throw new GatewayError(
167
+ "platform_unavailable",
168
+ 502,
169
+ message,
170
+ { ...(providerId ? { providerId } : {}) },
171
+ "upstream",
172
+ );
137
173
  }
138
174
 
139
175
  class TraeAdapter implements ProviderAdapter {
@@ -152,11 +188,7 @@ class TraeAdapter implements ProviderAdapter {
152
188
  context: ProviderDispatchContext,
153
189
  ): AsyncIterable<CanonicalEvent> {
154
190
  if (candidate.wire_family !== "chat") {
155
- throw new GatewayError(
156
- "capability_unsupported",
157
- 400,
158
- `trae supports chat only, got ${candidate.wire_family}`,
159
- );
191
+ assertWireFamily(candidate, "chat", "trae");
160
192
  }
161
193
  const secret = readCredentialSecret(context.credential, "Trae credential is required");
162
194
  const modelId = candidate.model_id || request.model;
@@ -175,7 +207,13 @@ class TraeAdapter implements ProviderAdapter {
175
207
  * hash) and thread it through.
176
208
  */
177
209
  const sessionId = request.session_id ?? resolvePromptCacheKey(request, context);
178
- const body = buildTraeChatBody(modelId, request, this.realm, sessionId);
210
+ const body = buildTraeChatBody(
211
+ modelId,
212
+ request,
213
+ this.realm,
214
+ sessionId,
215
+ candidate.output_limit ?? undefined,
216
+ );
179
217
  // The cache estimator is scoped per (session, model): upstream cache keys
180
218
  // are model-specific, so two models sharing a conversation id must not
181
219
  // treat each other's identical prefixes as hits.
@@ -214,7 +252,7 @@ class TraeAdapter implements ProviderAdapter {
214
252
  });
215
253
  if (!response.ok) throw await mapUpstreamHttpError(response, this.provider_id);
216
254
  if (!response.body) {
217
- throw new GatewayError("platform_unavailable", 502, "Trae returned empty body", {}, "upstream");
255
+ throw new GatewayError("platform_unavailable", 502, "Trae returned empty body (request {requestId}). The upstream came back empty-handed — retry 🌙", {}, "upstream");
218
256
  }
219
257
  // Headers arrived, so the pre-stream deadline has served its purpose;
220
258
  // from here the gateway's own stall watchdog governs the body.
@@ -270,7 +308,7 @@ class TraeAdapter implements ProviderAdapter {
270
308
  }
271
309
  if (frame.event === "error") {
272
310
  const data = frame.data as { message?: unknown; code?: unknown };
273
- throwTraeUpstreamError(data.code, data.message);
311
+ throwTraeUpstreamError(data.code, data.message, this.provider_id);
274
312
  }
275
313
  if (typeof frame.data !== "object" || frame.data === null) continue;
276
314
  const record = frame.data as Record<string, unknown>;
@@ -283,7 +321,7 @@ class TraeAdapter implements ProviderAdapter {
283
321
  const nested = record["error"] as Record<string, unknown> | undefined;
284
322
  const code = record["code"] ?? nested?.["code"];
285
323
  const message = record["message"] ?? nested?.["message"];
286
- throwTraeUpstreamError(code, message);
324
+ throwTraeUpstreamError(code, message, this.provider_id);
287
325
  }
288
326
  /**
289
327
  * Two frame layouts reach here and both are live.
@@ -441,8 +479,10 @@ class TraeAdapter implements ProviderAdapter {
441
479
  const record = usageFromProvider(usage);
442
480
  if (record === undefined) return undefined;
443
481
  // Trae's agent surface never reports prompt-cache hits; for repeated
444
- // prefixes we estimate them locally (see trae-cache.ts).
445
- return estimateTraeSessionCache(record, sessionId, messages);
482
+ // prefixes we estimate them locally (see trae-cache.ts). Then the
483
+ // operator's cache mode decides whether a hit makes the whole input count
484
+ // as cached.
485
+ return applyCacheMode(estimateTraeSessionCache(record, sessionId, messages));
446
486
  }
447
487
 
448
488
  }
@@ -44,10 +44,10 @@ const XAI_AUTH_SERVER = {
44
44
  } as const;
45
45
 
46
46
  export { XAI_AUTH_SERVER };
47
- export const XAI_CLIENT_ID = XAI_AUTH_SERVER.clientId;
48
- export const XAI_DEVICE_URL = XAI_AUTH_SERVER.deviceUrl;
49
- export const XAI_TOKEN_URL = XAI_AUTH_SERVER.tokenUrl;
50
- export const XAI_USERINFO_URL = XAI_AUTH_SERVER.userinfoUrl;
47
+ const XAI_CLIENT_ID = XAI_AUTH_SERVER.clientId;
48
+ const XAI_DEVICE_URL = XAI_AUTH_SERVER.deviceUrl;
49
+ const XAI_TOKEN_URL = XAI_AUTH_SERVER.tokenUrl;
50
+ const XAI_USERINFO_URL = XAI_AUTH_SERVER.userinfoUrl;
51
51
 
52
52
  /**
53
53
  * Scopes the subscription token needs.
@@ -56,7 +56,7 @@ export const XAI_USERINFO_URL = XAI_AUTH_SERVER.userinfoUrl;
56
56
  * what admits the token to `api.x.ai`. The rest are the OIDC identity scopes the
57
57
  * userinfo label is read from.
58
58
  */
59
- export const XAI_SCOPE = [
59
+ const XAI_SCOPE = [
60
60
  "openid",
61
61
  "profile",
62
62
  "email",
@@ -78,7 +78,7 @@ function unwrapEnvelope(body: unknown, operation: string): unknown {
78
78
  // codebase is 401. A 400 told the client to fix its body when the real
79
79
  // action is to fix the credential — and HTTP itself reserves 401 for
80
80
  // exactly this, so a standard client reads the class from the status.
81
- throw new GatewayError("authentication_failed", 401, `Z.AI ${message}`, { providerId: "zcode" });
81
+ throw new GatewayError("authentication_failed", 401, `Z.AI ${message} (request {requestId}). Wrong key, right door — check the credential 🔑`, { providerId: "zcode" });
82
82
  }
83
83
  }
84
84
  return root.data ?? body;