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
@@ -23,7 +23,7 @@ export interface ConnectionUrlCandidate {
23
23
  }
24
24
 
25
25
  /** How one backing service's connection string is resolved. */
26
- export interface ConnectionUrlSpec {
26
+ interface ConnectionUrlSpec {
27
27
  /** Accepted URL schemes, e.g. `postgres:` / `postgresql:`. */
28
28
  readonly schemes: readonly string[];
29
29
  /** URL variables, in resolution order. */
@@ -17,7 +17,7 @@ export const fullSchema = schema;
17
17
  export type CartethyiaDatabase = NodePgDatabase<typeof fullSchema>;
18
18
 
19
19
  /** Raw rows from a parameter query, without driver-specific decoration. */
20
- export interface QueryRows {
20
+ interface QueryRows {
21
21
  readonly rows: unknown[];
22
22
  }
23
23
 
@@ -81,7 +81,7 @@ function databaseUrlFromLibpqEnv(): string | undefined {
81
81
  return `postgres://${credentials}${authorityHost}:${port}${path}`;
82
82
  }
83
83
 
84
- export function requireDatabaseUrl(): string {
84
+ function requireDatabaseUrl(): string {
85
85
  return requireConnectionUrl({
86
86
  schemes: ["postgres:", "postgresql:"],
87
87
  candidates: databaseUrlCandidates(),
@@ -124,7 +124,7 @@ export function poolIdleFloorFromEnv(): number {
124
124
  * only closes an idle client after `idleTimeoutMillis` (60s here); this gives
125
125
  * the pool a faster, explicit shrink path while still keeping the floor warm.
126
126
  */
127
- export function startPoolShrinker(pool: Pool, floor: number): () => void {
127
+ function startPoolShrinker(pool: Pool, floor: number): () => void {
128
128
  const interval = setInterval(() => {
129
129
  try {
130
130
  const idle = pool.idleCount;
@@ -326,7 +326,7 @@ const AUTH_KEY_COLUMNS = [
326
326
  "id", "tenant_id", "key_hash", "key_mode", "parent_key_id", "issued_client_ip",
327
327
  "issued_client_ip_key", "label", "scopes", "requests_per_minute", "daily_token_limit",
328
328
  "monthly_token_limit", "lifetime_token_budget", "lifetime_tokens_consumed",
329
- "max_concurrent_requests", "model_access_mode", "model_list", "client_router_denylist",
329
+ "max_concurrent_requests", "concurrency_scope", "model_access_mode", "model_list", "client_router_denylist",
330
330
  "model_prefix", "created_at", "enabled", "revoked_at", "banned_at", "ban_reason", "banned_until",
331
331
  "key_prefix", "key_encrypted",
332
332
  "notes_title", "notes_subtitle", "notes_body", "is_default", "sort_index",
@@ -341,7 +341,7 @@ export interface SqliteAuthStatements {
341
341
  readonly childrenConsumed: { get: (parentId: string) => { total: number } | null };
342
342
  }
343
343
 
344
- export function prepareAuthStatements(sqlite: Database): SqliteAuthStatements {
344
+ function prepareAuthStatements(sqlite: Database): SqliteAuthStatements {
345
345
  // A key is active while not revoked and not under an active ban: a ban is
346
346
  // active when `banned_at` is set and `banned_until` is null (permanent) or
347
347
  // still in the future. SQLite stores timestamps as ISO text, so the
@@ -507,7 +507,7 @@ function applyFilePragmas(db: Database): void {
507
507
  }
508
508
 
509
509
  /** The SQLite set lives beside the PostgreSQL one, never inside it. */
510
- export function resolveSqliteMigrationsFolder(): string {
510
+ function resolveSqliteMigrationsFolder(): string {
511
511
  return resolvePackagePath("migrations", "lite-sqlite3");
512
512
  }
513
513
 
@@ -143,7 +143,11 @@ export function affectedRows(result: unknown): number {
143
143
  * `.for()`, but a transaction there is already the write lock, so the query
144
144
  * runs as-is. The two builders disagree on `.for()`, so the call is typed at
145
145
  * the boundary instead of pushed into every store.
146
+ *
147
+ * The dialect is read from the query itself, not the process environment: a
148
+ * test may build a SQLite handle while the suite runs in full mode, and a
149
+ * PostgreSQL query always carries `.for` while a SQLite one never does.
146
150
  */
147
151
  export function lockRows<T>(query: T & { for?(mode: string): PromiseLike<unknown> }): PromiseLike<T extends PromiseLike<infer R> ? R : never> {
148
- return (sqliteDialect() ? query : query.for!("update")) as PromiseLike<T extends PromiseLike<infer R> ? R : never>;
152
+ return (typeof query.for === "function" ? query.for!("update") : query) as PromiseLike<T extends PromiseLike<infer R> ? R : never>;
149
153
  }
@@ -45,7 +45,7 @@ function sameMemoKey(left: ReadinessMemoKey, right: ReadinessMemoKey): boolean {
45
45
  * Returns typed ready/not_ready response.
46
46
  */
47
47
 
48
- export type ReadinessStatus = "ready" | "not_ready";
48
+ type ReadinessStatus = "ready" | "not_ready";
49
49
 
50
50
  export interface ReadinessCheckResult {
51
51
  readonly status: ReadinessStatus;
@@ -92,7 +92,7 @@ export function resolveRedisBackend(client: RedisClient | undefined): RedisBacke
92
92
  return client === undefined ? "memory" : "redis";
93
93
  }
94
94
 
95
- export interface CloseRedisOptions {
95
+ interface CloseRedisOptions {
96
96
  /** Bounded wait for `QUIT` before falling back to `disconnect()`. Defaults to 2s. */
97
97
  readonly quitTimeoutMs?: number;
98
98
  }
@@ -4,9 +4,23 @@ import {
4
4
  bigint, boolean, check, customType, index, integer, jsonb, numeric, pgEnum, pgTable,
5
5
  primaryKey, text, timestamp, unique, uniqueIndex, uuid, type AnyPgColumn,
6
6
  } from "drizzle-orm/pg-core";
7
+ import type { ProviderQuotaResult } from "../providers/quota/quota-contracts";
7
8
 
8
- export const TENANT_STATUSES = ["active", "suspended", "deleted"] as const;
9
- export type TenantStatus = (typeof TENANT_STATUSES)[number];
9
+ /**
10
+ * The persisted copy of one account's last successful quota read.
11
+ *
12
+ * Survives process restarts, which the in-process quota cache does not — so a
13
+ * cold page open can render the last known balance immediately while the sweep
14
+ * refreshes it. Stored only on success; a failed fetch leaves the previous
15
+ * snapshot in place.
16
+ */
17
+ export interface ProviderQuotaResultSnapshot {
18
+ readonly quota: ProviderQuotaResult;
19
+ readonly fetchedAt: string;
20
+ }
21
+
22
+ const TENANT_STATUSES = ["active", "suspended", "deleted"] as const;
23
+ type TenantStatus = (typeof TENANT_STATUSES)[number];
10
24
 
11
25
  export const tenants = pgTable(
12
26
  "tenants",
@@ -26,35 +40,35 @@ export const tenants = pgTable(
26
40
 
27
41
  // Canonical tenant/timestamp column definitions shared by every table.
28
42
 
29
- export function tenantRefNullable() {
43
+ function tenantRefNullable() {
30
44
  return uuid("tenant_id").references(() => tenants.id, { onDelete: "cascade" });
31
45
  }
32
46
 
33
- export function tenantRefRequired() {
47
+ function tenantRefRequired() {
34
48
  return uuid("tenant_id")
35
49
  .notNull()
36
50
  .references(() => tenants.id, { onDelete: "cascade" });
37
51
  }
38
52
 
39
- export function tenantRefPrimaryKey() {
53
+ function tenantRefPrimaryKey() {
40
54
  return uuid("tenant_id")
41
55
  .primaryKey()
42
56
  .references(() => tenants.id, { onDelete: "cascade" });
43
57
  }
44
58
 
45
- export function tenantCascadeSetNull() {
59
+ function tenantCascadeSetNull() {
46
60
  return uuid("tenant_id").references(() => tenants.id, { onDelete: "set null" });
47
61
  }
48
62
 
49
- export function createdAtColumn() {
63
+ function createdAtColumn() {
50
64
  return timestamp("created_at", { withTimezone: true }).notNull().defaultNow();
51
65
  }
52
66
 
53
- export function updatedAtColumn() {
67
+ function updatedAtColumn() {
54
68
  return timestamp("updated_at", { withTimezone: true }).notNull().defaultNow();
55
69
  }
56
70
 
57
- export function timestampColumns() {
71
+ function timestampColumns() {
58
72
  return { createdAt: createdAtColumn(), updatedAt: updatedAtColumn() };
59
73
  }
60
74
 
@@ -90,7 +104,7 @@ export const healthStatus = pgEnum("health_status", ["active", "cooldown", "disa
90
104
  * One definition, because the two tables are driven by the same transitions and
91
105
  * a column added to one of them by hand is how they drift.
92
106
  */
93
- export function healthColumns() {
107
+ function healthColumns() {
94
108
  return {
95
109
  status: healthStatus("status").notNull().default("active"),
96
110
  consecutiveFailures: integer("consecutive_failures").notNull().default(0),
@@ -295,6 +309,18 @@ export const providerAccounts = pgTable("provider_accounts", {
295
309
  * to an account that may well be refused.
296
310
  */
297
311
  quotaPlan: text("quota_plan"),
312
+ /**
313
+ * The last successful quota read for this account, as a JSON snapshot.
314
+ *
315
+ * Persisted rather than left only in the quota cache: that cache is a short
316
+ * in-process TTL and empty on a cold start, so right after a restart the
317
+ * console would show no balance for every account until the sweep re-read
318
+ * them. The row survives the restart, so a cold page open renders the last
319
+ * known numbers immediately (and the sweep refreshes them). Only a
320
+ * *successful* read is stored — a failed fetch leaves the previous snapshot
321
+ * in place, mirroring the plan column's behaviour.
322
+ */
323
+ quotaSnapshot: jsonb("quota_snapshot").$type<ProviderQuotaResultSnapshot | null>(),
298
324
 
299
325
  /**
300
326
  * Qoder native machine identity bound to this account, as one JSON object
@@ -342,7 +368,6 @@ export const providerAccounts = pgTable("provider_accounts", {
342
368
  ],
343
369
  );
344
370
 
345
-
346
371
  // OAuth refresh token + cross-process lease, normalized out of
347
372
  // `provider_accounts` into its own 1:0/1 table. The vast majority of
348
373
  // provider accounts are `credentialKind: "api_key"`, for which these four
@@ -381,7 +406,6 @@ export const providerOauthStates = pgTable("provider_oauth_states", {
381
406
  leaseExpiresAt: timestamp("lease_expires_at", { withTimezone: true }),
382
407
  });
383
408
 
384
-
385
409
  // One row per (provider_id, model_id, route), with `endpoint_path`
386
410
  // identifying the route — the same model through two providers, or through
387
411
  // two routes of one provider, is two rows. `enabled` is a hard routing
@@ -423,7 +447,7 @@ export const models = pgTable(
423
447
  * that predicts access — `credits` and `vendor` were both measured against
424
448
  * real dispatches and neither correlates. Only the refusal itself is a
425
449
  * signal, so the answer has to be recorded. See
426
- * `.skills/cartethyia-reverse-engineering/references/codebuddy-dispatch-headers.md`.
450
+ * `documentation/research/codebuddy/2026-10-19-codebuddy-chat-dispatch-headers.md`.
427
451
  */
428
452
  proOnly: boolean("pro_only"),
429
453
  /**
@@ -435,6 +459,12 @@ export const models = pgTable(
435
459
  * provider did not state it, which is not the same as billed.
436
460
  */
437
461
  freeTier: boolean("free_tier"),
462
+ /**
463
+ * Explicit wire dialect for this row (nullable). Absent = resolver
464
+ * fallback (heuristic + family default). See
465
+ * `src/protocol/translation/dialect/`.
466
+ */
467
+ dialect: text("dialect"),
438
468
  },
439
469
  (table) => [
440
470
  uniqueIndex("models_provider_model_route_uidx").on(
@@ -476,7 +506,6 @@ export const tenantDisabledModels = pgTable(
476
506
  ],
477
507
  );
478
508
 
479
-
480
509
  // Tenant-owned HTTP/HTTPS/SOCKS5 pools share the provider-account health state machine.
481
510
  export const networkPools = pgTable("network_pools", {
482
511
  id: uuid("id").primaryKey().defaultRandom(),
@@ -611,8 +640,6 @@ export const providerPoolAccounts = pgTable(
611
640
  index("provider_pool_accounts_provider_status_idx").on(table.providerId, table.status),
612
641
  ],
613
642
  );
614
- export type ProviderPoolAccount = typeof providerPoolAccounts.$inferSelect;
615
-
616
643
 
617
644
  // Account and network-pool health events share one table. The entity kind
618
645
  // selects exactly one owner FK, and the CHECK constraint below preserves
@@ -653,7 +680,6 @@ export const healthEvents = pgTable(
653
680
  ],
654
681
  );
655
682
 
656
-
657
683
  // Model aliasing & combos. Aliases resolve a client-facing name to a
658
684
  // real model; combos back a client-facing name with >=1 real models,
659
685
  // auto-selected via `fallback` or `round_robin`.
@@ -806,7 +832,6 @@ export const poolRoutingSettings = pgTable("pool_routing_settings", {
806
832
  rotateCount: integer("rotate_count").notNull().default(1),
807
833
  });
808
834
 
809
-
810
835
  export const API_KEY_MODES = ["personal", "share"] as const;
811
836
  export type ApiKeyMode = (typeof API_KEY_MODES)[number];
812
837
 
@@ -820,6 +845,10 @@ export type ApiKeyMode = (typeof API_KEY_MODES)[number];
820
845
  export const API_KEY_MODEL_ACCESS_MODES = ["whitelist", "blacklist"] as const;
821
846
  export type ApiKeyModelAccessMode = (typeof API_KEY_MODEL_ACCESS_MODES)[number];
822
847
 
848
+ /** Share-template concurrency scope — see `apiKeys.concurrencyScope`. */
849
+ export const API_KEY_CONCURRENCY_SCOPES = ["family", "per_key"] as const;
850
+ export type ApiKeyConcurrencyScope = (typeof API_KEY_CONCURRENCY_SCOPES)[number];
851
+
823
852
  /**
824
853
  * Inbound `/v1/*` keys never store plaintext secrets. Personal keys carry an
825
854
  * authentication hash; share templates carry policy and child keys point back
@@ -858,6 +887,24 @@ export const apiKeys = pgTable(
858
887
  .notNull()
859
888
  .default(0),
860
889
  maxConcurrentRequests: integer("max_concurrent_requests"),
890
+ /**
891
+ * How `maxConcurrentRequests` applies to a share family:
892
+ *
893
+ * - `family` (default) — one cap across the whole family: every recipient
894
+ * key shares the same admission counter and budget, so 20 means 20
895
+ * concurrent requests across all children of the template.
896
+ * - `per_key` — each recipient key gets its own independent concurrent
897
+ * window and cap. The cap is copied from the template to each child at
898
+ * issue time (children carry their own `maxConcurrentRequests`), and a
899
+ * child's admission identity is its own id, not the parent's.
900
+ *
901
+ * Only meaningful for `share` keys; personal keys always use their own
902
+ * per-key cap.
903
+ */
904
+ concurrencyScope: text("concurrency_scope")
905
+ .$type<ApiKeyConcurrencyScope>()
906
+ .notNull()
907
+ .default("family"),
861
908
  /**
862
909
  * Slot cap for a share template: the maximum number of concurrently
863
910
  * active child keys it may mint. `null` = unlimited (legacy behavior).
@@ -984,7 +1031,6 @@ export const sharePopups = pgTable(
984
1031
  ],
985
1032
  );
986
1033
 
987
-
988
1034
  // Public bearer links for enrolling one shared key per resolved client IP, and
989
1035
  // for handing a personal key to its owner. The hash is the lookup key; the
990
1036
  // token is additionally retained encrypted so the owner's console can show the
@@ -993,12 +1039,11 @@ export const sharePopups = pgTable(
993
1039
  * Share-link kinds, as a runtime tuple. Route schemas and DTOs project this
994
1040
  * list rather than restating it.
995
1041
  */
996
- export const SHARE_LINK_KINDS = ["enroll", "handoff"] as const;
1042
+ const SHARE_LINK_KINDS = ["enroll", "handoff"] as const;
997
1043
 
998
1044
  /** One share-link kind. */
999
1045
  export type ShareLinkKind = (typeof SHARE_LINK_KINDS)[number];
1000
1046
 
1001
-
1002
1047
  export const shareLinks = pgTable(
1003
1048
  "share_links",
1004
1049
  {
@@ -1040,7 +1085,6 @@ export const shareLinks = pgTable(
1040
1085
  ],
1041
1086
  );
1042
1087
 
1043
-
1044
1088
  /**
1045
1089
  * Console dashboard users — distinct from API-key tenants.
1046
1090
  */
@@ -1113,7 +1157,6 @@ export const consoleLockouts = pgTable(
1113
1157
  ],
1114
1158
  );
1115
1159
 
1116
-
1117
1160
  // Configuration-change audit has its own retention lifecycle; it is separate
1118
1161
  // from metadata telemetry and short-lived optional payload capture.
1119
1162
  export const adminAuditLog = pgTable(
@@ -1136,7 +1179,6 @@ export const adminAuditLog = pgTable(
1136
1179
  ],
1137
1180
  );
1138
1181
 
1139
-
1140
1182
  // Runtime preferences are stored in one validated JSONB bag. The filter
1141
1183
  // master toggle remains a typed column because it is read on the proxy path.
1142
1184
  export interface ConsoleSettingsPreferences {
@@ -1232,6 +1274,14 @@ export interface ConsoleSettingsPreferences {
1232
1274
  * the safer direction and the more common need.
1233
1275
  */
1234
1276
  imageClampMaxBytes?: number | null;
1277
+ /**
1278
+ * Ordered list of vision model ids (`provider/model`) used to describe
1279
+ * images when the selected model is not image-capable. The first healthy
1280
+ * model wins; if it fails (cooldown/quota/upstream error), the handoff
1281
+ * falls through to the next entry. Empty/absent = legacy `[image]`
1282
+ * placeholder behavior.
1283
+ */
1284
+ visionHandoffModels?: readonly string[];
1235
1285
  }
1236
1286
 
1237
1287
  export const consoleSettings = pgTable("console_settings", {
@@ -1242,21 +1292,33 @@ export const consoleSettings = pgTable("console_settings", {
1242
1292
 
1243
1293
  // Tenant-scoped system prompt injection (append/override). One row per
1244
1294
  // tenant; `global` NULL means never configured, distinct from an explicit
1245
- // disabled setting. Providers/models are JSON object maps keyed by
1246
- // providerId and `providerId::modelId` respectively — see
1247
- // `src/console/system-prompt/contracts.ts` for the value shapes and the
1248
- // resolution rules implemented by the dispatch-path transform.
1295
+ // disabled setting. Providers/models/combos/aliases are JSON object maps
1296
+ // keyed by providerId, `providerId::modelId`, combo name, and alias name
1297
+ // respectively — see `src/console/system-prompt/contracts.ts` for the value
1298
+ // shapes and the resolution rules implemented by the dispatch-path transform.
1249
1299
  export const tenantSystemPrompts = pgTable("tenant_system_prompts", {
1250
1300
  tenantId: tenantRefPrimaryKey(),
1251
- global: jsonb("global").$type<import("../console/system-prompt/contracts").PromptSetting | null>(),
1301
+ global: jsonb("global").$type<import("../console/system-prompt/contracts").ScopePromptRef | null>(),
1302
+ presets: jsonb("presets")
1303
+ .notNull()
1304
+ .default({})
1305
+ .$type<Record<string, import("../console/system-prompt/contracts").SystemPromptPreset>>(),
1252
1306
  providers: jsonb("providers")
1253
1307
  .notNull()
1254
1308
  .default({})
1255
- .$type<Record<string, import("../console/system-prompt/contracts").ProviderPromptEntry>>(),
1309
+ .$type<Record<string, import("../console/system-prompt/contracts").ScopePromptRef>>(),
1256
1310
  models: jsonb("models")
1257
1311
  .notNull()
1258
1312
  .default({})
1259
- .$type<Record<string, import("../console/system-prompt/contracts").PromptSetting>>(),
1313
+ .$type<Record<string, import("../console/system-prompt/contracts").ScopePromptRef>>(),
1314
+ combos: jsonb("combos")
1315
+ .notNull()
1316
+ .default({})
1317
+ .$type<Record<string, import("../console/system-prompt/contracts").ScopePromptRef>>(),
1318
+ aliases: jsonb("aliases")
1319
+ .notNull()
1320
+ .default({})
1321
+ .$type<Record<string, import("../console/system-prompt/contracts").ScopePromptRef>>(),
1260
1322
  updatedAt: updatedAtColumn(),
1261
1323
  });
1262
1324
 
@@ -1276,7 +1338,6 @@ export const inferhubConfigKeys = pgTable("inferhub_config_keys", {
1276
1338
  updatedAt: updatedAtColumn(),
1277
1339
  });
1278
1340
 
1279
-
1280
1341
  // CLI Tools (CLI tool configuration): per-tenant mapping table that lets a coding-agent
1281
1342
  // slot (e.g. Claude Code's "opus" slot) target a specific Cartethyia model. Rows
1282
1343
  // are opaque strings — validation happens at the API boundary against the
@@ -1306,7 +1367,6 @@ export const cliToolMappings = pgTable(
1306
1367
  ],
1307
1368
  );
1308
1369
 
1309
-
1310
1370
  // Per-(tenant, tool, api_key) settings: whether mappings are active and which
1311
1371
  // mode the tool is configured for. Primary key is the composite of all three.
1312
1372
  export const cliToolSettings = pgTable(
@@ -1324,7 +1384,6 @@ export const cliToolSettings = pgTable(
1324
1384
  (table) => [primaryKey({ columns: [table.tenantId, table.toolId, table.apiKeyId] })],
1325
1385
  );
1326
1386
 
1327
-
1328
1387
  // Metadata-only request telemetry. Retention is configured independently of
1329
1388
  // payload capture (`CARTETHYIA_TELEMETRY_RETENTION_DAYS`, default 30 days).
1330
1389
  // No prompt text, raw body, API key, encrypted-reasoning payload, or generic
@@ -1473,6 +1532,22 @@ export const telemetryEvents = pgTable(
1473
1532
  table.accountId,
1474
1533
  table.createdAt,
1475
1534
  ),
1535
+ // Provider usage matrix + `breakdownTelemetry("provider")`: equality on
1536
+ // `provider_id`, range+aggregate on `created_at`. Was served by the
1537
+ // tenant-range index, which scanned every event in the window for one
1538
+ // provider's card.
1539
+ index("telemetry_events_tenant_provider_created_idx").on(
1540
+ table.tenantId,
1541
+ table.providerId,
1542
+ table.createdAt,
1543
+ ),
1544
+ // `breakdownTelemetry("model")` (top-model lists): equality on
1545
+ // `requested_model`, range+aggregate on `created_at`.
1546
+ index("telemetry_events_tenant_model_created_idx").on(
1547
+ table.tenantId,
1548
+ table.requestedModel,
1549
+ table.createdAt,
1550
+ ),
1476
1551
  /**
1477
1552
  * Serves the public share page's per-key aggregate (`share-usage.ts`):
1478
1553
  * equality on `api_key_id`, range and aggregate on `created_at`. Without
@@ -1514,7 +1589,7 @@ export const telemetryReconciliationState = pgTable(
1514
1589
  );
1515
1590
 
1516
1591
  /** Durable aggregates retained after metadata telemetry expires. */
1517
- export const TELEMETRY_USAGE_IDENTITY_TYPES = ["account", "api_key"] as const;
1592
+ const TELEMETRY_USAGE_IDENTITY_TYPES = ["account", "api_key"] as const;
1518
1593
  export type TelemetryUsageIdentityType = (typeof TELEMETRY_USAGE_IDENTITY_TYPES)[number];
1519
1594
 
1520
1595
  export const telemetryUsageTotals = pgTable(
@@ -1553,7 +1628,6 @@ export const telemetryUsageTotals = pgTable(
1553
1628
  ],
1554
1629
  );
1555
1630
 
1556
-
1557
1631
  export const telemetryPayloads = pgTable(
1558
1632
  "telemetry_payloads",
1559
1633
  {
@@ -1596,8 +1670,6 @@ export const telemetryPayloads = pgTable(
1596
1670
  ],
1597
1671
  );
1598
1672
 
1599
-
1600
-
1601
1673
  // Daily check-in ledger: one row per (account, calendar day) once the sweep has
1602
1674
  // attempted that account's claim.
1603
1675
  //
@@ -1610,7 +1682,9 @@ export const dailyCheckinLedger = pgTable(
1610
1682
  "daily_checkin_ledger",
1611
1683
  {
1612
1684
  dayKey: text("day_key").notNull(),
1613
- accountId: uuid("account_id").notNull(),
1685
+ accountId: uuid("account_id")
1686
+ .notNull()
1687
+ .references(() => providerAccounts.id, { onDelete: "cascade" }),
1614
1688
  claimedAt: timestamp("claimed_at", { withTimezone: true }).notNull().defaultNow(),
1615
1689
  },
1616
1690
  (table) => [
@@ -1618,7 +1692,6 @@ export const dailyCheckinLedger = pgTable(
1618
1692
  ],
1619
1693
  );
1620
1694
 
1621
-
1622
1695
  /**
1623
1696
  * Per-day, per-model credit deductions the buddy billing meter reported.
1624
1697
  *
@@ -33,7 +33,7 @@ const INVALIDATION_CHANNEL = "cartethyia:cache:invalidate";
33
33
  * collide, and so a `FLUSHDB`-free deploy can drop one namespace without
34
34
  * touching another.
35
35
  */
36
- export type SharedCacheNamespace = "auth" | "preferences" | "credential" | "routing" | "public-models";
36
+ type SharedCacheNamespace = "auth" | "preferences" | "credential" | "routing" | "public-models";
37
37
 
38
38
  const NAMESPACE_PREFIX: Readonly<Record<SharedCacheNamespace, string>> = {
39
39
  auth: "cartethyia:cache:auth:",
@@ -50,7 +50,7 @@ const NAMESPACE_PREFIX: Readonly<Record<SharedCacheNamespace, string>> = {
50
50
  };
51
51
 
52
52
  /** One notice that peers must drop an entry. */
53
- export interface InvalidationNotice {
53
+ interface InvalidationNotice {
54
54
  readonly namespace: SharedCacheNamespace;
55
55
  /** Omitted means "all keys in the namespace". */
56
56
  readonly key?: string;
@@ -27,7 +27,7 @@ export type SortOrderDb =
27
27
  * `idColumn`/`sortIndexColumn`, and every caller passes its own schema-typed
28
28
  * table plus the two columns.
29
29
  */
30
- export interface SortOrderTable {
30
+ interface SortOrderTable {
31
31
  readonly table: PgTable;
32
32
  readonly idColumn: AnyColumn;
33
33
  readonly sortIndexColumn: AnyColumn;
@@ -5,7 +5,7 @@ import { nextSortIndex, reorderSortIndex, type SortOrderDb } from "../sort-order
5
5
  import { getDbHandle } from "../boot";
6
6
  import type { CartethyiaDatabase } from "../db-handle";
7
7
  import { lockRows } from "../dialect";
8
- import { apiKeys, shareLinks, sharePopups, telemetryUsageTotals, type ApiKeyMode, type ApiKeyModelAccessMode } from "../schema";
8
+ import { apiKeys, shareLinks, sharePopups, telemetryUsageTotals, type ApiKeyMode, type ApiKeyModelAccessMode, type ApiKeyConcurrencyScope } from "../schema";
9
9
  import type { AccessScope } from "../../security/access-control";
10
10
 
11
11
  /** Sortable columns for the paged share-child listing (api_keys columns only). */
@@ -78,6 +78,7 @@ export interface ApiKeyRecord {
78
78
  readonly monthlyTokenLimit?: number;
79
79
  readonly lifetimeTokenBudget?: number;
80
80
  readonly maxConcurrentRequests?: number;
81
+ readonly concurrencyScope?: ApiKeyConcurrencyScope;
81
82
  /** Share-template recipient slot cap; undefined = unlimited. */
82
83
  readonly maxChildren?: number;
83
84
  readonly modelPrefix?: string;
@@ -344,6 +345,9 @@ export class DrizzleApiKeyStore implements ApiKeyStore {
344
345
  ...(row.maxConcurrentRequests === null
345
346
  ? {}
346
347
  : { maxConcurrentRequests: row.maxConcurrentRequests }),
348
+ ...(row.concurrencyScope
349
+ ? { concurrencyScope: row.concurrencyScope as ApiKeyConcurrencyScope }
350
+ : {}),
347
351
  ...(row.maxChildren === null ? {} : { maxChildren: row.maxChildren }),
348
352
  ...(row.modelPrefix === null ? {} : { modelPrefix: row.modelPrefix }),
349
353
  modelAccessMode: row.modelAccessMode,
@@ -547,6 +551,7 @@ export class DrizzleApiKeyStore implements ApiKeyStore {
547
551
  monthlyTokenLimit: record.monthlyTokenLimit ?? null,
548
552
  lifetimeTokenBudget: record.lifetimeTokenBudget ?? null,
549
553
  maxConcurrentRequests: record.maxConcurrentRequests ?? null,
554
+ concurrencyScope: record.concurrencyScope ?? "family",
550
555
  maxChildren: record.maxChildren ?? null,
551
556
  modelPrefix: record.modelPrefix ?? null,
552
557
  modelAccessMode: record.modelAccessMode ?? "whitelist",
@@ -615,6 +620,9 @@ export class DrizzleApiKeyStore implements ApiKeyStore {
615
620
  ...(patch.maxConcurrentRequests !== undefined
616
621
  ? { maxConcurrentRequests: patch.maxConcurrentRequests }
617
622
  : {}),
623
+ ...(patch.concurrencyScope !== undefined
624
+ ? { concurrencyScope: patch.concurrencyScope }
625
+ : {}),
618
626
  ...(patch.maxChildren !== undefined ? { maxChildren: patch.maxChildren } : {}),
619
627
  ...(patch.modelPrefix !== undefined ? { modelPrefix: patch.modelPrefix } : {}),
620
628
  ...(patch.modelAccessMode !== undefined ? { modelAccessMode: patch.modelAccessMode } : {}),
@@ -802,6 +810,7 @@ export class DrizzleApiKeyStore implements ApiKeyStore {
802
810
  lifetimeTokenBudget: integer("lifetime_token_budget"),
803
811
  lifetimeTokensConsumed: integer("lifetime_tokens_consumed") ?? 0,
804
812
  maxConcurrentRequests: integer("max_concurrent_requests"),
813
+ concurrencyScope: (text("concurrency_scope") ?? "family") as ApiKeyConcurrencyScope,
805
814
  modelAccessMode: (text("model_access_mode") ?? "whitelist") as ApiKeyModelAccessMode,
806
815
  modelList: json("model_list"),
807
816
  clientRouterDenylist: json("client_router_denylist"),