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
@@ -7,6 +7,7 @@ import {
7
7
  grokHeaderRequestsWindow,
8
8
  grokHeaderWindow,
9
9
  GROK_FREE_USAGE_EXHAUSTED,
10
+ GROK_SPENDING_LIMIT_EXHAUSTED,
10
11
  parseGrokFreeUsageVerdict,
11
12
  readGrokRateLimitHeaders,
12
13
  } from "./grok-ratelimit";
@@ -15,7 +16,6 @@ import { storedGrokRateLimit } from "./grok-ratelimit-store";
15
16
  import type { QuotaCollectionContext } from "../../quota/quota-support";
16
17
 
17
18
  const BILLING_URL = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
18
- const BILLING_SOURCE = "cli-chat-proxy.grok.com/v1/billing";
19
19
  const USER_URL = "https://cli-chat-proxy.grok.com/v1/user?include=subscription";
20
20
  const GRPC_CREDITS_URL = "https://grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig";
21
21
  const GRPC_EMPTY_FRAME = new Uint8Array([0, 0, 0, 0, 0]);
@@ -31,10 +31,10 @@ const GRPC_EMPTY_FRAME = new Uint8Array([0, 0, 0, 0, 0]);
31
31
  */
32
32
  const PROBE_URL = "https://cli-chat-proxy.grok.com/v1/responses";
33
33
  const PROBE_BODY = {
34
- model: "grok-4.6",
35
- stream: false,
36
- max_output_tokens: 1,
37
- input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] }],
34
+ model: "grok-4.7",
35
+ stream: true,
36
+ max_output_tokens: 256,
37
+ input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "Hi" }] }],
38
38
  };
39
39
 
40
40
  /**
@@ -194,10 +194,21 @@ async function probeRateLimit(
194
194
  const verdict = parseGrokFreeUsageVerdict(parsePayload(body), body);
195
195
  authoritative = verdict ? grokAuthoritativeWindow(verdict) : null;
196
196
  note = GROK_FREE_USAGE_EXHAUSTED;
197
+ } else if (response.status === 402) {
198
+ // A 402 names a spend/entitlement wall (e.g.
199
+ // `personal-team-blocked:spending-limit`), not a reading failure. The
200
+ // account cannot serve, so it is a refusal — but there is no token
201
+ // allowance to display, so we carry the note without a window.
202
+ await response.text();
203
+ note = GROK_SPENDING_LIMIT_EXHAUSTED;
197
204
  } else if (!response.ok) {
198
205
  // Drain so the connection is reusable, then report nothing: an unrelated
199
206
  // failure must not read as an exhausted allowance.
200
207
  await response.text();
208
+ } else {
209
+ // A 2xx stream is read for its headers only; cancel the body so the
210
+ // connection is released without waiting for the full completion.
211
+ await response.body?.cancel?.();
201
212
  }
202
213
  return {
203
214
  header: grokHeaderWindow(reading),
@@ -275,5 +286,3 @@ export async function fetchGrokQuota(
275
286
  // broken; the authoritative window below is what carries the verdict.
276
287
  return { source: "grok", plan, windows: ordered, error: null };
277
288
  }
278
-
279
- export { BILLING_SOURCE as GROK_BILLING_SOURCE };
@@ -62,11 +62,6 @@ export function storedGrokRateLimit(accountId: string, now = Date.now()): readon
62
62
  return snapshot.windows;
63
63
  }
64
64
 
65
- /** Whether a fresh reading exists, so the collector can skip its probe. */
66
- export function hasFreshGrokRateLimit(accountId: string, now = Date.now()): boolean {
67
- return storedGrokRateLimit(accountId, now) !== null;
68
- }
69
-
70
65
  /** Test seam. */
71
66
  export function clearGrokRateLimitSnapshots(): void {
72
67
  snapshots.clear();
@@ -37,6 +37,9 @@ const HEADER_RESET_TOKENS = "x-ratelimit-reset-tokens";
37
37
  /** The upstream code that carries the authoritative free-usage allowance. */
38
38
  export const GROK_FREE_USAGE_EXHAUSTED = "subscription:free-usage-exhausted";
39
39
 
40
+ /** A spend/entitlement wall code (402) — the account cannot serve. */
41
+ export const GROK_SPENDING_LIMIT_EXHAUSTED = "spending-limit";
42
+
40
43
  /** Kinds, so the view can tell an indicator from a verdict. */
41
44
  export const GROK_HEADER_WINDOW_KIND = "grok:cli-header";
42
45
  export const GROK_HEADER_REQUESTS_WINDOW_KIND = "grok:cli-header-requests";
@@ -35,15 +35,25 @@ export const GROK_BASE_URL = providerBaseUrl("grok");
35
35
  export const GROK_CLIENT_IDENTIFIER = "grok-shell" as const;
36
36
  export const GROK_TOKEN_AUTH = "xai-grok-cli" as const;
37
37
 
38
+ /**
39
+ * Tool types the Grok Build proxy accepts verbatim (hosted tools). Verified
40
+ * live 2026-11-02: a `web_search_preview` (OpenAI Responses spelling) was
41
+ * rejected with `tools[0].type: unknown variant, expected one of function,
42
+ * web_search, x_search, image_generation, collections_search, file_search,
43
+ * code_execution, code_interpreter, mcp, shell, tool_search`. Anything not in
44
+ * this set is normalized to a flat `function` tool instead.
45
+ */
38
46
  const GROK_HOSTED_TOOLS = new Set([
39
47
  "web_search",
40
48
  "x_search",
41
- "web_search_preview",
42
- "file_search",
43
49
  "image_generation",
50
+ "collections_search",
51
+ "file_search",
52
+ "code_execution",
44
53
  "code_interpreter",
45
54
  "mcp",
46
- "local_shell",
55
+ "shell",
56
+ "tool_search",
47
57
  ]);
48
58
  const GROK_ALLOWED_FIELDS = new Set([
49
59
  "model",
@@ -62,6 +72,24 @@ const GROK_ALLOWED_FIELDS = new Set([
62
72
  "text",
63
73
  "metadata",
64
74
  "prompt_cache_key",
75
+ // Session/response linkage fields — verified in the 1.0.70 binary's
76
+ // `struct Response with 31 elements` / `struct Conversation with 1 element`
77
+ // (OpenAI Responses shape). Without them a fresh request cannot reference
78
+ // earlier turns, and the proxy treats each call as a brand-new session.
79
+ "previous_response_id",
80
+ "conversation",
81
+ // Extra Responses fields the binary accepts; harmless and useful for parity.
82
+ "background",
83
+ "truncation",
84
+ "max_tool_calls",
85
+ "stream_options",
86
+ "prompt_cache_retention",
87
+ "top_logprobs",
88
+ "moderation",
89
+ "safety_identifier",
90
+ "prompt",
91
+ "context_management",
92
+ "user",
65
93
  ]);
66
94
  const GROK_SERVER_ID = /^(rs|fc|resp|msg)_/i;
67
95
  const GROK_NATIVE_ID = /^(rs|msg|fc)_[0-9a-f-]{20,}$/i;
@@ -166,7 +194,7 @@ export async function fetchGrokModels(
166
194
  authorization: `Bearer ${options.credential}`,
167
195
  "x-xai-token-auth": GROK_TOKEN_AUTH,
168
196
  "x-grok-client-identifier": GROK_CLIENT_IDENTIFIER,
169
- "x-grok-client-mode": "headless",
197
+ "x-grok-client-mode": "Desktop",
170
198
  "x-grok-client-version": getGrokVersion(),
171
199
  "user-agent": buildGrokUserAgent(),
172
200
  accept: "application/json",
@@ -177,8 +205,6 @@ export async function fetchGrokModels(
177
205
  const entries = modelEntries(await response.json());
178
206
  if (entries === null) return null;
179
207
  const models = new Map<string, ModelDefinition>();
180
- const profiles = new Map<string, ModelDefinition>();
181
- const defaultEfforts = new Map<string, ReasoningEffortLevel>();
182
208
  for (const raw of entries) {
183
209
  const entry = raw as GrokModelCatalogEntry;
184
210
  const metadata = isRecord(entry._meta) ? entry._meta : undefined;
@@ -197,7 +223,6 @@ export async function fetchGrokModels(
197
223
  max: 10_000_000,
198
224
  }) ?? reference?.outputLimit ?? 64_000;
199
225
  const menu = parseGrokReasoningMenu(entry.reasoning_efforts ?? entry.reasoningEfforts);
200
- const metadataEffort = normalizeEffort(entry.reasoning_effort ?? entry.reasoningEffort);
201
226
  const supportsReasoning =
202
227
  entry.supports_reasoning_effort ?? entry.supportsReasoningEffort;
203
228
  const reasoning =
@@ -217,18 +242,15 @@ export async function fetchGrokModels(
217
242
  cost: modelsDevCatalog.costFor(GROK_PROVIDER_ID, id),
218
243
  };
219
244
  models.set(id, model);
220
- profiles.set(id.toLowerCase(), model);
221
- if (metadataEffort !== undefined) defaultEfforts.set(id.toLowerCase(), metadataEffort);
222
245
  }
223
246
  if (models.size === 0) return null;
224
- discoveredModels.clear();
225
- for (const [id, model] of profiles) discoveredModels.set(id, model);
226
- // Replace discovered defaults, retaining the static defaults as fallback
227
- // only for catalog ids absent from this upstream response.
228
- for (const id of defaultGrokEfforts.keys()) {
229
- if (profiles.has(id)) defaultGrokEfforts.delete(id);
230
- }
231
- for (const [id, effort] of defaultEfforts) defaultGrokEfforts.set(id, effort);
247
+ // Deliberately no module-global cache here. Discovery results are persisted
248
+ // to the DB (source=discovered) by the probing service; a process-global
249
+ // `discoveredModels` map was clobbered by whichever account synced last —
250
+ // the per-account catalog can differ by plan, so account B's sync replaced
251
+ // account A's limits/reasoning menus for the whole process. Dispatch reads
252
+ // the static `GROK_MODELS` fallback (which is verified accurate against the
253
+ // live `/v1/models`), and the DB rows feed routing.
232
254
  return [...models.values()].sort((a, b) => a.modelId.localeCompare(b.modelId));
233
255
  } catch {
234
256
  return null;
@@ -245,28 +267,29 @@ export async function fetchGrokModels(
245
267
  * a model is effort-capable exactly when it is a served model that the catalog
246
268
  * declares as reasoning-capable. Suffixed variants of a served model (e.g.
247
269
  * `grok-4.6-high`) inherit that capability, matching the previous prefix rule.
270
+ *
271
+ * There is intentionally no discovered/cached map here: the static catalog is
272
+ * the single source for dispatch-time limits and reasoning, so a per-account
273
+ * catalog can never clobber another account's model behavior (see
274
+ * `fetchGrokModels`).
248
275
  */
249
- const discoveredModels = new Map<string, ModelDefinition>();
250
- const defaultGrokEfforts = new Map<string, ReasoningEffortLevel>([
251
- ["grok-4.7", "high"],
252
- ["grok-4.5", "high"],
253
- ["grok-4.6", "high"],
254
- ]);
255
-
256
276
  function grokModelDefinition(modelId: string): ModelDefinition | undefined {
257
277
  const normalized = modelId.toLowerCase();
258
- return (
259
- discoveredModels.get(normalized) ??
260
- GROK_MODELS.find((model) => model.modelId.toLowerCase() === normalized)
261
- );
278
+ return GROK_MODELS.find((model) => model.modelId.toLowerCase() === normalized);
262
279
  }
263
280
 
281
+ const GROK_STATIC_DEFAULT_EFFORTS: Readonly<Record<string, ReasoningEffortLevel>> = {
282
+ "grok-4.7": "high",
283
+ "grok-4.5": "high",
284
+ "grok-4.6": "high",
285
+ };
286
+
264
287
  function grokDefaultEffort(modelId: string): ReasoningEffortLevel | undefined {
265
288
  const exact = modelId.toLowerCase();
266
- const discovered = defaultGrokEfforts.get(exact);
267
- if (discovered !== undefined) return discovered;
268
- for (const [id, effort] of defaultGrokEfforts) {
269
- if (exact === id || exact.startsWith(`${id}-`)) return effort;
289
+ const exactDefault = GROK_STATIC_DEFAULT_EFFORTS[exact];
290
+ if (exactDefault !== undefined) return exactDefault;
291
+ for (const [id, effort] of Object.entries(GROK_STATIC_DEFAULT_EFFORTS)) {
292
+ if (exact.startsWith(`${id}-`)) return effort;
270
293
  }
271
294
  return undefined;
272
295
  }
@@ -300,14 +323,24 @@ async function grokHeaders(
300
323
  "x-xai-token-auth": GROK_TOKEN_AUTH,
301
324
  "x-grok-client-identifier": GROK_CLIENT_IDENTIFIER,
302
325
  "x-grok-client-version": version,
303
- "x-grok-client-mode": "headless",
326
+ // Client-mode enum recovered from the 1.0.70 binary: Generic, GrokTUI,
327
+ // GrokWeb, NebulaExtension, GrokPager, Desktop. We present as `Desktop`
328
+ // (the desktop-app surface) — all values are accepted by the proxy, and
329
+ // `Desktop` is the closest 1:1 match to a hosted/BYOK runtime.
330
+ "x-grok-client-mode": "Desktop",
304
331
  "x-authenticateresponse": "authenticate-response",
305
332
  "user-agent": buildGrokUserAgent(version),
306
333
  "x-grok-agent-id": agentId,
307
334
  "x-grok-req-id": randomUUID(),
308
335
  };
309
- // The auth store retains the display label, not xAI's upstream user ID, so
310
- // do not substitute a local account or tenant id in identity headers.
336
+ // The real CLI's sampler header builder stamps the upstream user id on every
337
+ // request when it is known (xai-grok-sampler client.rs). The OAuth flow
338
+ // already persisted it as `auth_state.userId` from `/v1/user`; sending it
339
+ // makes our wire match the first-party client 1:1. It is an upstream
340
+ // identity, not a local account/tenant id — never substitute those.
341
+ const authState = isRecord(context.credential.auth_state) ? context.credential.auth_state : undefined;
342
+ const userId = typeof authState?.userId === "string" ? authState.userId.trim() : "";
343
+ if (userId.length > 0) headers["x-grok-user-id"] = userId;
311
344
  if (candidate?.model_id) {
312
345
  headers["x-grok-model-override"] = candidate.model_id;
313
346
  }
@@ -347,6 +380,12 @@ function normalizeInput(input: unknown): unknown {
347
380
  // request/preparer, which runs for every route including grok) plus the
348
381
  // factory Responses payload path — wire-side pairing filters duplicated
349
382
  // that logic and are deleted.
383
+ //
384
+ // The proxy is stateless: the model sees ONLY what is in `input`, so the
385
+ // full conversation history must survive to it (verified live 2026-11-02 —
386
+ // a turn 2 with the same session id but no history loses the turn 1
387
+ // context). We therefore never drop message items; only server-scoped id
388
+ // hygiene is applied.
350
389
  return input.filter((item) => {
351
390
  if (typeof item === "string") return !GROK_SERVER_ID.test(item);
352
391
  if (!item || typeof item !== "object" || Array.isArray(item)) return false;
@@ -493,19 +532,30 @@ function normalizeGrokPayload(
493
532
  if (cacheKey !== undefined && typeof payload.prompt_cache_key !== "string")
494
533
  payload.prompt_cache_key = cacheKey.slice(0, 512);
495
534
 
535
+ // The Grok Build proxy does NOT persist responses: a `previous_response_id`
536
+ // (even from a real `response.id` of an earlier turn, with `store:true`)
537
+ // returns 404 "Previous response cannot be found" — verified live
538
+ // 2026-11-02. The proxy is stateless; continuity comes only from the full
539
+ // `input` history, so referencing a previous response id can never succeed
540
+ // and would fail the whole request. Drop it here.
541
+ delete payload.previous_response_id;
542
+
496
543
  for (const key of Object.keys(payload)) {
497
544
  if (!GROK_ALLOWED_FIELDS.has(key)) delete payload[key];
498
545
  }
499
546
  }
500
547
 
501
548
 
502
- const GrokConfig = withBearerAuthentication({
549
+ export const GrokConfig = withBearerAuthentication({
503
550
  provider_id: GROK_PROVIDER_ID,
504
551
  base_url: GROK_BASE_URL,
505
552
  endpoint_paths_by_wire_family: { responses: "/v1/responses" },
506
553
  extra_headers: { accept: "text/event-stream", "accept-encoding": "identity" },
507
554
  buildExtraHeaders: grokHeaders,
508
555
  prePayload: normalizeGrokPayload,
556
+ // The real CLI compresses the request body with zstd (sampler
557
+ // `request_compression`); stamp the matching Content-Encoding and compress.
558
+ request_compression: "zstd",
509
559
  });
510
560
 
511
561
  /**
@@ -30,7 +30,7 @@ import type { OAuthTokenRefreshResult } from "../../authentication/oauth-refresh
30
30
  import { OAuthDeviceFlow } from "../../authentication/oauth-device-flow";
31
31
  import type { FetchLike } from "../../authentication/oauth-client";
32
32
 
33
- export const KILO_API_BASE_URL = "https://api.kilo.ai" as const;
33
+ const KILO_API_BASE_URL = "https://api.kilo.ai" as const;
34
34
  export const KILO_DEVICE_CODES_URL = `${KILO_API_BASE_URL}/api/device-auth/codes` as const;
35
35
  export const KILO_PROFILE_URL = `${KILO_API_BASE_URL}/api/profile` as const;
36
36
 
@@ -0,0 +1,31 @@
1
+ // Kiro session-cache estimation.
2
+ //
3
+ // The Kiro runtime surface never reports prompt-cache hits: the EventStream
4
+ // carries only `contextUsageEvent` (window percentage) and `meteringEvent`
5
+ // (billed credits), with no metrics event and no cache token counters. The
6
+ // underlying models do cache byte-identical prefixes, so for the same
7
+ // conversation we ESTIMATE the hit locally from the request history — exactly
8
+ // how the Trae adapter bridges the same gap. This only fills the gap when
9
+ // upstream reports nothing (0 or unavailable); a genuine upstream report (>0)
10
+ // is trusted and left untouched.
11
+ //
12
+ // The state lives in a factory-created instance, so Kiro's sessions are fully
13
+ // isolated from Trae's (and any other consumer of the shared factory).
14
+
15
+ import type { CanonicalMessage, UsageRecord } from "../../../protocol/canonical-model";
16
+ import { createSessionCache, estimateSessionCache, resetSessionCacheForTesting } from "../shared/session-cache";
17
+
18
+ const cache = createSessionCache();
19
+
20
+ export function estimateKiroSessionCache(
21
+ record: UsageRecord,
22
+ sessionId: string | undefined,
23
+ messages: readonly CanonicalMessage[] | undefined,
24
+ ): UsageRecord {
25
+ return estimateSessionCache(cache, record, sessionId, messages);
26
+ }
27
+
28
+ /** Drops all tracked sessions. Test-only. */
29
+ export function resetKiroSessionCacheForTesting(): void {
30
+ resetSessionCacheForTesting(cache);
31
+ }
@@ -12,6 +12,25 @@ export const KIRO_PROVIDER_ID = "kiro" as const;
12
12
  */
13
13
  export const KIRO_GENERATE_PATH = "/generateAssistantResponse" as const;
14
14
 
15
+ /** AWS region shape, checked before a region is interpolated into a URL. */
16
+ export const AWS_REGION_PATTERN = /^[a-z]{2}-[a-z]+-\d{1,2}$/;
17
+
18
+ /** Fallback region when no (or an invalid) region is configured. */
19
+ export const KIRO_DEFAULT_REGION = "us-east-1" as const;
20
+
21
+ /**
22
+ * Runtime service host template (generation). `{region}` is interpolated.
23
+ *
24
+ * The 1.4.62 IDE targets the Kiro runtime service (`KiroRuntimeService`,
25
+ * apiVersion 2026-01-13) at `https://runtime.{region}.kiro.dev` instead of the
26
+ * legacy `q.{region}.amazonaws.com` AWS surface. Discovery/usage use the
27
+ * control-plane `management` host; generation uses `runtime`.
28
+ */
29
+ export const KIRO_RUNTIME_HOST_TEMPLATE = "https://runtime.{region}.kiro.dev" as const;
30
+
31
+ /** Control-plane (management) service host template (models/usage). */
32
+ export const KIRO_MANAGEMENT_HOST_TEMPLATE = "https://management.{region}.kiro.dev" as const;
33
+
15
34
  /**
16
35
  * Effort tiers the Kiro models that accept an effort field advertise.
17
36
  *
@@ -39,6 +58,8 @@ function kiroModel(options: {
39
58
  readonly reasoning?: boolean;
40
59
  readonly toolCall?: boolean;
41
60
  readonly webSearch?: boolean;
61
+ /** Marks the row as served on the provider's free plan tier (the free pill). */
62
+ readonly freeTier?: boolean;
42
63
  }): ModelDefinition {
43
64
  return defineModel({
44
65
  id: options.id,
@@ -51,6 +72,7 @@ function kiroModel(options: {
51
72
  ...(options.reasoning === undefined ? {} : { reasoning: options.reasoning }),
52
73
  ...(options.toolCall === undefined ? {} : { toolCall: options.toolCall }),
53
74
  ...(options.webSearch === undefined ? {} : { webSearch: options.webSearch }),
75
+ ...(options.freeTier === undefined ? {} : { freeTier: options.freeTier }),
54
76
  ...(options.reasoning ? { reasoningEfforts: KIRO_EFFORTS } : {}),
55
77
  });
56
78
  }
@@ -64,7 +86,14 @@ function kiroModel(options: {
64
86
  * guessing at what an individual account's plan reaches.
65
87
  */
66
88
  export const KIRO_MODELS: readonly ModelDefinition[] = [
67
- kiroModel({ id: "auto", ctx: 1_000_000, out: 32_000, reasoning: true, toolCall: true }),
89
+ // Free-tier rows (KIRO FREE plan): the models the free tier serves. Marked
90
+ // `freeTier` so the model list groups them under the free pill like every
91
+ // other provider's free roster; latency measured live 2026-11-02.
92
+ kiroModel({ id: "auto", ctx: 1_000_000, out: 32_000, reasoning: true, toolCall: true, freeTier: true }),
93
+ kiroModel({ id: "claude-haiku-4.5", ctx: 200_000, out: 64_000, vision: true, reasoning: true, toolCall: true, freeTier: true }),
94
+ kiroModel({ id: "claude-sonnet-4.5", ctx: 200_000, out: 64_000, vision: true, reasoning: true, toolCall: true, freeTier: true }),
95
+ kiroModel({ id: "glm-5", ctx: 200_000, out: 64_000, reasoning: true, toolCall: true, freeTier: true }),
96
+ // Paid-tier rows (Pro).
68
97
  kiroModel({ id: "claude-opus-5", ctx: 1_000_000, out: 128_000, vision: true, reasoning: true, toolCall: true }),
69
98
  kiroModel({ id: "claude-opus-4.8", ctx: 1_000_000, out: 128_000, vision: true, reasoning: true, toolCall: true }),
70
99
  kiroModel({ id: "claude-opus-4.7", ctx: 1_000_000, out: 128_000, vision: true, reasoning: true, toolCall: true }),
@@ -74,8 +103,6 @@ export const KIRO_MODELS: readonly ModelDefinition[] = [
74
103
  // 200K, not the 1M the 1M-window models use: Sonnet 4.5 predates it. The
75
104
  // million-token window arrived with Opus 4.6 and the 5.x generation; the 4.5
76
105
  // trio is 200K, and Opus and Haiku here already say so.
77
- kiroModel({ id: "claude-sonnet-4.5", ctx: 200_000, out: 64_000, vision: true, reasoning: true, toolCall: true }),
78
- kiroModel({ id: "claude-haiku-4.5", ctx: 200_000, out: 64_000, vision: true, reasoning: true, toolCall: true }),
79
106
  // 1M/128K, not the 200K/64K of the 4.5 row above it: Haiku moved to the
80
107
  // million-token window and the doubled output ceiling with the rest of the
81
108
  // 5.x generation, and this line had been copied from its predecessor.
@@ -85,7 +112,6 @@ export const KIRO_MODELS: readonly ModelDefinition[] = [
85
112
  kiroModel({ id: "gpt-5.6-terra", ctx: 272_000, out: 128_000, reasoning: true, toolCall: true }),
86
113
  kiroModel({ id: "gpt-5.6-luna", ctx: 272_000, out: 128_000, reasoning: true, toolCall: true }),
87
114
  // The non-Anthropic rows reject image and audio input upstream.
88
- kiroModel({ id: "glm-5", ctx: 200_000, out: 64_000, reasoning: true, toolCall: true }),
89
115
  ];
90
116
 
91
117
  /**
@@ -109,4 +135,4 @@ export function kiroContextWindow(modelId: string): number {
109
135
  }
110
136
 
111
137
  /** Window used for a model this catalog does not name; the Anthropic rows' value. */
112
- export const KIRO_DEFAULT_CONTEXT_WINDOW = 200_000;
138
+ const KIRO_DEFAULT_CONTEXT_WINDOW = 200_000;
@@ -1,13 +1,16 @@
1
1
  // Kiro model discovery.
2
2
  //
3
3
  // The account's own model list is authoritative — which models a credential
4
- // reaches depends on the plan it is bound to — and it is served by the Amazon Q
5
- // catalog for a resolved profile. The request is scoped by the account's region
6
- // and profile for the same reason dispatch is.
4
+ // reaches depends on the plan it is bound to — and it is served by the Kiro
5
+ // control-plane (management) service for a resolved profile. The request is
6
+ // scoped by the account's region and profile for the same reason dispatch is.
7
7
  //
8
- // This surface has its own client identity: it is the IDE's model-list call,
9
- // not the agent's chat call, and the upstream validates the User-Agent's shape
10
- // rather than ignoring it.
8
+ // This surface has its own client identity: it is the IDE's model-list call
9
+ // (client `@amzn/kiro-control-plane-bearer-client`), not the agent's chat
10
+ // call, and the upstream validates the User-Agent's shape rather than ignoring
11
+ // it. In the 1.4.62 build the operation is bound to `GET /List-Available-Models`
12
+ // on `https://management.{region}.kiro.dev` (awsJson1_0, `x-amz-target`
13
+ // `KiroControlPlaneBearerService.ListAvailableModels`).
11
14
 
12
15
  import type { FetchLike } from "../../quota/quota-contracts";
13
16
  import type { ModelDefinition } from "../../provider-model-definition";
@@ -19,10 +22,7 @@ import {
19
22
  } from "../../operations/client-versions";
20
23
  import { machineIdForAuthState } from "./kiro-machine-id";
21
24
  import { resolveKiroProfileArn } from "./kiro-profile";
22
- import { KIRO_MODELS } from "./kiro-catalog";
23
-
24
- /** AWS region shape, checked before a region is interpolated into a URL. */
25
- const AWS_REGION_PATTERN = /^[a-z]{2}-[a-z]+-\d{1,2}$/;
25
+ import { AWS_REGION_PATTERN, KIRO_DEFAULT_REGION, KIRO_GENERATE_PATH, KIRO_MODELS, KIRO_MANAGEMENT_HOST_TEMPLATE } from "./kiro-catalog";
26
26
 
27
27
  /** Longest model list this will read; the upstream sends a few dozen at most. */
28
28
  const MAX_DISCOVERED_MODELS = 500;
@@ -30,6 +30,9 @@ const MAX_DISCOVERED_MODELS = 500;
30
30
  /** Effort tiers the models that accept an effort field advertise. */
31
31
  const KIRO_EFFORTS = ["low", "medium", "high", "xhigh"] as const;
32
32
 
33
+ /** The management service target used in `x-amz-target`. */
34
+ const KIRO_MANAGEMENT_TARGET = "KiroControlPlaneBearerService.ListAvailableModels" as const;
35
+
33
36
  /**
34
37
  * Ids the seed catalog deliberately excludes.
35
38
  *
@@ -44,7 +47,6 @@ const RETIRED_KIRO_MODEL_IDS: ReadonlySet<string> = new Set([
44
47
  ]);
45
48
 
46
49
  /** Path the adapter dispatches to; recorded on every discovered row. */
47
- const KIRO_GENERATE_PATH = "/generateAssistantResponse";
48
50
  /** Options for one discovery run. */
49
51
  export interface KiroModelDiscoveryOptions {
50
52
  readonly credential: string;
@@ -61,7 +63,7 @@ interface DiscoveryScope {
61
63
 
62
64
  function readScope(authState: Readonly<Record<string, unknown>> | undefined): DiscoveryScope {
63
65
  const regionRaw = typeof authState?.["region"] === "string" ? authState["region"].trim() : "";
64
- const region = AWS_REGION_PATTERN.test(regionRaw) ? regionRaw : "us-east-1";
66
+ const region = AWS_REGION_PATTERN.test(regionRaw) ? regionRaw : KIRO_DEFAULT_REGION;
65
67
  const profileArn = resolveKiroProfileArn(authState);
66
68
  return { region, profileArn };
67
69
  }
@@ -80,36 +82,42 @@ export async function fetchKiroModels(
80
82
  if (credential.length === 0) return null;
81
83
  const fetcher = options.fetcher ?? fetch;
82
84
  const scope = readScope(options.authState);
85
+ const version = getKiroVersion();
86
+ const machineId = machineIdForAuthState(options.authState);
87
+ const host = KIRO_MANAGEMENT_HOST_TEMPLATE.replace("{region}", scope.region);
83
88
  const params = new URLSearchParams({ origin: "AI_EDITOR" });
84
89
  if (scope.profileArn.length > 0) params.set("profileArn", scope.profileArn);
85
90
 
86
91
  let response: Response;
87
92
  try {
88
- // The catalog surface correlates the credential against the same device the
89
- // generation surface sees, so it resolves the identity through the shared
90
- // resolver rather than stating one of its own.
91
- const version = getKiroVersion();
92
- const machineId = machineIdForAuthState(options.authState);
93
- response = await fetcher(
94
- `https://q.${scope.region}.amazonaws.com/ListAvailableModels?${params.toString()}`,
95
- {
96
- headers: {
97
- authorization: `Bearer ${credential}`,
98
- accept: "application/json",
99
- connection: "close",
100
- "x-amzn-kiro-agent-mode": "vibe",
101
- "x-amzn-codewhisperer-optout": "true",
102
- "amz-sdk-request": "attempt=1; max=1",
103
- "amz-sdk-invocation-id": crypto.randomUUID(),
104
- // The upstream validates this value's shape and rejects a malformed
105
- // one outright, so it is built from the same source the generation
106
- // surface uses rather than spelled out here.
107
- "user-agent": buildKiroRuntimeUserAgent(version, machineId),
108
- "x-amz-user-agent": buildKiroAmzUserAgent(version, machineId),
109
- },
110
- signal: AbortSignal.timeout(20_000),
111
- },
112
- );
93
+ const headers: Record<string, string> = {
94
+ authorization: `Bearer ${credential}`,
95
+ accept: "application/json",
96
+ connection: "close",
97
+ "x-amz-target": KIRO_MANAGEMENT_TARGET,
98
+ "amz-sdk-request": "attempt=1; max=1",
99
+ "amz-sdk-invocation-id": crypto.randomUUID(),
100
+ "user-agent": buildKiroRuntimeUserAgent(version, machineId),
101
+ "x-amz-user-agent": buildKiroAmzUserAgent(version, machineId),
102
+ "x-kiro-machineid": machineId,
103
+ };
104
+ // The management surface labels API-key/enterprise/IdC credentials with
105
+ // `TokenType`; social/Builder-ID sessions send none. Mirror the client's
106
+ // `qje` map and the probe verified against the live service.
107
+ const authMethod = options.authState?.["authMethod"];
108
+ const tokenType =
109
+ authMethod === "api_key"
110
+ ? "API_KEY"
111
+ : authMethod === "external_idp"
112
+ ? "EXTERNAL_IDP"
113
+ : authMethod === "idc"
114
+ ? "SSO_OIDC"
115
+ : undefined;
116
+ if (tokenType !== undefined) headers["TokenType"] = tokenType;
117
+ response = await fetcher(`${host}/List-Available-Models?${params.toString()}`, {
118
+ headers,
119
+ signal: AbortSignal.timeout(20_000),
120
+ });
113
121
  } catch {
114
122
  return null;
115
123
  }
@@ -131,9 +139,6 @@ export async function fetchKiroModels(
131
139
  const modelId = typeof rawId === "string" ? rawId.trim() : "";
132
140
  if (modelId.length === 0 || seen.has(modelId) || RETIRED_KIRO_MODEL_IDS.has(modelId)) continue;
133
141
  seen.add(modelId);
134
- // The seed row owns the limits and capabilities of an id it declares. The
135
- // upstream listing reports an input ceiling only, and trusting it overwrote
136
- // the output ceiling the catalog states.
137
142
  const seeded = KIRO_MODELS.find((model) => model.modelId === modelId);
138
143
  if (seeded !== undefined) {
139
144
  definitions.push(seeded);
@@ -145,8 +150,6 @@ export async function fetchKiroModels(
145
150
  ? (limits as Record<string, unknown>)["maxInputTokens"]
146
151
  : undefined;
147
152
  const contextLimit = typeof maxInput === "number" && maxInput > 0 ? Math.trunc(maxInput) : null;
148
- // The catalog reports an input ceiling, not an output one; the static row
149
- // carries the output ceiling the model family advertises.
150
153
  definitions.push(
151
154
  defineModel({
152
155
  id: modelId,
@@ -157,7 +160,8 @@ export async function fetchKiroModels(
157
160
  vision: true,
158
161
  reasoning: true,
159
162
  reasoningEfforts: KIRO_EFFORTS,
160
- toolCall: true,}),
163
+ toolCall: true,
164
+ }),
161
165
  );
162
166
  }
163
167
  return definitions.length > 0 ? definitions : null;
@@ -18,9 +18,12 @@ import { sha256Hex } from "../../../shared/hash";
18
18
  * account's `auth_state` so a refresh — which rotates the refresh token, and
19
19
  * with it any value derived from that token — cannot silently change it.
20
20
  *
21
- * The salts below are wire facts: they are what the observed client hashes.
22
- * They are deliberately different per credential family, because an API key and
23
- * a refresh token for the same account must not derive the same device id.
21
+ * The salts below are locally derived (stable per credential, distinct
22
+ * between credentials). They are NOT proven upstream wire facts: the
23
+ * unpacked IDE 1.4.62 uses VS Code's `machineIdSync()` and sends the device
24
+ * in `KiroIDE-{version}-{machineId}` (UA) plus `x-kiro-machineid` (header);
25
+ * the CLI 2.37.0 sends `x-kiro-machineid`. The legacy `KotlinNativeAPI`,
26
+ * `KiroAPIKey`, `KiroFallback` salts are absent from both binaries.
24
27
  */
25
28
 
26
29
  /** Prefix the observed client hashes for an OAuth (refresh-token) credential. */