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
@@ -18,6 +18,7 @@
18
18
  * - `isGatewayError()` semantics live in one shared SQL predicate.
19
19
  */
20
20
  import { and, desc, eq, gte, inArray, isNotNull, or, sql, type SQL } from "drizzle-orm";
21
+ import { PgDialect } from "drizzle-orm/pg-core";
21
22
  import type { CartethyiaDatabase } from "../persistence/db-handle";
22
23
  import { apiKeys, telemetryEvents, telemetryUsageTotals } from "../persistence/schema";
23
24
  import type { TelemetryEventRecord } from "./event-log";
@@ -33,6 +34,20 @@ import { gatewayErrorSql } from "./telemetry-status";
33
34
  */
34
35
  export const IS_GATEWAY_ERROR_SQL = gatewayErrorSql(telemetryEvents.status, telemetryEvents.httpStatus);
35
36
 
37
+ /**
38
+ * The aggregate select fragments shared by every tenant-window read. The
39
+ * `errors` count uses the single shared gateway-error predicate (see
40
+ * {@link IS_GATEWAY_ERROR_SQL}) so the row-level rule and the SQL aggregate
41
+ * cannot drift; the sum fragments coalesce to 0 so an empty window reads as
42
+ * zero rather than null.
43
+ */
44
+ const AGGREGATE_SELECT = {
45
+ errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
46
+ inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
47
+ outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
48
+ cachedInputTokens: sql<number>`coalesce(sum(${telemetryEvents.cachedInputTokens}), 0)`,
49
+ } as const;
50
+
36
51
  /** One bounded page of events, newest first. */
37
52
  export interface EventPage {
38
53
  readonly events: TelemetryEventRecord[];
@@ -40,7 +55,7 @@ export interface EventPage {
40
55
  readonly nextCursor?: string;
41
56
  }
42
57
 
43
- export interface EventListQuery {
58
+ interface EventListQuery {
44
59
  readonly tenantId: string;
45
60
  /**
46
61
  * Lower bound. Omitting it means "the whole retained window" — the SQL table
@@ -96,7 +111,7 @@ export interface UsageSummary {
96
111
  readonly unpriced: number;
97
112
  }
98
113
 
99
- export interface BreakdownGroup {
114
+ interface BreakdownGroup {
100
115
  readonly key: string;
101
116
  readonly requests: number;
102
117
  readonly errors: number;
@@ -116,15 +131,8 @@ export interface ChartBucket {
116
131
  readonly errors: number;
117
132
  readonly inputTokens: number;
118
133
  readonly outputTokens: number;
119
- }
120
-
121
- export interface HealthTotals {
122
- readonly requests: number;
123
- readonly errors: number;
124
- readonly inputTokens: number;
125
- readonly outputTokens: number;
134
+ /** Cached-input share of the prompt, summed for the bucket. */
126
135
  readonly cachedInputTokens: number;
127
- readonly latencyAvgMs: number | null;
128
136
  }
129
137
 
130
138
  const DEFAULT_LIMIT = 50;
@@ -141,7 +149,7 @@ function numericNullable(value: unknown): number | null {
141
149
  }
142
150
 
143
151
  /** Maps one `telemetry_events` row to the console's record shape. */
144
- export function eventRecordFromRow(row: {
152
+ function eventRecordFromRow(row: {
145
153
  readonly id: string | null;
146
154
  readonly createdAt: Date;
147
155
  readonly tenantId: string;
@@ -225,11 +233,28 @@ export function eventRecordFromRow(row: {
225
233
  * renders the SQL, so it is the only answer that cannot disagree with it.
226
234
  */
227
235
  function isPostgres(db: CartethyiaDatabase): boolean {
228
- const dialect = (db as unknown as { dialect?: { constructor?: { name?: string } } }).dialect;
229
- const name = dialect?.constructor?.name;
236
+ const dialect = (db as unknown as { dialect?: unknown }).dialect;
237
+ if (dialect instanceof PgDialect) return true;
238
+ const name = (dialect as { constructor?: { name?: string } } | undefined)?.constructor?.name;
230
239
  return name === "PostgresDialect" || name === "PgDialect";
231
240
  }
232
241
 
242
+ /**
243
+ * The epoch-bucket SQL expression for one time column.
244
+ *
245
+ * Inlined (not parameterised) so Postgres sees the SELECT and GROUP BY
246
+ * expressions as identical: parameter numbers differing between the two
247
+ * clauses made Postgres treat them as unrelated expressions referencing
248
+ * `created_at`, which 42803-rejected the query. The width is a raw SQL
249
+ * literal for the same reason.
250
+ */
251
+ function bucketExpression(db: CartethyiaDatabase, column: typeof telemetryEvents.createdAt, widthSeconds: number): SQL {
252
+ const w = sql.raw(String(Math.max(1, Math.trunc(widthSeconds))));
253
+ return isPostgres(db)
254
+ ? sql<number>`(cast(extract(epoch from ${column}) as bigint) / ${w}) * ${w}`
255
+ : sql<number>`(cast(strftime('%s', ${column}) as integer) / ${w}) * ${w}`;
256
+ }
257
+
233
258
  /**
234
259
  * The tenant predicate — the scope every read shares — plus the window when
235
260
  * one is given.
@@ -400,90 +425,9 @@ export async function queryTelemetryEvents(
400
425
  };
401
426
  }
402
427
 
403
- /** One event by request id — a single indexed row, never a window scan. */
404
- export async function eventByRequestId(
405
- db: CartethyiaDatabase,
406
- tenantId: string,
407
- requestId: string,
408
- ): Promise<TelemetryEventRecord | undefined> {
409
- const [row] = await db
410
- .select()
411
- .from(telemetryEvents)
412
- .where(and(eq(telemetryEvents.tenantId, tenantId), eq(telemetryEvents.requestId, requestId)))
413
- .limit(1);
414
- if (!row) return undefined;
415
- return eventRecordFromRow(row as Parameters<typeof eventRecordFromRow>[0]);
416
- }
417
-
418
428
  /**
419
- * Totals plus latency percentiles for one tenant window.
420
- *
421
- * Percentiles are computed by the database. Postgres uses `percentile_cont`;
422
- * SQLite (no ordered-set aggregates) computes nearest-rank percentiles from
423
- * the ordered latency column via OFFSET/LIMIT. Either way, latency values are
424
- * never returned to JavaScript — the array that the old raw reader built to
425
- * sort in JS was the memory cost this replaces.
429
+ * The SQL column one breakdown dimension groups by.
426
430
  */
427
- export async function summarizeTelemetry(
428
- db: CartethyiaDatabase,
429
- tenantId: string,
430
- since: Date,
431
- ): Promise<UsageSummary> {
432
- const condition = scoped(tenantId, since);
433
- const [row] = await db
434
- .select({
435
- requests: sql<number>`count(*)`,
436
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
437
- cancelled: sql<number>`sum(case when ${telemetryEvents.status} = 'cancelled' then 1 else 0 end)`,
438
- truncated: sql<number>`sum(case when ${telemetryEvents.status} = 'truncated' then 1 else 0 end)`,
439
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
440
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
441
- cachedInputTokens: sql<number>`coalesce(sum(${telemetryEvents.cachedInputTokens}), 0)`,
442
- reasoningTokens: sql<number>`coalesce(sum(${telemetryEvents.reasoningTokens}), 0)`,
443
- estimatedCostUsd: sql<number>`coalesce(sum(${telemetryEvents.estimatedCostUsd}), 0)`,
444
- sampled: sql<number>`count(${telemetryEvents.latencyMs})`,
445
- latencyAvg: sql<number>`avg(${telemetryEvents.latencyMs})`,
446
- unpriced: sql<number>`sum(case when ${telemetryEvents.estimatedCostUsd} is null then 1 else 0 end)`,
447
- })
448
- .from(telemetryEvents)
449
- .where(condition);
450
- if (!row) {
451
- return {
452
- requests: 0,
453
- errors: 0,
454
- cancelled: 0,
455
- truncated: 0,
456
- inputTokens: 0,
457
- outputTokens: 0,
458
- cachedInputTokens: 0,
459
- reasoningTokens: 0,
460
- estimatedCostUsd: 0,
461
- sampled: 0,
462
- latencyMs: { avg: null, p50: null, p95: null, p99: null },
463
- unpriced: 0,
464
- };
465
- }
466
-
467
- const sampled = numeric(row.sampled);
468
- const percentiles = await latencyPercentiles(db, tenantId, since, sampled);
469
- return {
470
- requests: numeric(row.requests),
471
- errors: numeric(row.errors),
472
- cancelled: numeric(row.cancelled),
473
- truncated: numeric(row.truncated),
474
- inputTokens: numeric(row.inputTokens),
475
- outputTokens: numeric(row.outputTokens),
476
- cachedInputTokens: numeric(row.cachedInputTokens),
477
- reasoningTokens: numeric(row.reasoningTokens),
478
- estimatedCostUsd: numeric(row.estimatedCostUsd),
479
- sampled,
480
- latencyMs: {
481
- avg: numericNullable(row.latencyAvg),
482
- ...percentiles,
483
- },
484
- unpriced: numeric(row.unpriced),
485
- };
486
- }
487
431
 
488
432
  type Percentiles = { p50: number | null; p95: number | null; p99: number | null };
489
433
 
@@ -546,9 +490,6 @@ async function latencyPercentiles(
546
490
  };
547
491
  }
548
492
 
549
- /**
550
- * The SQL column one breakdown dimension groups by.
551
- */
552
493
  function dimensionColumn(dimension: string) {
553
494
  if (dimension === "model") return telemetryEvents.requestedModel;
554
495
  if (dimension === "provider") return telemetryEvents.providerId;
@@ -587,9 +528,7 @@ export async function breakdownTelemetry(
587
528
  .select({
588
529
  key: column,
589
530
  requests: sql<number>`count(*)`,
590
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
591
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
592
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
531
+ ...AGGREGATE_SELECT,
593
532
  cachedInputTokens: sql<number>`coalesce(sum(${telemetryEvents.cachedInputTokens}), 0)`,
594
533
  costUsd: sql<number>`coalesce(sum(${telemetryEvents.estimatedCostUsd}), 0)`,
595
534
  avgTokensPerSec: sql<number>`coalesce(avg(${telemetryEvents.tokensPerSec}), 0)`,
@@ -626,32 +565,23 @@ export async function chartTelemetry(
626
565
  since: Date,
627
566
  bucketSeconds: number,
628
567
  ): Promise<ChartBucket[]> {
629
- const width = Math.max(1, Math.trunc(bucketSeconds));
630
- // Inlined (not parameterised) so Postgres sees the SELECT and GROUP BY
631
- // expressions as identical: parameter numbers differing between the two
632
- // clauses made Postgres treat them as unrelated expressions referencing
633
- // `created_at`, which 42803-rejected the query.
634
- const w = sql.raw(String(width));
635
- const bucketExpression = isPostgres(db)
636
- ? sql<number>`(cast(extract(epoch from ${telemetryEvents.createdAt}) as bigint) / ${w}) * ${w}`
637
- : sql<number>`(cast(strftime('%s', ${telemetryEvents.createdAt}) as integer) / ${w}) * ${w}`;
568
+ const bucketExpr = bucketExpression(db, telemetryEvents.createdAt, bucketSeconds);
638
569
  const rows = await db
639
570
  .select({
640
- at: bucketExpression,
571
+ at: bucketExpr,
641
572
  requests: sql<number>`count(*)`,
642
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
643
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
644
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
573
+ ...AGGREGATE_SELECT,
645
574
  })
646
575
  .from(telemetryEvents)
647
576
  .where(scoped(tenantId, since))
648
- .groupBy(bucketExpression);
577
+ .groupBy(bucketExpr);
649
578
  return rows.map((row) => ({
650
579
  at: numeric(row.at) * 1000,
651
580
  requests: numeric(row.requests),
652
581
  errors: numeric(row.errors),
653
582
  inputTokens: numeric(row.inputTokens),
654
583
  outputTokens: numeric(row.outputTokens),
584
+ cachedInputTokens: numeric(row.cachedInputTokens),
655
585
  }));
656
586
  }
657
587
 
@@ -681,20 +611,15 @@ export async function providerUsageMatrix(
681
611
  providerId: string,
682
612
  since: Date,
683
613
  ): Promise<ProviderUsageDayRow[]> {
684
- // Same inlining rule as chartTelemetry: SELECT and GROUP BY must spell the
685
- // identical expression or Postgres 42803-rejects the grouped reference.
686
- const w = sql.raw(String(86400));
687
- const dayExpression = isPostgres(db)
688
- ? sql<number>`(cast(extract(epoch from ${telemetryEvents.createdAt}) as bigint) / ${w}) * ${w}`
689
- : sql<number>`(cast(strftime('%s', ${telemetryEvents.createdAt}) as integer) / ${w}) * ${w}`;
614
+ const dayExpression = bucketExpression(db, telemetryEvents.createdAt, 86400);
690
615
  const rows = await db
691
616
  .select({
692
617
  day: dayExpression,
693
618
  model: telemetryEvents.requestedModel,
694
619
  requests: sql<number>`count(*)`,
695
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
620
+ inputTokens: AGGREGATE_SELECT.inputTokens,
696
621
  cachedInputTokens: sql<number>`coalesce(sum(${telemetryEvents.cachedInputTokens}), 0)`,
697
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
622
+ outputTokens: AGGREGATE_SELECT.outputTokens,
698
623
  costUsd: sql<number>`coalesce(sum(${telemetryEvents.estimatedCostUsd}), 0)`,
699
624
  })
700
625
  .from(telemetryEvents)
@@ -712,43 +637,6 @@ export async function providerUsageMatrix(
712
637
  }));
713
638
  }
714
639
 
715
- /** Overview/health totals for one tenant window. */
716
- export async function healthTelemetry(
717
- db: CartethyiaDatabase,
718
- tenantId: string,
719
- since: Date,
720
- ): Promise<HealthTotals> {
721
- const [row] = await db
722
- .select({
723
- requests: sql<number>`count(*)`,
724
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
725
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
726
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
727
- cachedInputTokens: sql<number>`coalesce(sum(${telemetryEvents.cachedInputTokens}), 0)`,
728
- latencyAvg: sql<number>`avg(${telemetryEvents.latencyMs})`,
729
- })
730
- .from(telemetryEvents)
731
- .where(scoped(tenantId, since));
732
- if (!row) {
733
- return {
734
- requests: 0,
735
- errors: 0,
736
- inputTokens: 0,
737
- outputTokens: 0,
738
- cachedInputTokens: 0,
739
- latencyAvgMs: null,
740
- };
741
- }
742
- return {
743
- requests: numeric(row.requests),
744
- errors: numeric(row.errors),
745
- inputTokens: numeric(row.inputTokens),
746
- outputTokens: numeric(row.outputTokens),
747
- cachedInputTokens: numeric(row.cachedInputTokens),
748
- latencyAvgMs: numericNullable(row.latencyAvg),
749
- };
750
- }
751
-
752
640
  /**
753
641
  * Summed input+output tokens for a set of API keys over one window — the
754
642
  * family bucket spend query.
@@ -783,9 +671,6 @@ export async function sumTelemetryTokens(
783
671
  return numeric(row?.total ?? 0);
784
672
  }
785
673
 
786
- /** One hour, in milliseconds — the share page's hourly bucket width. */
787
- const HOUR_MS = 3_600_000;
788
-
789
674
  /**
790
675
  * All-time family counts from the durable rollup, not from a scan of the
791
676
  * retained telemetry window.
@@ -798,7 +683,7 @@ const HOUR_MS = 3_600_000;
798
683
  * event on every tick. The rollup is the same definition as the read-side
799
684
  * counts, so the two cannot drift.
800
685
  */
801
- export interface FamilyKpiTotals {
686
+ interface FamilyKpiTotals {
802
687
  readonly requests: number;
803
688
  readonly errors: number;
804
689
  readonly tokens: number;
@@ -830,43 +715,6 @@ export async function familyKpiTotals(
830
715
  };
831
716
  }
832
717
 
833
- /**
834
- * All-time family counts: the numbers a share page's KPI card shows.
835
- *
836
- * These must be computed in SQL, not derived from the bounded page read — the
837
- * page caps at {@link MAX_LIMIT}, so a busy family would freeze at 500
838
- * requests/errors/last-hour regardless of real traffic.
839
- */
840
- export interface FamilyUsageTotals {
841
- readonly requests: number;
842
- readonly errors: number;
843
- readonly lastHourRequests: number;
844
- }
845
-
846
- /** Counts one share family's requests, errors, and last-hour traffic in SQL. */
847
- export async function familyUsageTotals(
848
- db: CartethyiaDatabase,
849
- tenantId: string,
850
- familyKeyId: string,
851
- now: Date,
852
- ): Promise<FamilyUsageTotals> {
853
- const lastHourStart = new Date(now.getTime() - HOUR_MS);
854
- const conditions = [eq(telemetryEvents.tenantId, tenantId), familyKeyCondition(familyKeyId)];
855
- const [row] = await db
856
- .select({
857
- requests: sql<number>`count(*)`,
858
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
859
- lastHourRequests: sql<number>`sum(case when ${telemetryEvents.createdAt} >= ${lastHourStart} then 1 else 0 end)`,
860
- })
861
- .from(telemetryEvents)
862
- .where(and(...conditions));
863
- return {
864
- requests: numeric(row?.requests ?? 0),
865
- errors: numeric(row?.errors ?? 0),
866
- lastHourRequests: numeric(row?.lastHourRequests ?? 0),
867
- };
868
- }
869
-
870
718
  /** Counts one share family's requests in a bounded window — a range scan, not a full-window aggregate. */
871
719
  export async function familyWindowRequests(
872
720
  db: CartethyiaDatabase,
@@ -945,83 +793,36 @@ export async function familyHourlyTelemetry(
945
793
  since: Date,
946
794
  bucketSeconds: number,
947
795
  ): Promise<ChartBucket[]> {
948
- const width = Math.max(1, Math.trunc(bucketSeconds));
949
- // Inlined (not parameterised) so Postgres sees the SELECT and GROUP BY
950
- // expressions as identical — see chartTelemetry for the failure this avoids.
951
- const w = sql.raw(String(width));
952
- const bucketExpression = isPostgres(db)
953
- ? sql<number>`(cast(extract(epoch from ${telemetryEvents.createdAt}) as bigint) / ${w}) * ${w}`
954
- : sql<number>`(cast(strftime('%s', ${telemetryEvents.createdAt}) as integer) / ${w}) * ${w}`;
796
+ const bucketExpr = bucketExpression(db, telemetryEvents.createdAt, bucketSeconds);
955
797
  const conditions = [scoped(tenantId, since), familyKeyCondition(familyKeyId)];
956
798
  const rows = await db
957
799
  .select({
958
- at: bucketExpression,
800
+ at: bucketExpr,
959
801
  requests: sql<number>`count(*)`,
960
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
961
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
962
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
802
+ ...AGGREGATE_SELECT,
963
803
  })
964
804
  .from(telemetryEvents)
965
805
  .where(and(...conditions))
966
- .groupBy(bucketExpression);
806
+ .groupBy(bucketExpr);
967
807
  return rows.map((row) => ({
968
808
  at: numeric(row.at) * 1000,
969
809
  requests: numeric(row.requests),
970
810
  errors: numeric(row.errors),
971
811
  inputTokens: numeric(row.inputTokens),
972
812
  outputTokens: numeric(row.outputTokens),
813
+ cachedInputTokens: numeric(row.cachedInputTokens),
973
814
  }));
974
815
  }
975
816
 
976
- /**
977
- * The health card's latency and throughput figures for one window.
978
- *
979
- * Same principle as {@link summarizeTelemetry}: `avg(tokens_per_sec)` and the
980
- * latency percentiles are computed by the database. The console's health card
981
- * used to pull every retained event into an array to average `tokensPerSec`
982
- * and sort latencies in JavaScript.
983
- */
984
- export interface HealthPerformance {
985
- readonly latencyAvgMs: number | null;
986
- readonly latencyP50Ms: number | null;
987
- readonly latencyP95Ms: number | null;
988
- readonly latencyP99Ms: number | null;
989
- readonly avgTokensPerSec: number;
990
- }
991
-
992
- export async function summarizeHealthPerformance(
993
- db: CartethyiaDatabase,
994
- tenantId: string,
995
- since: Date,
996
- ): Promise<HealthPerformance> {
997
- const [row] = await db
998
- .select({
999
- latencyAvg: sql<number>`avg(${telemetryEvents.latencyMs})`,
1000
- sampled: sql<number>`count(${telemetryEvents.latencyMs})`,
1001
- avgTokensPerSec: sql<number>`coalesce(avg(${telemetryEvents.tokensPerSec}), 0)`,
1002
- })
1003
- .from(telemetryEvents)
1004
- .where(scoped(tenantId, since));
1005
- const sampled = numeric(row?.sampled ?? 0);
1006
- const percentiles = await latencyPercentiles(db, tenantId, since, sampled);
1007
- return {
1008
- latencyAvgMs: numericNullable(row?.latencyAvg ?? null),
1009
- latencyP50Ms: percentiles.p50,
1010
- latencyP95Ms: percentiles.p95,
1011
- latencyP99Ms: percentiles.p99,
1012
- avgTokensPerSec: numeric(row?.avgTokensPerSec ?? 0),
1013
- };
1014
- }
1015
-
1016
817
  /**
1017
818
  * The Usage summary's performance block, computed in SQL.
1018
819
  *
1019
820
  * Replaces `summarizeUsagePerformance` (which sorted a latency array in
1020
821
  * JavaScript): `avg(resolve_ms)` and `avg(tokens_per_sec)` are SQL averages,
1021
822
  * and the latency percentiles come from the same database-side percentile
1022
- * path {@link summarizeTelemetry} uses.
823
+ * path {@link summarizeUsageWithPerformance} uses.
1023
824
  */
1024
- export interface UsagePerformanceTotals {
825
+ interface UsagePerformanceTotals {
1025
826
  readonly avgResolveMs: number;
1026
827
  readonly avgDurationMs: number;
1027
828
  /**
@@ -1038,42 +839,9 @@ export interface UsagePerformanceTotals {
1038
839
  readonly avgTokensPerSec: number;
1039
840
  }
1040
841
 
1041
- export async function summarizeUsagePerformanceSql(
1042
- db: CartethyiaDatabase,
1043
- tenantId: string,
1044
- since: Date,
1045
- ): Promise<UsagePerformanceTotals> {
1046
- const [row] = await db
1047
- .select({
1048
- sampled: sql<number>`count(${telemetryEvents.latencyMs})`,
1049
- latencyAvg: sql<number>`avg(${telemetryEvents.latencyMs})`,
1050
- resolveSum: sql<number>`coalesce(sum(${telemetryEvents.resolveMs}), 0)`,
1051
- resolveCount: sql<number>`count(${telemetryEvents.resolveMs})`,
1052
- avgTokensPerSec: sql<number>`coalesce(avg(${telemetryEvents.tokensPerSec}), 0)`,
1053
- })
1054
- .from(telemetryEvents)
1055
- .where(scoped(tenantId, since));
1056
- const sampled = numeric(row?.sampled ?? 0);
1057
- const resolveCount = numeric(row?.resolveCount ?? 0);
1058
- const percentiles = await latencyPercentiles(db, tenantId, since, sampled);
1059
- return {
1060
- avgResolveMs: resolveCount > 0 ? numeric(row?.resolveSum ?? 0) / resolveCount : 0,
1061
- avgDurationMs: numericNullable(row?.latencyAvg ?? null) ?? 0,
1062
- latencyP50Ms: percentiles.p50 ?? 0,
1063
- latencyP95Ms: percentiles.p95 ?? 0,
1064
- latencyP99Ms: percentiles.p99 ?? 0,
1065
- latencySampleCount: sampled,
1066
- resolveSampleCount: resolveCount,
1067
- avgTokensPerSec: numeric(row?.avgTokensPerSec ?? 0),
1068
- };
1069
- }
1070
-
1071
842
  /**
1072
843
  * Combined usage totals + performance in ONE window scan.
1073
844
  *
1074
- * `summarizeTelemetry` and `summarizeUsagePerformanceSql` both scan the same
1075
- * tenant window and each additionally run the percentile path, so the Usage
1076
- * summary endpoint paid two scans plus two percentile passes for one response.
1077
845
  * This runs the combined SELECT once and one percentile pass, returning both
1078
846
  * shapes so the caller needs no second query.
1079
847
  */
@@ -1086,11 +854,11 @@ export async function summarizeUsageWithPerformance(
1086
854
  const [row] = await db
1087
855
  .select({
1088
856
  requests: sql<number>`count(*)`,
1089
- errors: sql<number>`sum(case when ${IS_GATEWAY_ERROR_SQL} then 1 else 0 end)`,
857
+ errors: AGGREGATE_SELECT.errors,
1090
858
  cancelled: sql<number>`sum(case when ${telemetryEvents.status} = 'cancelled' then 1 else 0 end)`,
1091
859
  truncated: sql<number>`sum(case when ${telemetryEvents.status} = 'truncated' then 1 else 0 end)`,
1092
- inputTokens: sql<number>`coalesce(sum(${telemetryEvents.inputTokens}), 0)`,
1093
- outputTokens: sql<number>`coalesce(sum(${telemetryEvents.outputTokens}), 0)`,
860
+ inputTokens: AGGREGATE_SELECT.inputTokens,
861
+ outputTokens: AGGREGATE_SELECT.outputTokens,
1094
862
  cachedInputTokens: sql<number>`coalesce(sum(${telemetryEvents.cachedInputTokens}), 0)`,
1095
863
  reasoningTokens: sql<number>`coalesce(sum(${telemetryEvents.reasoningTokens}), 0)`,
1096
864
  estimatedCostUsd: sql<number>`coalesce(sum(${telemetryEvents.estimatedCostUsd}), 0)`,
@@ -36,7 +36,7 @@ export const LOG_RING_MAX_CODE_UNITS = 8_192;
36
36
 
37
37
  /** Marker appended wherever content was dropped. */
38
38
  export const LOG_TRUNCATED_MARKER = "[truncated]";
39
- export const LOG_CIRCULAR_MARKER = "[circular]";
39
+ const LOG_CIRCULAR_MARKER = "[circular]";
40
40
 
41
41
  function isHighSurrogate(code: number): boolean {
42
42
  return code >= 0xd800 && code <= 0xdbff;
@@ -5,18 +5,18 @@
5
5
  * `render()` emits the Prometheus exposition format on demand.
6
6
  */
7
7
 
8
- export type MetricLabels = Readonly<Record<string, string | number>>;
8
+ type MetricLabels = Readonly<Record<string, string | number>>;
9
9
 
10
- export interface CounterMetric {
10
+ interface CounterMetric {
11
11
  inc(value?: number, labels?: MetricLabels): void;
12
12
  }
13
13
 
14
- export interface GaugeMetric extends CounterMetric {
14
+ interface GaugeMetric extends CounterMetric {
15
15
  set(value: number, labels?: MetricLabels): void;
16
16
  dec(value?: number, labels?: MetricLabels): void;
17
17
  }
18
18
 
19
- export interface HistogramMetric {
19
+ interface HistogramMetric {
20
20
  observe(value: number, labels?: MetricLabels): void;
21
21
  }
22
22
 
@@ -8,7 +8,7 @@ import type {
8
8
  TelemetryPayloadDepth,
9
9
  TelemetryPayloadMode,
10
10
  } from "../console/settings/contracts";
11
- export type CaptureScope = "tenant" | "debug_session" | "operator_flag";
11
+ type CaptureScope = "tenant" | "debug_session" | "operator_flag";
12
12
 
13
13
  /**
14
14
  * How long a captured payload frame lives when the deployment has not chosen.
@@ -203,13 +203,13 @@ export interface PayloadCaptureInput {
203
203
  operatorFlagOptIn?: boolean;
204
204
  }
205
205
 
206
- export interface PayloadSignals {
206
+ interface PayloadSignals {
207
207
  readonly toolCalls: number;
208
208
  readonly images: number;
209
209
  readonly attachments: number;
210
210
  }
211
211
 
212
- export interface StoredPayload {
212
+ interface StoredPayload {
213
213
  id: string;
214
214
  /**
215
215
  * JSON text of the five body surfaces, in drawer order, built while the
@@ -412,8 +412,9 @@ export function buildPayloadRecord(
412
412
 
413
413
  /**
414
414
  * Postgres-backed redacted request/response payload capture. Payloads live for
415
- * the tenant's chosen retention — 15 minutes by default — and are pruned by the
416
- * sweep.
415
+ * the tenant's chosen retention — an hour by default (see
416
+ * {@link payloadRetentionMs} / `DEFAULT_PAYLOAD_RETENTION_MS`) — and are pruned
417
+ * by the sweep.
417
418
 
418
419
  */
419
420
  export class TelemetryPayloadCapture {
@@ -22,7 +22,7 @@ interface PayloadFrame {
22
22
  readonly payload: unknown;
23
23
  }
24
24
 
25
- export function isPayloadFileReference(value: unknown): value is PayloadFileReference {
25
+ function isPayloadFileReference(value: unknown): value is PayloadFileReference {
26
26
  if (typeof value !== "object" || value === null) return false;
27
27
  const record = value as Record<string, unknown>;
28
28
  return (
@@ -32,7 +32,7 @@ export interface RuntimeMemorySnapshot {
32
32
  }
33
33
 
34
34
  /** Live collection sizes sampled alongside process memory. */
35
- export interface RuntimeMetricSources {
35
+ interface RuntimeMetricSources {
36
36
  readonly routingRoundRobinEntries: () => { readonly combo: number; readonly provider: number };
37
37
  /**
38
38
  * Tracked keys in the in-memory IP abuse store, or 0 when the store is
@@ -158,7 +158,7 @@ function telemetryEventRow(event: TelemetryEventInput) {
158
158
  };
159
159
  }
160
160
 
161
- export interface TelemetryBatchBufferOptions {
161
+ interface TelemetryBatchBufferOptions {
162
162
  readonly flushIntervalMs?: number;
163
163
  readonly maxBatch?: number;
164
164
  readonly maxItems?: number;
@@ -184,8 +184,17 @@ function drainRetryDelayMs(attempt: number, baseDelayMs = DRAIN_RETRY_BASE_MS):
184
184
  return exponentialBackoff(attempt, options);
185
185
  }
186
186
 
187
- /** Floor for the adaptive active interval so a full queue still drains promptly. */
188
- const ADAPTIVE_FLUSH_MIN_MS = 50;
187
+ /**
188
+ * Floor for the adaptive active interval so a full queue still drains promptly.
189
+ *
190
+ * Raised to 200ms (from 50ms) so a flush does not collide with console reads:
191
+ * under load the queue saturates `maxBatch`, the interval fell to 50ms, and a
192
+ * drain landed in the middle of the console's own telemetry reads — the GROUP BY
193
+ * behind the Usage/ConsoleLog pages — making the page's queries wait on the
194
+ * drain's insert lock. 200ms still drains a 500-row batch ~5x/sec, which is a
195
+ * steady 2500 rows/sec ceiling; the adaptive curve otherwise keeps its shape.
196
+ */
197
+ const ADAPTIVE_FLUSH_MIN_MS = 200;
189
198
  /** Multiplier applied to the base interval while the queue is empty. */
190
199
  const ADAPTIVE_IDLE_MULTIPLIER = 4;
191
200
 
@@ -66,13 +66,13 @@ const MAX_FILES_PER_RUN = 64;
66
66
  */
67
67
  const HOURS_TO_SKIP = 2;
68
68
 
69
- export interface ReconcileOptions {
69
+ interface ReconcileOptions {
70
70
  /** Report only: count the gap without writing anything. */
71
71
  readonly verify?: boolean;
72
72
  readonly now?: Date;
73
73
  }
74
74
 
75
- export interface ReconcileReport {
75
+ interface ReconcileReport {
76
76
  readonly ran: boolean;
77
77
  /** Why the run did nothing, when it did nothing. */
78
78
  readonly skippedReason?: "lease_held" | "no_files" | "uptodate";
@@ -393,7 +393,7 @@ async function insertChunk(
393
393
  .set({
394
394
  fileName,
395
395
  byteOffset,
396
- filesCompleted: sql`${telemetryReconciliationState.filesCompleted} + 0`,
396
+ filesCompleted: sql`${telemetryReconciliationState.filesCompleted} + 1`,
397
397
  eventsExamined: sql`${telemetryReconciliationState.eventsExamined} + ${events.length}`,
398
398
  eventsInserted: sql`${telemetryReconciliationState.eventsInserted} + ${rows.length}`,
399
399
  conflicts: sql`${telemetryReconciliationState.conflicts} + ${events.length - rows.length}`,
@@ -31,7 +31,7 @@
31
31
  * but those spans measure local response processing, not decode. Only a
32
32
  * client-visible stream window counts as decode time.
33
33
  */
34
- export interface TokenSpeedInput {
34
+ interface TokenSpeedInput {
35
35
  /** Completion/output tokens reported for the request. */
36
36
  readonly outputTokens?: number | undefined;
37
37
  /** End-to-end gateway latency in milliseconds. */