cartethyia 2.7.4 → 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 (553) hide show
  1. package/.env.example +2 -0
  2. package/README.md +17 -5
  3. package/dist/dashboard/assets/{BannedPage-ChG5svFb.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-BIcWQun7.js → CliToolDetailPage-DZKmVuJN.js} +1 -1
  8. package/dist/dashboard/assets/CliToolDetailPage-DZKmVuJN.js.gz +0 -0
  9. package/dist/dashboard/assets/{CliToolsPage-Bf2VelDe.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-ggeMSjte.js → CustomizationPage-BKj_r0rp.js} +1 -1
  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-U6AKaJcF.js → LoginPage-DkXb6dx-.js} +1 -1
  20. package/dist/dashboard/assets/LoginPage-DkXb6dx-.js.gz +0 -0
  21. package/dist/dashboard/assets/{ModelPicker-BMS2t8BA.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-lsrx7NYg.js → ProxyPage-5SnUSy3j.js} +1 -1
  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-f0DE1h0-.js → SetupPage-WTa0sktC.js} +1 -1
  38. package/dist/dashboard/assets/SetupPage-WTa0sktC.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-Cq5tW7hW.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-C0K-c4eo.js +1 -0
  48. package/dist/dashboard/assets/assert-C0K-c4eo.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-D9CS6dZk.js → badge-DfbhQU4k.js} +1 -1
  50. package/dist/dashboard/assets/badge-DfbhQU4k.js.gz +0 -0
  51. package/dist/dashboard/assets/{banner-DympBNq4.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-ibRWU_uT.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-CQXVMn4P.js +1 -0
  62. package/dist/dashboard/assets/cli-tools-CQXVMn4P.js.gz +0 -0
  63. package/dist/dashboard/assets/{clipboard-button-DJm-9pz7.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-8fiE6tec.js → dialog-BEK7KP0H.js} +1 -1
  66. package/dist/dashboard/assets/dialog-BEK7KP0H.js.gz +0 -0
  67. package/dist/dashboard/assets/{drawer-CqGYeOrd.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-BSAsYsmV.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-D-MTJxMr.js → formatters-BAACA727.js} +1 -1
  76. package/dist/dashboard/assets/formatters-BAACA727.js.gz +0 -0
  77. package/dist/dashboard/assets/{github-badge-CPK47xQx.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-DBNPOfhV.js → index-FQlj0HUT.js} +2 -2
  80. package/dist/dashboard/assets/index-FQlj0HUT.js.gz +0 -0
  81. package/dist/dashboard/assets/{inline-BT0zntEr.js → inline-C4gU5iOL.js} +1 -1
  82. package/dist/dashboard/assets/inline-C4gU5iOL.js.gz +0 -0
  83. package/dist/dashboard/assets/{input-Da2ZViWg.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-BXNeLw6M.js → layout-CajrYUnD.js} +1 -1
  86. package/dist/dashboard/assets/layout-CajrYUnD.js.gz +0 -0
  87. package/dist/dashboard/assets/{list-row-BycOrrIV.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/network-C5UBACrJ.js +1 -0
  92. package/dist/dashboard/assets/network-C5UBACrJ.js.gz +0 -0
  93. package/dist/dashboard/assets/numbers-CUWAZK4J.js +2 -0
  94. package/dist/dashboard/assets/numbers-CUWAZK4J.js.gz +0 -0
  95. package/dist/dashboard/assets/pagination-Xsi9Qx04.js +1 -0
  96. package/dist/dashboard/assets/pagination-Xsi9Qx04.js.gz +0 -0
  97. package/dist/dashboard/assets/quota-DvQbD_sr.js +1 -0
  98. package/dist/dashboard/assets/quota-DvQbD_sr.js.gz +0 -0
  99. package/dist/dashboard/assets/routing-in0f_IfK.js +1 -0
  100. package/dist/dashboard/assets/routing-in0f_IfK.js.gz +0 -0
  101. package/dist/dashboard/assets/{select-BIYIBkMU.js → select-BLULNqTp.js} +1 -1
  102. package/dist/dashboard/assets/select-BLULNqTp.js.gz +0 -0
  103. package/dist/dashboard/assets/settings-CcGczj6I.js +1 -0
  104. package/dist/dashboard/assets/settings-CcGczj6I.js.gz +0 -0
  105. package/dist/dashboard/assets/shield-BMQNxORh.js +1 -0
  106. package/dist/dashboard/assets/shield-BMQNxORh.js.gz +0 -0
  107. package/dist/dashboard/assets/{stack-DfgnFDWY.js → stack-D2lIR0tg.js} +1 -1
  108. package/dist/dashboard/assets/stack-D2lIR0tg.js.gz +0 -0
  109. package/dist/dashboard/assets/{state-CkfdYWel.js → state-DTARjfiW.js} +1 -1
  110. package/dist/dashboard/assets/state-DTARjfiW.js.gz +0 -0
  111. package/dist/dashboard/assets/{switch-SYm237HG.js → switch-c0oPSnqW.js} +1 -1
  112. package/dist/dashboard/assets/switch-c0oPSnqW.js.gz +0 -0
  113. package/dist/dashboard/assets/{useMutation-BQqCRNIi.js → useMutation-m8WGNPrz.js} +1 -1
  114. package/dist/dashboard/assets/useMutation-m8WGNPrz.js.gz +0 -0
  115. package/dist/dashboard/console-backgrounds.jpg +0 -0
  116. package/dist/dashboard/console-backgrounds_initial.jpg +0 -0
  117. package/dist/dashboard/index.html +2 -2
  118. package/dist/dashboard/index.html.gz +0 -0
  119. package/dist/dashboard/precompressed-assets.json +56 -55
  120. package/migrations/full-postgres/0036_system_prompt_presets_refs.sql +10 -0
  121. package/migrations/full-postgres/0037_share_concurrency_scope.sql +3 -0
  122. package/migrations/full-postgres/0038_add_accounts_quota_snapshot.sql +7 -0
  123. package/migrations/full-postgres/0039_add_telemetry_provider_model_indexes.sql +13 -0
  124. package/migrations/full-postgres/0040_add_models_dialect.sql +3 -0
  125. package/migrations/full-postgres/0041_add_daily_checkin_ledger_account_fk.sql +7 -0
  126. package/migrations/lite-sqlite3/0036_system_prompt_presets_refs.sql +14 -0
  127. package/migrations/lite-sqlite3/0037_share_concurrency_scope.sql +3 -0
  128. package/migrations/lite-sqlite3/0038_add_accounts_quota_snapshot.sql +4 -0
  129. package/migrations/lite-sqlite3/0039_add_telemetry_provider_model_indexes.sql +6 -0
  130. package/migrations/lite-sqlite3/0040_add_models_dialect.sql +3 -0
  131. package/migrations/lite-sqlite3/0041_add_daily_checkin_ledger_account_fk.sql +26 -0
  132. package/package.json +4 -6
  133. package/scripts/cli/update.ts +15 -41
  134. package/src/boot/app.ts +58 -2
  135. package/src/boot/dependencies.ts +786 -732
  136. package/src/boot/lifecycle.ts +11 -12
  137. package/src/config/cooldowns.ts +34 -55
  138. package/src/config/network.ts +1 -1
  139. package/src/config/package-paths.ts +1 -1
  140. package/src/config/providers.ts +13 -14
  141. package/src/config/resources.ts +0 -5
  142. package/src/config/runtime.ts +2 -5
  143. package/src/config/spec.ts +26 -6
  144. package/src/console/api-keys/ban-constants.ts +38 -0
  145. package/src/console/api-keys/contracts.ts +71 -62
  146. package/src/console/api-keys/routes.ts +48 -12
  147. package/src/console/auth/access.ts +4 -4
  148. package/src/console/auth/account-reset.ts +1 -1
  149. package/src/console/auth/audit-recorder.ts +1 -1
  150. package/src/console/auth/lockout.ts +7 -3
  151. package/src/console/auth/row-coercion.ts +57 -12
  152. package/src/console/auth/session-resolver.ts +1 -1
  153. package/src/console/auth/session-service.ts +8 -2
  154. package/src/console/auth/session.ts +37 -31
  155. package/src/console/auth/setup-service.ts +4 -3
  156. package/src/console/auth/user-store.ts +1 -1
  157. package/src/console/backup/9router-map.ts +0 -3
  158. package/src/console/backup/contracts.ts +9 -9
  159. package/src/console/backup/export-endpoint.ts +5 -6
  160. package/src/console/backup/nine-router.ts +1 -7
  161. package/src/console/backup/routes.ts +29 -33
  162. package/src/console/backup/service.ts +468 -468
  163. package/src/console/backup/store.ts +47 -29
  164. package/src/console/backup/validate.ts +11 -1
  165. package/src/console/cli-tools/contracts.ts +7 -7
  166. package/src/console/cli-tools/injectors/cline.ts +110 -110
  167. package/src/console/cli-tools/injectors/codex.ts +181 -181
  168. package/src/console/cli-tools/injectors/copilot.ts +108 -108
  169. package/src/console/cli-tools/injectors/driver.ts +247 -247
  170. package/src/console/cli-tools/injectors/jcode.ts +115 -115
  171. package/src/console/cli-tools/injectors/openclaw.ts +161 -161
  172. package/src/console/cli-tools/injectors/opencode.ts +153 -153
  173. package/src/console/cli-tools/routes.ts +1 -1
  174. package/src/console/cli-tools/service.ts +1 -1
  175. package/src/console/cli-tools/store.ts +2 -2
  176. package/src/console/console-router.ts +32 -0
  177. package/src/console/dashboard-assets.ts +9 -9
  178. package/src/console/domain-registration.ts +16 -2
  179. package/src/console/inferhub/client.ts +0 -7
  180. package/src/console/inferhub/key-store.ts +1 -1
  181. package/src/console/inferhub/normalize.ts +2 -2
  182. package/src/console/inferhub/routes.ts +1 -1
  183. package/src/console/inferhub/types.ts +1 -1
  184. package/src/console/observability/contracts.ts +1 -1
  185. package/src/console/observability/live.ts +31 -18
  186. package/src/console/observability/logs.ts +1 -1
  187. package/src/console/observability/sse.ts +62 -8
  188. package/src/console/observability/store.ts +20 -4
  189. package/src/console/providers/catalog/catalog-projections.ts +1 -1
  190. package/src/console/providers/catalog/contracts.ts +39 -0
  191. package/src/console/providers/catalog/model-operations.ts +1 -1
  192. package/src/console/providers/catalog/provider-operations.ts +95 -17
  193. package/src/console/providers/catalog/public-model-store.ts +0 -0
  194. package/src/console/providers/catalog/routes.ts +27 -3
  195. package/src/console/providers/catalog/store.ts +147 -8
  196. package/src/console/providers/detail/routes.ts +1 -1
  197. package/src/console/providers/oauth/callback-listener.ts +100 -18
  198. package/src/console/providers/oauth/routes.ts +92 -13
  199. package/src/console/quota/account-quota-global.ts +41 -3
  200. package/src/console/quota/account-quota-shared.ts +10 -3
  201. package/src/console/quota/account-quota-tenant.ts +259 -66
  202. package/src/console/quota/daily-growth-job.ts +308 -0
  203. package/src/console/quota/native-identity.ts +2 -2
  204. package/src/console/quota/quota-view.ts +1 -1
  205. package/src/console/remote-support/routes.ts +1 -1
  206. package/src/console/remote-support/service.ts +2 -2
  207. package/src/console/routing/model/contracts.ts +1 -1
  208. package/src/console/routing/pools/contracts.ts +2 -2
  209. package/src/console/routing/pools/import-parse.ts +3 -3
  210. package/src/console/routing/pools/relay-deploy.ts +3 -3
  211. package/src/console/settings/contracts.ts +29 -2
  212. package/src/console/settings/store.ts +20 -0
  213. package/src/console/share/share-router.ts +100 -32
  214. package/src/console/share/share-stats.ts +4 -4
  215. package/src/console/share/share-usage.ts +1 -1
  216. package/src/console/shared/errors.ts +2 -2
  217. package/src/console/shared/object.ts +18 -0
  218. package/src/console/shared/read-through-cache.ts +4 -4
  219. package/src/console/shared/transaction.ts +14 -0
  220. package/src/console/system-prompt/contracts.ts +89 -12
  221. package/src/console/system-prompt/routes.ts +98 -45
  222. package/src/console/updates/apply-update.ts +244 -0
  223. package/src/console/updates/routes.ts +252 -97
  224. package/src/main.ts +11 -5
  225. package/src/network/http2-bidi.ts +1 -1
  226. package/src/network/ip-utils.ts +298 -0
  227. package/src/network/outbound-fetch.ts +1 -1
  228. package/src/network/pool/agent.ts +7 -6
  229. package/src/network/pool/byte-accounting.ts +1 -1
  230. package/src/network/pool/resolver.ts +16 -12
  231. package/src/network/pool/selector.ts +150 -136
  232. package/src/network/pool-health-machine.ts +1 -1
  233. package/src/network/rate-limit-verdict.ts +1 -1
  234. package/src/network/retry.ts +1 -1
  235. package/src/network/ssrf.ts +20 -71
  236. package/src/observability/event-log.ts +2 -2
  237. package/src/observability/event-query.ts +59 -291
  238. package/src/observability/log-sanitize.ts +1 -1
  239. package/src/observability/metrics.ts +4 -4
  240. package/src/observability/payload-capture.ts +6 -5
  241. package/src/observability/payload-store.ts +1 -1
  242. package/src/observability/runtime-metrics.ts +1 -1
  243. package/src/observability/telemetry-buffer.ts +12 -3
  244. package/src/observability/telemetry-reconciliation.ts +3 -3
  245. package/src/observability/token-speed.ts +1 -1
  246. package/src/persistence/connection-url.ts +1 -1
  247. package/src/persistence/db-handle.ts +1 -1
  248. package/src/persistence/db-pg.ts +2 -2
  249. package/src/persistence/db-sqlite.ts +3 -3
  250. package/src/persistence/dialect.ts +5 -1
  251. package/src/persistence/readiness.ts +1 -1
  252. package/src/persistence/redis.ts +1 -1
  253. package/src/persistence/schema.ts +113 -40
  254. package/src/persistence/shared-cache.ts +2 -2
  255. package/src/persistence/sort-order.ts +1 -1
  256. package/src/persistence/stores/api-key-store.ts +10 -1
  257. package/src/persistence/stores/share-store.ts +20 -8
  258. package/src/persistence/system-prompt-store.ts +63 -18
  259. package/src/persistence/tenant-preferences.ts +1 -1
  260. package/src/persistence/ttl-cache.ts +3 -3
  261. package/src/persistence/usage-flush.ts +7 -2
  262. package/src/protocol/canonical-model.ts +1 -1
  263. package/src/protocol/codecs.ts +6 -10
  264. package/src/protocol/dsml.ts +3 -49
  265. package/src/protocol/image-clamp.ts +2 -2
  266. package/src/protocol/reasoning-text.ts +1 -1
  267. package/src/protocol/reasoning.ts +7 -52
  268. package/src/protocol/registry.ts +50 -15
  269. package/src/protocol/request/chat.ts +46 -19
  270. package/src/protocol/request/codex.ts +1 -1
  271. package/src/protocol/request/messages.ts +46 -14
  272. package/src/protocol/request/responses.ts +19 -10
  273. package/src/protocol/response/chat.ts +25 -10
  274. package/src/protocol/response/codex.ts +1 -1
  275. package/src/protocol/response/messages.ts +1 -1
  276. package/src/protocol/response/omp-tool-call-markup.ts +1 -1
  277. package/src/protocol/response/responses.ts +1 -1
  278. package/src/protocol/sse-decoder.ts +50 -1
  279. package/src/protocol/stop-reason.ts +2 -2
  280. package/src/protocol/think-split.ts +347 -0
  281. package/src/protocol/translation/attachment-integrity.ts +3 -3
  282. package/src/protocol/translation/cache-controls.ts +8 -20
  283. package/src/protocol/translation/capabilities.ts +6 -6
  284. package/src/protocol/translation/dialect/deepseek.ts +10 -0
  285. package/src/protocol/translation/dialect/inband.ts +39 -0
  286. package/src/protocol/translation/dialect/model-thinking.ts +89 -0
  287. package/src/protocol/translation/dialect/qwen.ts +114 -0
  288. package/src/protocol/translation/dialect/resolver.ts +83 -0
  289. package/src/protocol/translation/dialect/rules.ts +93 -0
  290. package/src/protocol/translation/dialect/thinking-ladder.ts +245 -0
  291. package/src/protocol/translation/dialect/types.ts +58 -0
  292. package/src/protocol/translation/quirks.ts +18 -4
  293. package/src/protocol/translation/thinking.ts +12 -252
  294. package/src/protocol/translation/tool-id.ts +3 -3
  295. package/src/protocol/translation/tool-repair.ts +1 -1
  296. package/src/protocol/upstream/post-json.ts +6 -1
  297. package/src/providers/adapters/compatible-adapter.ts +42 -3
  298. package/src/providers/authentication/jwt-validator.ts +0 -5
  299. package/src/providers/authentication/oauth-client.ts +254 -253
  300. package/src/providers/authentication/oauth-flow-store.ts +42 -7
  301. package/src/providers/bundled-discovery-providers.ts +6 -30
  302. package/src/providers/configured-openai-providers.ts +82 -97
  303. package/src/providers/default-registry.ts +23 -35
  304. package/src/providers/discovery/catalog/catalog-format.ts +13 -2
  305. package/src/providers/discovery/discovery-types.ts +0 -1
  306. package/src/providers/discovery/openai-model-discovery.ts +2 -2
  307. package/src/providers/discovery/probe-phases.ts +48 -13
  308. package/src/providers/discovery/probing-service.ts +6 -8
  309. package/src/providers/integrations/agentrouter/agentrouter.ts +12 -2
  310. package/src/providers/integrations/antigravity/antigravity-oauth.ts +0 -1
  311. package/src/providers/integrations/antigravity/antigravity-protocol.ts +0 -14
  312. package/src/providers/integrations/antigravity/antigravity.ts +2 -2
  313. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -1
  314. package/src/providers/integrations/buddy/buddy-chat-shared.ts +20 -4
  315. package/src/providers/integrations/buddy/buddy-cli-headers.ts +19 -52
  316. package/src/providers/integrations/buddy/buddy-identity.ts +86 -0
  317. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +1 -1
  318. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +1 -2
  319. package/src/providers/integrations/buddy/codebuddy/provider.ts +4 -15
  320. package/src/providers/integrations/buddy/codebuddy/shared.ts +30 -9
  321. package/src/providers/integrations/buddy/workbuddy/provider.ts +5 -9
  322. package/src/providers/integrations/buddy/workbuddy/shared.ts +21 -3
  323. package/src/providers/integrations/claude/claude-cch.ts +148 -148
  324. package/src/providers/integrations/claude/fallback-credit.ts +3 -7
  325. package/src/providers/integrations/cline/cline.ts +1 -1
  326. package/src/providers/integrations/codex/codex-device-code.ts +101 -101
  327. package/src/providers/integrations/codex/codex-oauth.ts +0 -1
  328. package/src/providers/integrations/commandcode/commandcode.ts +75 -115
  329. package/src/providers/integrations/commandcode/quota.ts +131 -51
  330. package/src/providers/integrations/cursor/cursor-http2.ts +0 -3
  331. package/src/providers/integrations/cursor/cursor-quota.ts +2 -6
  332. package/src/providers/integrations/cursor/cursor-request.ts +0 -87
  333. package/src/providers/integrations/cursor/cursor-shared.ts +0 -4
  334. package/src/providers/integrations/cursor/cursor.ts +38 -5
  335. package/src/providers/integrations/cursor/protocol/framing.ts +0 -56
  336. package/src/providers/integrations/cursor/protocol/messages.ts +0 -96
  337. package/src/providers/integrations/factory/factory.ts +9 -9
  338. package/src/providers/integrations/github/github-discovery.ts +55 -10
  339. package/src/providers/integrations/github/github-oauth.ts +6 -5
  340. package/src/providers/integrations/github/github.ts +41 -14
  341. package/src/providers/integrations/grok/grok-oauth.ts +261 -261
  342. package/src/providers/integrations/grok/grok-quota-frame.ts +1 -1
  343. package/src/providers/integrations/grok/grok-quota.ts +16 -7
  344. package/src/providers/integrations/grok/grok-ratelimit-store.ts +0 -5
  345. package/src/providers/integrations/grok/grok-ratelimit.ts +3 -0
  346. package/src/providers/integrations/grok/grok.ts +86 -36
  347. package/src/providers/integrations/kilo/kilo-oauth.ts +1 -1
  348. package/src/providers/integrations/kiro/kiro-cache.ts +31 -0
  349. package/src/providers/integrations/kiro/kiro-catalog.ts +31 -5
  350. package/src/providers/integrations/kiro/kiro-discovery.ts +47 -43
  351. package/src/providers/integrations/kiro/kiro-machine-id.ts +6 -3
  352. package/src/providers/integrations/kiro/kiro-oauth.ts +523 -255
  353. package/src/providers/integrations/kiro/kiro-quota.ts +35 -47
  354. package/src/providers/integrations/kiro/kiro-request.ts +8 -11
  355. package/src/providers/integrations/kiro/kiro-stream.ts +13 -0
  356. package/src/providers/integrations/kiro/kiro.ts +81 -68
  357. package/src/providers/integrations/muse/muse-oauth.ts +0 -1
  358. package/src/providers/integrations/muse/muse-quota.ts +0 -4
  359. package/src/providers/integrations/opencode/fingerprint.ts +7 -5
  360. package/src/providers/integrations/opencode/provider.ts +17 -24
  361. package/src/providers/integrations/qoder/qoder-catalog.ts +85 -8
  362. package/src/providers/integrations/qoder/qoder-oauth.ts +165 -25
  363. package/src/providers/integrations/qoder/qoder-quota.ts +48 -6
  364. package/src/providers/integrations/qoder/qoder-realm.ts +10 -31
  365. package/src/providers/integrations/qoder/qoder-sse.ts +159 -0
  366. package/src/providers/integrations/qoder/qoder-umid.ts +21 -25
  367. package/src/providers/integrations/qoder/qoder-virtual.ts +12 -0
  368. package/src/providers/integrations/qoder/qoder.ts +354 -62
  369. package/src/providers/integrations/shared/connect.ts +0 -54
  370. package/src/providers/integrations/shared/hash.ts +15 -0
  371. package/src/providers/integrations/shared/session-cache.ts +136 -0
  372. package/src/providers/integrations/trae/trae-cache.ts +7 -87
  373. package/src/providers/integrations/trae/trae-catalog.ts +1 -6
  374. package/src/providers/integrations/trae/trae-protocol.ts +17 -8
  375. package/src/providers/integrations/trae/trae-realm.ts +0 -7
  376. package/src/providers/integrations/trae/trae.ts +53 -10
  377. package/src/providers/integrations/xai/xai-oauth.ts +5 -5
  378. package/src/providers/integrations/zcode-start-plan/gifts.ts +265 -0
  379. package/src/providers/integrations/zcode-start-plan/oauth.ts +154 -0
  380. package/src/providers/integrations/zcode-start-plan/provider.ts +131 -0
  381. package/src/providers/integrations/zcode-start-plan/quota.ts +152 -0
  382. package/src/providers/integrations/zcode-start-plan/zcode_prompt.json +10 -0
  383. package/src/providers/operations/account-error-classification.ts +131 -116
  384. package/src/providers/operations/account-health-service.ts +31 -39
  385. package/src/providers/operations/account-reset-service.ts +58 -1
  386. package/src/providers/operations/cli-platform.ts +31 -5
  387. package/src/providers/operations/client-version-resolver.ts +4 -6
  388. package/src/providers/operations/client-versions.ts +10 -7
  389. package/src/providers/operations/provider-catalog-seeder.ts +2 -0
  390. package/src/providers/operations/provider-catalog-service.ts +18 -2
  391. package/src/providers/operations/provider-credential-service.ts +19 -2
  392. package/src/providers/provider-contracts.ts +18 -7
  393. package/src/providers/provider-metadata.ts +17 -2
  394. package/src/providers/provider-model-definition.ts +22 -1
  395. package/src/providers/provider-probe.ts +4 -2
  396. package/src/providers/provider-usage.ts +81 -16
  397. package/src/providers/quota/cache.ts +29 -0
  398. package/src/providers/quota/quota-contracts.ts +4 -0
  399. package/src/providers/quota/refresh.ts +27 -4
  400. package/src/providers/quota/snapshot.ts +94 -0
  401. package/src/providers/search/search-provider.ts +1 -3
  402. package/src/providers/search/search-providers.ts +2 -1
  403. package/src/security/abuse.ts +4 -4
  404. package/src/security/admission/service.ts +2 -2
  405. package/src/security/admission/ttl.ts +61 -61
  406. package/src/security/api-key-auth.ts +16 -4
  407. package/src/security/client-router-fingerprint.ts +4 -4
  408. package/src/security/credential-codec.ts +3 -3
  409. package/src/security/csrf.ts +2 -2
  410. package/src/security/ip-boundary.ts +16 -189
  411. package/src/security/model-access-rule.ts +1 -1
  412. package/src/security/outbound-headers.ts +18 -0
  413. package/src/shared/invoke-guard.ts +47 -0
  414. package/src/transport/contracts.ts +13 -4
  415. package/src/transport/dispatch/attempt-finalize.ts +1 -1
  416. package/src/transport/dispatch/capture-policy.ts +34 -37
  417. package/src/transport/dispatch/empty-stream.ts +23 -20
  418. package/src/transport/dispatch/generation.ts +25 -45
  419. package/src/transport/dispatch/native-shared.ts +127 -0
  420. package/src/transport/dispatch/proxy-request.ts +3 -1
  421. package/src/transport/dispatch/responses-compact.ts +25 -46
  422. package/src/transport/dispatch/streaming/encoder.ts +18 -72
  423. package/src/transport/dispatch/streaming/finalize.ts +2 -2
  424. package/src/transport/dispatch/streaming/stream.ts +7 -3
  425. package/src/transport/dispatch/streaming/thinking-loop.ts +1 -1
  426. package/src/transport/dispatch/systemone.ts +20 -48
  427. package/src/transport/dispatch/token-count.ts +41 -38
  428. package/src/transport/dispatch/websearch.ts +19 -45
  429. package/src/transport/drain-endpoint.ts +1 -1
  430. package/src/transport/failure-policy.ts +6 -0
  431. package/src/transport/guards/auth-guard.ts +0 -6
  432. package/src/transport/guards/body-policy.ts +3 -3
  433. package/src/transport/guards/headroom-guard.ts +1 -1
  434. package/src/transport/guards/pipeline.ts +1 -1
  435. package/src/transport/guards/request-context.ts +12 -17
  436. package/src/transport/request/preparer.ts +286 -7
  437. package/src/transport/request/rtk/compress-request.ts +3 -3
  438. package/src/transport/request/rtk/rtk-constants.ts +2 -2
  439. package/src/transport/request/rtk/rtk-filters.ts +8 -8
  440. package/src/transport/request/state.ts +1 -13
  441. package/src/transport/request/system-prompt-injection.ts +74 -11
  442. package/src/transport/request/tenant-preferences.ts +22 -0
  443. package/src/transport/routing/candidate-index.ts +2 -2
  444. package/src/transport/routing/round-robin.ts +1 -1
  445. package/src/transport/routing/route-catalog.ts +17 -18
  446. package/src/transport/routing/route-model.ts +126 -33
  447. package/src/transport/routing/router.ts +152 -37
  448. package/src/transport/shutdown-notice.ts +2 -2
  449. package/src/transport/surface/adapters.ts +3 -3
  450. package/src/transport/surface/chat/encode.ts +7 -7
  451. package/src/transport/surface/chat/parse.ts +7 -7
  452. package/src/transport/surface/completion.ts +2 -2
  453. package/src/transport/surface/content-parts.ts +1 -1
  454. package/src/transport/surface/dialects.ts +2 -2
  455. package/src/transport/surface/messages/parse.ts +3 -3
  456. package/src/transport/surface/responses/adapter.ts +1 -1
  457. package/src/transport/surface/responses/errors.ts +0 -9
  458. package/src/transport/vision-handoff-cache.ts +58 -0
  459. package/src/transport/vision-handoff.ts +376 -0
  460. package/src/workers/account-identity-sweep.ts +2 -2
  461. package/src/workers/buddy-growth-tasks.ts +392 -346
  462. package/src/workers/daily-checkin.ts +102 -49
  463. package/src/workers/maintenance-lease.ts +2 -35
  464. package/src/workers/oauth-refresh-sweep.ts +8 -1
  465. package/src/workers/quota-refresh-sweep.ts +120 -82
  466. package/src/workers/scheduler.ts +67 -4
  467. package/src/workers/sweep-runner.ts +24 -5
  468. package/src/workers/zcode-gift-claim.ts +108 -0
  469. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js +0 -1
  470. package/dist/dashboard/assets/AccountCooldown-Bjo92Qat.js.gz +0 -0
  471. package/dist/dashboard/assets/BannedPage-ChG5svFb.js.gz +0 -0
  472. package/dist/dashboard/assets/CliToolDetailPage-BIcWQun7.js.gz +0 -0
  473. package/dist/dashboard/assets/CliToolsPage-Bf2VelDe.js.gz +0 -0
  474. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js +0 -1
  475. package/dist/dashboard/assets/CombosPage-DCgm5g6g.js.gz +0 -0
  476. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js +0 -1
  477. package/dist/dashboard/assets/ConsoleLogPage-a8mD0QF1.js.gz +0 -0
  478. package/dist/dashboard/assets/CustomizationPage-ggeMSjte.js.gz +0 -0
  479. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js +0 -1
  480. package/dist/dashboard/assets/HealthEventsModal-DzSWzE_j.js.gz +0 -0
  481. package/dist/dashboard/assets/LoginPage-U6AKaJcF.js.gz +0 -0
  482. package/dist/dashboard/assets/ModelPicker-BMS2t8BA.js.gz +0 -0
  483. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js +0 -1
  484. package/dist/dashboard/assets/OverviewPage-D2D4IiHl.js.gz +0 -0
  485. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js +0 -5
  486. package/dist/dashboard/assets/ProviderDetailPage-CrNf7j_X.js.gz +0 -0
  487. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +0 -1
  488. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  489. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js +0 -1
  490. package/dist/dashboard/assets/ProvidersPage-BSDbquc1.js.gz +0 -0
  491. package/dist/dashboard/assets/ProxyPage-lsrx7NYg.js.gz +0 -0
  492. package/dist/dashboard/assets/QuotaPage-L0skzML8.js +0 -1
  493. package/dist/dashboard/assets/QuotaPage-L0skzML8.js.gz +0 -0
  494. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js +0 -1
  495. package/dist/dashboard/assets/SettingsPage-CmAbjRHW.js.gz +0 -0
  496. package/dist/dashboard/assets/SetupPage-f0DE1h0-.js.gz +0 -0
  497. package/dist/dashboard/assets/SortableList-ClzpwyET.js +0 -1
  498. package/dist/dashboard/assets/SortableList-ClzpwyET.js.gz +0 -0
  499. package/dist/dashboard/assets/StudioPage-Cq5tW7hW.js.gz +0 -0
  500. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js +0 -56
  501. package/dist/dashboard/assets/UsagePage-Dfc9rWQn.js.gz +0 -0
  502. package/dist/dashboard/assets/api-keys-C38iXoO4.js +0 -1
  503. package/dist/dashboard/assets/api-keys-C38iXoO4.js.gz +0 -0
  504. package/dist/dashboard/assets/app-a159k0ub.css +0 -2
  505. package/dist/dashboard/assets/app-a159k0ub.css.gz +0 -0
  506. package/dist/dashboard/assets/assert-DbRA8EG2.js +0 -15
  507. package/dist/dashboard/assets/assert-DbRA8EG2.js.gz +0 -0
  508. package/dist/dashboard/assets/badge-D9CS6dZk.js.gz +0 -0
  509. package/dist/dashboard/assets/banner-DympBNq4.js.gz +0 -0
  510. package/dist/dashboard/assets/card-ibRWU_uT.js.gz +0 -0
  511. package/dist/dashboard/assets/cli-tools-63qBGaRw.js +0 -1
  512. package/dist/dashboard/assets/cli-tools-63qBGaRw.js.gz +0 -0
  513. package/dist/dashboard/assets/clipboard-button-DJm-9pz7.js.gz +0 -0
  514. package/dist/dashboard/assets/dialog-8fiE6tec.js.gz +0 -0
  515. package/dist/dashboard/assets/drawer-CqGYeOrd.js.gz +0 -0
  516. package/dist/dashboard/assets/entry-BSAsYsmV.js.gz +0 -0
  517. package/dist/dashboard/assets/entry-CiIQULZD.js +0 -4
  518. package/dist/dashboard/assets/entry-CiIQULZD.js.gz +0 -0
  519. package/dist/dashboard/assets/entry-Daz0lJ-W.js +0 -1
  520. package/dist/dashboard/assets/entry-Daz0lJ-W.js.gz +0 -0
  521. package/dist/dashboard/assets/formatters-D-MTJxMr.js.gz +0 -0
  522. package/dist/dashboard/assets/github-badge-CPK47xQx.js.gz +0 -0
  523. package/dist/dashboard/assets/index-DBNPOfhV.js.gz +0 -0
  524. package/dist/dashboard/assets/inline-BT0zntEr.js.gz +0 -0
  525. package/dist/dashboard/assets/input-Da2ZViWg.js.gz +0 -0
  526. package/dist/dashboard/assets/layout-BXNeLw6M.js.gz +0 -0
  527. package/dist/dashboard/assets/list-row-BycOrrIV.js.gz +0 -0
  528. package/dist/dashboard/assets/live-DCQNZpF7.js +0 -1
  529. package/dist/dashboard/assets/live-DCQNZpF7.js.gz +0 -0
  530. package/dist/dashboard/assets/network-9Yj2ZyLo.js +0 -1
  531. package/dist/dashboard/assets/network-9Yj2ZyLo.js.gz +0 -0
  532. package/dist/dashboard/assets/numbers-CEagj6ZZ.js +0 -2
  533. package/dist/dashboard/assets/numbers-CEagj6ZZ.js.gz +0 -0
  534. package/dist/dashboard/assets/quota-Caw7wqci.js +0 -1
  535. package/dist/dashboard/assets/quota-Caw7wqci.js.gz +0 -0
  536. package/dist/dashboard/assets/routing-CO9zCUus.js +0 -1
  537. package/dist/dashboard/assets/routing-CO9zCUus.js.gz +0 -0
  538. package/dist/dashboard/assets/select-BIYIBkMU.js.gz +0 -0
  539. package/dist/dashboard/assets/settings-jS3-PNSA.js +0 -1
  540. package/dist/dashboard/assets/settings-jS3-PNSA.js.gz +0 -0
  541. package/dist/dashboard/assets/stack-DfgnFDWY.js.gz +0 -0
  542. package/dist/dashboard/assets/state-CkfdYWel.js.gz +0 -0
  543. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js +0 -1
  544. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  545. package/dist/dashboard/assets/switch-SYm237HG.js.gz +0 -0
  546. package/dist/dashboard/assets/useMutation-BQqCRNIi.js.gz +0 -0
  547. package/src/network/response-headers.ts +0 -39
  548. package/src/protocol/response/dsml.ts +0 -38
  549. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +0 -229
  550. /package/dist/dashboard/assets/{app-BayTTy01.js → app-Bgd3zANQ.js} +0 -0
  551. /package/dist/dashboard/assets/{app-BayTTy01.js.gz → app-Bgd3zANQ.js.gz} +0 -0
  552. /package/dist/dashboard/assets/brand/{og_bansos.webp → og_bansos_initial.webp} +0 -0
  553. /package/dist/dashboard/assets/brand/{og_image.webp → og_image_initial.webp} +0 -0
@@ -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
+ }
@@ -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,7 +7,7 @@
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
13
  assertWireFamily,
@@ -103,7 +103,11 @@ function extractToken(secret: string): string | undefined {
103
103
  * `quota_exceeded` 429, not a platform fault.
104
104
  * - Everything else is a platform fault (`platform_unavailable`).
105
105
  */
106
- function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
106
+ function throwTraeUpstreamError(
107
+ codeRaw: unknown,
108
+ messageRaw: unknown,
109
+ providerId?: string,
110
+ ): never {
107
111
  const code =
108
112
  typeof codeRaw === "number" || typeof codeRaw === "string" ? String(codeRaw) : undefined;
109
113
  const message =
@@ -118,7 +122,12 @@ function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
118
122
  "authentication_failed",
119
123
  401,
120
124
  `Trae could not authenticate the account (upstream code 1001): ${message} (request {requestId}). Wrong key, right door — check the credential 🔑`,
121
- { providerCode: "1001", providerStatus: 1001, credentialEvidence: true },
125
+ {
126
+ providerCode: "1001",
127
+ providerStatus: 1001,
128
+ credentialEvidence: true,
129
+ ...(providerId ? { providerId } : {}),
130
+ },
122
131
  "upstream",
123
132
  );
124
133
  }
@@ -129,12 +138,38 @@ function throwTraeUpstreamError(codeRaw: unknown, messageRaw: unknown): never {
129
138
  "quota_exceeded",
130
139
  429,
131
140
  `Trae quota exceeded (upstream code ${code ?? "unknown"}): ${message} (request {requestId}). You've maxed this window — pace yourself ⏳`,
132
- { providerCode: code ?? "4008", providerStatus: code === "4008" ? 4008 : 429 },
141
+ {
142
+ providerCode: code ?? "4008",
143
+ providerStatus: code === "4008" ? 4008 : 429,
144
+ ...(providerId ? { providerId } : {}),
145
+ },
133
146
  "upstream",
134
147
  );
135
148
  }
136
149
 
137
- 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
+ );
138
173
  }
139
174
 
140
175
  class TraeAdapter implements ProviderAdapter {
@@ -172,7 +207,13 @@ class TraeAdapter implements ProviderAdapter {
172
207
  * hash) and thread it through.
173
208
  */
174
209
  const sessionId = request.session_id ?? resolvePromptCacheKey(request, context);
175
- 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
+ );
176
217
  // The cache estimator is scoped per (session, model): upstream cache keys
177
218
  // are model-specific, so two models sharing a conversation id must not
178
219
  // treat each other's identical prefixes as hits.
@@ -267,7 +308,7 @@ class TraeAdapter implements ProviderAdapter {
267
308
  }
268
309
  if (frame.event === "error") {
269
310
  const data = frame.data as { message?: unknown; code?: unknown };
270
- throwTraeUpstreamError(data.code, data.message);
311
+ throwTraeUpstreamError(data.code, data.message, this.provider_id);
271
312
  }
272
313
  if (typeof frame.data !== "object" || frame.data === null) continue;
273
314
  const record = frame.data as Record<string, unknown>;
@@ -280,7 +321,7 @@ class TraeAdapter implements ProviderAdapter {
280
321
  const nested = record["error"] as Record<string, unknown> | undefined;
281
322
  const code = record["code"] ?? nested?.["code"];
282
323
  const message = record["message"] ?? nested?.["message"];
283
- throwTraeUpstreamError(code, message);
324
+ throwTraeUpstreamError(code, message, this.provider_id);
284
325
  }
285
326
  /**
286
327
  * Two frame layouts reach here and both are live.
@@ -438,8 +479,10 @@ class TraeAdapter implements ProviderAdapter {
438
479
  const record = usageFromProvider(usage);
439
480
  if (record === undefined) return undefined;
440
481
  // Trae's agent surface never reports prompt-cache hits; for repeated
441
- // prefixes we estimate them locally (see trae-cache.ts).
442
- 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));
443
486
  }
444
487
 
445
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",