cartethyia 2.6.7 → 2.7.1

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 (335) hide show
  1. package/.env.example +1 -7
  2. package/README.md +25 -2
  3. package/dist/dashboard/assets/{BannedPage-Dskhyp0l.js → BannedPage-D-J75hBM.js} +1 -1
  4. package/dist/dashboard/assets/BannedPage-D-J75hBM.js.gz +0 -0
  5. package/dist/dashboard/assets/{CliToolDetailPage--SJhk7qQ.js → CliToolDetailPage-CVe6RaBH.js} +1 -1
  6. package/dist/dashboard/assets/CliToolDetailPage-CVe6RaBH.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolsPage-C203VT-c.js → CliToolsPage-Dd8ZSamp.js} +1 -1
  8. package/dist/dashboard/assets/CliToolsPage-Dd8ZSamp.js.gz +0 -0
  9. package/dist/dashboard/assets/{CombosPage-BcS7kGG1.js → CombosPage-QoJ6foxo.js} +1 -1
  10. package/dist/dashboard/assets/CombosPage-QoJ6foxo.js.gz +0 -0
  11. package/dist/dashboard/assets/ConsoleLogPage-DpNRay4C.js +1 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-DpNRay4C.js.gz +0 -0
  13. package/dist/dashboard/assets/{CustomizationPage-uujbBYwC.js → CustomizationPage-CKUFTcW4.js} +1 -1
  14. package/dist/dashboard/assets/CustomizationPage-CKUFTcW4.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-CzSLiDzr.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-CzSLiDzr.js.gz +0 -0
  17. package/dist/dashboard/assets/LoginPage-DubdQcvX.js +1 -0
  18. package/dist/dashboard/assets/LoginPage-DubdQcvX.js.gz +0 -0
  19. package/dist/dashboard/assets/{ModelPicker-CA1kLs45.js → ModelPicker-BH8Tehdi.js} +1 -1
  20. package/dist/dashboard/assets/ModelPicker-BH8Tehdi.js.gz +0 -0
  21. package/dist/dashboard/assets/OverviewPage-DuWzAQFL.js +1 -0
  22. package/dist/dashboard/assets/OverviewPage-DuWzAQFL.js.gz +0 -0
  23. package/dist/dashboard/assets/ProviderDetailPage-BKEKe2Fm.js +4 -0
  24. package/dist/dashboard/assets/ProviderDetailPage-BKEKe2Fm.js.gz +0 -0
  25. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js +1 -0
  26. package/dist/dashboard/assets/ProviderIcon-FB6yS4v1.js.gz +0 -0
  27. package/dist/dashboard/assets/ProvidersPage-Bwotu8UJ.js +1 -0
  28. package/dist/dashboard/assets/ProvidersPage-Bwotu8UJ.js.gz +0 -0
  29. package/dist/dashboard/assets/ProxyPage-D7hpWbg9.js +9 -0
  30. package/dist/dashboard/assets/ProxyPage-D7hpWbg9.js.gz +0 -0
  31. package/dist/dashboard/assets/{QuotaPage-BueSWX5D.js → QuotaPage-ATpaxrbl.js} +1 -1
  32. package/dist/dashboard/assets/QuotaPage-ATpaxrbl.js.gz +0 -0
  33. package/dist/dashboard/assets/SettingsPage-CETophpx.js +1 -0
  34. package/dist/dashboard/assets/SettingsPage-CETophpx.js.gz +0 -0
  35. package/dist/dashboard/assets/SetupPage-BdgECjqq.js +1 -0
  36. package/dist/dashboard/assets/SetupPage-BdgECjqq.js.gz +0 -0
  37. package/dist/dashboard/assets/{SortableList-DrKeMcGN.js → SortableList-CAK-EN9z.js} +1 -1
  38. package/dist/dashboard/assets/SortableList-CAK-EN9z.js.gz +0 -0
  39. package/dist/dashboard/assets/{StudioPage-qjuYtccc.js → StudioPage-B7W2_RhT.js} +3 -3
  40. package/dist/dashboard/assets/StudioPage-B7W2_RhT.js.gz +0 -0
  41. package/dist/dashboard/assets/UsagePage-6T4EFDjW.js +56 -0
  42. package/dist/dashboard/assets/UsagePage-6T4EFDjW.js.gz +0 -0
  43. package/dist/dashboard/assets/{api-keys-C23S9sgp.js → api-keys-CUi6UXsR.js} +1 -1
  44. package/dist/dashboard/assets/api-keys-CUi6UXsR.js.gz +0 -0
  45. package/dist/dashboard/assets/app-KvsUJUMF.css +2 -0
  46. package/dist/dashboard/assets/app-KvsUJUMF.css.gz +0 -0
  47. package/dist/dashboard/assets/{assert-DU6qrMA_.js → assert-67xXH5rf.js} +1 -1
  48. package/dist/dashboard/assets/assert-67xXH5rf.js.gz +0 -0
  49. package/dist/dashboard/assets/{badge-Bkz_-RrM.js → badge-DC2L43Mj.js} +1 -1
  50. package/dist/dashboard/assets/badge-DC2L43Mj.js.gz +0 -0
  51. package/dist/dashboard/assets/{banner-C-7y3VKV.js → banner-BBVcb0J3.js} +1 -1
  52. package/dist/dashboard/assets/banner-BBVcb0J3.js.gz +0 -0
  53. package/dist/dashboard/assets/{card-BOPBuBzD.js → card-Cca1XC6G.js} +1 -1
  54. package/dist/dashboard/assets/card-Cca1XC6G.js.gz +0 -0
  55. package/dist/dashboard/assets/{cli-tools-BaFUuFFF.js → cli-tools-KvsWa1Jl.js} +1 -1
  56. package/dist/dashboard/assets/cli-tools-KvsWa1Jl.js.gz +0 -0
  57. package/dist/dashboard/assets/{clipboard-button-e-Mlk0FH.js → clipboard-button-DUzEbynq.js} +1 -1
  58. package/dist/dashboard/assets/clipboard-button-DUzEbynq.js.gz +0 -0
  59. package/dist/dashboard/assets/{dialog-Iec_ywbD.js → dialog-DFvWhwTa.js} +1 -1
  60. package/dist/dashboard/assets/dialog-DFvWhwTa.js.gz +0 -0
  61. package/dist/dashboard/assets/{drawer-Bs8MIIHc.js → drawer-CFM2sMX1.js} +1 -1
  62. package/dist/dashboard/assets/drawer-CFM2sMX1.js.gz +0 -0
  63. package/dist/dashboard/assets/{entry-DOddwoc0.js → entry-BLBLxX0h.js} +3 -3
  64. package/dist/dashboard/assets/entry-BLBLxX0h.js.gz +0 -0
  65. package/dist/dashboard/assets/{entry-DcobaKFu.js → entry-Bqy8RFvM.js} +1 -1
  66. package/dist/dashboard/assets/entry-Bqy8RFvM.js.gz +0 -0
  67. package/dist/dashboard/assets/{entry-BRszm4_Z.js → entry-_xHo5x6r.js} +1 -1
  68. package/dist/dashboard/assets/entry-_xHo5x6r.js.gz +0 -0
  69. package/dist/dashboard/assets/formatters-mpBPqAQ8.js +1 -0
  70. package/dist/dashboard/assets/formatters-mpBPqAQ8.js.gz +0 -0
  71. package/dist/dashboard/assets/{github-badge-BuDsrsPn.js → github-badge-C9e8Ts7e.js} +1 -1
  72. package/dist/dashboard/assets/github-badge-C9e8Ts7e.js.gz +0 -0
  73. package/dist/dashboard/assets/{index-BeLRhsmt.js → index-D6QzEC_n.js} +2 -2
  74. package/dist/dashboard/assets/index-D6QzEC_n.js.gz +0 -0
  75. package/dist/dashboard/assets/{inline-DToMICwl.js → inline-BFUcvllj.js} +1 -1
  76. package/dist/dashboard/assets/inline-BFUcvllj.js.gz +0 -0
  77. package/dist/dashboard/assets/{input-WlyHWeG2.js → input-C_ILAvBb.js} +1 -1
  78. package/dist/dashboard/assets/input-C_ILAvBb.js.gz +0 -0
  79. package/dist/dashboard/assets/{layout-DaJ5baJr.js → layout-CBIyT6Rt.js} +1 -1
  80. package/dist/dashboard/assets/layout-CBIyT6Rt.js.gz +0 -0
  81. package/dist/dashboard/assets/{list-row-B3oSK13z.js → list-row-ebJ_-Nsb.js} +1 -1
  82. package/dist/dashboard/assets/list-row-ebJ_-Nsb.js.gz +0 -0
  83. package/dist/dashboard/assets/{live-ta6GMb-8.js → live-D0mm--ME.js} +1 -1
  84. package/dist/dashboard/assets/live-D0mm--ME.js.gz +0 -0
  85. package/dist/dashboard/assets/minimize-2-D-MN8W8a.js +1 -0
  86. package/dist/dashboard/assets/minimize-2-D-MN8W8a.js.gz +0 -0
  87. package/dist/dashboard/assets/{mutation-g_fduiNw.js → mutation-sMD965oO.js} +1 -1
  88. package/dist/dashboard/assets/mutation-sMD965oO.js.gz +0 -0
  89. package/dist/dashboard/assets/{numbers-Dulqgys5.js → numbers-BO9dKaFr.js} +1 -1
  90. package/dist/dashboard/assets/numbers-BO9dKaFr.js.gz +0 -0
  91. package/dist/dashboard/assets/providers/inception.svg +5 -0
  92. package/dist/dashboard/assets/providers/inception.svg.gz +0 -0
  93. package/dist/dashboard/assets/{query-keys-UETqfytp.js → query-keys-CfL_Zdoh.js} +1 -1
  94. package/dist/dashboard/assets/query-keys-CfL_Zdoh.js.gz +0 -0
  95. package/dist/dashboard/assets/{routing-BPUo-W8d.js → routing-BnIpi1IJ.js} +1 -1
  96. package/dist/dashboard/assets/routing-BnIpi1IJ.js.gz +0 -0
  97. package/dist/dashboard/assets/{select-BfZ3SCTM.js → select-Cj5Nw43g.js} +1 -1
  98. package/dist/dashboard/assets/select-Cj5Nw43g.js.gz +0 -0
  99. package/dist/dashboard/assets/settings-BAFhDgX8.js +1 -0
  100. package/dist/dashboard/assets/settings-BAFhDgX8.js.gz +0 -0
  101. package/dist/dashboard/assets/{stack-B1w5BM0u.js → stack-EMrOMt4I.js} +1 -1
  102. package/dist/dashboard/assets/stack-EMrOMt4I.js.gz +0 -0
  103. package/dist/dashboard/assets/{state-DhZBfWgx.js → state-CWoo7ty5.js} +1 -1
  104. package/dist/dashboard/assets/state-CWoo7ty5.js.gz +0 -0
  105. package/dist/dashboard/assets/{switch-yD7D99Lg.js → switch-CCjT6IkF.js} +1 -1
  106. package/dist/dashboard/assets/switch-CCjT6IkF.js.gz +0 -0
  107. package/dist/dashboard/assets/{useMutation-EDFRkn1i.js → useMutation-DjkLHUcE.js} +1 -1
  108. package/dist/dashboard/assets/useMutation-DjkLHUcE.js.gz +0 -0
  109. package/dist/dashboard/index.html +1 -1
  110. package/dist/dashboard/index.html.gz +0 -0
  111. package/dist/dashboard/precompressed-assets.json +55 -54
  112. package/migrations/full-postgres/0024_add_pool_provider_cooldowns.sql +12 -0
  113. package/migrations/full-postgres/0025_add_pool_random_strategy.sql +3 -0
  114. package/migrations/lite-sqlite3/0024_add_pool_provider_cooldowns.sql +12 -0
  115. package/migrations/lite-sqlite3/0025_add_pool_random_strategy.sql +20 -0
  116. package/package.json +1 -1
  117. package/scripts/cli/console-menu.ts +5 -2
  118. package/scripts/cli/tray.ts +21 -6
  119. package/src/boot/app.ts +24 -62
  120. package/src/boot/dependencies.ts +732 -750
  121. package/src/config/cooldowns.ts +16 -0
  122. package/src/config/providers.ts +13 -1
  123. package/src/config/resources.ts +13 -80
  124. package/src/config/security.ts +2 -38
  125. package/src/config/spec.ts +16 -23
  126. package/src/console/console-router.ts +7 -7
  127. package/src/console/domain-registration.ts +19 -12
  128. package/src/console/providers/catalog/catalog-projections.ts +2 -6
  129. package/src/console/providers/catalog/contracts.ts +19 -0
  130. package/src/console/providers/catalog/provider-operations.ts +38 -0
  131. package/src/console/providers/catalog/routes.ts +14 -0
  132. package/src/console/providers/catalog/store-helpers.ts +326 -0
  133. package/src/console/providers/catalog/store.ts +1292 -1563
  134. package/src/console/quota/account-quota-global.ts +2 -2
  135. package/src/console/quota/account-quota-shared.ts +1 -1
  136. package/src/console/quota/account-quota-tenant.ts +35 -12
  137. package/src/console/quota/quota-view.ts +2 -2
  138. package/src/console/remote-support/contracts.ts +3 -1
  139. package/src/console/remote-support/service.ts +115 -6
  140. package/src/console/routing/pools/contracts.ts +41 -1
  141. package/src/console/routing/pools/operations.ts +183 -4
  142. package/src/console/routing/pools/relay-deploy.ts +17 -4
  143. package/src/console/routing/pools/routes.ts +30 -0
  144. package/src/console/routing/pools/store.ts +98 -8
  145. package/src/main.ts +16 -2
  146. package/src/network/outbound-fetch.ts +226 -365
  147. package/src/network/pool/agent.ts +8 -0
  148. package/src/network/pool/pool-state.ts +7 -0
  149. package/src/network/pool/selector.ts +110 -2
  150. package/src/network/pool-cooldown-store.ts +252 -0
  151. package/src/network/pool-health-machine.ts +5 -3
  152. package/src/network/pool-health.ts +36 -9
  153. package/src/observability/event-query.ts +57 -0
  154. package/src/observability/metrics.ts +15 -5
  155. package/src/observability/runtime-metrics.ts +30 -15
  156. package/src/persistence/health-event-flush.ts +2 -0
  157. package/src/persistence/schema.ts +19 -0
  158. package/src/persistence/usage-flush.ts +8 -3
  159. package/src/protocol/canonical-model.ts +1 -1
  160. package/src/protocol/dsml.ts +377 -0
  161. package/src/protocol/gateway-error.ts +0 -1
  162. package/src/{providers/provider-reasoning.ts → protocol/reasoning.ts} +10 -9
  163. package/src/protocol/request/chat.ts +7 -7
  164. package/src/protocol/request/codex.ts +2 -2
  165. package/src/protocol/request/gemini.ts +1 -1
  166. package/src/protocol/request/messages.ts +6 -6
  167. package/src/protocol/request/responses.ts +7 -7
  168. package/src/protocol/response/dsml.ts +12 -133
  169. package/src/{transport → protocol}/translation/attachment-integrity.ts +2 -2
  170. package/src/{transport → protocol}/translation/cache-controls.ts +1 -1
  171. package/src/{transport → protocol}/translation/capabilities.ts +2 -2
  172. package/src/{transport → protocol}/translation/normalize.ts +1 -1
  173. package/src/{transport → protocol}/translation/quirks.ts +1 -1
  174. package/src/{transport → protocol}/translation/search.ts +1 -1
  175. package/src/{transport → protocol}/translation/thinking.ts +23 -1
  176. package/src/{transport → protocol}/translation/tool-id.ts +1 -1
  177. package/src/{transport → protocol}/translation/tool-repair.ts +2 -2
  178. package/src/protocol/upstream-parsing.ts +176 -0
  179. package/src/providers/adapters/compatible-adapter.ts +11 -2
  180. package/src/providers/authentication/oauth-refresh-service.ts +9 -5
  181. package/src/providers/default-registry.ts +21 -5
  182. package/src/providers/discovery/probe-phases.ts +16 -3
  183. package/src/providers/discovery/probing-service.ts +4 -1
  184. package/src/providers/integrations/anthropic.ts +1 -1
  185. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +1 -4
  186. package/src/providers/integrations/buddy/buddy-chat-shared.ts +141 -8
  187. package/src/providers/integrations/buddy/buddy-checkin.ts +5 -1
  188. package/src/providers/integrations/buddy/buddy-growth-shared.ts +0 -82
  189. package/src/providers/integrations/buddy/buddy-identity.ts +25 -0
  190. package/src/providers/integrations/buddy/buddy-server-tools.ts +240 -0
  191. package/src/providers/integrations/buddy/codebuddy/cn-catalog.ts +36 -0
  192. package/src/providers/integrations/buddy/codebuddy/cn-provider.ts +6 -31
  193. package/src/providers/integrations/buddy/codebuddy/provider.ts +2 -0
  194. package/src/providers/integrations/buddy/codebuddy/shared.ts +19 -4
  195. package/src/providers/integrations/buddy/turing-device-token.ts +262 -0
  196. package/src/providers/integrations/buddy/workbuddy/provider.ts +2 -0
  197. package/src/providers/integrations/buddy/workbuddy/shared.ts +56 -3
  198. package/src/providers/integrations/claude/claude.ts +1 -1
  199. package/src/providers/integrations/cloudflareai/cloudflareai.ts +1 -1
  200. package/src/providers/integrations/codex/codex-errors.ts +1 -1
  201. package/src/providers/integrations/codex/codex.ts +1 -1
  202. package/src/providers/integrations/commandcode/commandcode.ts +134 -104
  203. package/src/providers/integrations/commandcode/discovery.ts +6 -5
  204. package/src/providers/integrations/factory/factory.ts +1 -1
  205. package/src/providers/integrations/github/github.ts +1 -1
  206. package/src/providers/integrations/grok/grok.ts +1 -1
  207. package/src/providers/integrations/inception/provider.ts +91 -0
  208. package/src/providers/integrations/inferhub.ts +1 -1
  209. package/src/providers/integrations/kiro/kiro-request.ts +1 -1
  210. package/src/providers/integrations/mistral.ts +193 -19
  211. package/src/providers/integrations/opencode/fingerprint.ts +19 -2
  212. package/src/providers/integrations/opencode/prompt.ts +111 -0
  213. package/src/providers/integrations/opencode/provider.ts +101 -23
  214. package/src/providers/integrations/opencode/tool-definitions.ts +4 -4
  215. package/src/providers/integrations/qoder/qoder-checkin.ts +303 -0
  216. package/src/providers/integrations/qoder/qoder.ts +1641 -884
  217. package/src/providers/integrations/shared/install-id.ts +2 -1
  218. package/src/providers/integrations/trae/trae-cache.ts +110 -0
  219. package/src/providers/integrations/trae/trae-oauth.ts +29 -4
  220. package/src/providers/integrations/trae/trae-protocol.ts +2 -1
  221. package/src/providers/integrations/trae/trae.ts +106 -23
  222. package/src/providers/operations/account-error-classification.ts +1660 -0
  223. package/src/providers/operations/account-health-service.ts +621 -2097
  224. package/src/providers/operations/account-reset-service.ts +2 -0
  225. package/src/providers/provider-contracts.ts +0 -2
  226. package/src/providers/provider-metadata.ts +25 -4
  227. package/src/providers/provider-probe.ts +2 -2
  228. package/src/{console → providers}/quota/cache.ts +1 -1
  229. package/src/{console → providers}/quota/refresh.ts +5 -5
  230. package/src/security/abuse.ts +17 -0
  231. package/src/transport/dispatch/attempt-finalize.ts +114 -12
  232. package/src/transport/dispatch/attempt-loop.ts +3 -0
  233. package/src/transport/dispatch/empty-stream.ts +224 -217
  234. package/src/transport/dispatch/generation.ts +37 -55
  235. package/src/transport/dispatch/handler-deps.ts +32 -0
  236. package/src/transport/dispatch/leases.ts +9 -4
  237. package/src/transport/dispatch/proxy-request.ts +6 -30
  238. package/src/transport/dispatch/responses-compact.ts +22 -43
  239. package/src/transport/dispatch/streaming/finalize.ts +3 -0
  240. package/src/transport/dispatch/streaming/stream.ts +0 -8
  241. package/src/transport/dispatch/systemone.ts +22 -42
  242. package/src/transport/dispatch/token-count.ts +23 -39
  243. package/src/transport/dispatch/upstream.ts +1 -3
  244. package/src/transport/dispatch/websearch.ts +22 -41
  245. package/src/transport/failure-policy.ts +59 -178
  246. package/src/transport/guards/abuse-guard.ts +10 -0
  247. package/src/transport/guards/auth-guard.ts +0 -18
  248. package/src/transport/guards/error-lifecycle.ts +1 -1
  249. package/src/transport/guards/pipeline.ts +0 -6
  250. package/src/transport/guards/request-context.ts +18 -91
  251. package/src/transport/request/degradation.ts +20 -1
  252. package/src/transport/request/inflight.ts +4 -95
  253. package/src/transport/request/preparer.ts +6 -6
  254. package/src/transport/request/state.ts +66 -38
  255. package/src/transport/request/tenant-preferences.ts +1 -1
  256. package/src/transport/routing/route-catalog.ts +41 -31
  257. package/src/transport/routing/router.ts +2 -2
  258. package/src/transport/surface/messages/parse.ts +1 -1
  259. package/src/workers/buddy-growth-tasks.ts +346 -425
  260. package/src/workers/daily-checkin.ts +17 -6
  261. package/src/workers/quota-refresh-sweep.ts +2 -2
  262. package/src/workers/scheduler.ts +17 -1
  263. package/dist/dashboard/assets/BannedPage-Dskhyp0l.js.gz +0 -0
  264. package/dist/dashboard/assets/CliToolDetailPage--SJhk7qQ.js.gz +0 -0
  265. package/dist/dashboard/assets/CliToolsPage-C203VT-c.js.gz +0 -0
  266. package/dist/dashboard/assets/CombosPage-BcS7kGG1.js.gz +0 -0
  267. package/dist/dashboard/assets/ConsoleLogPage-ChmiSLwO.js +0 -1
  268. package/dist/dashboard/assets/ConsoleLogPage-ChmiSLwO.js.gz +0 -0
  269. package/dist/dashboard/assets/CustomizationPage-uujbBYwC.js.gz +0 -0
  270. package/dist/dashboard/assets/HealthEventsModal-fKAWd-OQ.js +0 -1
  271. package/dist/dashboard/assets/HealthEventsModal-fKAWd-OQ.js.gz +0 -0
  272. package/dist/dashboard/assets/LoginPage-DoOUthbG.js +0 -1
  273. package/dist/dashboard/assets/LoginPage-DoOUthbG.js.gz +0 -0
  274. package/dist/dashboard/assets/ModelPicker-CA1kLs45.js.gz +0 -0
  275. package/dist/dashboard/assets/OverviewPage-C5Z-UBz1.js +0 -1
  276. package/dist/dashboard/assets/OverviewPage-C5Z-UBz1.js.gz +0 -0
  277. package/dist/dashboard/assets/ProviderDetailPage-CFu1qGcT.js +0 -3
  278. package/dist/dashboard/assets/ProviderDetailPage-CFu1qGcT.js.gz +0 -0
  279. package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js +0 -1
  280. package/dist/dashboard/assets/ProviderIcon-CmfzxpVM.js.gz +0 -0
  281. package/dist/dashboard/assets/ProvidersPage-CnlJZbxF.js +0 -1
  282. package/dist/dashboard/assets/ProvidersPage-CnlJZbxF.js.gz +0 -0
  283. package/dist/dashboard/assets/ProxyPage-B9mBTweh.js +0 -7
  284. package/dist/dashboard/assets/ProxyPage-B9mBTweh.js.gz +0 -0
  285. package/dist/dashboard/assets/QuotaPage-BueSWX5D.js.gz +0 -0
  286. package/dist/dashboard/assets/SettingsPage-B0x00MVY.js +0 -1
  287. package/dist/dashboard/assets/SettingsPage-B0x00MVY.js.gz +0 -0
  288. package/dist/dashboard/assets/SetupPage-DQ9oDRpi.js +0 -1
  289. package/dist/dashboard/assets/SetupPage-DQ9oDRpi.js.gz +0 -0
  290. package/dist/dashboard/assets/SortableList-DrKeMcGN.js.gz +0 -0
  291. package/dist/dashboard/assets/StudioPage-qjuYtccc.js.gz +0 -0
  292. package/dist/dashboard/assets/UsagePage-Be7aNviQ.js +0 -56
  293. package/dist/dashboard/assets/UsagePage-Be7aNviQ.js.gz +0 -0
  294. package/dist/dashboard/assets/api-keys-C23S9sgp.js.gz +0 -0
  295. package/dist/dashboard/assets/app-BUSiYL6F.css +0 -2
  296. package/dist/dashboard/assets/app-BUSiYL6F.css.gz +0 -0
  297. package/dist/dashboard/assets/assert-DU6qrMA_.js.gz +0 -0
  298. package/dist/dashboard/assets/badge-Bkz_-RrM.js.gz +0 -0
  299. package/dist/dashboard/assets/banner-C-7y3VKV.js.gz +0 -0
  300. package/dist/dashboard/assets/card-BOPBuBzD.js.gz +0 -0
  301. package/dist/dashboard/assets/cli-tools-BaFUuFFF.js.gz +0 -0
  302. package/dist/dashboard/assets/clipboard-button-e-Mlk0FH.js.gz +0 -0
  303. package/dist/dashboard/assets/cog-CdWhsajs.js +0 -1
  304. package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
  305. package/dist/dashboard/assets/dialog-Iec_ywbD.js.gz +0 -0
  306. package/dist/dashboard/assets/drawer-Bs8MIIHc.js.gz +0 -0
  307. package/dist/dashboard/assets/entry-BRszm4_Z.js.gz +0 -0
  308. package/dist/dashboard/assets/entry-DOddwoc0.js.gz +0 -0
  309. package/dist/dashboard/assets/entry-DcobaKFu.js.gz +0 -0
  310. package/dist/dashboard/assets/github-badge-BuDsrsPn.js.gz +0 -0
  311. package/dist/dashboard/assets/index-BeLRhsmt.js.gz +0 -0
  312. package/dist/dashboard/assets/inline-DToMICwl.js.gz +0 -0
  313. package/dist/dashboard/assets/input-WlyHWeG2.js.gz +0 -0
  314. package/dist/dashboard/assets/layout-DaJ5baJr.js.gz +0 -0
  315. package/dist/dashboard/assets/list-row-B3oSK13z.js.gz +0 -0
  316. package/dist/dashboard/assets/live-ta6GMb-8.js.gz +0 -0
  317. package/dist/dashboard/assets/model-bans-BmYTmbAk.js +0 -1
  318. package/dist/dashboard/assets/model-bans-BmYTmbAk.js.gz +0 -0
  319. package/dist/dashboard/assets/mutation-g_fduiNw.js.gz +0 -0
  320. package/dist/dashboard/assets/numbers-Dulqgys5.js.gz +0 -0
  321. package/dist/dashboard/assets/query-keys-UETqfytp.js.gz +0 -0
  322. package/dist/dashboard/assets/routing-BPUo-W8d.js.gz +0 -0
  323. package/dist/dashboard/assets/select-BfZ3SCTM.js.gz +0 -0
  324. package/dist/dashboard/assets/settings--3hxSyry.js +0 -1
  325. package/dist/dashboard/assets/settings--3hxSyry.js.gz +0 -0
  326. package/dist/dashboard/assets/stack-B1w5BM0u.js.gz +0 -0
  327. package/dist/dashboard/assets/state-DhZBfWgx.js.gz +0 -0
  328. package/dist/dashboard/assets/switch-yD7D99Lg.js.gz +0 -0
  329. package/dist/dashboard/assets/useMutation-EDFRkn1i.js.gz +0 -0
  330. package/src/console/admin/model-abuse/contracts.ts +0 -38
  331. package/src/console/admin/model-abuse/routes.ts +0 -97
  332. package/src/security/model-abuse.ts +0 -704
  333. package/src/transport/guards/concurrency-guard.ts +0 -125
  334. /package/dist/dashboard/assets/{app-MdVfwraB.js → app-BaWd0puM.js} +0 -0
  335. /package/dist/dashboard/assets/{app-MdVfwraB.js.gz → app-BaWd0puM.js.gz} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cartethyia",
3
- "version": "2.6.7",
3
+ "version": "2.7.1",
4
4
  "description": "A powerful, self-hosted reverse proxy for OpenAI- and Anthropic-compatible AI clients, powered by native Bun and Elysia. It serves both protocols from a single server, routes every model across any configured provider, and translates requests and responses in real time — streaming and prompt caching included. Underneath it runs a full delivery engine: per-account health tracking, quota and cooldown enforcement, automatic failover across pools and providers, usage accounting, and telemetry. Point OpenCode, Cline, Claude Code, Codex, or any compatible client at Cartethyia and it keeps its native protocol while the gateway absorbs every provider-specific difference behind it. Runs on embedded SQLite or external PostgreSQL with optional Redis coordination, ships as a global CLI with a system-tray console, and needs only Bun 1.4+ alongside Node.js/npm.",
5
5
  "license": "GPL-3.0-only",
6
6
  "type": "module",
@@ -18,7 +18,6 @@ import { exportBackup, resetConsoleAccount } from "./admin";
18
18
  import { printUpdateInstructions, runDetachedUpdate } from "./update";
19
19
  import { acquireController } from "./controller";
20
20
  import { restoreControllerAfterFailedHandoff } from "./controller";
21
- import { attachGateway as attachRunningGateway } from "./instance";
22
21
 
23
22
  /**
24
23
  * Seconds to keep the update notice on screen before returning to the shell.
@@ -316,7 +315,11 @@ async function runMenu(handoff: { readonly token: string; readonly parentPid: nu
316
315
  // would stop the very process the tray just adopted, which is why the menu
317
316
  // appeared to hand over a gateway that was not listening.
318
317
  if (handedOff) return;
319
- if (runningAttached !== null || (await attachRunningGateway(port, drainToken)) !== null) {
318
+ // An attached (externally owned) gateway is left running for its owner; our
319
+ // own child is drained before the menu returns to the shell. `attachGateway`
320
+ // is deliberately NOT probed again here: it would always see our own child's
321
+ // lock and turn a clean drain into a rough kill on the exit backstop.
322
+ if (runningAttached !== null) {
320
323
  detachAttached();
321
324
  return;
322
325
  }
@@ -64,15 +64,16 @@ export async function startTray(): Promise<void> {
64
64
  const handoff = inheritedControllerHandoff();
65
65
  const controller = acquireController("tray", handoff);
66
66
  const releaseController = (): void => controller.release();
67
- const failedHandoff = (): void => {
68
- if (handoff) restoreControllerAfterFailedHandoff(handoff);
69
- };
70
- process.once("exit", failedHandoff);
71
67
  process.once("exit", releaseController);
72
68
  try {
73
69
  await runTray();
70
+ } catch (error) {
71
+ // Only a tray that never became ready restores the menu's lease. After a
72
+ // successful handoff the tray owns the controller; restoring it on a later
73
+ // normal exit would pin a controller record to the long-gone menu pid.
74
+ if (handoff) restoreControllerAfterFailedHandoff(handoff);
75
+ throw error;
74
76
  } finally {
75
- process.removeListener("exit", failedHandoff);
76
77
  controller.release();
77
78
  process.removeListener("exit", releaseController);
78
79
  }
@@ -174,7 +175,21 @@ async function runTray(): Promise<void> {
174
175
  // over HTTP before it ever reaches for `kill()`, so detaching costs the
175
176
  // exit path nothing: the tray can still stop the gateway on Exit.
176
177
  adoptedGateway = await attachGateway(port, drainToken);
177
- if (adoptedGateway === null) gateway = await startGateway(port, drainToken, { detached: true });
178
+ if (adoptedGateway === null) {
179
+ gateway = await startGateway(port, drainToken, { detached: true });
180
+ } else {
181
+ // The adopted gateway was started by the menu as a non-detached child of
182
+ // the menu's console. When the menu exits — and especially when the
183
+ // operator closes that terminal window afterwards — Windows delivers
184
+ // CTRL_CLOSE to the whole console group and the gateway (handling
185
+ // SIGTERM) shuts down with it: "Hide to tray" left nothing serving. The
186
+ // menu cannot hand the same process off to another console, so re-cycle
187
+ // it into a detached gateway now, before reporting ready, so the tray
188
+ // owns a gateway that is not attached to any console after the handoff.
189
+ await stopAttachedGateway(adoptedGateway, drainToken);
190
+ adoptedGateway = null;
191
+ gateway = await startGateway(port, drainToken, { detached: true });
192
+ }
178
193
  // The launcher that spawned this tray is blocked on a signal file: it
179
194
  // cannot read our stdio, because the tray is detached. Without this write
180
195
  // it waits out its 60 s deadline and reports a failure for a tray that is
package/src/boot/app.ts CHANGED
@@ -30,8 +30,8 @@ import { ProxyRequestStateStore } from "../transport/request/state";
30
30
  import { fastPathname } from "../transport/pathname";
31
31
  import {
32
32
  handleProviderProxyRequest,
33
- type ProviderProxyHandlerDeps,
34
33
  } from "../transport/dispatch/proxy-request";
34
+ import type { GatewayHandlerDeps } from "../transport/dispatch/handler-deps";
35
35
  import { createResponsesCompactHandler } from "../transport/dispatch/responses-compact";
36
36
  import { createSystemoneHandler } from "../transport/dispatch/systemone";
37
37
  import { createWebsearchHandler } from "../transport/dispatch/websearch";
@@ -45,7 +45,6 @@ import {
45
45
  import { createTokenCountHandler } from "../transport/dispatch/token-count";
46
46
 
47
47
  import { createTransportPipeline } from "../transport/guards/pipeline";
48
- import { defaultProcessConcurrencyController } from "../transport/guards/concurrency-guard";
49
48
  import { createDrainHandler, isLoopbackPeer, tokenMatches } from "../transport/drain-endpoint";
50
49
  import { createConsoleAccountResetHandler } from "../console/auth/account-reset";
51
50
  import { resetConsoleAuthState } from "../console/auth/account-reset-store";
@@ -61,7 +60,6 @@ import type { ValidatedNetworkBindingFactory } from "../network/pool/resolver";
61
60
  import { metrics } from "../observability/metrics";
62
61
  import type { RuntimeMetricsSampler } from "../observability/runtime-metrics";
63
62
  import { API_CONTENT_SECURITY_POLICY, X_FRAME_OPTIONS } from "../security/outbound-headers";
64
- import type { ModelStrikeService } from "../security/model-abuse";
65
63
 
66
64
 
67
65
  import type { TelemetryBatchBuffer } from "../observability/telemetry-buffer";
@@ -112,7 +110,6 @@ export interface ProductionAppDeps {
112
110
  readonly db: CartethyiaDatabase;
113
111
  readonly proxyPreparer: ProxyRequestPreparer;
114
112
  readonly resolveProviderAdapter: (providerId: string) => Promise<ProviderAdapter | undefined>;
115
- readonly providerAdapters?: ReadonlyMap<string, ProviderAdapter>;
116
113
  /** Live lookup of a provider's SSRF-validated upstream host. */
117
114
  readonly byokUpstreamHosts: { readonly get: (providerId: string) => ByokUpstreamHost | undefined };
118
115
  readonly networkBindingFactory: ValidatedNetworkBindingFactory;
@@ -125,7 +122,6 @@ export interface ProductionAppDeps {
125
122
  readonly resolveOAuthRefresher: (providerId: string) => Promise<OAuthTokenRefresher | undefined>;
126
123
  readonly oauthRefreshService: OAuthRefreshService;
127
124
  /** Graduated strikes for repeated invalid-model requests. */
128
- readonly modelStrikes?: ModelStrikeService;
129
125
  /**
130
126
  * The console control plane. Optional so reduced compositions (route-only
131
127
  * shell, console stubs) stay valid; production always mounts it. Without
@@ -245,10 +241,6 @@ export function createGatewayApp(deps: GatewayAppDeps) {
245
241
  deps.mode === "production" ? deps.shutdownCoordinator : undefined,
246
242
  );
247
243
  deps.runtimeMetricsSampler?.bindInFlight(() => requestStateStore.inFlightCount());
248
- // The concurrency ceiling is derived (memory limit ÷ body budget), so it is
249
- // published as a gauge: an operator reading "shedding at 16 in flight" needs
250
- // to see that 16 IS the limit on this box, not that the process is broken.
251
- deps.runtimeMetricsSampler?.bindConcurrencyLimit(defaultProcessConcurrencyController.limit());
252
244
  // Shutdown ordering: abort in-flight proxy controllers first so the
253
245
  // bounded drain observes cancellation and finalizers run before
254
246
  // telemetry flush and pool close. The reason is threaded through so the
@@ -282,6 +274,9 @@ export function createGatewayApp(deps: GatewayAppDeps) {
282
274
  backstopTasks?.register({
283
275
  name: "inflight-backstop",
284
276
  intervalMs: INFLIGHT_BACKSTOP_INTERVAL_MS,
277
+ // Same stagger rationale as account-health-sweep: keep the 30s cluster
278
+ // from aligning under the single-flight gate.
279
+ initialDelayMs: 15_000,
285
280
  run: () => {
286
281
  requestStateStore.sweepOverdueInFlight(
287
282
  Date.now(),
@@ -392,7 +387,6 @@ export function createGatewayApp(deps: GatewayAppDeps) {
392
387
  ...(deps.verifiedHttps ? { verifiedHttps: true } : {}),
393
388
  shutdownCoordinator: deps.shutdownCoordinator,
394
389
  telemetry: deps.telemetryBuffer,
395
- ...(deps.modelStrikes ? { modelStrikes: deps.modelStrikes } : {}),
396
390
  ...(deps.consoleApi?.redis ? { redis: deps.consoleApi.redis } : {}),
397
391
  // Bound at construction so the guard holds the sampler's live snapshot
398
392
  // rather than a value captured at boot.
@@ -406,22 +400,27 @@ export function createGatewayApp(deps: GatewayAppDeps) {
406
400
  (await deps.snapshotService.getSnapshot())?.invokeDisabledTenants?.has(tenantId),
407
401
  });
408
402
  transportPipeline.mountRoot(app);
409
- const proxyDeps: ProviderProxyHandlerDeps = {
403
+ // One dependency bundle for every gateway handler. Proxy, generation,
404
+ // responses-compact, system one, web search, and token count all receive
405
+ // the same wiring — a handler dep is added once, here, not in five
406
+ // literals.
407
+ const gatewayDeps: GatewayHandlerDeps = {
410
408
  db: deps.db,
411
- providerAdapters: deps.providerAdapters ?? new Map(),
412
409
  resolveProviderAdapter: deps.resolveProviderAdapter,
413
410
  stateStore: requestStateStore,
414
411
  proxyPreparer: deps.proxyPreparer,
415
412
  snapshotService: deps.snapshotService,
416
413
  networkBindingFactory: deps.networkBindingFactory,
417
- byokUpstreamHosts: deps.byokUpstreamHosts,
418
414
  poolSelector: deps.poolSelector,
419
415
  telemetryBuffer: deps.telemetryBuffer,
420
416
  resolveOAuthRefresher: deps.resolveOAuthRefresher,
421
417
  oauthRefreshService: deps.oauthRefreshService,
422
418
  };
423
419
  const proxyHandler = ({ request }: { request: Request }) =>
424
- handleProviderProxyRequest(request, proxyDeps);
420
+ handleProviderProxyRequest(request, {
421
+ ...gatewayDeps,
422
+ byokUpstreamHosts: deps.byokUpstreamHosts,
423
+ });
425
424
 
426
425
  const publicModelStore = new PublicModelCatalogStore(deps.db);
427
426
  const queryAllowedModels = (auth: {
@@ -483,16 +482,7 @@ export function createGatewayApp(deps: GatewayAppDeps) {
483
482
  };
484
483
 
485
484
  const handleResponsesCompact = createResponsesCompactHandler({
486
- db: deps.db,
487
- providerAdapters: deps.providerAdapters ?? new Map(),
488
- resolveProviderAdapter: deps.resolveProviderAdapter,
489
- proxyPreparer: deps.proxyPreparer,
490
- stateStore: requestStateStore,
491
- poolSelector: deps.poolSelector,
492
- networkBindingFactory: deps.networkBindingFactory,
493
- snapshotService: deps.snapshotService,
494
- resolveOAuthRefresher: deps.resolveOAuthRefresher,
495
- oauthRefreshService: deps.oauthRefreshService,
485
+ ...gatewayDeps,
496
486
  // The compact handler completes its attempt through `completeAttempt`,
497
487
  // which marks the request completed and finalizes telemetry itself —
498
488
  // so the afterResponse lifecycle skips it. Without the buffer here the
@@ -501,48 +491,14 @@ export function createGatewayApp(deps: GatewayAppDeps) {
501
491
  });
502
492
 
503
493
  const handleSystemone = createSystemoneHandler({
504
- db: deps.db,
505
- providerAdapters: deps.providerAdapters ?? new Map(),
506
- resolveProviderAdapter: deps.resolveProviderAdapter,
507
- proxyPreparer: deps.proxyPreparer,
508
- stateStore: requestStateStore,
509
- poolSelector: deps.poolSelector,
510
- networkBindingFactory: deps.networkBindingFactory,
511
- snapshotService: deps.snapshotService,
512
- resolveOAuthRefresher: deps.resolveOAuthRefresher,
513
- oauthRefreshService: deps.oauthRefreshService,
494
+ ...gatewayDeps,
514
495
  // Same reasoning as compact: the handler finalizes telemetry itself, so
515
496
  // the buffer must be threaded here or the route emits no row.
516
497
  telemetryBuffer: deps.telemetryBuffer,
517
498
  });
518
499
 
519
- const handleWebsearch = createWebsearchHandler({
520
- db: deps.db,
521
- providerAdapters: deps.providerAdapters ?? new Map(),
522
- resolveProviderAdapter: deps.resolveProviderAdapter,
523
- proxyPreparer: deps.proxyPreparer,
524
- stateStore: requestStateStore,
525
- poolSelector: deps.poolSelector,
526
- networkBindingFactory: deps.networkBindingFactory,
527
- snapshotService: deps.snapshotService,
528
- resolveOAuthRefresher: deps.resolveOAuthRefresher,
529
- oauthRefreshService: deps.oauthRefreshService,
530
- telemetryBuffer: deps.telemetryBuffer,
531
- });
532
-
533
- const generationDeps = {
534
- db: deps.db,
535
- providerAdapters: deps.providerAdapters ?? new Map(),
536
- resolveProviderAdapter: deps.resolveProviderAdapter,
537
- proxyPreparer: deps.proxyPreparer,
538
- stateStore: requestStateStore,
539
- poolSelector: deps.poolSelector,
540
- networkBindingFactory: deps.networkBindingFactory,
541
- snapshotService: deps.snapshotService,
542
- resolveOAuthRefresher: deps.resolveOAuthRefresher,
543
- oauthRefreshService: deps.oauthRefreshService,
544
- telemetryBuffer: deps.telemetryBuffer,
545
- };
500
+ const handleWebsearch = createWebsearchHandler(gatewayDeps);
501
+ const generationDeps = gatewayDeps;
546
502
  const handleImageGeneration = createImageGenerationHandler(generationDeps);
547
503
  // Mounted with no model behind it on purpose: the surface exists so it can
548
504
  // be finished when an upstream is known, rather than 404ing like a typo.
@@ -660,6 +616,11 @@ export function createGatewayApp(deps: GatewayAppDeps) {
660
616
  });
661
617
  }
662
618
 
619
+ // One share-link store for both surfaces: the public share router and the
620
+ // console's API-key/share domain wrap the same table, and one instance
621
+ // keeps the "one owner per store" convention.
622
+ const shareStore = new DrizzleShareLinkStore(deps.db);
623
+
663
624
  // `peerAddresses` is populated by the root `beforeHandle` above from
664
625
  // `server.requestIP`. The console login route needs it to key its lockout
665
626
  // bucket, and the trusted-proxy boundary decides whether an
@@ -669,6 +630,7 @@ export function createGatewayApp(deps: GatewayAppDeps) {
669
630
  app.use(
670
631
  createConsoleRouter({
671
632
  ...deps.consoleApi,
633
+ ...(shareStore ? { shareStore } : {}),
672
634
  stateStore: requestStateStore,
673
635
  resolvePeerAddress: (request) => peerAddresses.get(request) ?? null,
674
636
  trustedProxyBoundary: deps.trustedProxyBoundary,
@@ -681,7 +643,7 @@ export function createGatewayApp(deps: GatewayAppDeps) {
681
643
  app.use(
682
644
  createShareRouter({
683
645
  db: deps.db,
684
- shareStore: new DrizzleShareLinkStore(deps.db),
646
+ shareStore,
685
647
  stats: createShareStatsPort({ db: deps.db, redis: deps.consoleApi?.redis }),
686
648
  resolveClientIp: (request) => {
687
649
  const peer = peerAddresses.get(request);