cartethyia 2.5.4 → 2.5.6

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 (395) hide show
  1. package/.env.example +13 -4
  2. package/README.md +2 -2
  3. package/dist/dashboard/assets/{BannedPage-C2orBsI2.js → BannedPage-CADDq4IU.js} +1 -1
  4. package/dist/dashboard/assets/BannedPage-CADDq4IU.js.gz +0 -0
  5. package/dist/dashboard/assets/CliToolDetailPage-_z1hID7E.js +1 -0
  6. package/dist/dashboard/assets/CliToolDetailPage-_z1hID7E.js.gz +0 -0
  7. package/dist/dashboard/assets/{CliToolsPage-BV6pxVQo.js → CliToolsPage-DuO1Z7dq.js} +1 -1
  8. package/dist/dashboard/assets/CliToolsPage-DuO1Z7dq.js.gz +0 -0
  9. package/dist/dashboard/assets/CombosPage-DNEPi3xU.js +1 -0
  10. package/dist/dashboard/assets/CombosPage-DNEPi3xU.js.gz +0 -0
  11. package/dist/dashboard/assets/{ConsoleLogPage-CW-wPmJ6.js → ConsoleLogPage-BVdpfiz1.js} +1 -1
  12. package/dist/dashboard/assets/ConsoleLogPage-BVdpfiz1.js.gz +0 -0
  13. package/dist/dashboard/assets/{CustomizationPage-0p8uX7vB.js → CustomizationPage-BR5HHvbi.js} +1 -1
  14. package/dist/dashboard/assets/CustomizationPage-BR5HHvbi.js.gz +0 -0
  15. package/dist/dashboard/assets/{HealthEventsModal-BjqSMfko.js → HealthEventsModal-mUfcknqm.js} +1 -1
  16. package/dist/dashboard/assets/HealthEventsModal-mUfcknqm.js.gz +0 -0
  17. package/dist/dashboard/assets/{LoginPage-BvzCx8Kr.js → LoginPage-V5faV9V2.js} +1 -1
  18. package/dist/dashboard/assets/LoginPage-V5faV9V2.js.gz +0 -0
  19. package/dist/dashboard/assets/ModelPicker-C7pDb41R.js +1 -0
  20. package/dist/dashboard/assets/ModelPicker-C7pDb41R.js.gz +0 -0
  21. package/dist/dashboard/assets/OverviewPage-BDu20Jdx.js +1 -0
  22. package/dist/dashboard/assets/OverviewPage-BDu20Jdx.js.gz +0 -0
  23. package/dist/dashboard/assets/ProviderDetailPage-Dllr_aFO.js +3 -0
  24. package/dist/dashboard/assets/ProviderDetailPage-Dllr_aFO.js.gz +0 -0
  25. package/dist/dashboard/assets/{ProvidersPage-Js9jUPSb.js → ProvidersPage-uPiGVTTK.js} +1 -1
  26. package/dist/dashboard/assets/ProvidersPage-uPiGVTTK.js.gz +0 -0
  27. package/dist/dashboard/assets/ProxyPage-BaUkO-4O.js +7 -0
  28. package/dist/dashboard/assets/ProxyPage-BaUkO-4O.js.gz +0 -0
  29. package/dist/dashboard/assets/QuotaPage-o0IFAsFb.js +1 -0
  30. package/dist/dashboard/assets/QuotaPage-o0IFAsFb.js.gz +0 -0
  31. package/dist/dashboard/assets/SettingsPage-CYWqbXjp.js +1 -0
  32. package/dist/dashboard/assets/SettingsPage-CYWqbXjp.js.gz +0 -0
  33. package/dist/dashboard/assets/{SetupPage-DDbMQsoo.js → SetupPage-UB690SE2.js} +1 -1
  34. package/dist/dashboard/assets/SetupPage-UB690SE2.js.gz +0 -0
  35. package/dist/dashboard/assets/{SortableList-CB3Z7VTf.js → SortableList-BLujdX7N.js} +1 -1
  36. package/dist/dashboard/assets/SortableList-BLujdX7N.js.gz +0 -0
  37. package/dist/dashboard/assets/{StudioPage-D95UCPHI.js → StudioPage-D5C2raAc.js} +3 -3
  38. package/dist/dashboard/assets/StudioPage-D5C2raAc.js.gz +0 -0
  39. package/dist/dashboard/assets/UsagePage-8uIcxa1W.js +56 -0
  40. package/dist/dashboard/assets/UsagePage-8uIcxa1W.js.gz +0 -0
  41. package/dist/dashboard/assets/api-keys-DQYLQxpW.js +1 -0
  42. package/dist/dashboard/assets/api-keys-DQYLQxpW.js.gz +0 -0
  43. package/dist/dashboard/assets/app-CX_Z8cMs.css +2 -0
  44. package/dist/dashboard/assets/app-CX_Z8cMs.css.gz +0 -0
  45. package/dist/dashboard/assets/{assert-Chi7pCnt.js → assert-C9FD_JwJ.js} +1 -1
  46. package/dist/dashboard/assets/assert-C9FD_JwJ.js.gz +0 -0
  47. package/dist/dashboard/assets/{badge-D4pQapKj.js → badge-CR72dasT.js} +1 -1
  48. package/dist/dashboard/assets/badge-CR72dasT.js.gz +0 -0
  49. package/dist/dashboard/assets/{banner-DH6cg-_B.js → banner-CI9_eSfO.js} +1 -1
  50. package/dist/dashboard/assets/banner-CI9_eSfO.js.gz +0 -0
  51. package/dist/dashboard/assets/{card-BKqlUOe4.js → card-DS7CQEsO.js} +1 -1
  52. package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
  53. package/dist/dashboard/assets/{cli-tools-fTgljTGA.js → cli-tools-CNqzrfdb.js} +1 -1
  54. package/dist/dashboard/assets/cli-tools-CNqzrfdb.js.gz +0 -0
  55. package/dist/dashboard/assets/{clipboard-button-D5Ys_sM0.js → clipboard-button-611pSsaX.js} +1 -1
  56. package/dist/dashboard/assets/clipboard-button-611pSsaX.js.gz +0 -0
  57. package/dist/dashboard/assets/{fingerprint-pattern-BWuHtbW4.js → concurrency-BDF0ok7y.js} +1 -1
  58. package/dist/dashboard/assets/concurrency-BDF0ok7y.js.gz +0 -0
  59. package/dist/dashboard/assets/dialog-k37exjNt.js +1 -0
  60. package/dist/dashboard/assets/dialog-k37exjNt.js.gz +0 -0
  61. package/dist/dashboard/assets/drawer-CX7N8ucR.js +1 -0
  62. package/dist/dashboard/assets/drawer-CX7N8ucR.js.gz +0 -0
  63. package/dist/dashboard/assets/{entry-CQBr6U9c.js → entry-B9Xvtnfj.js} +1 -1
  64. package/dist/dashboard/assets/entry-B9Xvtnfj.js.gz +0 -0
  65. package/dist/dashboard/assets/entry-CTP8AyiS.js +1 -0
  66. package/dist/dashboard/assets/entry-CTP8AyiS.js.gz +0 -0
  67. package/dist/dashboard/assets/entry-DxBHnauy.js +4 -0
  68. package/dist/dashboard/assets/entry-DxBHnauy.js.gz +0 -0
  69. package/dist/dashboard/assets/{github-badge-BlptL8Uf.js → github-badge-sltk1qUi.js} +1 -1
  70. package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
  71. package/dist/dashboard/assets/{index-js6TJvdr.js → index-CmxZr14F.js} +2 -2
  72. package/dist/dashboard/assets/index-CmxZr14F.js.gz +0 -0
  73. package/dist/dashboard/assets/{inline-DUWDSmDV.js → inline-BhY2sSnO.js} +1 -1
  74. package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
  75. package/dist/dashboard/assets/{input-LVjgZq4f.js → input-V1umFiBk.js} +1 -1
  76. package/dist/dashboard/assets/input-V1umFiBk.js.gz +0 -0
  77. package/dist/dashboard/assets/layout-BBOYycyS.js +1 -0
  78. package/dist/dashboard/assets/layout-BBOYycyS.js.gz +0 -0
  79. package/dist/dashboard/assets/{list-row-DupvLfDx.js → list-row-1zzZYM0B.js} +1 -1
  80. package/dist/dashboard/assets/list-row-1zzZYM0B.js.gz +0 -0
  81. package/dist/dashboard/assets/{live-C4pEJUqI.js → live-BivGfuUs.js} +1 -1
  82. package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
  83. package/dist/dashboard/assets/{model-bans-BRiuufkB.js → model-bans-CmffjLuG.js} +1 -1
  84. package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
  85. package/dist/dashboard/assets/{mutation-B4ROwk8L.js → mutation-46P0oWMe.js} +1 -1
  86. package/dist/dashboard/assets/mutation-46P0oWMe.js.gz +0 -0
  87. package/dist/dashboard/assets/numbers-DkfMR5Qs.js +2 -0
  88. package/dist/dashboard/assets/numbers-DkfMR5Qs.js.gz +0 -0
  89. package/dist/dashboard/assets/{query-keys-gmjzC3RS.js → query-keys-BFhGpwR1.js} +1 -1
  90. package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
  91. package/dist/dashboard/assets/{routing-C7tBT5o-.js → routing-CAb4F37R.js} +1 -1
  92. package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
  93. package/dist/dashboard/assets/{select-WUCXorXw.js → select-BYR_5K2c.js} +1 -1
  94. package/dist/dashboard/assets/select-BYR_5K2c.js.gz +0 -0
  95. package/dist/dashboard/assets/{settings-C_zKl1GS.js → settings-DNX9sydi.js} +1 -1
  96. package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
  97. package/dist/dashboard/assets/{stack-_3O0F8Xn.js → stack-BHTfXdz_.js} +1 -1
  98. package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
  99. package/dist/dashboard/assets/{state-BgTxHcJS.js → state-mPDRlQkl.js} +1 -1
  100. package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
  101. package/dist/dashboard/assets/{switch-DEjTtOWf.js → switch-DOmJxg7H.js} +1 -1
  102. package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
  103. package/dist/dashboard/assets/tokens-COzario9.js +1 -0
  104. package/dist/dashboard/assets/tokens-COzario9.js.gz +0 -0
  105. package/dist/dashboard/assets/use-modal-focus-By7oJoGd.js +1 -0
  106. package/dist/dashboard/assets/use-modal-focus-By7oJoGd.js.gz +0 -0
  107. package/dist/dashboard/assets/{useMutation-BWSC0UAS.js → useMutation-Dem0lXQj.js} +1 -1
  108. package/dist/dashboard/assets/useMutation-Dem0lXQj.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 +54 -54
  112. package/migrations/README.md +52 -52
  113. package/migrations/lite-sqlite3/0000_baseline.sql +2 -2
  114. package/package.json +96 -95
  115. package/scripts/cli/admin.ts +125 -0
  116. package/scripts/cli/{ui/background.ts → background.ts} +1 -1
  117. package/scripts/cli/{command/console-menu.ts → console-menu.ts} +275 -244
  118. package/scripts/cli/doctor.ts +37 -0
  119. package/scripts/cli/{support/env.ts → env.ts} +99 -99
  120. package/scripts/cli/{gateway/spawn.ts → gateway.ts} +112 -24
  121. package/scripts/cli/instance.ts +224 -0
  122. package/scripts/cli/main.ts +61 -18
  123. package/scripts/cli/{support/platform.ts → platform.ts} +64 -64
  124. package/scripts/cli/port.ts +100 -0
  125. package/scripts/cli/{support/services.ts → services.ts} +88 -88
  126. package/scripts/cli/{command/setup.ts → setup.ts} +35 -34
  127. package/scripts/cli/{command/start.ts → start.ts} +10 -5
  128. package/scripts/cli/{support/startup-signal.ts → startup-signal.ts} +23 -23
  129. package/scripts/cli/tray/index.ts +62 -12
  130. package/scripts/cli/{command/tray.ts → tray.ts} +208 -208
  131. package/scripts/cli/{command/update.ts → update.ts} +39 -39
  132. package/scripts/cli/version.ts +67 -0
  133. package/scripts/cli/{ui/wordmark.ts → wordmark.ts} +58 -58
  134. package/src/boot/app.ts +697 -693
  135. package/src/boot/dependencies.ts +647 -646
  136. package/src/boot/timeout.ts +2 -13
  137. package/src/config/cooldowns.ts +186 -138
  138. package/src/config/network.ts +8 -14
  139. package/src/config/providers.ts +7 -10
  140. package/src/config/runtime.ts +76 -76
  141. package/src/config/security.ts +15 -0
  142. package/src/config/spec.ts +20 -30
  143. package/src/config/telemetry.ts +0 -20
  144. package/src/config/timeouts.ts +0 -6
  145. package/src/console/admin/model-abuse/contracts.ts +28 -6
  146. package/src/console/admin/model-abuse/routes.ts +56 -3
  147. package/src/console/api-keys/contracts.ts +410 -414
  148. package/src/console/api-keys/routes.ts +881 -880
  149. package/src/console/auth/credentials.ts +3 -3
  150. package/src/console/auth/setup-service.ts +2 -2
  151. package/src/console/backup/export-endpoint.ts +6 -2
  152. package/src/console/backup/nine-router.ts +2 -5
  153. package/src/console/backup/service.ts +4 -0
  154. package/src/console/backup/store.ts +192 -29
  155. package/src/console/backup/validate.ts +3 -45
  156. package/src/console/cli-tools/fs-ops.ts +487 -487
  157. package/src/console/console-router-guards.ts +1 -1
  158. package/src/console/data-management/contracts.ts +13 -6
  159. package/src/console/data-management/operations.ts +23 -18
  160. package/src/console/data-management/routes.ts +0 -1
  161. package/src/console/domain-registration.ts +10 -5
  162. package/src/console/observability/live.ts +22 -0
  163. package/src/console/observability/store.ts +39 -16
  164. package/src/console/observability/usage-dimensions.ts +4 -4
  165. package/src/console/providers/catalog/catalog-projections.ts +6 -7
  166. package/src/console/providers/catalog/model-operations.ts +5 -2
  167. package/src/console/providers/catalog/provider-operations.ts +4 -4
  168. package/src/console/providers/catalog/public-model-store.ts +8 -11
  169. package/src/console/providers/catalog/store.ts +1553 -1553
  170. package/src/console/providers/oauth/routes.ts +8 -12
  171. package/src/console/quota/account-quota-tenant.ts +6 -6
  172. package/src/console/quota/quota-view.ts +1 -1
  173. package/src/console/remote-support/contracts.ts +61 -0
  174. package/src/console/remote-support/routes.ts +65 -0
  175. package/src/console/remote-support/service.ts +207 -0
  176. package/src/console/response-compression.ts +0 -3
  177. package/src/console/routing/pools/probe-result.ts +3 -2
  178. package/src/console/routing/pools/probe-verdict.ts +132 -132
  179. package/src/console/routing/pools/store.ts +8 -8
  180. package/src/console/settings/contracts.ts +58 -2
  181. package/src/console/settings/store.ts +30 -3
  182. package/src/console/shared/cursor.ts +8 -8
  183. package/src/console/shared/errors.ts +1 -3
  184. package/src/network/http2-bidi.ts +2 -4
  185. package/src/network/pool/agent.ts +478 -478
  186. package/src/network/pool/selector.ts +5 -4
  187. package/src/network/retry.ts +1 -2
  188. package/src/network/ssrf.ts +5 -4
  189. package/src/observability/event-compaction.ts +80 -78
  190. package/src/observability/event-day-index.ts +13 -15
  191. package/src/observability/event-log.ts +4 -4
  192. package/src/observability/logger.ts +6 -6
  193. package/src/observability/payload-capture.ts +151 -33
  194. package/src/observability/payload-store.ts +397 -440
  195. package/src/observability/redaction.ts +5 -6
  196. package/src/observability/request-notify.ts +43 -0
  197. package/src/observability/telemetry-status.ts +8 -9
  198. package/src/observability/token-speed.ts +5 -4
  199. package/src/persistence/db-mode.ts +7 -7
  200. package/src/persistence/readiness.ts +1 -1
  201. package/src/persistence/schema.ts +1406 -1402
  202. package/src/persistence/shared-cache.ts +1 -2
  203. package/src/persistence/stores/api-key-store.ts +18 -6
  204. package/src/persistence/stores/share-store.ts +4 -3
  205. package/src/persistence/stores/telemetry-store.ts +236 -237
  206. package/src/protocol/canonical-model.ts +11 -3
  207. package/src/protocol/codecs.ts +138 -4
  208. package/src/protocol/gateway-error.ts +6 -4
  209. package/src/protocol/request/chat.ts +21 -1
  210. package/src/protocol/request/codex.ts +10 -1
  211. package/src/protocol/request/messages.ts +4 -5
  212. package/src/protocol/request/responses.ts +9 -1
  213. package/src/protocol/response/chat.ts +34 -4
  214. package/src/protocol/response/codex.ts +7 -4
  215. package/src/protocol/response/dsml.ts +140 -28
  216. package/src/protocol/response/responses.ts +11 -5
  217. package/src/protocol/stream-error-frames.ts +4 -5
  218. package/src/providers/authentication/jwt-validator.ts +9 -10
  219. package/src/providers/authentication/oauth-refresh-service.ts +9 -11
  220. package/src/providers/configured-openai-providers.ts +134 -136
  221. package/src/providers/discovery/catalog/catalog-blob.ts +18 -18
  222. package/src/providers/discovery/catalog/catalog-format.ts +3 -6
  223. package/src/providers/discovery/models-dev-catalog.ts +354 -354
  224. package/src/providers/discovery/probe-phases.ts +4 -4
  225. package/src/providers/discovery/probe-wire.ts +6 -13
  226. package/src/providers/discovery/probing-service.ts +1117 -1045
  227. package/src/providers/integrations/alibabacp/alibabacp.ts +1 -1
  228. package/src/providers/integrations/antigravity/antigravity-quota.ts +5 -7
  229. package/src/providers/integrations/buddy/buddy-chat-shared.ts +23 -2
  230. package/src/providers/integrations/buddy/buddy-checkin.ts +1 -4
  231. package/src/providers/integrations/buddy/buddy-cli-headers.ts +23 -6
  232. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -1
  233. package/src/providers/integrations/buddy/buddy-identity.ts +52 -0
  234. package/src/providers/integrations/buddy/buddy-media.ts +2 -2
  235. package/src/providers/integrations/buddy/buddy-usage-store.ts +3 -4
  236. package/src/providers/integrations/buddy/codebuddy/quota.ts +2 -13
  237. package/src/providers/integrations/buddy/codebuddy/shared.ts +118 -115
  238. package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -11
  239. package/src/providers/integrations/buddy/workbuddy/shared.ts +5 -2
  240. package/src/providers/integrations/claude/claude.ts +608 -608
  241. package/src/providers/integrations/cline/cline-quota.ts +132 -132
  242. package/src/providers/integrations/cline/cline.ts +537 -539
  243. package/src/providers/integrations/codex/codex-oauth.ts +1 -1
  244. package/src/providers/integrations/commandcode/commandcode.ts +674 -675
  245. package/src/providers/integrations/commandcode/discovery.ts +117 -116
  246. package/src/providers/integrations/cursor/cursor-auth.ts +418 -418
  247. package/src/providers/integrations/cursor/cursor-quota.ts +309 -310
  248. package/src/providers/integrations/cursor/cursor.ts +11 -163
  249. package/src/providers/integrations/factory/factory-models.ts +3 -5
  250. package/src/providers/integrations/grok/grok-install-id.ts +2 -3
  251. package/src/providers/integrations/grok/grok.ts +6 -7
  252. package/src/providers/integrations/hermes.ts +14 -18
  253. package/src/providers/integrations/kiro/kiro-discovery.ts +1 -1
  254. package/src/providers/integrations/kiro/kiro.ts +1 -1
  255. package/src/providers/integrations/mistral.ts +6 -6
  256. package/src/providers/integrations/opencode/fingerprint.ts +3 -3
  257. package/src/providers/integrations/opencode/provider.ts +8 -8
  258. package/src/providers/integrations/qoder/qoder-catalog.ts +450 -450
  259. package/src/providers/integrations/qoder/qoder-oauth.ts +388 -310
  260. package/src/providers/integrations/qoder/qoder.ts +884 -865
  261. package/src/providers/integrations/shared/connect.ts +6 -6
  262. package/src/providers/integrations/trae/trae-catalog.ts +1 -2
  263. package/src/providers/integrations/trae/trae.ts +2 -2
  264. package/src/providers/integrations/zcode/oauth.ts +6 -1
  265. package/src/providers/operations/account-health-service.ts +1528 -1523
  266. package/src/providers/operations/account-reset-service.ts +1 -1
  267. package/src/providers/operations/client-versions.ts +6 -6
  268. package/src/providers/operations/custom-cli-headers.ts +3 -4
  269. package/src/providers/operations/provider-catalog-seeder.ts +95 -95
  270. package/src/providers/operations/provider-catalog-service.ts +3 -4
  271. package/src/providers/provider-metadata.ts +4 -8
  272. package/src/providers/provider-registry.ts +6 -7
  273. package/src/providers/provider-usage.ts +1 -1
  274. package/src/security/abuse.ts +15 -10
  275. package/src/security/access-control.ts +144 -146
  276. package/src/security/admission/contracts.ts +11 -0
  277. package/src/security/admission/in-memory-store.ts +4 -3
  278. package/src/security/admission/lease-sweep.ts +6 -6
  279. package/src/security/admission/reasons.ts +5 -1
  280. package/src/security/admission/redis-store.ts +211 -210
  281. package/src/security/admission/service.ts +4 -0
  282. package/src/security/api-key-auth.ts +504 -504
  283. package/src/security/ip-boundary.ts +155 -15
  284. package/src/security/model-abuse.ts +366 -94
  285. package/src/security/outbound-headers.ts +3 -4
  286. package/src/shared/sleep.ts +4 -0
  287. package/src/transport/dispatch/attempt-finalize.ts +47 -5
  288. package/src/transport/dispatch/attempt-loop.ts +531 -530
  289. package/src/transport/dispatch/stream-bridge.ts +1 -3
  290. package/src/transport/dispatch/streaming/finalize.ts +1 -1
  291. package/src/transport/dispatch/streaming/stream.ts +5 -6
  292. package/src/transport/failure-policy.ts +162 -8
  293. package/src/transport/guards/auth-guard.ts +7 -4
  294. package/src/transport/guards/concurrency-guard.ts +0 -5
  295. package/src/transport/guards/error-lifecycle.ts +13 -6
  296. package/src/transport/guards/pipeline.ts +15 -3
  297. package/src/transport/guards/request-context.ts +8 -2
  298. package/src/transport/request/inflight.ts +5 -6
  299. package/src/transport/request/preparer.ts +2 -2
  300. package/src/transport/request/state.ts +12 -8
  301. package/src/transport/routing/admission.ts +4 -0
  302. package/src/transport/routing/route-catalog.ts +8 -1
  303. package/src/transport/routing/route-model.ts +46 -14
  304. package/src/transport/routing/router.ts +21 -14
  305. package/src/transport/surface/completion.ts +2 -3
  306. package/src/transport/surface/dialects.ts +5 -6
  307. package/src/transport/surface/responses/encode.ts +38 -0
  308. package/src/transport/surface/responses/parse.ts +4 -0
  309. package/src/transport/translation/capabilities.ts +2 -3
  310. package/src/transport/translation/quirks.ts +3 -3
  311. package/src/workers/buddy-growth-tasks.ts +5 -10
  312. package/src/workers/daily-checkin.ts +17 -23
  313. package/src/workers/quota-refresh-sweep.ts +26 -26
  314. package/dist/dashboard/assets/BannedPage-C2orBsI2.js.gz +0 -0
  315. package/dist/dashboard/assets/CliToolDetailPage-DUcZ6pMB.js +0 -1
  316. package/dist/dashboard/assets/CliToolDetailPage-DUcZ6pMB.js.gz +0 -0
  317. package/dist/dashboard/assets/CliToolsPage-BV6pxVQo.js.gz +0 -0
  318. package/dist/dashboard/assets/CombosPage-Bsan4679.js +0 -1
  319. package/dist/dashboard/assets/CombosPage-Bsan4679.js.gz +0 -0
  320. package/dist/dashboard/assets/ConsoleLogPage-CW-wPmJ6.js.gz +0 -0
  321. package/dist/dashboard/assets/CustomizationPage-0p8uX7vB.js.gz +0 -0
  322. package/dist/dashboard/assets/HealthEventsModal-BjqSMfko.js.gz +0 -0
  323. package/dist/dashboard/assets/LoginPage-BvzCx8Kr.js.gz +0 -0
  324. package/dist/dashboard/assets/ModelPicker-BY1aKEkP.js +0 -1
  325. package/dist/dashboard/assets/ModelPicker-BY1aKEkP.js.gz +0 -0
  326. package/dist/dashboard/assets/OverviewPage-DOQpy1y0.js +0 -1
  327. package/dist/dashboard/assets/OverviewPage-DOQpy1y0.js.gz +0 -0
  328. package/dist/dashboard/assets/ProviderDetailPage-ecxyUMzt.js +0 -3
  329. package/dist/dashboard/assets/ProviderDetailPage-ecxyUMzt.js.gz +0 -0
  330. package/dist/dashboard/assets/ProvidersPage-Js9jUPSb.js.gz +0 -0
  331. package/dist/dashboard/assets/ProxyPage-J3TBi3Kx.js +0 -7
  332. package/dist/dashboard/assets/ProxyPage-J3TBi3Kx.js.gz +0 -0
  333. package/dist/dashboard/assets/QuotaPage-C1gZS6xr.js +0 -1
  334. package/dist/dashboard/assets/QuotaPage-C1gZS6xr.js.gz +0 -0
  335. package/dist/dashboard/assets/SettingsPage-CS86ho5X.js +0 -1
  336. package/dist/dashboard/assets/SettingsPage-CS86ho5X.js.gz +0 -0
  337. package/dist/dashboard/assets/SetupPage-DDbMQsoo.js.gz +0 -0
  338. package/dist/dashboard/assets/SortableList-CB3Z7VTf.js.gz +0 -0
  339. package/dist/dashboard/assets/StudioPage-D95UCPHI.js.gz +0 -0
  340. package/dist/dashboard/assets/UsagePage-Cnae9SWA.js +0 -56
  341. package/dist/dashboard/assets/UsagePage-Cnae9SWA.js.gz +0 -0
  342. package/dist/dashboard/assets/api-keys-VY68Mhd1.js +0 -1
  343. package/dist/dashboard/assets/api-keys-VY68Mhd1.js.gz +0 -0
  344. package/dist/dashboard/assets/app-COlK95oi.css +0 -2
  345. package/dist/dashboard/assets/app-COlK95oi.css.gz +0 -0
  346. package/dist/dashboard/assets/assert-Chi7pCnt.js.gz +0 -0
  347. package/dist/dashboard/assets/badge-D4pQapKj.js.gz +0 -0
  348. package/dist/dashboard/assets/banner-DH6cg-_B.js.gz +0 -0
  349. package/dist/dashboard/assets/card-BKqlUOe4.js.gz +0 -0
  350. package/dist/dashboard/assets/cli-tools-fTgljTGA.js.gz +0 -0
  351. package/dist/dashboard/assets/clipboard-button-D5Ys_sM0.js.gz +0 -0
  352. package/dist/dashboard/assets/dialog-BYj-8WuK.js +0 -1
  353. package/dist/dashboard/assets/dialog-BYj-8WuK.js.gz +0 -0
  354. package/dist/dashboard/assets/drawer-CmXIZ6H1.js +0 -1
  355. package/dist/dashboard/assets/drawer-CmXIZ6H1.js.gz +0 -0
  356. package/dist/dashboard/assets/entry-CBg5zeu8.js +0 -1
  357. package/dist/dashboard/assets/entry-CBg5zeu8.js.gz +0 -0
  358. package/dist/dashboard/assets/entry-CQBr6U9c.js.gz +0 -0
  359. package/dist/dashboard/assets/entry-CgdSAzEV.js +0 -4
  360. package/dist/dashboard/assets/entry-CgdSAzEV.js.gz +0 -0
  361. package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
  362. package/dist/dashboard/assets/github-badge-BlptL8Uf.js.gz +0 -0
  363. package/dist/dashboard/assets/index-js6TJvdr.js.gz +0 -0
  364. package/dist/dashboard/assets/inline-DUWDSmDV.js.gz +0 -0
  365. package/dist/dashboard/assets/input-LVjgZq4f.js.gz +0 -0
  366. package/dist/dashboard/assets/layout-CPfxpsfy.js +0 -1
  367. package/dist/dashboard/assets/layout-CPfxpsfy.js.gz +0 -0
  368. package/dist/dashboard/assets/list-row-DupvLfDx.js.gz +0 -0
  369. package/dist/dashboard/assets/live-C4pEJUqI.js.gz +0 -0
  370. package/dist/dashboard/assets/model-bans-BRiuufkB.js.gz +0 -0
  371. package/dist/dashboard/assets/mutation-B4ROwk8L.js.gz +0 -0
  372. package/dist/dashboard/assets/numbers-YNcHvRY7.js +0 -2
  373. package/dist/dashboard/assets/numbers-YNcHvRY7.js.gz +0 -0
  374. package/dist/dashboard/assets/query-keys-gmjzC3RS.js.gz +0 -0
  375. package/dist/dashboard/assets/routing-C7tBT5o-.js.gz +0 -0
  376. package/dist/dashboard/assets/select-WUCXorXw.js.gz +0 -0
  377. package/dist/dashboard/assets/settings-C_zKl1GS.js.gz +0 -0
  378. package/dist/dashboard/assets/stack-_3O0F8Xn.js.gz +0 -0
  379. package/dist/dashboard/assets/state-BgTxHcJS.js.gz +0 -0
  380. package/dist/dashboard/assets/switch-DEjTtOWf.js.gz +0 -0
  381. package/dist/dashboard/assets/tokens-DDxMbSRL.js +0 -1
  382. package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
  383. package/dist/dashboard/assets/use-presence-BSZEBx7U.js +0 -1
  384. package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
  385. package/dist/dashboard/assets/useMutation-BWSC0UAS.js.gz +0 -0
  386. package/scripts/cli/command/admin.ts +0 -65
  387. package/scripts/cli/command/doctor.ts +0 -257
  388. package/scripts/cli/gateway/drain-token.ts +0 -78
  389. package/scripts/cli/gateway/instance-lock.ts +0 -105
  390. package/scripts/cli/gateway/stop.ts +0 -51
  391. package/scripts/cli/support/bun.ts +0 -27
  392. package/scripts/cli/support/version.ts +0 -37
  393. /package/dist/dashboard/assets/{app-DCQZRmHY.js → app-BIt446yE.js} +0 -0
  394. /package/dist/dashboard/assets/{app-DCQZRmHY.js.gz → app-BIt446yE.js.gz} +0 -0
  395. /package/scripts/cli/{ui/prompt.ts → prompt.ts} +0 -0
@@ -1,146 +1,144 @@
1
- // Shared authorization primitives: closed scope model and immutable access decisions.
2
-
3
- /**
4
- * Closed set of authorization scopes.
5
- * - `routing:invoke`: May call only /v1/* gateway routes within holder's tenant.
6
- * - `routing:cli_mapping`: May use persisted CLI source→target model mappings.
7
- * - `dashboard:read`: Reads only holder's tenant configuration and usage.
8
- * - `dashboard:write`: Modifies only holder's tenant configuration.
9
- * - `providers:read` / `providers:write`: Reads or modifies provider rows —
10
- * including registering a BYOK upstream and its credential.
11
- * - `models:read` / `models:write`: Reads or modifies catalog model rows.
12
- * - `platform:admin`: Cross-tenant operator actions (account health, kill-switch, catalog sync).
13
- *
14
- * Catalog mutation is deliberately separate from `dashboard:write`. A key
15
- * minted to read usage, or to change a display setting, must not thereby be
16
- * able to add an upstream or delete a model: those writes change where traffic
17
- * is sent and which credentials are used, so they are granted explicitly.
18
- */
19
- export type AccessScope =
20
- | "routing:invoke"
21
- | "routing:cli_mapping"
22
- | "search:invoke"
23
- | "dashboard:read"
24
- | "dashboard:write"
25
- | "providers:read"
26
- | "providers:write"
27
- | "models:read"
28
- | "models:write"
29
- | "platform:admin";
30
-
31
- /** Scopes a tenant API key may hold; `platform:admin` is never assignable. */
32
- export type TenantScope = Exclude<AccessScope, "platform:admin">;
33
-
34
- /**
35
- * The scopes a signed-in console session holds, per principal kind.
36
- *
37
- * Stated here rather than inline at the session resolver so the dashboard's
38
- * authority has one home, and so the catalog scopes are granted by name.
39
- *
40
- * They must be granted by name because `dashboard:write` deliberately does not
41
- * imply them: a tenant API key can hold `dashboard:write`, and such a key must
42
- * not be able to add an upstream or delete a model. The session is the operator
43
- * and needs the catalog routes to work, so it holds the catalog scopes
44
- * explicitly instead — which keeps the separation honest without narrowing the
45
- * dashboard.
46
- *
47
- * A regular console user reads their tenant's configuration and catalog but
48
- * writes nothing; that read-only ceiling is the pre-existing behaviour and is
49
- * preserved exactly, just spelled with the catalog read scopes the routes now
50
- * require.
51
- */
52
- export function consoleSessionScopes(isPlatformAdmin: boolean): readonly AccessScope[] {
53
- if (isPlatformAdmin) {
54
- return [
55
- "dashboard:read",
56
- "dashboard:write",
57
- "providers:read",
58
- "providers:write",
59
- "models:read",
60
- "models:write",
61
- "platform:admin",
62
- ];
63
- }
64
- return ["dashboard:read", "providers:read", "models:read"];
65
- }
66
-
67
- /**
68
- * Immutable authorization decision snapshot.
69
- * Contains the principal identity, tenant binding, and scopes.
70
- * Created at authentication boundary and passed unchanged through routing and provider dispatch.
71
- *
72
- * `tenantId` is null for platform:admin cross-tenant operator sessions.
73
- */
74
- export interface AccessDecision {
75
- readonly id: string;
76
- readonly tenantId: string | null;
77
- /** Scopes present on this key/user. */
78
- readonly scopes: readonly AccessScope[];
79
- /** Identity recorded for audit attribution; defaults to `id` if absent. */
80
- readonly admissionIdentity: string;
81
- }
82
-
83
- /**
84
- * Every scope a tenant API key may be granted, in display order.
85
- *
86
- * The single source of truth for what the API-key editor offers: the predicate
87
- * below is derived from it, and the dashboard renders it directly. Keeping the
88
- * two in step by hand is how the editor came to offer only the four
89
- * routing/dashboard scopes while the backend accepted eight — a `providers:write`
90
- * key could be created through the API but not through the UI.
91
- *
92
- * `platform:admin` is deliberately absent: it is a console-session scope for
93
- * cross-tenant operator actions and is never assignable to a tenant key.
94
- */
95
- export const TENANT_KEY_SCOPES = [
96
- "routing:invoke",
97
- "routing:cli_mapping",
98
- "search:invoke",
99
- "dashboard:read",
100
- "dashboard:write",
101
- "providers:read",
102
- "providers:write",
103
- "models:read",
104
- "models:write",
105
- ] as const satisfies readonly TenantScope[];
106
- /**
107
- * Determine if a scope is valid for a tenant API key.
108
- *
109
- * Tenant keys default to routing:invoke only.
110
- * platform:admin is never assignable to tenant keys.
111
- */
112
- export const isValidTenantKeyScope = (scope: AccessScope): scope is TenantScope =>
113
- (TENANT_KEY_SCOPES as readonly AccessScope[]).includes(scope);
114
-
115
- /**
116
- * Create an immutable frozen AccessDecision.
117
- * Default tenant keys to routing:invoke scope if scopes are empty.
118
- */
119
- export function createAccessDecision(input: {
120
- readonly id: string;
121
- readonly tenantId: string | null;
122
- readonly scopes: readonly AccessScope[];
123
- readonly admissionIdentity?: string;
124
- }): AccessDecision {
125
- // What was persisted is what the key holds. `search:invoke` used to be
126
- // re-granted here to any key holding `routing:invoke`, so unchecking the
127
- // scope in the console saved a revocation that vanished on the next read.
128
- // Migration 0040 wrote the grant onto the rows that were receiving it, so
129
- // the stored array is now the whole truth.
130
- const scopes =
131
- input.scopes.length === 0 && input.tenantId !== null
132
- ? (["routing:invoke"] as readonly AccessScope[])
133
- : (Array.from(input.scopes) as readonly AccessScope[]);
134
- const decision: AccessDecision = {
135
- id: input.id,
136
- tenantId: input.tenantId,
137
- scopes,
138
- admissionIdentity: input.admissionIdentity ?? input.id,
139
- };
140
-
141
- // Deep freeze the decision
142
- return Object.freeze({
143
- ...decision,
144
- scopes: Object.freeze([...decision.scopes]),
145
- });
146
- }
1
+ // Shared authorization primitives: closed scope model and immutable access decisions.
2
+
3
+ /**
4
+ * Closed set of authorization scopes.
5
+ * - `routing:invoke`: May call only /v1/* gateway routes within holder's tenant.
6
+ * - `routing:cli_mapping`: May use persisted CLI source→target model mappings.
7
+ * - `dashboard:read`: Reads only holder's tenant configuration and usage.
8
+ * - `dashboard:write`: Modifies only holder's tenant configuration.
9
+ * - `providers:read` / `providers:write`: Reads or modifies provider rows —
10
+ * including registering a BYOK upstream and its credential.
11
+ * - `models:read` / `models:write`: Reads or modifies catalog model rows.
12
+ * - `platform:admin`: Cross-tenant operator actions (account health, kill-switch, catalog sync).
13
+ *
14
+ * Catalog mutation is deliberately separate from `dashboard:write`. A key
15
+ * minted to read usage, or to change a display setting, must not thereby be
16
+ * able to add an upstream or delete a model: those writes change where traffic
17
+ * is sent and which credentials are used, so they are granted explicitly.
18
+ */
19
+ export type AccessScope =
20
+ | "routing:invoke"
21
+ | "routing:cli_mapping"
22
+ | "search:invoke"
23
+ | "dashboard:read"
24
+ | "dashboard:write"
25
+ | "providers:read"
26
+ | "providers:write"
27
+ | "models:read"
28
+ | "models:write"
29
+ | "platform:admin";
30
+
31
+ /** Scopes a tenant API key may hold; `platform:admin` is never assignable. */
32
+ export type TenantScope = Exclude<AccessScope, "platform:admin">;
33
+
34
+ /**
35
+ * The scopes a signed-in console session holds, per principal kind.
36
+ *
37
+ * Stated here rather than inline at the session resolver so the dashboard's
38
+ * authority has one home, and so the catalog scopes are granted by name.
39
+ *
40
+ * They must be granted by name because `dashboard:write` deliberately does not
41
+ * imply them: a tenant API key can hold `dashboard:write`, and such a key must
42
+ * not be able to add an upstream or delete a model. The session is the operator
43
+ * and needs the catalog routes to work, so it holds the catalog scopes
44
+ * explicitly instead — which keeps the separation honest without narrowing the
45
+ * dashboard.
46
+ *
47
+ * A regular console user reads their tenant's configuration and catalog but
48
+ * writes nothing; that read-only ceiling is the pre-existing behaviour and is
49
+ * preserved exactly, just spelled with the catalog read scopes the routes now
50
+ * require.
51
+ */
52
+ export function consoleSessionScopes(isPlatformAdmin: boolean): readonly AccessScope[] {
53
+ if (isPlatformAdmin) {
54
+ return [
55
+ "dashboard:read",
56
+ "dashboard:write",
57
+ "providers:read",
58
+ "providers:write",
59
+ "models:read",
60
+ "models:write",
61
+ "platform:admin",
62
+ ];
63
+ }
64
+ return ["dashboard:read", "providers:read", "models:read"];
65
+ }
66
+
67
+ /**
68
+ * Immutable authorization decision snapshot.
69
+ * Contains the principal identity, tenant binding, and scopes.
70
+ * Created at authentication boundary and passed unchanged through routing and provider dispatch.
71
+ *
72
+ * `tenantId` is null for platform:admin cross-tenant operator sessions.
73
+ */
74
+ export interface AccessDecision {
75
+ readonly id: string;
76
+ readonly tenantId: string | null;
77
+ /** Scopes present on this key/user. */
78
+ readonly scopes: readonly AccessScope[];
79
+ /** Identity recorded for audit attribution; defaults to `id` if absent. */
80
+ readonly admissionIdentity: string;
81
+ }
82
+
83
+ /**
84
+ * Every scope a tenant API key may be granted, in display order.
85
+ *
86
+ * The single source of truth for what the API-key editor offers: the predicate
87
+ * below is derived from it, and the dashboard renders it directly. Keeping the
88
+ * two in step by hand is how the editor came to offer only the four
89
+ * routing/dashboard scopes while the backend accepted eight — a `providers:write`
90
+ * key could be created through the API but not through the UI.
91
+ *
92
+ * `platform:admin` is deliberately absent: it is a console-session scope for
93
+ * cross-tenant operator actions and is never assignable to a tenant key.
94
+ */
95
+ export const TENANT_KEY_SCOPES = [
96
+ "routing:invoke",
97
+ "routing:cli_mapping",
98
+ "search:invoke",
99
+ "dashboard:read",
100
+ "dashboard:write",
101
+ "providers:read",
102
+ "providers:write",
103
+ "models:read",
104
+ "models:write",
105
+ ] as const satisfies readonly TenantScope[];
106
+ /**
107
+ * Determine if a scope is valid for a tenant API key.
108
+ *
109
+ * Tenant keys default to routing:invoke only.
110
+ * platform:admin is never assignable to tenant keys.
111
+ */
112
+ export const isValidTenantKeyScope = (scope: AccessScope): scope is TenantScope =>
113
+ (TENANT_KEY_SCOPES as readonly AccessScope[]).includes(scope);
114
+
115
+ /**
116
+ * Create an immutable frozen AccessDecision.
117
+ * Default tenant keys to routing:invoke scope if scopes are empty.
118
+ */
119
+ export function createAccessDecision(input: {
120
+ readonly id: string;
121
+ readonly tenantId: string | null;
122
+ readonly scopes: readonly AccessScope[];
123
+ readonly admissionIdentity?: string;
124
+ }): AccessDecision {
125
+ // What was persisted is what the key holds: no scope is re-granted here, so
126
+ // unchecking a scope in the console saves a revocation that survives the next
127
+ // read. The stored array is the whole truth.
128
+ const scopes =
129
+ input.scopes.length === 0 && input.tenantId !== null
130
+ ? (["routing:invoke"] as readonly AccessScope[])
131
+ : (Array.from(input.scopes) as readonly AccessScope[]);
132
+ const decision: AccessDecision = {
133
+ id: input.id,
134
+ tenantId: input.tenantId,
135
+ scopes,
136
+ admissionIdentity: input.admissionIdentity ?? input.id,
137
+ };
138
+
139
+ // Deep freeze the decision
140
+ return Object.freeze({
141
+ ...decision,
142
+ scopes: Object.freeze([...decision.scopes]),
143
+ });
144
+ }
@@ -25,6 +25,17 @@ export interface ApiKeyAdmissionRequest {
25
25
  export interface AdmissionReserveRequest {
26
26
  readonly reservationId: string;
27
27
  readonly apiKeyId: string;
28
+ /**
29
+ * The key whose rpm and concurrency counters are charged.
30
+ *
31
+ * Share child keys set this to their own id so each child has an independent
32
+ * rpm window and concurrency slot. Token budgets (daily / monthly / lifetime)
33
+ * are still charged to `apiKeyId` — the parent — so the shared pool is
34
+ * enforced globally across all children.
35
+ *
36
+ * Defaults to `apiKeyId` when absent (non-share keys, backward compat).
37
+ */
38
+ readonly rpmConcurrencyKeyId?: string;
28
39
  readonly now: number;
29
40
  readonly estimatedTokens: number;
30
41
  readonly rpmLimit: number | null;
@@ -94,12 +94,13 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
94
94
  ) {
95
95
  throw reasonToGatewayError("admission-unavailable", { reason: "invalid_counter" });
96
96
  }
97
- const rpm = this.pruneRpm(request.apiKeyId, request.now);
97
+ const rpmConcId = request.rpmConcurrencyKeyId ?? request.apiKeyId;
98
+ const rpm = this.pruneRpm(rpmConcId, request.now);
98
99
  const dailyKey = bucketKey(request.apiKeyId, dailyBucket(request.now));
99
100
  const monthlyKey = bucketKey(request.apiKeyId, monthlyBucket(request.now));
100
101
  const daily = this.value(this.daily, dailyKey);
101
102
  const monthly = this.value(this.monthly, monthlyKey);
102
- const concurrent = this.value(this.concurrent, request.apiKeyId);
103
+ const concurrent = this.value(this.concurrent, rpmConcId);
103
104
  const tenantConcurrent = this.value(this.tenantConcurrent, request.tenantId);
104
105
  // A missing counter is the only path that seeds from the snapshot; on
105
106
  // that path prefer a fresh persisted read over the ≤3s-stale snapshot,
@@ -165,7 +166,7 @@ export class InMemoryAdmissionCounterStore implements AdmissionCounterStore {
165
166
  this.evictCounter(this.lifetime);
166
167
  }
167
168
  if (request.concurrencyLimit != null) {
168
- this.concurrent.set(request.apiKeyId, concurrent + 1);
169
+ this.concurrent.set(rpmConcId, concurrent + 1);
169
170
  this.evictCounter(this.concurrent);
170
171
  }
171
172
  if (request.tenantConcurrencyLimit != null) {
@@ -14,12 +14,12 @@ const ADMISSION_LEASE_PATTERN = "admission:lease:*";
14
14
  /**
15
15
  * Bounds for one pass.
16
16
  *
17
- * The scan walks the whole keyspace and the loop used to follow the cursor
18
- * until it wrapped, reaping every expired lease it found. On a keyspace that
19
- * has grown for months that is one pass with no ceiling: it holds the timer
20
- * slot for as long as the backlog takes and starves every other sweep. A
21
- * backlog drains over successive passes instead; leases the cap leaves behind
22
- * are still expired on the next tick.
17
+ * The scan walks the whole keyspace, so following the cursor until it wraps and
18
+ * reaping every expired lease it finds is one pass with no ceiling on a
19
+ * keyspace that has grown for months: it would hold the timer slot for as long
20
+ * as the backlog takes and starve every other sweep. A backlog drains over
21
+ * successive passes instead; leases the cap leaves behind are still expired on
22
+ * the next tick.
23
23
  */
24
24
  export const MAX_LEASE_SCAN_ITERATIONS = 50;
25
25
  export const MAX_LEASE_REAPS_PER_PASS = 500;
@@ -43,7 +43,11 @@ const REASON_META: Record<
43
43
  metricLabel: "lifetime",
44
44
  },
45
45
  "concurrency-limit": {
46
- message: "This model is already serving its maximum number of concurrent requests. Retry shortly, or raise the provider's max-inflight.",
46
+ // This ceiling is the API key's own `max_concurrent`, not the provider's
47
+ // max-inflight. The two used to be indistinguishable and both named the
48
+ // provider, sending operators to the wrong setting after a rejection. The
49
+ // `details` carry the limit so a client can tell which one fired.
50
+ message: "This API key is already serving its maximum number of concurrent requests. Retry shortly, or raise the key's concurrency limit.",
47
51
  code: "capacity_exhausted",
48
52
  status: 429,
49
53
  metricLabel: "concurrency",