cartethyia 2.5.9 → 2.6.0

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 (386) hide show
  1. package/.env.example +15 -42
  2. package/README.md +11 -10
  3. package/dist/dashboard/assets/{BannedPage-Brvuj_Eb.js → BannedPage-l6XMnfr9.js} +1 -1
  4. package/dist/dashboard/assets/BannedPage-l6XMnfr9.js.gz +0 -0
  5. package/dist/dashboard/assets/{CliToolDetailPage-CqfXtI3y.js → CliToolDetailPage-DwOzAW45.js} +1 -1
  6. package/dist/dashboard/assets/CliToolDetailPage-DwOzAW45.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolsPage-GQeS91bg.js → CliToolsPage-BT3Up3QA.js} +1 -1
  8. package/dist/dashboard/assets/CliToolsPage-BT3Up3QA.js.gz +0 -0
  9. package/dist/dashboard/assets/{CombosPage-BDRsTXBB.js → CombosPage-6kYIUpzR.js} +1 -1
  10. package/dist/dashboard/assets/CombosPage-6kYIUpzR.js.gz +0 -0
  11. package/dist/dashboard/assets/{ConsoleLogPage-zP8AFHX0.js → ConsoleLogPage-zRnj1mlR.js} +1 -1
  12. package/dist/dashboard/assets/ConsoleLogPage-zRnj1mlR.js.gz +0 -0
  13. package/dist/dashboard/assets/{CustomizationPage-BmfrNZ14.js → CustomizationPage-C7m-H1Rz.js} +1 -1
  14. package/dist/dashboard/assets/CustomizationPage-C7m-H1Rz.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-C8MR_BdB.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-C8MR_BdB.js.gz +0 -0
  17. package/dist/dashboard/assets/{LoginPage-DoreIgm8.js → LoginPage-CbphLvjg.js} +1 -1
  18. package/dist/dashboard/assets/LoginPage-CbphLvjg.js.gz +0 -0
  19. package/dist/dashboard/assets/{ModelPicker-C7pDb41R.js → ModelPicker-DVny4S5_.js} +1 -1
  20. package/dist/dashboard/assets/ModelPicker-DVny4S5_.js.gz +0 -0
  21. package/dist/dashboard/assets/OverviewPage-DABu2Wgt.js +1 -0
  22. package/dist/dashboard/assets/OverviewPage-DABu2Wgt.js.gz +0 -0
  23. package/dist/dashboard/assets/ProviderDetailPage-C15x9q13.js +3 -0
  24. package/dist/dashboard/assets/ProviderDetailPage-C15x9q13.js.gz +0 -0
  25. package/dist/dashboard/assets/{ProvidersPage-BnoPgA7w.js → ProvidersPage-Dfb2896L.js} +1 -1
  26. package/dist/dashboard/assets/ProvidersPage-Dfb2896L.js.gz +0 -0
  27. package/dist/dashboard/assets/{ProxyPage-Bq_TGgdb.js → ProxyPage-BaCIdAUt.js} +1 -1
  28. package/dist/dashboard/assets/ProxyPage-BaCIdAUt.js.gz +0 -0
  29. package/dist/dashboard/assets/QuotaPage-BsdoCIw1.js +1 -0
  30. package/dist/dashboard/assets/QuotaPage-BsdoCIw1.js.gz +0 -0
  31. package/dist/dashboard/assets/SettingsPage-KVJFh3Ip.js +1 -0
  32. package/dist/dashboard/assets/SettingsPage-KVJFh3Ip.js.gz +0 -0
  33. package/dist/dashboard/assets/{SetupPage-Day3mCOn.js → SetupPage-D4g6vOGc.js} +1 -1
  34. package/dist/dashboard/assets/SetupPage-D4g6vOGc.js.gz +0 -0
  35. package/dist/dashboard/assets/{SortableList-DQxllnB5.js → SortableList-C93i14BD.js} +1 -1
  36. package/dist/dashboard/assets/SortableList-C93i14BD.js.gz +0 -0
  37. package/dist/dashboard/assets/{StudioPage-uMExoWu1.js → StudioPage-SgQpymjm.js} +1 -1
  38. package/dist/dashboard/assets/{StudioPage-uMExoWu1.js.gz → StudioPage-SgQpymjm.js.gz} +0 -0
  39. package/dist/dashboard/assets/{UsagePage-DXa1oR-4.js → UsagePage-BFME-eba.js} +2 -2
  40. package/dist/dashboard/assets/UsagePage-BFME-eba.js.gz +0 -0
  41. package/dist/dashboard/assets/{api-keys-DQYLQxpW.js → api-keys-C23S9sgp.js} +1 -1
  42. package/dist/dashboard/assets/api-keys-C23S9sgp.js.gz +0 -0
  43. package/dist/dashboard/assets/{app-BIt446yE.js → app-2KhtHCv9.js} +1 -1
  44. package/dist/dashboard/assets/{app-BIt446yE.js.gz → app-2KhtHCv9.js.gz} +0 -0
  45. package/dist/dashboard/assets/app-CEeaMHOy.css +2 -0
  46. package/dist/dashboard/assets/app-CEeaMHOy.css.gz +0 -0
  47. package/dist/dashboard/assets/{assert-C9FD_JwJ.js → assert-DU6qrMA_.js} +1 -1
  48. package/dist/dashboard/assets/assert-DU6qrMA_.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-CR72dasT.js → badge-CKsF123d.js} +1 -1
  50. package/dist/dashboard/assets/badge-CKsF123d.js.gz +0 -0
  51. package/dist/dashboard/assets/{banner-CI9_eSfO.js → banner-8j7uChA9.js} +1 -1
  52. package/dist/dashboard/assets/banner-8j7uChA9.js.gz +0 -0
  53. package/dist/dashboard/assets/{card-DS7CQEsO.js → card-CdsSlWA3.js} +1 -1
  54. package/dist/dashboard/assets/card-CdsSlWA3.js.gz +0 -0
  55. package/dist/dashboard/assets/{cli-tools-CNqzrfdb.js → cli-tools-BaFUuFFF.js} +1 -1
  56. package/dist/dashboard/assets/cli-tools-BaFUuFFF.js.gz +0 -0
  57. package/dist/dashboard/assets/{clipboard-button-611pSsaX.js → clipboard-button-uL5aYLfW.js} +1 -1
  58. package/dist/dashboard/assets/clipboard-button-uL5aYLfW.js.gz +0 -0
  59. package/dist/dashboard/assets/{dialog-k37exjNt.js → dialog-C07hr5_G.js} +1 -1
  60. package/dist/dashboard/assets/dialog-C07hr5_G.js.gz +0 -0
  61. package/dist/dashboard/assets/{drawer-CX7N8ucR.js → drawer-BPO1TcKH.js} +1 -1
  62. package/dist/dashboard/assets/drawer-BPO1TcKH.js.gz +0 -0
  63. package/dist/dashboard/assets/{entry-CTP8AyiS.js → entry-Bz_CtDfC.js} +1 -1
  64. package/dist/dashboard/assets/entry-Bz_CtDfC.js.gz +0 -0
  65. package/dist/dashboard/assets/entry-CwPRKk0d.js +4 -0
  66. package/dist/dashboard/assets/entry-CwPRKk0d.js.gz +0 -0
  67. package/dist/dashboard/assets/entry-GJRbmrpA.js +1 -0
  68. package/dist/dashboard/assets/entry-GJRbmrpA.js.gz +0 -0
  69. package/dist/dashboard/assets/{github-badge-sltk1qUi.js → github-badge-DmQreSDd.js} +1 -1
  70. package/dist/dashboard/assets/github-badge-DmQreSDd.js.gz +0 -0
  71. package/dist/dashboard/assets/{index-z3zDOSMM.js → index-Bblu6erR.js} +2 -2
  72. package/dist/dashboard/assets/index-Bblu6erR.js.gz +0 -0
  73. package/dist/dashboard/assets/{inline-BhY2sSnO.js → inline-C9dCYaBZ.js} +1 -1
  74. package/dist/dashboard/assets/inline-C9dCYaBZ.js.gz +0 -0
  75. package/dist/dashboard/assets/{input-V1umFiBk.js → input-CjCnXweJ.js} +1 -1
  76. package/dist/dashboard/assets/input-CjCnXweJ.js.gz +0 -0
  77. package/dist/dashboard/assets/{layout-BBOYycyS.js → layout-V6y8DAkl.js} +1 -1
  78. package/dist/dashboard/assets/layout-V6y8DAkl.js.gz +0 -0
  79. package/dist/dashboard/assets/{list-row-1zzZYM0B.js → list-row-CM1AaG_y.js} +1 -1
  80. package/dist/dashboard/assets/list-row-CM1AaG_y.js.gz +0 -0
  81. package/dist/dashboard/assets/{live-BivGfuUs.js → live-ta6GMb-8.js} +1 -1
  82. package/dist/dashboard/assets/live-ta6GMb-8.js.gz +0 -0
  83. package/dist/dashboard/assets/{model-bans-CmffjLuG.js → model-bans-BmYTmbAk.js} +1 -1
  84. package/dist/dashboard/assets/model-bans-BmYTmbAk.js.gz +0 -0
  85. package/dist/dashboard/assets/{mutation-46P0oWMe.js → mutation-g_fduiNw.js} +1 -1
  86. package/dist/dashboard/assets/mutation-g_fduiNw.js.gz +0 -0
  87. package/dist/dashboard/assets/{numbers-DkfMR5Qs.js → numbers-BOevJzdz.js} +1 -1
  88. package/dist/dashboard/assets/numbers-BOevJzdz.js.gz +0 -0
  89. package/dist/dashboard/assets/{query-keys-BFhGpwR1.js → query-keys-UETqfytp.js} +1 -1
  90. package/dist/dashboard/assets/query-keys-UETqfytp.js.gz +0 -0
  91. package/dist/dashboard/assets/{routing-CAb4F37R.js → routing-BPUo-W8d.js} +1 -1
  92. package/dist/dashboard/assets/routing-BPUo-W8d.js.gz +0 -0
  93. package/dist/dashboard/assets/{select-C6MMiaio.js → select-C980c4cz.js} +1 -1
  94. package/dist/dashboard/assets/select-C980c4cz.js.gz +0 -0
  95. package/dist/dashboard/assets/{settings-DNX9sydi.js → settings--3hxSyry.js} +1 -1
  96. package/dist/dashboard/assets/settings--3hxSyry.js.gz +0 -0
  97. package/dist/dashboard/assets/{stack-BHTfXdz_.js → stack-_gfTdLVB.js} +1 -1
  98. package/dist/dashboard/assets/stack-_gfTdLVB.js.gz +0 -0
  99. package/dist/dashboard/assets/{state-mPDRlQkl.js → state-2c5V4zo7.js} +1 -1
  100. package/dist/dashboard/assets/state-2c5V4zo7.js.gz +0 -0
  101. package/dist/dashboard/assets/{switch-DOmJxg7H.js → switch-Dkke7Naf.js} +1 -1
  102. package/dist/dashboard/assets/switch-Dkke7Naf.js.gz +0 -0
  103. package/dist/dashboard/assets/{useMutation-Dem0lXQj.js → useMutation-EDFRkn1i.js} +1 -1
  104. package/dist/dashboard/assets/useMutation-EDFRkn1i.js.gz +0 -0
  105. package/dist/dashboard/index.html +1 -1
  106. package/dist/dashboard/index.html.gz +0 -0
  107. package/dist/dashboard/precompressed-assets.json +51 -51
  108. package/migrations/README.md +52 -52
  109. package/migrations/full-postgres/0020_add_telemetry_event_analytics.sql +77 -0
  110. package/migrations/full-postgres/0021_add_api_key_concurrency_tolerance.sql +13 -0
  111. package/migrations/full-postgres/0022_add_inferhub_config_key.sql +17 -0
  112. package/migrations/full-postgres/0023_drop_api_key_concurrency_tolerance.sql +13 -0
  113. package/migrations/lite-sqlite3/0020_add_telemetry_event_analytics.sql +69 -0
  114. package/migrations/lite-sqlite3/0021_add_api_key_concurrency_tolerance.sql +13 -0
  115. package/migrations/lite-sqlite3/0022_add_inferhub_config_key.sql +17 -0
  116. package/migrations/lite-sqlite3/0023_drop_api_key_concurrency_tolerance.sql +13 -0
  117. package/package.json +96 -97
  118. package/scripts/cli/admin.ts +126 -125
  119. package/scripts/cli/autostart.ts +237 -237
  120. package/scripts/cli/background.ts +120 -110
  121. package/scripts/cli/bin/carte.cjs +8 -8
  122. package/scripts/cli/bin/cartethyia.cjs +167 -167
  123. package/scripts/cli/console-menu.ts +308 -275
  124. package/scripts/cli/controller.ts +145 -0
  125. package/scripts/cli/doctor.ts +1 -1
  126. package/scripts/cli/env.ts +99 -99
  127. package/scripts/cli/gateway.ts +264 -261
  128. package/scripts/{health.ts → cli/health.ts} +4 -4
  129. package/scripts/cli/instance.ts +234 -224
  130. package/scripts/cli/main.ts +188 -164
  131. package/scripts/cli/platform.ts +64 -64
  132. package/scripts/cli/prompt.ts +275 -107
  133. package/scripts/cli/services.ts +88 -88
  134. package/scripts/cli/setup.ts +445 -445
  135. package/scripts/cli/start.ts +85 -82
  136. package/scripts/cli/startup-signal.ts +23 -23
  137. package/scripts/cli/telemetry.ts +70 -0
  138. package/scripts/cli/tray/index.ts +263 -263
  139. package/scripts/cli/tray/windows.ps1 +107 -107
  140. package/scripts/cli/tray.ts +192 -208
  141. package/scripts/cli/update.ts +39 -39
  142. package/scripts/cli/version.ts +67 -67
  143. package/scripts/cli/wordmark.ts +58 -58
  144. package/src/boot/app.ts +16 -1
  145. package/src/boot/dependencies.ts +128 -25
  146. package/src/config/package-paths.ts +24 -0
  147. package/src/config/resources.ts +137 -0
  148. package/src/config/runtime.ts +133 -76
  149. package/src/config/spec.ts +30 -29
  150. package/src/config/telemetry.ts +0 -25
  151. package/src/console/api-keys/bucket-spend.ts +14 -17
  152. package/src/console/api-keys/contracts.ts +410 -410
  153. package/src/console/api-keys/routes.ts +12 -0
  154. package/src/console/audit/store.ts +2 -3
  155. package/src/console/auth/setup-service.ts +8 -1
  156. package/src/console/backup/routes.ts +7 -0
  157. package/src/console/backup/service.ts +463 -463
  158. package/src/console/backup/store.ts +16 -11
  159. package/src/console/backup/validate.ts +1 -4
  160. package/src/console/cli-tools/fs-ops.ts +18 -2
  161. package/src/console/data-management/contracts.ts +1 -8
  162. package/src/console/data-management/operations.ts +61 -48
  163. package/src/console/data-management/routes.ts +4 -2
  164. package/src/console/domain-registration.ts +25 -3
  165. package/src/console/inferhub/client.ts +139 -0
  166. package/src/console/inferhub/key-store.ts +129 -0
  167. package/src/console/inferhub/normalize.ts +347 -0
  168. package/src/console/inferhub/routes.ts +411 -0
  169. package/src/console/inferhub/store.ts +109 -0
  170. package/src/console/inferhub/types.ts +183 -0
  171. package/src/console/observability/contracts.ts +2 -41
  172. package/src/console/observability/store.ts +176 -371
  173. package/src/console/providers/catalog/public-model-store.ts +0 -0
  174. package/src/console/providers/catalog/store.ts +23 -36
  175. package/src/console/quota/account-quota-shared.ts +52 -52
  176. package/src/console/quota/account-quota-tenant.ts +16 -24
  177. package/src/console/quota/refresh.ts +441 -441
  178. package/src/console/remote-support/service.ts +270 -114
  179. package/src/console/routing/pools/import-parse.ts +206 -206
  180. package/src/console/routing/pools/operations.ts +543 -543
  181. package/src/console/routing/pools/probe-verdict.ts +132 -132
  182. package/src/console/routing/pools/routes.ts +181 -181
  183. package/src/console/routing/pools/store.ts +1 -1
  184. package/src/console/settings/contracts.ts +42 -40
  185. package/src/console/settings/store.ts +25 -25
  186. package/src/console/share/share-stats.ts +22 -4
  187. package/src/console/share/share-usage.ts +30 -4
  188. package/src/console/shared/cursor.ts +15 -0
  189. package/src/console/updates/repository-updates.ts +40 -39
  190. package/src/console/updates/routes.ts +12 -0
  191. package/src/main.ts +13 -5
  192. package/src/network/pool/resolver.ts +1104 -1104
  193. package/src/observability/client-name.ts +22 -0
  194. package/src/observability/event-log.ts +5 -29
  195. package/src/observability/event-query.ts +690 -0
  196. package/src/observability/log-ring.ts +26 -2
  197. package/src/observability/log-sanitize.ts +118 -0
  198. package/src/observability/logger.ts +17 -13
  199. package/src/observability/metrics.ts +35 -0
  200. package/src/observability/payload-capture.ts +114 -41
  201. package/src/observability/payload-store.ts +249 -24
  202. package/src/observability/raw-event-writer.ts +118 -0
  203. package/src/observability/runtime-metrics.ts +71 -1
  204. package/src/observability/telemetry-buffer.ts +100 -17
  205. package/src/observability/telemetry-reconciliation.ts +417 -0
  206. package/src/persistence/boot.ts +20 -9
  207. package/src/persistence/db-pg.ts +13 -0
  208. package/src/persistence/db-sqlite.ts +569 -497
  209. package/src/persistence/dialect.ts +3 -2
  210. package/src/persistence/migrate.ts +181 -181
  211. package/src/persistence/schema.ts +1496 -1406
  212. package/src/persistence/shared-cache.ts +5 -1
  213. package/src/persistence/stores/api-key-store.ts +581 -581
  214. package/src/persistence/stores/telemetry-store.ts +124 -63
  215. package/src/protocol/reasoning-text.ts +30 -0
  216. package/src/protocol/registry.ts +2 -0
  217. package/src/protocol/response/chat.ts +33 -7
  218. package/src/protocol/response/codex.ts +14 -2
  219. package/src/protocol/response/messages.ts +5 -2
  220. package/src/providers/authentication/oauth-flow-store.ts +3 -10
  221. package/src/providers/bundled-discovery-providers.ts +122 -122
  222. package/src/providers/default-registry.ts +14 -0
  223. package/src/providers/discovery/catalog/catalog-blob.ts +18 -18
  224. package/src/providers/discovery/models-dev-catalog.ts +354 -354
  225. package/src/providers/discovery/probe-phases.ts +43 -7
  226. package/src/providers/discovery/probing-service.ts +70 -32
  227. package/src/providers/integrations/antigravity/antigravity.ts +9 -2
  228. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +85 -17
  229. package/src/providers/integrations/buddy/buddy-chat-shared.ts +934 -934
  230. package/src/providers/integrations/buddy/buddy-checkin.ts +5 -9
  231. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +3 -7
  232. package/src/providers/integrations/buddy/buddy-quota-shared.ts +3 -1
  233. package/src/providers/integrations/buddy/capabilities.ts +4 -0
  234. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +57 -49
  235. package/src/providers/integrations/buddy/codebuddy/provider.ts +180 -180
  236. package/src/providers/integrations/buddy/workbuddy/provider.ts +206 -206
  237. package/src/providers/integrations/buddy/workbuddy/quota.ts +161 -161
  238. package/src/providers/integrations/claude/claude-quota.ts +2 -2
  239. package/src/providers/integrations/claude/claude-user-profiles.ts +3 -2
  240. package/src/providers/integrations/claude/claude.ts +3 -4
  241. package/src/providers/integrations/cline/cline.ts +94 -8
  242. package/src/providers/integrations/codex/codex.ts +61 -37
  243. package/src/providers/integrations/cursor/cursor-catalog.ts +368 -368
  244. package/src/providers/integrations/cursor/cursor-http2.ts +300 -300
  245. package/src/providers/integrations/cursor/cursor-identity.ts +2 -4
  246. package/src/providers/integrations/cursor/cursor-request.ts +11 -0
  247. package/src/providers/integrations/cursor/cursor.ts +29 -17
  248. package/src/providers/integrations/cursor/protocol/framing.ts +129 -129
  249. package/src/providers/integrations/cursor/protocol/messages.ts +2380 -2380
  250. package/src/providers/integrations/cursor/protocol/struct.ts +305 -305
  251. package/src/providers/integrations/cursor/protocol/tool-canonical.ts +275 -0
  252. package/src/providers/integrations/github/github.ts +3 -1
  253. package/src/providers/integrations/grok/grok-quota.ts +279 -279
  254. package/src/providers/integrations/grok/grok-ratelimit-store.ts +73 -73
  255. package/src/providers/integrations/grok/grok-ratelimit.ts +218 -218
  256. package/src/providers/integrations/hermes.ts +7 -1
  257. package/src/providers/integrations/inferhub.ts +201 -73
  258. package/src/providers/integrations/kilo/kilo.ts +152 -152
  259. package/src/providers/integrations/kiro/kiro-machine-id.ts +2 -4
  260. package/src/providers/integrations/opencode/provider.ts +2 -0
  261. package/src/providers/integrations/openrouter/provider.ts +129 -129
  262. package/src/providers/integrations/qoder/qoder-quota.ts +193 -192
  263. package/src/providers/integrations/qoder/qoder-realm.ts +106 -106
  264. package/src/providers/integrations/trae/trae-headers.ts +17 -48
  265. package/src/providers/integrations/trae/trae-oauth.ts +4 -26
  266. package/src/providers/integrations/trae/trae-quota.ts +389 -384
  267. package/src/providers/integrations/trae/trae-realm.ts +15 -2
  268. package/src/providers/integrations/trae/trae.ts +22 -24
  269. package/src/providers/integrations/xiaomi-mimo/think-stream.ts +100 -24
  270. package/src/providers/integrations/zcode/oauth.ts +1 -1
  271. package/src/providers/operations/account-health-service.ts +605 -279
  272. package/src/providers/provider-metadata.ts +12 -1
  273. package/src/providers/provider-model-definition.ts +373 -373
  274. package/src/providers/provider-probe.ts +3 -0
  275. package/src/providers/quota/quota-contracts.ts +3 -7
  276. package/src/providers/search/search-provider.ts +2 -6
  277. package/src/security/admission/contracts.ts +10 -0
  278. package/src/security/admission/in-memory-store.ts +89 -14
  279. package/src/security/admission/lua.ts +191 -182
  280. package/src/security/admission/redis-store.ts +30 -0
  281. package/src/security/admission/service.ts +18 -0
  282. package/src/security/api-key-auth-cache.ts +96 -0
  283. package/src/security/api-key-auth.ts +11 -100
  284. package/src/security/client-router-fingerprint.ts +3 -7
  285. package/src/security/ip-boundary.ts +7 -3
  286. package/src/shared/coerce.ts +67 -0
  287. package/src/shared/hash.ts +6 -0
  288. package/src/shared/time.ts +7 -0
  289. package/src/transport/dispatch/attempt-finalize.ts +26 -138
  290. package/src/transport/dispatch/attempt-loop.ts +103 -81
  291. package/src/transport/dispatch/capture-policy.ts +78 -0
  292. package/src/transport/dispatch/proxy-request.ts +4 -2
  293. package/src/transport/dispatch/streaming/encoder.ts +111 -5
  294. package/src/transport/dispatch/streaming/stream.ts +19 -2
  295. package/src/transport/dispatch/streaming/thinking-loop.ts +300 -0
  296. package/src/transport/failure-policy.ts +27 -0
  297. package/src/transport/guards/abuse-guard.ts +2 -2
  298. package/src/transport/guards/auth-guard.ts +17 -0
  299. package/src/transport/guards/body-policy.ts +3 -2
  300. package/src/transport/guards/concurrency-guard.ts +89 -13
  301. package/src/transport/guards/early-rejection-capture.ts +43 -3
  302. package/src/transport/guards/error-lifecycle.ts +10 -2
  303. package/src/transport/guards/guard-errors.ts +23 -0
  304. package/src/transport/guards/headroom-guard.ts +41 -7
  305. package/src/transport/guards/pipeline.ts +24 -0
  306. package/src/transport/guards/request-context.ts +2 -1
  307. package/src/transport/routing/admission.ts +51 -9
  308. package/src/transport/routing/bounded-lru.ts +49 -0
  309. package/src/transport/routing/candidate-index.ts +88 -0
  310. package/src/transport/routing/reservations.ts +121 -7
  311. package/src/transport/routing/round-robin.ts +10 -22
  312. package/src/transport/routing/route-catalog.ts +26 -13
  313. package/src/transport/routing/route-model.ts +22 -2
  314. package/src/transport/routing/router.ts +53 -31
  315. package/src/transport/surface/chat/encode.ts +2 -3
  316. package/src/transport/surface/chat/parse.ts +2 -1
  317. package/src/transport/surface/dialects.ts +11 -3
  318. package/src/transport/surface/messages/encode.ts +2 -1
  319. package/src/transport/surface/messages/parse.ts +3 -1
  320. package/src/transport/surface/messages/stream.ts +2 -6
  321. package/src/workers/maintenance-lease.ts +200 -0
  322. package/src/workers/scheduler.ts +101 -1
  323. package/dist/dashboard/assets/BannedPage-Brvuj_Eb.js.gz +0 -0
  324. package/dist/dashboard/assets/CliToolDetailPage-CqfXtI3y.js.gz +0 -0
  325. package/dist/dashboard/assets/CliToolsPage-GQeS91bg.js.gz +0 -0
  326. package/dist/dashboard/assets/CombosPage-BDRsTXBB.js.gz +0 -0
  327. package/dist/dashboard/assets/ConsoleLogPage-zP8AFHX0.js.gz +0 -0
  328. package/dist/dashboard/assets/CustomizationPage-BmfrNZ14.js.gz +0 -0
  329. package/dist/dashboard/assets/HealthEventsModal-Dn3M6WZc.js +0 -1
  330. package/dist/dashboard/assets/HealthEventsModal-Dn3M6WZc.js.gz +0 -0
  331. package/dist/dashboard/assets/LoginPage-DoreIgm8.js.gz +0 -0
  332. package/dist/dashboard/assets/ModelPicker-C7pDb41R.js.gz +0 -0
  333. package/dist/dashboard/assets/OverviewPage-CvvD1Ugk.js +0 -1
  334. package/dist/dashboard/assets/OverviewPage-CvvD1Ugk.js.gz +0 -0
  335. package/dist/dashboard/assets/ProviderDetailPage-Clbn1gsW.js +0 -3
  336. package/dist/dashboard/assets/ProviderDetailPage-Clbn1gsW.js.gz +0 -0
  337. package/dist/dashboard/assets/ProvidersPage-BnoPgA7w.js.gz +0 -0
  338. package/dist/dashboard/assets/ProxyPage-Bq_TGgdb.js.gz +0 -0
  339. package/dist/dashboard/assets/QuotaPage-D9DHXvom.js +0 -1
  340. package/dist/dashboard/assets/QuotaPage-D9DHXvom.js.gz +0 -0
  341. package/dist/dashboard/assets/SettingsPage-7xV8WkWL.js +0 -1
  342. package/dist/dashboard/assets/SettingsPage-7xV8WkWL.js.gz +0 -0
  343. package/dist/dashboard/assets/SetupPage-Day3mCOn.js.gz +0 -0
  344. package/dist/dashboard/assets/SortableList-DQxllnB5.js.gz +0 -0
  345. package/dist/dashboard/assets/UsagePage-DXa1oR-4.js.gz +0 -0
  346. package/dist/dashboard/assets/api-keys-DQYLQxpW.js.gz +0 -0
  347. package/dist/dashboard/assets/app-CX_Z8cMs.css +0 -2
  348. package/dist/dashboard/assets/app-CX_Z8cMs.css.gz +0 -0
  349. package/dist/dashboard/assets/assert-C9FD_JwJ.js.gz +0 -0
  350. package/dist/dashboard/assets/badge-CR72dasT.js.gz +0 -0
  351. package/dist/dashboard/assets/banner-CI9_eSfO.js.gz +0 -0
  352. package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
  353. package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
  354. package/dist/dashboard/assets/clipboard-button-611pSsaX.js.gz +0 -0
  355. package/dist/dashboard/assets/dialog-k37exjNt.js.gz +0 -0
  356. package/dist/dashboard/assets/drawer-CX7N8ucR.js.gz +0 -0
  357. package/dist/dashboard/assets/entry-B9Xvtnfj.js +0 -1
  358. package/dist/dashboard/assets/entry-B9Xvtnfj.js.gz +0 -0
  359. package/dist/dashboard/assets/entry-ByMGkR3C.js +0 -4
  360. package/dist/dashboard/assets/entry-ByMGkR3C.js.gz +0 -0
  361. package/dist/dashboard/assets/entry-CTP8AyiS.js.gz +0 -0
  362. package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
  363. package/dist/dashboard/assets/index-z3zDOSMM.js.gz +0 -0
  364. package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
  365. package/dist/dashboard/assets/input-V1umFiBk.js.gz +0 -0
  366. package/dist/dashboard/assets/layout-BBOYycyS.js.gz +0 -0
  367. package/dist/dashboard/assets/list-row-1zzZYM0B.js.gz +0 -0
  368. package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
  369. package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
  370. package/dist/dashboard/assets/mutation-46P0oWMe.js.gz +0 -0
  371. package/dist/dashboard/assets/numbers-DkfMR5Qs.js.gz +0 -0
  372. package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
  373. package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
  374. package/dist/dashboard/assets/select-C6MMiaio.js.gz +0 -0
  375. package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
  376. package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
  377. package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
  378. package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
  379. package/dist/dashboard/assets/useMutation-Dem0lXQj.js.gz +0 -0
  380. package/scripts/build/aot.ts +0 -143
  381. package/scripts/build/build.ts +0 -24
  382. package/scripts/build/compile.ts +0 -88
  383. package/scripts/build/restart.ts +0 -120
  384. package/scripts/build/start.ts +0 -25
  385. package/src/observability/event-compaction.ts +0 -317
  386. package/src/observability/event-day-index.ts +0 -440
@@ -3,6 +3,7 @@
3
3
  // stays bespoke; the chat leg is a declarative spec row.
4
4
  import type { ProviderDispatchTarget, ProviderAdapter, ProviderDispatchContext } from "../provider-contracts";
5
5
  import type { ModelDefinition } from "../provider-model-definition";
6
+ import type { ProviderModelDiscovery } from "../discovery/discovery-types";
6
7
  import { providerBaseUrl } from "../provider-metadata";
7
8
  import { defineModel, isResponsesNativeModelId } from "../provider-model-definition";
8
9
  import { createApiKeyAdapter, type ApiKeyProviderSpec } from "../configured-provider";
@@ -12,6 +13,7 @@ import type { CanonicalEvent, CanonicalRequest, ContentPart } from "../../protoc
12
13
  import { GatewayError } from "../../protocol/gateway-error";
13
14
  import { applyParamQuirks } from "../../transport/translation/quirks";
14
15
  import { buildClaudeMessagesRequest, filterClaudeCustomHeaders } from "./shared/claude-messages";
16
+ import { resolveInboundSessionId } from "../operations/session-resolution";
15
17
  import { isRecord } from "../../protocol/codecs";
16
18
  import { sendClaudeMessagesRequest } from "../../protocol/upstream/send-claude-messages";
17
19
 
@@ -91,6 +93,46 @@ export function ensureInferhubMessagesTextBreakpoints(
91
93
  export const INFERHUB_BASE_URL = providerBaseUrl("inferhub");
92
94
  export const INFERHUB_PROVIDER_ID = "inferhub" as const;
93
95
 
96
+ /**
97
+ * Live `/v1/models` discovery for InferHub.
98
+ *
99
+ * The generic OpenAI discovery loader classifies a model as `responses` only
100
+ * when `isResponsesNativeModelId` matches and otherwise says `chat`, so every
101
+ * Claude-backed InferHub id came back `chat` — and the chat wire strips
102
+ * thinking and native tool_use server-side. The wire family is therefore
103
+ * re-derived here from the id, the same way the offline catalog does it, with
104
+ * Claude ids forced onto Messages.
105
+ */
106
+ export function inferhubModelDiscovery(): () => Promise<ProviderModelDiscovery> {
107
+ return async () => async (input) => {
108
+ // dynamic-import: the OpenAI `/models` fetcher is the same module every
109
+ // discovery-backed provider loads lazily, and a static import here would
110
+ // pull it into every process that touches InferHub metadata.
111
+ const { fetchOpenAICompatibleModels } = await import("../discovery/openai-model-discovery");
112
+ const models = await fetchOpenAICompatibleModels({
113
+ baseUrl: input.baseUrl,
114
+ providerId: INFERHUB_PROVIDER_ID,
115
+ headers: { authorization: `Bearer ${input.credential}` },
116
+ ...(input.fetcher ? { fetcher: input.fetcher } : {}),
117
+ });
118
+ // A `config_read` key is rejected by the inference host with 403, and any
119
+ // other failure leaves `models` null. Neither means "InferHub has no
120
+ // models" — the committed list is a valid answer, so probing keeps working
121
+ // instead of failing the whole refresh with "no usable models".
122
+ const source: readonly ModelDefinition[] =
123
+ models === null || models.length === 0 ? INFERHUB_MODELS : models;
124
+ return source.map((model) =>
125
+ isInferhubClaudeModel(model.modelId)
126
+ ? {
127
+ ...model,
128
+ wireFamily: "messages" as const,
129
+ endpointPath: "/v1/messages",
130
+ }
131
+ : model,
132
+ );
133
+ };
134
+ }
135
+
94
136
  /**
95
137
  * Chat + Responses legs of InferHub. Claude-backed models are routed to
96
138
  * `InferhubMessagesAdapter` by wire family instead (see
@@ -99,85 +141,159 @@ export const INFERHUB_PROVIDER_ID = "inferhub" as const;
99
141
  * `POST /v1/responses` (native reasoning + tool_use survive; the chat wire
100
142
  * answers too but strips reasoning server-side).
101
143
  */
144
+ /**
145
+ * InferHub pins a conversation to one upstream provider for as long as
146
+ * `X-Session-Id` stays the same, which is what keeps the prompt cache warm
147
+ * across turns (the pin lapses after roughly ten minutes idle). The id is the
148
+ * client's own session when it sends one and a stable affinity key derived from
149
+ * the opening turn otherwise — never a per-request random value, which would
150
+ * re-pin on every turn and defeat the header.
151
+ */
152
+ function inferhubSessionHeaders(
153
+ context: ProviderDispatchContext,
154
+ request?: CanonicalRequest,
155
+ ): Record<string, string> {
156
+ const sessionId = resolveInboundSessionId(context, request);
157
+ return sessionId === undefined ? {} : { "X-Session-Id": sessionId };
158
+ }
159
+
102
160
  const INFERHUB_CHAT_SPEC: ApiKeyProviderSpec = {
103
161
  provider_id: INFERHUB_PROVIDER_ID,
104
162
  endpoint_paths_by_wire_family: { responses: "/responses" },
163
+ buildExtraHeaders: (context, request) => inferhubSessionHeaders(context, request),
105
164
  };
106
165
 
107
- /** InferHub — full marketplace catalog from your paste (80+ models, 4 providers ag/cc/cb/cbcn/cx/ocg/ali/mimo/zai). Context sizes via websearch (Claude 1M/200k, Gemini 1M). */
166
+ /**
167
+ * Offline fallback, used only when a live `/v1/models` read fails or returns
168
+ * nothing — a `config_read` key is rejected by the inference host with 403, so
169
+ * a failed discovery is common and is not "InferHub has no models".
170
+ *
171
+ * Every context, output, modality and reasoning scale below is copied from the
172
+ * upstream's own `/api/catalog` row rather than guessed, because a wrong limit
173
+ * is worse than a missing one: an overstated context window is rejected by the
174
+ * provider at request time, and an understated one truncates silently.
175
+ *
176
+ * Only `ag/` and `cc/` are listed. The marketplace republishes its whole roster
177
+ * (270 rows across 21 upstreams) and moves faster than a committed array can,
178
+ * so a wider hand-kept list would be stale the moment it was written.
179
+ */
108
180
  const INFERHUB_MODELS_RAW: readonly {
109
181
  id: string;
110
- contextLimit: number;
111
- outputLimit: number;
182
+ /** Null when the upstream states no window; `defineModel` marks it estimated. */
183
+ contextLimit: number | null;
184
+ outputLimit: number | null;
185
+ /** Upstream `modalities`. A row without `image` must not advertise vision. */
186
+ readonly modalities?: readonly ("text" | "image" | "video")[];
187
+ /** Upstream `reasoningLevels`; absent means the model exposes no scale. */
188
+ readonly reasoningLevels?: readonly string[];
112
189
  }[] = [
113
- // ag/ — Antigravity (4 models) — sonnet 251k per request
114
- { id: "ag/claude-sonnet-4-6", contextLimit: 251000, outputLimit: 64000 },
115
- { id: "ag/gemini-3.7-flash-high", contextLimit: 1048576, outputLimit: 65536 },
116
- { id: "ag/gemini-3.8-flash-high", contextLimit: 1048576, outputLimit: 65536 },
117
- { id: "ag/gemini-pro-agent", contextLimit: 1048576, outputLimit: 65536 },
118
- // cc/ — Claude Code (10 models)
119
- { id: "cc/claude-fable-5", contextLimit: 1000000, outputLimit: 128000 },
120
- { id: "cc/claude-fable-5-1", contextLimit: 1000000, outputLimit: 128000 },
121
- { id: "cc/claude-haiku-4-5", contextLimit: 200000, outputLimit: 64000 },
122
- { id: "cc/claude-opus-4-6", contextLimit: 1000000, outputLimit: 128000 },
123
- { id: "cc/claude-opus-4-7", contextLimit: 1000000, outputLimit: 128000 },
124
- { id: "cc/claude-opus-4-8", contextLimit: 1000000, outputLimit: 128000 },
125
- { id: "cc/claude-opus-5", contextLimit: 1000000, outputLimit: 128000 },
126
- { id: "cc/claude-sonnet-4-5", contextLimit: 200000, outputLimit: 64000 },
127
- // 128K: Sonnet 4.6 is in the 1M/128K generation, the same as the Opus 4.6
128
- // row directly above it and every other 4.6+ row here.
129
- { id: "cc/claude-sonnet-4-6", contextLimit: 1000000, outputLimit: 128000 },
130
- { id: "cc/claude-sonnet-5", contextLimit: 1000000, outputLimit: 128000 },
131
- // cb/ — CodeBuddy (12 models)
132
- { id: "cb/claude-opus-4.6", contextLimit: 1000000, outputLimit: 128000 },
133
- { id: "cb/claude-opus-4.7-1m", contextLimit: 1000000, outputLimit: 64000 },
134
- { id: "cb/claude-opus-5", contextLimit: 1000000, outputLimit: 128000 },
135
- { id: "cb/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 384000 },
136
- { id: "cb/gemini-3.1-pro", contextLimit: 1048576, outputLimit: 65536 },
137
- { id: "cb/glm-5.2", contextLimit: 1000000, outputLimit: 131072 },
138
- { id: "cb/glm-5.3", contextLimit: 1000000, outputLimit: 131072 },
139
- { id: "cb/gpt-5.6-luna", contextLimit: 1050000, outputLimit: 128000 },
140
- { id: "cb/gpt-5.6-sol", contextLimit: 1050000, outputLimit: 128000 },
141
- { id: "cb/gpt-5.6-terra", contextLimit: 1050000, outputLimit: 128000 },
142
- { id: "cb/kimi-k3", contextLimit: 1048576, outputLimit: 131072 },
143
- { id: "cb/minimax-m3", contextLimit: 512000, outputLimit: 80000 },
144
- // cbcn/ — CodeBuddy CN
145
- { id: "cbcn/deepseek-v4-flash", contextLimit: 1000000, outputLimit: 384000 },
146
- { id: "cbcn/deepseek-v4-pro", contextLimit: 1000000, outputLimit: 384000 },
147
- { id: "cbcn/glm-5.2", contextLimit: 1000000, outputLimit: 131072 },
148
- { id: "cbcn/glm-5.3", contextLimit: 1000000, outputLimit: 131072 },
149
- { id: "cbcn/glm-5.3-flash", contextLimit: 1000000, outputLimit: 131072 },
150
- { id: "cbcn/kimi-k2.6", contextLimit: 262144, outputLimit: 262144 },
151
- { id: "cbcn/kimi-k2.7", contextLimit: 128000, outputLimit: 8192 },
152
- { id: "cbcn/kimi-k3", contextLimit: 1048576, outputLimit: 131072 },
153
- { id: "cbcn/minimax-m2.7", contextLimit: 204800, outputLimit: 131072 },
154
- { id: "cbcn/minimax-m3", contextLimit: 512000, outputLimit: 80000 },
155
- // cx/ — Codex
156
- { id: "cx/gpt-5.6-luna", contextLimit: 1050000, outputLimit: 128000 },
157
- { id: "cx/gpt-5.6-sol", contextLimit: 1050000, outputLimit: 128000 },
158
- { id: "cx/gpt-5.6-terra", contextLimit: 1050000, outputLimit: 128000 },
159
- { id: "cx/gpt-6-astra", contextLimit: 1050000, outputLimit: 128000 },
160
- // ocg/ — OpenCode Go
161
- { id: "ocg/deepseek-v4-flash-0731", contextLimit: 1000000, outputLimit: 384000 },
162
- { id: "ocg/deepseek-v4-pro", contextLimit: 1000000, outputLimit: 384000 },
163
- { id: "ocg/glm-5.2", contextLimit: 1000000, outputLimit: 131072 },
164
- { id: "ocg/glm-5.3", contextLimit: 1000000, outputLimit: 131072 },
165
- { id: "ocg/glm-5.3-flash", contextLimit: 1000000, outputLimit: 131072 },
166
- // ali/ — Alibaba
167
- { id: "ali/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 384000 },
168
- { id: "ali/deepseek-v4-flash-0731", contextLimit: 1000000, outputLimit: 384000 },
169
- { id: "ali/deepseek-v4-pro-0813", contextLimit: 1048576, outputLimit: 384000 },
170
- { id: "ali/glm-5.2", contextLimit: 1000000, outputLimit: 131072 },
171
- { id: "ali/kimi-k2.7-code", contextLimit: 262144, outputLimit: 262144 },
172
- { id: "ali/kimi-k3", contextLimit: 1048576, outputLimit: 131072 },
173
- { id: "ali/qwen3.8-max", contextLimit: 991000, outputLimit: 65536 },
174
- // mimo/ — MiMo (2 models)
175
- { id: "mimo/mimo-v2.5", contextLimit: 1048576, outputLimit: 131072 },
176
- { id: "mimo/mimo-v2.5-pro", contextLimit: 1048576, outputLimit: 131072 },
177
- // zai/ — Z.AI
178
- { id: "zai/glm-5.2", contextLimit: 1000000, outputLimit: 131072 },
179
- { id: "zai/glm-5.3", contextLimit: 1000000, outputLimit: 131072 },
180
- { id: "zai/glm-5.3-flash", contextLimit: 1000000, outputLimit: 131072 },
190
+ // ag/ — Antigravity. Every row: 1M context, text+image input, text output.
191
+ { id: "ag/claude-opus-4-6-thinking", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"] },
192
+ { id: "ag/claude-opus-5-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["low", "medium", "high"] },
193
+ { id: "ag/claude-sonnet-4-6", contextLimit: 1000000, outputLimit: 64000, modalities: ["text", "image"] },
194
+ { id: "ag/claude-sonnet-5-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["low", "medium", "high"] },
195
+ { id: "ag/gemini-3.8-flash-high", contextLimit: 1000000, outputLimit: 65536, modalities: ["text", "image"], reasoningLevels: ["low", "medium", "high"] },
196
+ { id: "ag/gemini-4-argon", contextLimit: 1000000, outputLimit: 65536, modalities: ["text", "image"], reasoningLevels: ["low", "medium", "high"] },
197
+ // cc/ — Claude Code. Haiku 4-5 and Opus 4-5 are the 200k-context rows.
198
+ { id: "cc/claude-fable-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"] },
199
+ { id: "cc/claude-fable-5-1", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"] },
200
+ { id: "cc/claude-haiku-4-5", contextLimit: 200000, outputLimit: 64000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
201
+ { id: "cc/claude-haiku-5-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
202
+ { id: "cc/claude-opus-4-5", contextLimit: 200000, outputLimit: 64000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
203
+ { id: "cc/claude-opus-4-6", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
204
+ { id: "cc/claude-opus-4-7", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
205
+ { id: "cc/claude-opus-4-8", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
206
+ { id: "cc/claude-opus-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
207
+ { id: "cc/claude-opus-5-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["low", "medium", "high"] },
208
+ { id: "cc/claude-sonnet-4-6", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
209
+ { id: "cc/claude-sonnet-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["none", "low", "medium", "high"] },
210
+ { id: "cc/claude-sonnet-5-5", contextLimit: 1000000, outputLimit: 128000, modalities: ["text", "image"], reasoningLevels: ["low", "medium", "high"] },
211
+ // cb/
212
+ { id: "cb/claude-opus-4.6", contextLimit: 1000000, outputLimit: 128000, modalities: ["text","image"] },
213
+ { id: "cb/claude-opus-4.7-1m", contextLimit: 1000000, outputLimit: 128000, modalities: ["text","image"] },
214
+ { id: "cb/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
215
+ { id: "cb/gemini-2.5-flash-image", contextLimit: null, outputLimit: null, modalities: ["text","image"] },
216
+ { id: "cb/gemini-3.1-pro", contextLimit: 1000000, outputLimit: 65536, modalities: ["text","image","video"], reasoningLevels: ["low","high"] },
217
+ { id: "cb/glm-5.3", contextLimit: 1000000, outputLimit: 48000, modalities: ["text"], reasoningLevels: ["low","high","max"] },
218
+ { id: "cb/glm-5.3-flash", contextLimit: 1000000, outputLimit: 48000, modalities: ["text"], reasoningLevels: ["low","high","max"] },
219
+ { id: "cb/gpt-5.3-codex", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["low","medium","high"] },
220
+ { id: "cb/kimi-k3.1-pro", contextLimit: 1000000, outputLimit: 32000, modalities: ["text","image"], reasoningLevels: ["low","high","max"] },
221
+ { id: "cb/minimax-m3.1-flash", contextLimit: 1000000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["low","medium","high","xhigh","max"] },
222
+ // cbcn/
223
+ { id: "cbcn/deepseek-v4-pro", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
224
+ { id: "cbcn/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 128000, modalities: ["text","image"] },
225
+ { id: "cbcn/glm-5.3", contextLimit: 1000000, outputLimit: 48000, modalities: ["text","image"], reasoningLevels: ["low","high","max"] },
226
+ { id: "cbcn/glm-5.3-flash", contextLimit: 1000000, outputLimit: 48000, modalities: ["text","image"], reasoningLevels: ["low","high","max"] },
227
+ { id: "cbcn/hy4-preview", contextLimit: 1000000, outputLimit: 64000, modalities: ["text","image"] },
228
+ { id: "cbcn/kimi-k2.8-preview", contextLimit: 1000000, outputLimit: 32000, modalities: ["text","image"], reasoningLevels: ["none","low","high","max"] },
229
+ { id: "cbcn/kimi-k3.1-pro", contextLimit: 1000000, outputLimit: 32000, modalities: ["text","image"], reasoningLevels: ["low","high","max"] },
230
+ { id: "cbcn/minimax-m3.1-flash", contextLimit: 1000000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["low","medium","high","xhigh","max"] },
231
+ // cmc/
232
+ { id: "cmc/MiniMaxAI/MiniMax-M3", contextLimit: 1000000, outputLimit: 262144, modalities: ["text"] },
233
+ { id: "cmc/Qwen/Qwen3.7-Max", contextLimit: 1000000, outputLimit: null, modalities: ["text"] },
234
+ { id: "cmc/Qwen/Qwen3.7-Plus", contextLimit: 1000000, outputLimit: null, modalities: ["text"] },
235
+ { id: "cmc/Qwen/Qwen3.8-Flash", contextLimit: 1000000, outputLimit: 131072, modalities: ["text"] },
236
+ { id: "cmc/Qwen/Qwen3.8-Max", contextLimit: 1000000, outputLimit: 131072, modalities: ["text"] },
237
+ { id: "cmc/deepseek/deepseek-v4-flash", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"], reasoningLevels: ["none","low","high","max"] },
238
+ { id: "cmc/deepseek/deepseek-v4-pro", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"], reasoningLevels: ["none","low","high","max"] },
239
+ { id: "cmc/deepseek/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"], reasoningLevels: ["none","low","high","max"] },
240
+ { id: "cmc/deepseek/deepseek-v4.1-flash-fast", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"], reasoningLevels: ["none","low","high","max"] },
241
+ { id: "cmc/gpt-5.6-luna", contextLimit: 1050000, outputLimit: null, modalities: ["text"] },
242
+ { id: "cmc/gpt-6-luna", contextLimit: 1050000, outputLimit: null, modalities: ["text"] },
243
+ { id: "cmc/meituan/LongCat-2.0", contextLimit: 1048576, outputLimit: null, modalities: ["text"] },
244
+ { id: "cmc/meta/muse-spark-1.2", contextLimit: 1000000, outputLimit: null, modalities: ["text"] },
245
+ { id: "cmc/meta/muse-spark-1.2-contributor", contextLimit: 1000000, outputLimit: null, modalities: ["text"] },
246
+ { id: "cmc/meta/muse-spark-1.3", contextLimit: 1000000, outputLimit: null, modalities: ["text"] },
247
+ { id: "cmc/meta/muse-spark-1.3-contributor", contextLimit: 1000000, outputLimit: null, modalities: ["text"] },
248
+ { id: "cmc/mistral/mistral-large-4", contextLimit: 524288, outputLimit: 262144, modalities: ["text"] },
249
+ { id: "cmc/moonshotai/Kimi-K2.6", contextLimit: 262144, outputLimit: null, modalities: ["text"] },
250
+ { id: "cmc/moonshotai/Kimi-K2.7-Code", contextLimit: 262144, outputLimit: null, modalities: ["text"] },
251
+ { id: "cmc/moonshotai/Kimi-K2.7-Code-Highspeed", contextLimit: 262144, outputLimit: null, modalities: ["text"] },
252
+ { id: "cmc/moonshotai/Kimi-K3", contextLimit: 1000000, outputLimit: null, modalities: ["text"], reasoningLevels: ["low","high","max"] },
253
+ { id: "cmc/moonshotai/Kimi-K3.1-Pro", contextLimit: 1000000, outputLimit: null, modalities: ["text"], reasoningLevels: ["low","high","max"] },
254
+ { id: "cmc/tencent/hy4-preview", contextLimit: 1048576, outputLimit: 64000, modalities: ["text"] },
255
+ { id: "cmc/xai/grok-4.5", contextLimit: 500000, outputLimit: null, modalities: ["text"] },
256
+ { id: "cmc/xai/grok-4.6", contextLimit: 500000, outputLimit: null, modalities: ["text"] },
257
+ { id: "cmc/xai/grok-4.7", contextLimit: 500000, outputLimit: null, modalities: ["text"] },
258
+ { id: "cmc/xiaomi/mimo-v2.6-flash", contextLimit: 1000000, outputLimit: 131072, modalities: ["text"] },
259
+ { id: "cmc/xiaomi/mimo-v2.6-pro", contextLimit: 1000000, outputLimit: 131072, modalities: ["text"] },
260
+ { id: "cmc/z-ai/glm-5.3-flashx", contextLimit: 1000000, outputLimit: 128000, modalities: ["text"], reasoningLevels: ["low","high","max"] },
261
+ { id: "cmc/zai-org/GLM-5.2", contextLimit: 1000000, outputLimit: 128000, modalities: ["text"], reasoningLevels: ["high","max"] },
262
+ { id: "cmc/zai-org/GLM-5.3", contextLimit: 1000000, outputLimit: 128000, modalities: ["text"], reasoningLevels: ["low","high","max"] },
263
+ // grok/
264
+ { id: "grok/grok-4.5", contextLimit: 500000, outputLimit: null, modalities: ["text","image"], reasoningLevels: ["low","medium","high"] },
265
+ { id: "grok/grok-4.6", contextLimit: 500000, outputLimit: null, modalities: ["text"] },
266
+ { id: "grok/grok-4.7", contextLimit: 500000, outputLimit: null, modalities: ["text"] },
267
+ { id: "grok/grok-4.7-build-fast", contextLimit: 500000, outputLimit: null, modalities: ["text"], reasoningLevels: ["low","medium","high","xhigh"] },
268
+ // mm/
269
+ { id: "mm/MiniMax-M3.1-Flash", contextLimit: 1000000, outputLimit: 524288, modalities: ["text","image"], reasoningLevels: ["low","medium","high","xhigh","max"] },
270
+ // mmcn/
271
+ { id: "mmcn/MiniMax-M3.1-Flash", contextLimit: 1000000, outputLimit: 524288, modalities: ["text","image"], reasoningLevels: ["low","medium","high","xhigh","max"] },
272
+ // cx/
273
+ { id: "cx/gpt-5.6-luna", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["none","low","medium","high","xhigh","max"] },
274
+ { id: "cx/gpt-5.6-sol", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["none","low","medium","high","xhigh","max"] },
275
+ { id: "cx/gpt-5.6-terra", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["none","low","medium","high","xhigh","max"] },
276
+ { id: "cx/gpt-6-astra", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["low","medium","high","xhigh","max"] },
277
+ { id: "cx/gpt-6-luna", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["none","low","medium","high","xhigh","max"] },
278
+ { id: "cx/gpt-6-sol", contextLimit: 272000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["none","low","medium","high","xhigh","max"] },
279
+ { id: "cx/gpt-6.1-sol", contextLimit: 500000, outputLimit: 128000, modalities: ["text","image"], reasoningLevels: ["low","medium","high","xhigh","max"] },
280
+ { id: "cx/gpt-image-2-codex", contextLimit: null, outputLimit: null, modalities: ["text"] },
281
+ // ocg/
282
+ { id: "ocg/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
283
+ // ali/
284
+ { id: "ali/deepseek-v4-flash-0731", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"] },
285
+ { id: "ali/deepseek-v4-pro-0813", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"] },
286
+ { id: "ali/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
287
+ { id: "ali/deepseek-v4.1-flash-1017", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
288
+ { id: "ali/glm-5.3", contextLimit: 1000000, outputLimit: 128000, modalities: ["text"], reasoningLevels: ["low","high","max"] },
289
+ { id: "ali/kimi-k2.7-code", contextLimit: 262144, outputLimit: null, modalities: ["text","image"] },
290
+ // alicn/
291
+ { id: "alicn/deepseek-v4-flash-0731", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"] },
292
+ { id: "alicn/deepseek-v4-pro-0813", contextLimit: 1000000, outputLimit: 393216, modalities: ["text"] },
293
+ { id: "alicn/deepseek-v4.1-flash", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
294
+ { id: "alicn/deepseek-v4.1-flash-1017", contextLimit: 1000000, outputLimit: 393216, modalities: ["text","image"] },
295
+ { id: "alicn/glm-5.3", contextLimit: 1000000, outputLimit: 128000, modalities: ["text"], reasoningLevels: ["low","high","max"] },
296
+ { id: "alicn/kimi-k2.7-code", contextLimit: 262144, outputLimit: null, modalities: ["text","image"] },
181
297
  ] as const;
182
298
  /**
183
299
  * Claude-backed inferhub models (`*claude-*` across `ag/`/`cb/`/`cc/`) speak
@@ -238,6 +354,11 @@ export class InferhubMessagesAdapter implements ProviderAdapter {
238
354
  endpointPath: candidate.endpoint_path,
239
355
  mutatePayload: ensureInferhubMessagesTextBreakpoints,
240
356
  });
357
+ // Same conversation pin as the chat leg, applied after the shared Claude
358
+ // header builder rather than through `customHeaders`: that field is
359
+ // credential-derived (it is filtered and round-trips per account), and a
360
+ // per-conversation value does not belong in it.
361
+ Object.assign(outbound.headers, inferhubSessionHeaders(context, request));
241
362
  yield* sendClaudeMessagesRequest(
242
363
  outbound.url,
243
364
  outbound.headers,
@@ -310,8 +431,15 @@ export const INFERHUB_MODELS: readonly ModelDefinition[] = INFERHUB_MODELS_RAW.m
310
431
  id: e.id,
311
432
  ctx: e.contextLimit,
312
433
  out: e.outputLimit,
313
- vision: true,
314
- reasoning: true,
434
+ // Vision follows the upstream's own `modalities` rather than a blanket
435
+ // true: a row that does not accept images must not advertise that it does.
436
+ vision: e.modalities?.includes("image") ?? false,
437
+ // Reasoning is driven by the scale the upstream publishes. A model with no
438
+ // `reasoningLevels` at all exposes no effort control, so claiming it would
439
+ // let the console offer an effort the provider ignores.
440
+ ...(e.reasoningLevels !== undefined && e.reasoningLevels.length > 0
441
+ ? { reasoning: true, reasoningEfforts: e.reasoningLevels }
442
+ : { reasoning: false }),
315
443
  // Claude-backed models resolve to messages rows so thinking blocks and
316
444
  // native tool_use survive; the chat wire strips both server-side.
317
445
  // GPT-5/6 + o-series resolve to responses rows for the same reason.