cartethyia 2.5.3 → 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 (456) hide show
  1. package/.env.example +13 -4
  2. package/README.md +2 -2
  3. package/dist/dashboard/assets/{BannedPage-hfCzi-Ux.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-DEDyKBlC.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-bsLuZmYH.js → ConsoleLogPage-BVdpfiz1.js} +1 -1
  12. package/dist/dashboard/assets/ConsoleLogPage-BVdpfiz1.js.gz +0 -0
  13. package/dist/dashboard/assets/{CustomizationPage-_UWhwziJ.js → CustomizationPage-BR5HHvbi.js} +1 -1
  14. package/dist/dashboard/assets/CustomizationPage-BR5HHvbi.js.gz +0 -0
  15. package/dist/dashboard/assets/HealthEventsModal-mUfcknqm.js +1 -0
  16. package/dist/dashboard/assets/HealthEventsModal-mUfcknqm.js.gz +0 -0
  17. package/dist/dashboard/assets/{LoginPage-DDVIfZGW.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-uPiGVTTK.js +1 -0
  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-D6pmQ86L.js → SetupPage-UB690SE2.js} +1 -1
  34. package/dist/dashboard/assets/SetupPage-UB690SE2.js.gz +0 -0
  35. package/dist/dashboard/assets/{SortableList-DWvKiuSl.js → SortableList-BLujdX7N.js} +1 -1
  36. package/dist/dashboard/assets/SortableList-BLujdX7N.js.gz +0 -0
  37. package/dist/dashboard/assets/{StudioPage-CmkUrgdj.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-NHwYq95t.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-6uzDDvqs.js → badge-CR72dasT.js} +1 -1
  48. package/dist/dashboard/assets/badge-CR72dasT.js.gz +0 -0
  49. package/dist/dashboard/assets/{banner-4_WNg2WZ.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--AtFedAq.js → card-DS7CQEsO.js} +1 -1
  52. package/dist/dashboard/assets/card-DS7CQEsO.js.gz +0 -0
  53. package/dist/dashboard/assets/{cli-tools-B3e7dx3N.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-NreUx6c8.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/database-Dz9N3zGd.js +1 -0
  60. package/dist/dashboard/assets/database-Dz9N3zGd.js.gz +0 -0
  61. package/dist/dashboard/assets/dialog-k37exjNt.js +1 -0
  62. package/dist/dashboard/assets/dialog-k37exjNt.js.gz +0 -0
  63. package/dist/dashboard/assets/drawer-CX7N8ucR.js +1 -0
  64. package/dist/dashboard/assets/drawer-CX7N8ucR.js.gz +0 -0
  65. package/dist/dashboard/assets/entry-B9Xvtnfj.js +1 -0
  66. package/dist/dashboard/assets/entry-B9Xvtnfj.js.gz +0 -0
  67. package/dist/dashboard/assets/entry-CTP8AyiS.js +1 -0
  68. package/dist/dashboard/assets/entry-CTP8AyiS.js.gz +0 -0
  69. package/dist/dashboard/assets/entry-DxBHnauy.js +4 -0
  70. package/dist/dashboard/assets/entry-DxBHnauy.js.gz +0 -0
  71. package/dist/dashboard/assets/{github-badge-D_eM3IgG.js → github-badge-sltk1qUi.js} +1 -1
  72. package/dist/dashboard/assets/github-badge-sltk1qUi.js.gz +0 -0
  73. package/dist/dashboard/assets/{index-BydyKaDz.js → index-CmxZr14F.js} +2 -2
  74. package/dist/dashboard/assets/index-CmxZr14F.js.gz +0 -0
  75. package/dist/dashboard/assets/{inline-BcNGF8Gr.js → inline-BhY2sSnO.js} +1 -1
  76. package/dist/dashboard/assets/inline-BhY2sSnO.js.gz +0 -0
  77. package/dist/dashboard/assets/{input-BG41et9G.js → input-V1umFiBk.js} +1 -1
  78. package/dist/dashboard/assets/input-V1umFiBk.js.gz +0 -0
  79. package/dist/dashboard/assets/layout-BBOYycyS.js +1 -0
  80. package/dist/dashboard/assets/layout-BBOYycyS.js.gz +0 -0
  81. package/dist/dashboard/assets/{list-row-Gh_W4OR_.js → list-row-1zzZYM0B.js} +1 -1
  82. package/dist/dashboard/assets/list-row-1zzZYM0B.js.gz +0 -0
  83. package/dist/dashboard/assets/{live-BJGYRBnR.js → live-BivGfuUs.js} +1 -1
  84. package/dist/dashboard/assets/live-BivGfuUs.js.gz +0 -0
  85. package/dist/dashboard/assets/model-bans-CmffjLuG.js +1 -0
  86. package/dist/dashboard/assets/model-bans-CmffjLuG.js.gz +0 -0
  87. package/dist/dashboard/assets/{mutation-BkoLM5Ba.js → mutation-46P0oWMe.js} +1 -1
  88. package/dist/dashboard/assets/mutation-46P0oWMe.js.gz +0 -0
  89. package/dist/dashboard/assets/numbers-DkfMR5Qs.js +2 -0
  90. package/dist/dashboard/assets/numbers-DkfMR5Qs.js.gz +0 -0
  91. package/dist/dashboard/assets/{query-keys-D7wX2vM5.js → query-keys-BFhGpwR1.js} +1 -1
  92. package/dist/dashboard/assets/query-keys-BFhGpwR1.js.gz +0 -0
  93. package/dist/dashboard/assets/{routing-CcusqXA7.js → routing-CAb4F37R.js} +1 -1
  94. package/dist/dashboard/assets/routing-CAb4F37R.js.gz +0 -0
  95. package/dist/dashboard/assets/{select-BO6h8yNv.js → select-BYR_5K2c.js} +2 -2
  96. package/dist/dashboard/assets/select-BYR_5K2c.js.gz +0 -0
  97. package/dist/dashboard/assets/{settings-mpmXTgUa.js → settings-DNX9sydi.js} +1 -1
  98. package/dist/dashboard/assets/settings-DNX9sydi.js.gz +0 -0
  99. package/dist/dashboard/assets/{stack-DwLmjUFK.js → stack-BHTfXdz_.js} +1 -1
  100. package/dist/dashboard/assets/stack-BHTfXdz_.js.gz +0 -0
  101. package/dist/dashboard/assets/{state-DYdQmdAl.js → state-mPDRlQkl.js} +1 -1
  102. package/dist/dashboard/assets/state-mPDRlQkl.js.gz +0 -0
  103. package/dist/dashboard/assets/switch-DOmJxg7H.js +1 -0
  104. package/dist/dashboard/assets/switch-DOmJxg7H.js.gz +0 -0
  105. package/dist/dashboard/assets/terminal-0_IjPWTk.js +1 -0
  106. package/dist/dashboard/assets/terminal-0_IjPWTk.js.gz +0 -0
  107. package/dist/dashboard/assets/tokens-COzario9.js +1 -0
  108. package/dist/dashboard/assets/tokens-COzario9.js.gz +0 -0
  109. package/dist/dashboard/assets/use-modal-focus-By7oJoGd.js +1 -0
  110. package/dist/dashboard/assets/use-modal-focus-By7oJoGd.js.gz +0 -0
  111. package/dist/dashboard/assets/{useMutation-w4u4CVue.js → useMutation-Dem0lXQj.js} +1 -1
  112. package/dist/dashboard/assets/useMutation-Dem0lXQj.js.gz +0 -0
  113. package/dist/dashboard/assets/zap-C4EeVW4q.js +1 -0
  114. package/dist/dashboard/assets/zap-C4EeVW4q.js.gz +0 -0
  115. package/dist/dashboard/donation/qris-risun-marke.png +0 -0
  116. package/dist/dashboard/index.html +1 -1
  117. package/dist/dashboard/index.html.gz +0 -0
  118. package/dist/dashboard/precompressed-assets.json +57 -57
  119. package/migrations/README.md +52 -52
  120. package/migrations/lite-sqlite3/0000_baseline.sql +2 -2
  121. package/package.json +96 -95
  122. package/scripts/cli/admin.ts +125 -0
  123. package/scripts/cli/autostart.ts +237 -0
  124. package/scripts/cli/{ui/background.ts → background.ts} +1 -1
  125. package/scripts/cli/{command/console-menu.ts → console-menu.ts} +275 -248
  126. package/scripts/cli/doctor.ts +37 -0
  127. package/scripts/cli/{support/env.ts → env.ts} +99 -99
  128. package/scripts/cli/{gateway/spawn.ts → gateway.ts} +112 -24
  129. package/scripts/cli/instance.ts +224 -0
  130. package/scripts/cli/main.ts +88 -18
  131. package/scripts/cli/{support/platform.ts → platform.ts} +64 -64
  132. package/scripts/cli/port.ts +100 -0
  133. package/scripts/cli/{support/services.ts → services.ts} +88 -88
  134. package/scripts/cli/{command/setup.ts → setup.ts} +35 -34
  135. package/scripts/cli/{command/start.ts → start.ts} +10 -5
  136. package/scripts/cli/{support/startup-signal.ts → startup-signal.ts} +23 -23
  137. package/scripts/cli/tray/index.ts +62 -12
  138. package/scripts/cli/{command/tray.ts → tray.ts} +208 -208
  139. package/scripts/cli/update.ts +40 -0
  140. package/scripts/cli/version.ts +67 -0
  141. package/scripts/cli/{ui/wordmark.ts → wordmark.ts} +58 -58
  142. package/src/boot/app.ts +11 -7
  143. package/src/boot/dependencies.ts +50 -19
  144. package/src/boot/timeout.ts +2 -13
  145. package/src/config/cooldowns.ts +186 -138
  146. package/src/config/network.ts +8 -14
  147. package/src/config/providers.ts +7 -10
  148. package/src/config/runtime.ts +76 -76
  149. package/src/config/security.ts +15 -0
  150. package/src/config/spec.ts +52 -7
  151. package/src/config/telemetry.ts +26 -0
  152. package/src/config/timeouts.ts +0 -6
  153. package/src/console/admin/model-abuse/contracts.ts +28 -6
  154. package/src/console/admin/model-abuse/routes.ts +56 -3
  155. package/src/console/api-keys/bucket-spend.ts +15 -4
  156. package/src/console/api-keys/contracts.ts +410 -414
  157. package/src/console/api-keys/routes.ts +881 -880
  158. package/src/console/auth/credentials.ts +3 -3
  159. package/src/console/auth/setup-service.ts +2 -2
  160. package/src/console/backup/contracts.ts +15 -2
  161. package/src/console/backup/export-endpoint.ts +6 -2
  162. package/src/console/backup/nine-router.ts +2 -5
  163. package/src/console/backup/service.ts +4 -0
  164. package/src/console/backup/store.ts +192 -29
  165. package/src/console/backup/validate.ts +3 -45
  166. package/src/console/cli-tools/fs-ops.ts +487 -487
  167. package/src/console/console-router-guards.ts +1 -1
  168. package/src/console/console-router.ts +8 -0
  169. package/src/console/data-management/contracts.ts +100 -0
  170. package/src/console/data-management/operations.ts +234 -0
  171. package/src/console/data-management/routes.ts +103 -0
  172. package/src/console/domain-registration.ts +45 -1
  173. package/src/console/observability/contracts.ts +524 -485
  174. package/src/console/observability/live.ts +22 -0
  175. package/src/console/observability/store.ts +1138 -1018
  176. package/src/console/observability/usage-dimensions.ts +4 -4
  177. package/src/console/providers/catalog/catalog-projections.ts +6 -7
  178. package/src/console/providers/catalog/contracts.ts +6 -0
  179. package/src/console/providers/catalog/model-operations.ts +5 -2
  180. package/src/console/providers/catalog/provider-operations.ts +24 -4
  181. package/src/console/providers/catalog/public-model-store.ts +8 -11
  182. package/src/console/providers/catalog/routes.ts +7 -0
  183. package/src/console/providers/catalog/store.ts +1553 -1532
  184. package/src/console/providers/oauth/routes.ts +8 -12
  185. package/src/console/quota/account-quota-shared.ts +52 -39
  186. package/src/console/quota/account-quota-tenant.ts +6 -6
  187. package/src/console/quota/quota-view.ts +1 -1
  188. package/src/console/quota/refresh.ts +441 -429
  189. package/src/console/remote-support/contracts.ts +61 -0
  190. package/src/console/remote-support/routes.ts +65 -0
  191. package/src/console/remote-support/service.ts +207 -0
  192. package/src/console/response-compression.ts +0 -3
  193. package/src/console/routing/pools/import-parse.ts +206 -0
  194. package/src/console/routing/pools/operations.ts +543 -501
  195. package/src/console/routing/pools/probe-result.ts +3 -2
  196. package/src/console/routing/pools/probe-verdict.ts +132 -132
  197. package/src/console/routing/pools/routes.ts +181 -164
  198. package/src/console/routing/pools/store.ts +8 -8
  199. package/src/console/settings/contracts.ts +95 -2
  200. package/src/console/settings/store.ts +81 -3
  201. package/src/console/shared/cursor.ts +8 -8
  202. package/src/console/shared/errors.ts +1 -3
  203. package/src/console/updates/routes.ts +16 -0
  204. package/src/main.ts +10 -0
  205. package/src/network/http2-bidi.ts +2 -4
  206. package/src/network/pool/agent.ts +478 -478
  207. package/src/network/pool/selector.ts +5 -4
  208. package/src/network/retry.ts +1 -2
  209. package/src/network/ssrf.ts +5 -4
  210. package/src/observability/event-compaction.ts +317 -0
  211. package/src/observability/event-day-index.ts +440 -0
  212. package/src/observability/event-log.ts +155 -6
  213. package/src/observability/logger.ts +6 -6
  214. package/src/observability/payload-capture.ts +158 -33
  215. package/src/observability/payload-store.ts +82 -61
  216. package/src/observability/redaction.ts +5 -6
  217. package/src/observability/request-notify.ts +43 -0
  218. package/src/observability/telemetry-status.ts +8 -9
  219. package/src/observability/token-speed.ts +5 -4
  220. package/src/persistence/db-mode.ts +7 -7
  221. package/src/persistence/health-event-flush.ts +36 -0
  222. package/src/persistence/readiness.ts +1 -1
  223. package/src/persistence/schema.ts +75 -29
  224. package/src/persistence/shared-cache.ts +1 -2
  225. package/src/persistence/stores/api-key-store.ts +18 -6
  226. package/src/persistence/stores/share-store.ts +4 -3
  227. package/src/persistence/stores/telemetry-store.ts +33 -11
  228. package/src/protocol/canonical-model.ts +11 -3
  229. package/src/protocol/codecs.ts +139 -6
  230. package/src/protocol/gateway-error.ts +6 -4
  231. package/src/protocol/image-clamp.ts +19 -1
  232. package/src/protocol/registry.ts +8 -0
  233. package/src/protocol/request/chat.ts +21 -1
  234. package/src/protocol/request/codex.ts +10 -1
  235. package/src/protocol/request/gemini.ts +9 -2
  236. package/src/protocol/request/messages.ts +18 -7
  237. package/src/protocol/request/responses.ts +9 -1
  238. package/src/protocol/response/chat.ts +34 -4
  239. package/src/protocol/response/codex.ts +7 -4
  240. package/src/protocol/response/dsml.ts +140 -28
  241. package/src/protocol/response/responses.ts +11 -5
  242. package/src/protocol/stream-error-frames.ts +4 -5
  243. package/src/providers/adapters/compatible-adapter.ts +3 -0
  244. package/src/providers/authentication/jwt-validator.ts +9 -10
  245. package/src/providers/authentication/oauth-refresh-service.ts +9 -11
  246. package/src/providers/bundled-discovery-providers.ts +122 -119
  247. package/src/providers/configured-openai-providers.ts +4 -4
  248. package/src/providers/default-registry.ts +5 -4
  249. package/src/providers/discovery/catalog/catalog-blob.ts +18 -18
  250. package/src/providers/discovery/catalog/catalog-format.ts +3 -6
  251. package/src/providers/discovery/models-dev-catalog.ts +354 -354
  252. package/src/providers/discovery/openai-model-discovery.ts +5 -0
  253. package/src/providers/discovery/openrouter-free-roster.ts +15 -17
  254. package/src/providers/discovery/probe-phases.ts +4 -4
  255. package/src/providers/discovery/probe-wire.ts +6 -13
  256. package/src/providers/discovery/probing-service.ts +1117 -1045
  257. package/src/providers/integrations/alibabacp/alibabacp.ts +1 -1
  258. package/src/providers/integrations/antigravity/antigravity-quota.ts +5 -7
  259. package/src/providers/integrations/buddy/buddy-chat-shared.ts +23 -2
  260. package/src/providers/integrations/buddy/buddy-checkin.ts +1 -4
  261. package/src/providers/integrations/buddy/buddy-cli-headers.ts +23 -6
  262. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +0 -1
  263. package/src/providers/integrations/buddy/buddy-identity.ts +52 -0
  264. package/src/providers/integrations/buddy/buddy-media.ts +2 -2
  265. package/src/providers/integrations/buddy/buddy-usage-store.ts +3 -4
  266. package/src/providers/integrations/buddy/codebuddy/quota.ts +2 -13
  267. package/src/providers/integrations/buddy/codebuddy/shared.ts +118 -115
  268. package/src/providers/integrations/buddy/workbuddy/quota.ts +0 -11
  269. package/src/providers/integrations/buddy/workbuddy/shared.ts +5 -2
  270. package/src/providers/integrations/claude/claude.ts +608 -608
  271. package/src/providers/integrations/cline/cline-quota.ts +27 -20
  272. package/src/providers/integrations/cline/cline.ts +537 -539
  273. package/src/providers/integrations/codex/codex-headers.ts +25 -39
  274. package/src/providers/integrations/codex/codex-oauth.ts +1 -1
  275. package/src/providers/integrations/codex/codex.ts +2 -29
  276. package/src/providers/integrations/commandcode/commandcode.ts +674 -675
  277. package/src/providers/integrations/commandcode/discovery.ts +117 -116
  278. package/src/providers/integrations/cursor/cursor-auth.ts +418 -418
  279. package/src/providers/integrations/cursor/cursor-quota.ts +309 -0
  280. package/src/providers/integrations/cursor/cursor-request.ts +616 -471
  281. package/src/providers/integrations/cursor/cursor-session-manager.ts +319 -281
  282. package/src/providers/integrations/cursor/cursor.ts +1333 -960
  283. package/src/providers/integrations/cursor/protocol/messages.ts +25 -0
  284. package/src/providers/integrations/factory/factory-models.ts +3 -5
  285. package/src/providers/integrations/factory/factory.ts +8 -1
  286. package/src/providers/integrations/gemini.ts +6 -1
  287. package/src/providers/integrations/grok/grok-install-id.ts +2 -3
  288. package/src/providers/integrations/grok/grok-quota.ts +279 -177
  289. package/src/providers/integrations/grok/grok-ratelimit-store.ts +73 -0
  290. package/src/providers/integrations/grok/grok-ratelimit.ts +218 -0
  291. package/src/providers/integrations/grok/grok.ts +6 -7
  292. package/src/providers/integrations/hermes.ts +14 -18
  293. package/src/providers/integrations/kiro/kiro-discovery.ts +1 -1
  294. package/src/providers/integrations/kiro/kiro.ts +1 -1
  295. package/src/providers/integrations/mistral.ts +6 -6
  296. package/src/providers/integrations/opencode/fingerprint.ts +3 -3
  297. package/src/providers/integrations/opencode/provider.ts +19 -20
  298. package/src/providers/integrations/qoder/qoder-catalog.ts +450 -450
  299. package/src/providers/integrations/qoder/qoder-oauth.ts +388 -310
  300. package/src/providers/integrations/qoder/qoder-quota.ts +192 -0
  301. package/src/providers/integrations/qoder/qoder.ts +884 -865
  302. package/src/providers/integrations/shared/connect.ts +6 -6
  303. package/src/providers/integrations/trae/trae-catalog.ts +1 -2
  304. package/src/providers/integrations/trae/trae-quota.ts +384 -0
  305. package/src/providers/integrations/trae/trae.ts +2 -2
  306. package/src/providers/integrations/zcode/oauth.ts +6 -1
  307. package/src/providers/operations/account-health-service.ts +75 -27
  308. package/src/providers/operations/account-reset-service.ts +1 -1
  309. package/src/providers/operations/client-versions.ts +6 -6
  310. package/src/providers/operations/custom-cli-headers.ts +3 -4
  311. package/src/providers/operations/provider-catalog-seeder.ts +95 -95
  312. package/src/providers/operations/provider-catalog-service.ts +3 -4
  313. package/src/providers/provider-contracts.ts +7 -0
  314. package/src/providers/provider-metadata.ts +10 -8
  315. package/src/providers/provider-registry.ts +6 -7
  316. package/src/providers/provider-usage.ts +1 -1
  317. package/src/providers/quota/quota-support.ts +8 -0
  318. package/src/security/abuse.ts +15 -10
  319. package/src/security/access-control.ts +144 -146
  320. package/src/security/admission/contracts.ts +11 -0
  321. package/src/security/admission/in-memory-store.ts +4 -3
  322. package/src/security/admission/lease-sweep.ts +6 -6
  323. package/src/security/admission/reasons.ts +5 -1
  324. package/src/security/admission/redis-store.ts +211 -210
  325. package/src/security/admission/service.ts +4 -0
  326. package/src/security/api-key-auth.ts +27 -17
  327. package/src/security/ip-boundary.ts +155 -15
  328. package/src/security/model-abuse.ts +366 -94
  329. package/src/security/outbound-headers.ts +3 -4
  330. package/src/shared/sleep.ts +4 -0
  331. package/src/transport/dispatch/attempt-finalize.ts +47 -5
  332. package/src/transport/dispatch/attempt-loop.ts +531 -530
  333. package/src/transport/dispatch/generation.ts +6 -0
  334. package/src/transport/dispatch/proxy-request.ts +24 -1
  335. package/src/transport/dispatch/ratelimit-capture.ts +37 -0
  336. package/src/transport/dispatch/stream-bridge.ts +1 -3
  337. package/src/transport/dispatch/streaming/finalize.ts +1 -1
  338. package/src/transport/dispatch/streaming/stream.ts +19 -6
  339. package/src/transport/dispatch/upstream.ts +9 -0
  340. package/src/transport/failure-policy.ts +162 -8
  341. package/src/transport/guards/auth-guard.ts +7 -4
  342. package/src/transport/guards/concurrency-guard.ts +0 -5
  343. package/src/transport/guards/error-lifecycle.ts +13 -6
  344. package/src/transport/guards/pipeline.ts +15 -3
  345. package/src/transport/guards/request-context.ts +8 -2
  346. package/src/transport/request/inflight.ts +5 -6
  347. package/src/transport/request/preparer.ts +9 -8
  348. package/src/transport/request/state.ts +21 -8
  349. package/src/transport/request/tenant-preferences.ts +60 -0
  350. package/src/transport/routing/admission.ts +4 -0
  351. package/src/transport/routing/route-catalog.ts +65 -10
  352. package/src/transport/routing/route-model.ts +46 -14
  353. package/src/transport/routing/router.ts +21 -14
  354. package/src/transport/surface/completion.ts +2 -3
  355. package/src/transport/surface/dialects.ts +5 -6
  356. package/src/transport/surface/responses/encode.ts +38 -0
  357. package/src/transport/surface/responses/parse.ts +4 -0
  358. package/src/transport/translation/capabilities.ts +2 -3
  359. package/src/transport/translation/quirks.ts +3 -3
  360. package/src/workers/buddy-growth-tasks.ts +5 -10
  361. package/src/workers/daily-checkin.ts +17 -23
  362. package/src/workers/quota-refresh-sweep.ts +26 -26
  363. package/dist/dashboard/assets/BannedPage-hfCzi-Ux.js.gz +0 -0
  364. package/dist/dashboard/assets/CliToolDetailPage-DLGqYEwI.js +0 -1
  365. package/dist/dashboard/assets/CliToolDetailPage-DLGqYEwI.js.gz +0 -0
  366. package/dist/dashboard/assets/CliToolsPage-DEDyKBlC.js.gz +0 -0
  367. package/dist/dashboard/assets/CombosPage-CfuYiQ8Z.js +0 -1
  368. package/dist/dashboard/assets/CombosPage-CfuYiQ8Z.js.gz +0 -0
  369. package/dist/dashboard/assets/ConsoleLogPage-bsLuZmYH.js.gz +0 -0
  370. package/dist/dashboard/assets/CustomizationPage-_UWhwziJ.js.gz +0 -0
  371. package/dist/dashboard/assets/HealthEventsModal-Cjfc5WFS.js +0 -1
  372. package/dist/dashboard/assets/HealthEventsModal-Cjfc5WFS.js.gz +0 -0
  373. package/dist/dashboard/assets/LoginPage-DDVIfZGW.js.gz +0 -0
  374. package/dist/dashboard/assets/ModelPicker-CWkTUtpX.js +0 -1
  375. package/dist/dashboard/assets/ModelPicker-CWkTUtpX.js.gz +0 -0
  376. package/dist/dashboard/assets/OverviewPage-B53YYMng.js +0 -1
  377. package/dist/dashboard/assets/OverviewPage-B53YYMng.js.gz +0 -0
  378. package/dist/dashboard/assets/ProviderDetailPage-B0KaAQf0.js +0 -3
  379. package/dist/dashboard/assets/ProviderDetailPage-B0KaAQf0.js.gz +0 -0
  380. package/dist/dashboard/assets/ProvidersPage-Dx31DgIO.js +0 -1
  381. package/dist/dashboard/assets/ProvidersPage-Dx31DgIO.js.gz +0 -0
  382. package/dist/dashboard/assets/ProxyPage-BpnR4kXT.js +0 -7
  383. package/dist/dashboard/assets/ProxyPage-BpnR4kXT.js.gz +0 -0
  384. package/dist/dashboard/assets/QuotaPage-BpOQCnun.js +0 -1
  385. package/dist/dashboard/assets/QuotaPage-BpOQCnun.js.gz +0 -0
  386. package/dist/dashboard/assets/SettingsPage-DV1eo2J_.js +0 -1
  387. package/dist/dashboard/assets/SettingsPage-DV1eo2J_.js.gz +0 -0
  388. package/dist/dashboard/assets/SetupPage-D6pmQ86L.js.gz +0 -0
  389. package/dist/dashboard/assets/SortableList-DWvKiuSl.js.gz +0 -0
  390. package/dist/dashboard/assets/StudioPage-CmkUrgdj.js.gz +0 -0
  391. package/dist/dashboard/assets/UsagePage-B47uOydr.js +0 -56
  392. package/dist/dashboard/assets/UsagePage-B47uOydr.js.gz +0 -0
  393. package/dist/dashboard/assets/api-keys-uNywYlfv.js +0 -1
  394. package/dist/dashboard/assets/api-keys-uNywYlfv.js.gz +0 -0
  395. package/dist/dashboard/assets/app-DxivpfYG.css +0 -2
  396. package/dist/dashboard/assets/app-DxivpfYG.css.gz +0 -0
  397. package/dist/dashboard/assets/assert-NHwYq95t.js.gz +0 -0
  398. package/dist/dashboard/assets/badge-6uzDDvqs.js.gz +0 -0
  399. package/dist/dashboard/assets/banner-4_WNg2WZ.js.gz +0 -0
  400. package/dist/dashboard/assets/card--AtFedAq.js.gz +0 -0
  401. package/dist/dashboard/assets/cli-tools-B3e7dx3N.js.gz +0 -0
  402. package/dist/dashboard/assets/clipboard-button-NreUx6c8.js.gz +0 -0
  403. package/dist/dashboard/assets/dialog-BtpsJU98.js +0 -1
  404. package/dist/dashboard/assets/dialog-BtpsJU98.js.gz +0 -0
  405. package/dist/dashboard/assets/download-A0SW9OCW.js +0 -1
  406. package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
  407. package/dist/dashboard/assets/drawer-WwwtzihF.js +0 -1
  408. package/dist/dashboard/assets/drawer-WwwtzihF.js.gz +0 -0
  409. package/dist/dashboard/assets/entry-CkryrIea.js +0 -4
  410. package/dist/dashboard/assets/entry-CkryrIea.js.gz +0 -0
  411. package/dist/dashboard/assets/entry-TJIye_jT.js +0 -1
  412. package/dist/dashboard/assets/entry-TJIye_jT.js.gz +0 -0
  413. package/dist/dashboard/assets/entry-jy9_4-Ke.js +0 -1
  414. package/dist/dashboard/assets/entry-jy9_4-Ke.js.gz +0 -0
  415. package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
  416. package/dist/dashboard/assets/github-badge-D_eM3IgG.js.gz +0 -0
  417. package/dist/dashboard/assets/index-BydyKaDz.js.gz +0 -0
  418. package/dist/dashboard/assets/inline-BcNGF8Gr.js.gz +0 -0
  419. package/dist/dashboard/assets/input-BG41et9G.js.gz +0 -0
  420. package/dist/dashboard/assets/layout-C8mer_Ak.js +0 -1
  421. package/dist/dashboard/assets/layout-C8mer_Ak.js.gz +0 -0
  422. package/dist/dashboard/assets/list-row-Gh_W4OR_.js.gz +0 -0
  423. package/dist/dashboard/assets/live-BJGYRBnR.js.gz +0 -0
  424. package/dist/dashboard/assets/model-bans-DeVLDA7I.js +0 -1
  425. package/dist/dashboard/assets/model-bans-DeVLDA7I.js.gz +0 -0
  426. package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
  427. package/dist/dashboard/assets/numbers-Bs4LOOuf.js +0 -2
  428. package/dist/dashboard/assets/numbers-Bs4LOOuf.js.gz +0 -0
  429. package/dist/dashboard/assets/query-keys-D7wX2vM5.js.gz +0 -0
  430. package/dist/dashboard/assets/routing-CcusqXA7.js.gz +0 -0
  431. package/dist/dashboard/assets/select-BO6h8yNv.js.gz +0 -0
  432. package/dist/dashboard/assets/settings-mpmXTgUa.js.gz +0 -0
  433. package/dist/dashboard/assets/sparkles-BRaRUxAU.js +0 -1
  434. package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
  435. package/dist/dashboard/assets/stack-DwLmjUFK.js.gz +0 -0
  436. package/dist/dashboard/assets/state-DYdQmdAl.js.gz +0 -0
  437. package/dist/dashboard/assets/switch-CidSfbG7.js +0 -1
  438. package/dist/dashboard/assets/switch-CidSfbG7.js.gz +0 -0
  439. package/dist/dashboard/assets/terminal-Bd4ee8TA.js +0 -1
  440. package/dist/dashboard/assets/terminal-Bd4ee8TA.js.gz +0 -0
  441. package/dist/dashboard/assets/tokens-DDxMbSRL.js +0 -1
  442. package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
  443. package/dist/dashboard/assets/use-presence-BSZEBx7U.js +0 -1
  444. package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
  445. package/dist/dashboard/assets/useMutation-w4u4CVue.js.gz +0 -0
  446. package/scripts/cli/command/admin.ts +0 -65
  447. package/scripts/cli/command/doctor.ts +0 -257
  448. package/scripts/cli/command/update.ts +0 -23
  449. package/scripts/cli/gateway/drain-token.ts +0 -78
  450. package/scripts/cli/gateway/instance-lock.ts +0 -105
  451. package/scripts/cli/gateway/stop.ts +0 -51
  452. package/scripts/cli/support/bun.ts +0 -27
  453. package/scripts/cli/support/version.ts +0 -37
  454. /package/dist/dashboard/assets/{app-CafWtVXA.js → app-BIt446yE.js} +0 -0
  455. /package/dist/dashboard/assets/{app-CafWtVXA.js.gz → app-BIt446yE.js.gz} +0 -0
  456. /package/scripts/cli/{ui/prompt.ts → prompt.ts} +0 -0
package/.env.example CHANGED
@@ -49,10 +49,16 @@ CARTETHYIA_PUBLIC_ORIGIN=http://localhost:12800
49
49
  # REDIS_URL=redis://localhost:6379 # Shared Redis; omit for in-memory.
50
50
  # CARTETHYIA_DATA_DIR= # Writable state root. Lite stores <dir>/cartethyia.sqlite; OS default otherwise.
51
51
  # TRUSTED_PROXY_CIDRS= # Trust forwarded client-IP headers from these proxy ranges.
52
+ # Set this when a reverse proxy or tunnel fronts the gateway. Unset, the loopback
53
+ # peer (127.0.0.1, ::1) is trusted on its own so cloudflared and local Caddy/Nginx
54
+ # keep per-caller addresses; every other peer's headers are ignored. With the
55
+ # variable set, only the ranges named here are trusted.
56
+ # Behind cloudflared or a local reverse proxy: TRUSTED_PROXY_CIDRS=127.0.0.1/32,::1/128
52
57
  # CARTETHYIA_ALLOWED_NETWORKS= # Private CIDRs allowed for upstream connections.
53
58
  # CARTETHYIA_TELEMETRY_PAYLOAD_DIR=./data/telemetry-payloads # Payload capture directory.
54
59
  # CARTETHYIA_CONFIG_DIR= # npm CLI only: directory holding .env. OS default otherwise.
55
- # VITE_BACKEND_URL=http://127.0.0.1:12800 # Backend URL for dashboard development.
60
+ # DASHBOARD_PORT= # Dashboard dev port override (default 5173, fallback 1931 if occupied).
61
+ # VITE_BACKEND_URL= # Gateway URL for dashboard dev proxy (defaults to http://127.0.0.1:<PORT>).
56
62
 
57
63
  # Defaults and overrides. Uncomment only when the built-in default is not suitable.
58
64
 
@@ -74,16 +80,19 @@ CARTETHYIA_PUBLIC_ORIGIN=http://localhost:12800
74
80
  # CARTETHYIA_TELEMETRY_RETENTION_DAYS=30 # Metadata telemetry retention in days.
75
81
  # CARTETHYIA_TELEMETRY_PAYLOAD_MAX_BYTES=16777216 # Combined full-capture limit; 16 MiB (max).
76
82
  # CARTETHYIA_TELEMETRY_PAYLOAD_FILE_MAX_BYTES=268435456 # Backing file size limit.
77
- # CARTETHYIA_TELEMETRY_PAYLOAD_RETENTION_MS=900000 # Payload retention time.
83
+ # CARTETHYIA_TELEMETRY_PAYLOAD_RETENTION_MS=900000 # Payload retention time. The default a tenant
84
+ # gets when they have not chosen one; tenants may raise it to at most 7 days from Settings.
78
85
  # CARTETHYIA_INSTALL_ID_DIR=./data/.cartethyia # Writable installation-id directory.
79
86
 
80
87
  # Network and abuse policy.
81
88
  # CARTETHYIA_ALLOW_PRIVATE_UPSTREAMS=true # Allow private upstream addresses.
82
89
  # CARTETHYIA_MAX_REDIRECTS=3 # Maximum upstream redirects.
83
90
  # IP_RATE_MAX_PER_WINDOW=240 # Requests per client IP in the rate window.
84
- # CARTETHYIA_MODEL_STRIKE_THRESHOLD=10 # Invalid requests inside the window before an IP ban.
91
+ # CARTETHYIA_MODEL_STRIKE_THRESHOLD=10 # Invalid requests inside the window before a ban.
85
92
  # CARTETHYIA_MODEL_STRIKE_WINDOW_MS=1800000 # Sliding window that keeps invalid requests countable.
86
- # CARTETHYIA_MODEL_BAN_TTL_MS=21600000 # Invalid-model IP-ban duration.
93
+ # CARTETHYIA_MODEL_BAN_TTL_MS=21600000 # Ban duration for the graduated strike path.
94
+ # CARTETHYIA_MODEL_BAN_MAX_TTL_MS=604800000 # Longest ban the console will record, however long
95
+ # one is asked for. Bans are scoped to the address and the API key that was used.
87
96
 
88
97
  # Upstream deadlines and fallback retry timing.
89
98
  # CARTETHYIA_UPSTREAM_TIMEOUT_MS=120000 # Overall upstream request deadline.
package/README.md CHANGED
@@ -51,7 +51,7 @@ npm uninstall -g cartethyia # uninstall
51
51
  ```
52
52
 
53
53
  Full install guide, modes, Docker, VPS, systemd, and the one-shot script:
54
- [getting started](documentation/getting-started.md). To remove it:
54
+ [the installation guide](documentation/installation.md). To remove it:
55
55
  `npm uninstall -g cartethyia`.
56
56
 
57
57
  ## <img src="https://api.iconify.design/lucide/sparkles.svg?color=%238b949e" width="20" height="20" alt=""> What it actually does
@@ -147,7 +147,7 @@ Docker Compose defaults to Full. A local `.env` defaults to Lite. When Lite
147
147
  gets tight, export a JSON backup and restore it into Full. You do not rebuild
148
148
  the config.
149
149
 
150
- Details: [Getting started](documentation/getting-started.md#2-choose-a-database-mode).
150
+ Details: [Database modes and configuration](documentation/installation.md#database-modes-and-configuration).
151
151
 
152
152
  ## <img src="https://api.iconify.design/lucide/scale.svg?color=%238b949e" width="20" height="20" alt=""> License
153
153
 
@@ -1 +1 @@
1
- import{t as e}from"./jsx-runtime-CXUMngI_.js";import{nt as t}from"./entry-CkryrIea.js";var n=e();function r(){return(0,n.jsx)(`main`,{className:`auth-viewport`,children:(0,n.jsxs)(`div`,{className:`card-solid auth-window border border-red-soft`,children:[(0,n.jsxs)(`div`,{className:`auth-header`,children:[(0,n.jsx)(`div`,{"aria-hidden":`true`,className:`auth-logo bg-red bg-none`,children:(0,n.jsx)(t,{size:24})}),(0,n.jsx)(`h1`,{className:`auth-title`,children:`Access Restricted`}),(0,n.jsx)(`p`,{className:`auth-desc`,children:`Security policy lockout or untrusted origin address`})]}),(0,n.jsxs)(`div`,{className:`rounded-panel border border-inner-border bg-surface-2 p-7 text-caption leading-relaxed text-text-secondary`,children:[(0,n.jsx)(`strong`,{className:`block text-text-primary mb-2`,children:`HTTP 403 Forbidden`}),`This client IP has been temporarily locked out due to repeated invalid credential attempts or untrusted proxy headers.`]})]})})}export{r as default};
1
+ import{t as e}from"./jsx-runtime-CXUMngI_.js";import{rt as t}from"./entry-DxBHnauy.js";var n=e();function r(){return(0,n.jsx)(`main`,{className:`auth-viewport`,children:(0,n.jsxs)(`div`,{className:`card-solid auth-window border border-red-soft`,children:[(0,n.jsxs)(`div`,{className:`auth-header`,children:[(0,n.jsx)(`div`,{"aria-hidden":`true`,className:`auth-logo bg-red bg-none`,children:(0,n.jsx)(t,{size:24})}),(0,n.jsx)(`h1`,{className:`auth-title`,children:`Access Restricted`}),(0,n.jsx)(`p`,{className:`auth-desc`,children:`Security policy lockout or untrusted origin address`})]}),(0,n.jsxs)(`div`,{className:`rounded-panel border border-inner-border bg-surface-2 p-7 text-caption leading-relaxed text-text-secondary`,children:[(0,n.jsx)(`strong`,{className:`block text-text-primary mb-2`,children:`HTTP 403 Forbidden`}),`This client IP has been temporarily locked out due to repeated invalid credential attempts or untrusted proxy headers.`]})]})})}export{r as default};
@@ -0,0 +1 @@
1
+ import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{t as i}from"./arrow-left-CpBxkoxI.js";import{T as a,c as o,s}from"./numbers-DkfMR5Qs.js";import{t as ee}from"./circle-check-BU3v_mFW.js";import{n as c,r as l}from"./state-mPDRlQkl.js";import{t as te}from"./route-CNSNj9Zm.js";import{t as u}from"./search-JOKus9rb.js";import{l as d}from"./query-keys-BFhGpwR1.js";import{Q as f,et as p}from"./entry-DxBHnauy.js";import{n as m,r as h,t as g}from"./card-DS7CQEsO.js";import{n as _}from"./download-dRFo5_Wu.js";import{t as v}from"./badge-CR72dasT.js";import{n as y}from"./input-V1umFiBk.js";import{t as b}from"./select-BYR_5K2c.js";import{t as ne}from"./ModelPicker-C7pDb41R.js";import{t as re}from"./switch-DOmJxg7H.js";import{t as x}from"./stack-BHTfXdz_.js";import{n as S}from"./inline-BhY2sSnO.js";import{f as ie,t as C}from"./api-keys-DQYLQxpW.js";import{a as w,i as ae,n as oe,o as T,r as se,t as E}from"./cli-tools-CNqzrfdb.js";import{t as D}from"./ToolIcon-K1ckcDKg.js";var ce=e(`book-open`,[[`path`,{d:`M12 5v16`,key:`1f6ucr`}],[`path`,{d:`M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z`,key:`1fyvmf`}]]),le=e(`circle-x`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m15 9-6 6`,key:`1uzhvr`}],[`path`,{d:`m9 9 6 6`,key:`z0biqf`}]]),ue=e(`file-code-corner`,[[`path`,{d:`M4 12.15V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-3.35`,key:`1wthlu`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`m5 16-3 3 3 3`,key:`331omg`}],[`path`,{d:`m9 22 3-3-3-3`,key:`lsp7cz`}]]),de=e(`settings-2`,[[`path`,{d:`M14 17H5`,key:`gfn3mx`}],[`path`,{d:`M19 7h-9`,key:`6i9tg`}],[`circle`,{cx:`17`,cy:`17`,r:`3`,key:`18b49y`}],[`circle`,{cx:`7`,cy:`7`,r:`3`,key:`dfmy0x`}]]),O=t(n(),1);function k(e,t){return e==null?!1:e instanceof Set?e.has(t):e.includes(t)}function A(e){return e==null?0:e instanceof Set?e.size:e.length}function j(e){let t=e.lastIndexOf(`/`);return t<0?e:e.slice(t+1)}function M(e,t,n,r){let i=n?`${n}/${j(t)}`:void 0,a=[t,j(t),...i?[i]:[]];r&&r!==t&&a.push(r);let o=e.model_list;return e.model_access_mode===`blacklist`?a.some(e=>k(o,e))?`model-denied`:null:o==null||A(o)===0||a.some(e=>k(o,e))?null:`model-not-allowed`}function N(e,t,n,r){return M(e,t,n,r)===null}var P=r();function F(){let{toolId:e}=p(),t=w(),n=T(),r=C(),i=(0,O.useMemo)(()=>t.data?.find(t=>t.id===e)??null,[t.data,e]),a=(0,O.useMemo)(()=>{let t=n.data;if(t)return Array.isArray(t)?t.find(t=>t.toolId===e):t[e]},[n.data,e]);return t.isLoading?(0,P.jsx)(l,{label:`Loading tool details…`}):t.isError?(0,P.jsx)(c,{title:`Unable to load tool`,message:t.error?.message??`Could not load the CLI tool registry.`,onRetry:()=>void t.refetch()}):i?(0,P.jsx)(I,{tool:i,status:a,apiKeys:r.data??[]}):(0,P.jsxs)(x,{gap:`12px`,children:[(0,P.jsx)(f,{to:`/cli-tools`,className:`text-caption text-accent`,children:`← Back to CLI Tools`}),(0,P.jsx)(c,{title:`Tool not found`,message:`Unknown CLI tool id.`})]})}function I({tool:e,status:t,apiKeys:n}){let[r,c]=(0,O.useState)(``),[l,p]=(0,O.useState)(()=>typeof window>`u`?`http://localhost:12800`:window.location.origin),[C,w]=(0,O.useState)({}),[T,k]=(0,O.useState)(!1),[A,j]=(0,O.useState)({}),[M,F]=(0,O.useState)(null),[I,L]=(0,O.useState)(`slot`),R=(0,O.useRef)(null),z=(0,O.useMemo)(()=>n.filter(e=>e.keyMode===`personal`||e.keyMode===`share`&&e.parentKeyId===void 0),[n]),B=ae(e.id,r),V=se(),H=oe(),U=ie(),W=E(),G=z.find(e=>e.id===r),K=G?.scopes?.includes(`routing:cli_mapping`)===!0,q=G?.keyMode===`personal`,J=G?.modelAccessMode??`whitelist`,Y=G?.modelList,X=e=>N({model_access_mode:J,model_list:Y},e),fe=(0,O.useMemo)(()=>{let t=new Set;if(!e.mappingSupported)return t;for(let n of e.defaultModels){let e=A[n.alias]??``;if(e.length===0)continue;let r=C[n.alias]??n.defaultValue??n.id;!X(e)&&!X(r)&&t.add(n.alias)}return t},[e.defaultModels,e.mappingSupported,A,C,G]),pe=e=>{if(!G)return;let t=Y??[],n=J===`blacklist`?t.filter(t=>t!==e):[...new Set([...t,e])];U.mutate({keyId:G.id,request:{modelAccessMode:J,modelList:n}},{onSuccess:()=>s.success(J===`blacklist`?`Model unblocked for this key`:`Model allowed for this key`),onError:e=>s.error(d(e,`Could not update the API key.`))})};(0,O.useEffect)(()=>{let t=Object.fromEntries(e.defaultModels.map(e=>[e.alias,e.defaultValue??e.id]));w(t),j({}),R.current=null},[e,r]),(0,O.useEffect)(()=>{let t=B.data;if(t&&t.apiKeyId===r){if(k(t.enabled),t.mappings.length>0)w(e=>({...e,...Object.fromEntries(t.mappings.map(e=>[e.slotKey,e.sourceModel]))})),j(e=>({...e,...Object.fromEntries(t.mappings.map(e=>[e.slotKey,e.targetModel]))}));else{let t=Object.fromEntries(e.defaultModels.map(e=>[e.alias,e.defaultValue??e.id]));w(t),j({})}R.current=JSON.stringify({enabled:t.enabled,mappings:t.mappings})}},[r,B.data,e.defaultModels]);let me=t?.installed??!1,Z=t?.configured??!1,he=e.configType===`guide`,Q=(0,O.useMemo)(()=>e.defaultModels.map(e=>C[e.alias]??e.defaultValue??e.id),[C,e.defaultModels]),$=(0,O.useCallback)(()=>{if(e.mappingSupported)return{enabled:T,mappings:e.defaultModels.filter(e=>(A[e.alias]??``).length>0).map(e=>({slotKey:e.alias,sourceModel:C[e.alias]??e.defaultValue??e.id,targetModel:A[e.alias]??``,enabled:!0})).filter(e=>e.targetModel.length>0)}},[T,A,C,e.defaultModels,e.mappingSupported]);(0,O.useEffect)(()=>{if(!e.mappingSupported||r.length===0)return;let t=B.data;if(!t||t.apiKeyId!==r)return;let n=$();if(!n)return;let i=JSON.stringify({enabled:n.enabled,mappings:n.mappings});if(i===R.current)return;let a=setTimeout(()=>{V.mutate({toolId:e.id,keyId:r,input:n},{onSuccess:()=>{R.current=i},onError:e=>s.error(d(e,`Could not save mappings.`))})},600);return()=>clearTimeout(a)},[$,r,B.data,V,e.id,e.mappingSupported]);let ge=(0,O.useCallback)(()=>{let t=Object.fromEntries(e.defaultModels.map(e=>[e.alias,C[e.alias]??e.defaultValue??e.id])),n=e.defaultModels.find(e=>e.roleKind===`subagent`);return{endpoint:l,apiKey:``,modelIds:e.id===`claude`?[]:Q,modelSlots:t,...Q[0]?{activeModel:Q[0]}:{},...n?{subagentModel:C[n.alias]??n.defaultValue??n.id}:{},mappingOwnerId:r,...e.mappingSupported?{mapping:$()}:{}}},[Q,$,r,l,C,e]);return(0,P.jsxs)(x,{gap:`16px`,children:[(0,P.jsxs)(f,{to:`/cli-tools`,className:`inline-flex items-center gap-3 text-caption text-accent`,children:[(0,P.jsx)(i,{size:14}),`Back to CLI Tools`]}),(0,P.jsx)(g,{children:(0,P.jsxs)(m,{className:`flex flex-col gap-5`,children:[(0,P.jsxs)(S,{gap:`14px`,align:`flex-start`,className:`flex-wrap`,children:[(0,P.jsx)(D,{toolId:e.id,name:e.name,color:e.color,size:46}),(0,P.jsxs)(S,{gap:`8px`,className:`flex-wrap`,children:[(0,P.jsx)(`h1`,{className:`text-title font-bold m-0`,children:e.name}),me?(0,P.jsx)(v,{tone:`ok`,children:`Installed`}):(0,P.jsx)(v,{tone:`disabled`,children:`Not installed`}),Z?(0,P.jsx)(v,{tone:`accent`,children:`Configured`}):null,e.configType===`guide`?(0,P.jsx)(v,{tone:`info`,children:`Guide`}):null]})]}),(0,P.jsx)(`p`,{className:`m-0 text-caption text-text-secondary`,children:e.description}),e.docsUrl?(0,P.jsx)(`a`,{href:e.docsUrl,target:`_blank`,rel:`noreferrer`,className:`inline-block text-caption text-accent`,children:`Official documentation →`}):null,t?.settingsPath?(0,P.jsxs)(`div`,{className:`font-mono tabular-nums px-6 py-4 rounded-inset bg-surface-2 border border-inner-border text-badge text-text-secondary break-all`,children:[`Config file: `,t.settingsPath]}):null,t?.message?(0,P.jsxs)(`div`,{className:`flex items-center gap-3 text-badge ${Z?`text-green`:`text-orange`}`,children:[Z?(0,P.jsx)(ee,{size:13}):(0,P.jsx)(le,{size:13}),t.message]}):null]})}),(0,P.jsxs)(g,{children:[(0,P.jsx)(h,{title:`Setup`,subtitle:`Pick the Apikey Name and endpoint, set the models, then download. The key's secret is read server-side — you never paste it.`,icon:(0,P.jsx)(de,{size:16})}),(0,P.jsx)(m,{children:(0,P.jsx)(x,{gap:`12px`,children:(0,P.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-3 min-w-0`,children:[(0,P.jsx)(b,{label:`Apikey Name`,id:`api-key-select`,value:r,onValueChange:c,options:[{value:``,label:`Select…`},...z.map(e=>({value:e.id,label:`${e.label} — ${e.keyMode===`personal`?`Personal`:`Share template`}`}))]}),(0,P.jsx)(`div`,{className:`flex items-center gap-3 flex-wrap`,children:G===void 0?(0,P.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Choose the Apikey Name whose routes this CLI session should use.`}):K?(0,P.jsxs)(P.Fragment,{children:[(0,P.jsx)(v,{tone:`ok`,children:`routing:cli_mapping`}),(0,P.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Remote routes work with this key.`})]}):(0,P.jsxs)(P.Fragment,{children:[(0,P.jsx)(v,{tone:`warn`,title:`This key cannot resolve persisted CLI mappings on /v1/*. Turn on Remote Routing below to enable it.`,children:`no CLI scope`}),(0,P.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Remote routes stay inert on this key — turning on Remote Routing below will activate it.`})]})}),G?.keyMode===`share`?(0,P.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:`Share template: its child keys inherit these routes automatically.`}):null]}),(0,P.jsx)(`div`,{className:`min-w-0`,children:(0,P.jsx)(y,{label:`Endpoint`,value:l,onChange:e=>p(e.target.value)})})]})})})]}),(0,P.jsxs)(g,{children:[(0,P.jsx)(h,{title:`Model routing`,icon:(0,P.jsx)(te,{size:16}),subtitle:e.mappingSupported?`Left is the model name the CLI asks for. Right is the route Cartethyia sends it to. Leave a target empty to send that slot straight to the provider.`:`The model names written into this tool's config.`,action:e.mappingSupported?(0,P.jsxs)(`div`,{className:`flex items-center gap-5`,children:[(0,P.jsx)(re,{checked:T,disabled:!r,onChange:t=>{if(k(t),!r){s.error(`Select an API key first to configure its Remote Routing.`);return}if(t&&G&&!K){let e=[...new Set([...G.scopes??[],`routing:cli_mapping`])];U.mutate({keyId:G.id,request:{scopes:e}},{onSuccess:()=>{s.success(`Activated routing:cli_mapping on "${G.label}".`)},onError:e=>{s.error(d(e,`Could not update key scope.`))}})}let n=$();n&&V.mutate({toolId:e.id,keyId:r,input:{...n,enabled:t}},{onError:e=>s.error(d(e,`Could not save mappings.`))})},label:T?`Remote Routing on`:`Remote Routing off`}),(0,P.jsx)(o,{variant:`secondary`,size:`sm`,disabled:!r||H.isPending,onClick:()=>{if(!r){s.error(`Select an API key first.`);return}H.mutate({toolId:e.id,keyId:r},{onSuccess:()=>{k(!1),j({}),s.success(`Remote routes cleared and Remote Routing turned off.`)},onError:e=>s.error(d(e,`Could not reset remote routes.`))})},children:H.isPending?`Resetting…`:`Reset`})]}):void 0}),(0,P.jsxs)(m,{children:[r?null:(0,P.jsx)(`p`,{className:`text-badge text-text-tertiary mb-5`,children:`Select an API key above to load and save remote routes for that key. You can still set models below to download a config file.`}),e.mappingSupported?(0,P.jsxs)(`div`,{className:`mb-5 flex items-center gap-4 rounded-inset border border-inner-border bg-surface-2 px-5 py-3 text-micro text-text-tertiary`,children:[(0,P.jsx)(`span`,{className:`flex-1`,children:`CLI asks for`}),(0,P.jsx)(`span`,{className:`w-9 text-center`,children:`→`}),(0,P.jsx)(`span`,{className:`flex-1`,children:`Cartethyia routes to`})]}):null,(0,P.jsx)(x,{gap:`6px`,children:e.defaultModels.map(t=>{let n=C[t.alias]??t.defaultValue??t.id,r=A[t.alias]??``,i=r===n;return(0,P.jsxs)(`div`,{className:`grid items-center gap-4 ${e.mappingSupported?`grid-cols-2`:`grid-cols-1`}`,children:[(0,P.jsxs)(`div`,{className:`flex flex-col gap-1 min-w-0`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>{F(t.alias),L(`slot`)},className:`font-mono tabular-nums flex w-full min-w-0 cursor-pointer items-center justify-between gap-4 rounded-inset border border-inner-border bg-surface-2 px-5 py-3.5 text-left text-badge text-text-primary`,children:[(0,P.jsx)(`span`,{className:`overflow-hidden truncate whitespace-nowrap`,children:n}),(0,P.jsx)(u,{size:12,className:`text-text-tertiary shrink-0`})]}),(0,P.jsx)(`span`,{className:`text-micro text-text-tertiary pl-1`,children:t.roleLabel??t.name})]}),e.mappingSupported?(0,P.jsxs)(`div`,{className:`flex flex-col gap-1 min-w-0`,children:[(0,P.jsxs)(`button`,{type:`button`,onClick:()=>{F(t.alias),L(`target`)},className:`font-mono tabular-nums flex w-full min-w-0 cursor-pointer items-center justify-between gap-4 rounded-inset border px-5 py-3.5 text-left text-badge ${i?`border-inner-border bg-surface-2 text-text-tertiary`:`border-accent bg-accent-soft text-text-primary`}`,children:[(0,P.jsx)(`span`,{className:`overflow-hidden truncate whitespace-nowrap`,children:r.length>0?r:`Not routed`}),(0,P.jsx)(u,{size:12,className:`text-text-tertiary shrink-0`})]}),(0,P.jsxs)(`span`,{className:`pl-1 text-micro ${r.length===0?`text-text-tertiary`:`text-accent`}`,children:[r.length===0?`not routed`:`rerouted`,r.length>0?(0,P.jsx)(`button`,{type:`button`,onClick:()=>j(e=>({...e,[t.alias]:``})),className:`ml-3 border-none bg-none p-0 text-micro text-text-tertiary cursor-pointer underline`,children:`clear`}):null]}),fe.has(t.alias)?(0,P.jsxs)(`span`,{className:`mt-1 flex items-center gap-3 text-micro text-orange`,children:[(0,P.jsx)(`span`,{children:J===`blacklist`?`This key blocks the target model.`:`This key does not allow the target model.`}),(0,P.jsx)(`button`,{type:`button`,disabled:U.isPending,onClick:()=>pe(r),className:`border-none bg-none p-0 text-micro font-semibold text-accent underline ${U.isPending?`cursor-not-allowed`:`cursor-pointer`}`,children:J===`blacklist`?`Unblock`:`Allow this model`})]}):null]}):null]},t.alias)})})]})]}),he&&e.guideSteps?(0,P.jsxs)(g,{children:[(0,P.jsx)(h,{title:`Guide`,subtitle:`Manual setup steps for tools that do not support file injection.`,icon:(0,P.jsx)(ce,{size:16})}),(0,P.jsx)(m,{children:(0,P.jsx)(`ol`,{className:`flex flex-col gap-6 pl-9`,children:e.guideSteps.map(e=>(0,P.jsxs)(`li`,{children:[(0,P.jsx)(`strong`,{className:`text-body`,children:e.title}),e.desc?(0,P.jsx)(`p`,{className:`text-caption text-text-secondary mt-2`,children:e.desc}):null,e.value?(0,P.jsx)(`pre`,{className:`mt-3 overflow-x-auto rounded-control border border-inner-border bg-surface-2 p-5 font-mono text-badge`,children:e.value.replace(/\{\{baseUrl\}\}/g,l)}):null]},e.step))})})]}):null,(0,P.jsxs)(g,{children:[(0,P.jsx)(h,{title:`Config file`,subtitle:`Download the config file for this CLI tool. The selected API key secret is decrypted automatically into the download.`,icon:(0,P.jsx)(ue,{size:16})}),(0,P.jsxs)(m,{className:`flex flex-col gap-6`,children:[(0,P.jsx)(`div`,{className:`flex gap-4 flex-wrap justify-end`,children:(0,P.jsx)(o,{variant:`primary`,icon:(0,P.jsx)(a,{size:14}),onClick:()=>{if(!r){s.error(`Select an API key first.`);return}W.mutate({toolId:e.id,keyId:r,input:ge()},{onSuccess:e=>{_(e.filename,e.content,e.mimeType),s.success(`Downloaded ${e.filename}.`)},onError:e=>s.error(d(e,`Could not download config.`))})},disabled:W.isPending||!q,children:W.isPending?`Downloading…`:`Download config`})}),q?null:(0,P.jsx)(`p`,{className:`text-badge text-text-tertiary text-right`,children:G?.keyMode===`share`?`A share template has no secret to write into a config. Select a personal key to download the config file.`:`Select an Apikey Name above to enable downloading the config file.`})]})]}),(0,P.jsx)(ne,{open:M!==null,onClose:()=>F(null),selected:M?[I===`target`?A[M]??C[M]??``:C[M]??``]:[],onToggle:()=>{},onSelectOne:e=>{M&&(I===`target`?j(t=>({...t,[M]:e})):w(t=>({...t,[M]:e}))),F(null)},title:M?`Select ${M} model`:`Select model`,multi:!1})]})}export{F as default};
@@ -1 +1 @@
1
- import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{t as r}from"./terminal-Bd4ee8TA.js";import{n as i,r as a,t as o}from"./state-DYdQmdAl.js";import{Z as s}from"./entry-CkryrIea.js";import{n as c,r as l,t as u}from"./card--AtFedAq.js";import{t as d}from"./badge-6uzDDvqs.js";import{t as f}from"./stack-DwLmjUFK.js";import{n as p}from"./inline-BcNGF8Gr.js";import{a as m,o as h}from"./cli-tools-B3e7dx3N.js";import{t as g}from"./ToolIcon-K1ckcDKg.js";import{n as _}from"./layout-C8mer_Ak.js";var v=e(t(),1),y=n();function b(){let e=m(),t=h(),n=(0,v.useMemo)(()=>{let e=new Map,n=t.data;if(!n)return e;if(Array.isArray(n))for(let t of n)t?.toolId&&e.set(t.toolId,t);else if(typeof n==`object`)for(let[t,r]of Object.entries(n))r&&e.set(r.toolId||t,r);return e},[t.data]);if(e.isLoading)return(0,y.jsx)(a,{label:`Loading CLI tools…`});if(e.isError||!e.data)return(0,y.jsx)(i,{title:`Unable to load CLI tools`,message:e.error?.message??`Could not load the CLI tools registry.`,onRetry:()=>void e.refetch()});let b=e.data,x=b.filter(e=>e.configType!==`guide`),S=b.filter(e=>e.configType===`guide`),C=x.filter(e=>n.get(e.id)?.configured).length;return b.length===0?(0,y.jsx)(`div`,{className:`flex-1 flex items-center justify-center p-12 border border-dashed border-transparent rounded-card bg-transparent text-center`,children:(0,y.jsx)(o,{title:`No CLI tools registered`,message:`The registry is empty, so there is nothing to configure yet.`})}):(0,y.jsx)(f,{gap:`16px`,children:(0,y.jsxs)(u,{children:[(0,y.jsx)(l,{title:`CLI Tools`,subtitle:`${C}/${x.length} file-injected tools configured`,icon:(0,y.jsx)(r,{size:16}),action:(0,y.jsx)(d,{tone:`accent`,children:`${b.length} tools`})}),(0,y.jsxs)(c,{className:`flex flex-col gap-8`,children:[(0,y.jsxs)(`section`,{className:`flex flex-col gap-6`,children:[(0,y.jsx)(_,{title:`File-injected tools (${x.length})`,description:`Direct config file writing and preset model mappings`}),(0,y.jsx)(`div`,{className:`provider-grid grid gap-6 w-full min-w-0`,children:x.map(e=>{let t=n.get(e.id);return(0,y.jsx)(u,{interactive:!0,className:`relative overflow-hidden rounded-panel`,children:(0,y.jsx)(s,{to:`/cli-tools/${e.id}`,className:`no-underline text-inherit block p-6`,children:(0,y.jsxs)(p,{gap:`10px`,children:[(0,y.jsx)(g,{toolId:e.id,name:e.name,color:e.color,size:32}),(0,y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,y.jsx)(`div`,{className:`text-body font-semibold overflow-hidden truncate whitespace-nowrap`,children:e.name}),(0,y.jsx)(`div`,{className:`mt-1.5`,children:t?.configured?(0,y.jsx)(d,{tone:`ok`,dot:!0,children:`Configured`}):t?.installed?(0,y.jsx)(d,{tone:`warn`,dot:!0,children:`Installed`}):(0,y.jsx)(d,{children:`Not installed`})})]}),(0,y.jsxs)(`div`,{className:`flex flex-col items-end gap-1.5 shrink-0`,children:[(0,y.jsx)(`span`,{className:`font-mono tabular-nums text-micro font-semibold bg-kbd-bg py-0.5 px-2.5 rounded-tiny text-text-secondary`,children:e.id}),e.surface?(0,y.jsx)(d,{tone:`default`,children:e.surface}):null]})]})})},e.id)})})]}),(0,y.jsxs)(`section`,{className:`flex flex-col gap-6`,children:[(0,y.jsx)(_,{title:`Guide-only tools (${S.length})`,description:`Manual setup steps and exportable config templates`}),(0,y.jsx)(`div`,{className:`provider-grid grid gap-6 w-full min-w-0`,children:S.map(e=>(0,y.jsx)(u,{interactive:!0,className:`relative overflow-hidden rounded-panel`,children:(0,y.jsx)(s,{to:`/cli-tools/${e.id}`,className:`no-underline text-inherit block p-6`,children:(0,y.jsxs)(p,{gap:`10px`,children:[(0,y.jsx)(g,{toolId:e.id,name:e.name,color:e.color,size:32}),(0,y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,y.jsx)(`div`,{className:`text-body font-semibold overflow-hidden truncate whitespace-nowrap`,children:e.name}),(0,y.jsx)(`div`,{className:`mt-1.5`,children:(0,y.jsx)(d,{tone:`info`,children:`Guide`})})]}),(0,y.jsxs)(`div`,{className:`flex flex-col items-end gap-1.5 shrink-0`,children:[(0,y.jsx)(`span`,{className:`font-mono tabular-nums text-micro font-semibold bg-kbd-bg py-0.5 px-2.5 rounded-tiny text-text-secondary`,children:e.id}),e.surface?(0,y.jsx)(d,{tone:`default`,children:e.surface}):null]})]})})},e.id))})]})]})]})})}export{b as default};
1
+ import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{t as r}from"./terminal-0_IjPWTk.js";import{n as i,r as a,t as o}from"./state-mPDRlQkl.js";import{Q as s}from"./entry-DxBHnauy.js";import{n as c,r as l,t as u}from"./card-DS7CQEsO.js";import{t as d}from"./badge-CR72dasT.js";import{t as f}from"./stack-BHTfXdz_.js";import{n as p}from"./inline-BhY2sSnO.js";import{a as m,o as h}from"./cli-tools-CNqzrfdb.js";import{t as g}from"./ToolIcon-K1ckcDKg.js";import{n as _}from"./layout-BBOYycyS.js";var v=e(t(),1),y=n();function b(){let e=m(),t=h(),n=(0,v.useMemo)(()=>{let e=new Map,n=t.data;if(!n)return e;if(Array.isArray(n))for(let t of n)t?.toolId&&e.set(t.toolId,t);else if(typeof n==`object`)for(let[t,r]of Object.entries(n))r&&e.set(r.toolId||t,r);return e},[t.data]);if(e.isLoading)return(0,y.jsx)(a,{label:`Loading CLI tools…`});if(e.isError||!e.data)return(0,y.jsx)(i,{title:`Unable to load CLI tools`,message:e.error?.message??`Could not load the CLI tools registry.`,onRetry:()=>void e.refetch()});let b=e.data,x=b.filter(e=>e.configType!==`guide`),S=b.filter(e=>e.configType===`guide`),C=x.filter(e=>n.get(e.id)?.configured).length;return b.length===0?(0,y.jsx)(`div`,{className:`flex-1 flex items-center justify-center p-12 border border-dashed border-transparent rounded-card bg-transparent text-center`,children:(0,y.jsx)(o,{title:`No CLI tools registered`,message:`The registry is empty, so there is nothing to configure yet.`})}):(0,y.jsx)(f,{gap:`16px`,children:(0,y.jsxs)(u,{children:[(0,y.jsx)(l,{title:`CLI Tools`,subtitle:`${C}/${x.length} file-injected tools configured`,icon:(0,y.jsx)(r,{size:16}),action:(0,y.jsx)(d,{tone:`accent`,children:`${b.length} tools`})}),(0,y.jsxs)(c,{className:`flex flex-col gap-8`,children:[(0,y.jsxs)(`section`,{className:`flex flex-col gap-6`,children:[(0,y.jsx)(_,{title:`File-injected tools (${x.length})`,description:`Direct config file writing and preset model mappings`}),(0,y.jsx)(`div`,{className:`provider-grid grid gap-6 w-full min-w-0`,children:x.map(e=>{let t=n.get(e.id);return(0,y.jsx)(u,{interactive:!0,className:`relative overflow-hidden rounded-panel`,children:(0,y.jsx)(s,{to:`/cli-tools/${e.id}`,className:`no-underline text-inherit block p-6`,children:(0,y.jsxs)(p,{gap:`10px`,children:[(0,y.jsx)(g,{toolId:e.id,name:e.name,color:e.color,size:32}),(0,y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,y.jsx)(`div`,{className:`text-body font-semibold overflow-hidden truncate whitespace-nowrap`,children:e.name}),(0,y.jsx)(`div`,{className:`mt-1.5`,children:t?.configured?(0,y.jsx)(d,{tone:`ok`,dot:!0,children:`Configured`}):t?.installed?(0,y.jsx)(d,{tone:`warn`,dot:!0,children:`Installed`}):(0,y.jsx)(d,{children:`Not installed`})})]}),(0,y.jsxs)(`div`,{className:`flex flex-col items-end gap-1.5 shrink-0`,children:[(0,y.jsx)(`span`,{className:`font-mono tabular-nums text-micro font-semibold bg-kbd-bg py-0.5 px-2.5 rounded-tiny text-text-secondary`,children:e.id}),e.surface?(0,y.jsx)(d,{tone:`default`,children:e.surface}):null]})]})})},e.id)})})]}),(0,y.jsxs)(`section`,{className:`flex flex-col gap-6`,children:[(0,y.jsx)(_,{title:`Guide-only tools (${S.length})`,description:`Manual setup steps and exportable config templates`}),(0,y.jsx)(`div`,{className:`provider-grid grid gap-6 w-full min-w-0`,children:S.map(e=>(0,y.jsx)(u,{interactive:!0,className:`relative overflow-hidden rounded-panel`,children:(0,y.jsx)(s,{to:`/cli-tools/${e.id}`,className:`no-underline text-inherit block p-6`,children:(0,y.jsxs)(p,{gap:`10px`,children:[(0,y.jsx)(g,{toolId:e.id,name:e.name,color:e.color,size:32}),(0,y.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,y.jsx)(`div`,{className:`text-body font-semibold overflow-hidden truncate whitespace-nowrap`,children:e.name}),(0,y.jsx)(`div`,{className:`mt-1.5`,children:(0,y.jsx)(d,{tone:`info`,children:`Guide`})})]}),(0,y.jsxs)(`div`,{className:`flex flex-col items-end gap-1.5 shrink-0`,children:[(0,y.jsx)(`span`,{className:`font-mono tabular-nums text-micro font-semibold bg-kbd-bg py-0.5 px-2.5 rounded-tiny text-text-secondary`,children:e.id}),e.surface?(0,y.jsx)(d,{tone:`default`,children:e.surface}):null]})]})})},e.id))})]})]})]})})}export{b as default};
@@ -0,0 +1 @@
1
+ import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{t as i}from"./arrow-right-Dl5yKnp8.js";import{E as a,c as o,s}from"./numbers-DkfMR5Qs.js";import{t as c}from"./SortableList-BLujdX7N.js";import{n as ee,r as l,t as u}from"./state-mPDRlQkl.js";import{t as d}from"./layers-2-glBbjl.js";import{r as f}from"./use-modal-focus-By7oJoGd.js";import{t as p}from"./dialog-k37exjNt.js";import{t as m}from"./pencil-768ysRAr.js";import{t as te}from"./plus-DIdX_g-x.js";import{t as h}from"./route-CNSNj9Zm.js";import{t as g}from"./search-JOKus9rb.js";import{t as ne}from"./trash-Cppn5c3R.js";import{l as _}from"./query-keys-BFhGpwR1.js";import{t as v}from"./dialog-actions-B1axpEg7.js";import{R as y}from"./entry-DxBHnauy.js";import{n as b,r as re,t as ie}from"./card-DS7CQEsO.js";import{t as ae}from"./use-clipboard-B0Sy03fE.js";import{n as x}from"./input-V1umFiBk.js";import{t as S}from"./select-BYR_5K2c.js";import{t as C}from"./ModelPicker-C7pDb41R.js";import{t as w}from"./stack-BHTfXdz_.js";import{n as T,t as oe}from"./inline-BhY2sSnO.js";import{t as E}from"./list-row-1zzZYM0B.js";import{a as D,d as O,f as k,i as A,n as j,o as M,p as N,r as P,s as F,t as I,u as L}from"./routing-CAb4F37R.js";import{t as R}from"./use-timeout-BwcBBRrT.js";var z=e(`copy-plus`,[[`line`,{x1:`15`,x2:`15`,y1:`12`,y2:`18`,key:`1p7wdc`}],[`line`,{x1:`12`,x2:`18`,y1:`15`,y2:`15`,key:`1nscbv`}],[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]),B=t(n(),1),V=[{value:`fallback`,label:`Fallback (try in order)`},{value:`round_robin`,label:`Round Robin (rotate)`}],H=r(),U=()=>`m${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`;function W(){let e=M(),t=j(),n=k(),r=A(),d=L(),[f,S]=(0,B.useState)(!1),[D,O]=(0,B.useState)(null),[N,P]=(0,B.useState)(``),[F,I]=(0,B.useState)(``),[z,V]=(0,B.useState)(!1),[U,W]=(0,B.useState)(null),[G,K]=(0,B.useState)(null),{copy:q}=ae(),J=R(),Y=(0,B.useMemo)(()=>e.data??[],[e.data]),X=()=>{O(null),P(``),I(``),S(!0)},Z=e=>{O(e),P(e.alias),I(e.targetModel),S(!0)},Q=e=>{e.preventDefault(),N.trim()&&F.trim()&&(D?n.mutate({id:D.id,request:{alias:N.trim(),targetModel:F.trim()}},{onSuccess:()=>{S(!1),O(null),s.success(`Alias updated`)},onError:e=>s.error(_(e,`Could not save the alias.`))}):t.mutate({alias:N.trim(),targetModel:F.trim()},{onSuccess:()=>{S(!1),P(``),I(``),s.success(`Alias created`)},onError:e=>s.error(_(e,`Could not create the alias.`))}))},se=(e,t)=>{q(e).then(e=>{if(!e){s.error(`Copy failed`);return}K(t),J(()=>K(null),1500)})};return(0,H.jsxs)(ie,{children:[(0,H.jsx)(re,{title:`Model Aliases`,subtitle:`Map readable names to real models (e.g. claude-mythos-5 → claude-opus-5)`,icon:(0,H.jsx)(h,{size:16}),action:(0,H.jsx)(oe,{children:(0,H.jsx)(o,{variant:`primary`,size:`sm`,icon:(0,H.jsx)(te,{size:13}),onClick:X,children:`New Alias`})})}),(0,H.jsx)(b,{children:e.isPending?(0,H.jsx)(l,{label:`Loading aliases...`}):e.isError?(0,H.jsx)(ee,{message:`Failed to load aliases`,onRetry:()=>e.refetch()}):Y.length===0?(0,H.jsx)(u,{title:`No aliases defined`,message:`Create an alias to route short or friendly names to real provider model IDs.`}):(0,H.jsx)(c,{items:Y,label:`Model aliases`,gap:`8px`,disabled:d.isPending,onReorder:e=>d.mutate(e,{onError:e=>s.error(_(e,`Could not save the new order.`))}),renderItem:e=>(0,H.jsx)(E,{className:`items-start flex-col sm:flex-row`,actions:(0,H.jsxs)(T,{gap:`4px`,className:`w-full justify-start sm:w-auto sm:justify-end`,children:[(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(a,{size:13}),onClick:()=>se(e.alias,e.id),title:G===e.id?`Copied!`:`Copy alias`}),(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(m,{size:13}),onClick:()=>Z(e),title:`Edit target model`}),(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(ne,{size:13}),onClick:()=>W(e),title:`Delete alias`,className:`text-red`})]}),children:(0,H.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap min-w-0`,children:[(0,H.jsx)(y,{value:e.alias,tone:`accent`}),(0,H.jsx)(i,{size:13,className:`text-text-tertiary shrink-0`}),(0,H.jsx)(y,{value:e.targetModel,tone:`plain`})]})})})}),(0,H.jsx)(p,{open:f,onClose:()=>S(!1),title:D?`Edit Model Alias`:`New Model Alias`,footer:(0,H.jsxs)(H.Fragment,{children:[(0,H.jsx)(o,{variant:`secondary`,type:`button`,onClick:()=>S(!1),children:`Cancel`}),(0,H.jsx)(o,{variant:`primary`,type:`submit`,form:`alias-form`,disabled:t.isPending||n.isPending||!N.trim()||!F.trim(),children:D?`Save Changes`:`Create Alias`})]}),children:(0,H.jsxs)(`form`,{id:`alias-form`,onSubmit:Q,className:`flex flex-col gap-6`,children:[(0,H.jsx)(x,{label:`Alias name`,id:`alias-name-input`,value:N,onChange:e=>P(e.target.value),placeholder:`e.g. fast, sonnet, smart`,required:!0}),(0,H.jsxs)(T,{gap:`8px`,align:`flex-end`,children:[(0,H.jsx)(`div`,{className:`flex-1`,children:(0,H.jsx)(x,{label:`Target model`,id:`target-model-input`,value:F,onChange:e=>I(e.target.value),placeholder:`e.g. codex/gpt-5.5, claude/claude-sonnet-5`,required:!0})}),(0,H.jsx)(o,{variant:`secondary`,size:`sm`,type:`button`,onClick:()=>V(!0),icon:(0,H.jsx)(g,{size:13}),children:`Browse`})]}),(0,H.jsx)(C,{open:z,onClose:()=>V(!1),selected:F?[F]:[],onToggle:()=>{},onSelectOne:e=>I(e),title:`Select target model`,multi:!1})]})}),(0,H.jsx)(p,{open:!!U,onClose:()=>W(null),title:`Delete Model Alias`,children:(0,H.jsxs)(w,{gap:`12px`,children:[(0,H.jsxs)(`p`,{className:`text-body text-text-secondary`,children:[`Are you sure you want to delete alias `,(0,H.jsx)(`strong`,{children:U?.alias}),`? Clients requesting this name will need their full model path.`]}),(0,H.jsxs)(v,{children:[(0,H.jsx)(o,{variant:`secondary`,onClick:()=>W(null),children:`Cancel`}),(0,H.jsx)(o,{variant:`danger`,onClick:()=>{U&&r.mutate(U.id,{onSuccess:()=>W(null)})},disabled:r.isPending,children:r.isPending?`Deleting...`:`Delete Alias`})]})]})})]})}function G(){let e=F(),t=P(),n=I(),r=N(),i=D(),h=O(),[k,A]=(0,B.useState)(!1),[j,M]=(0,B.useState)(null),[L,W]=(0,B.useState)(``),[G,K]=(0,B.useState)([]),[q,J]=(0,B.useState)(`fallback`),[Y,X]=(0,B.useState)(!1),[Z,Q]=(0,B.useState)(null),[se,ce]=(0,B.useState)(null),{copy:le}=ae(),ue=R(),$=(0,B.useMemo)(()=>G.map(e=>e.value),[G]),de=e=>{$.includes(e)?K(G.filter(t=>t.value!==e)):K([...G,{id:U(),value:e.trim()}])},fe=e.data??[],pe=()=>{M(null),W(``),K([]),J(`fallback`),A(!0)},me=e=>{M(e),W(e.name),K(e.members.map(e=>({id:U(),value:e}))),A(!0)},he=e=>{n.mutate(e.id,{onSuccess:e=>{let t=e.skippedMembers;t.length>0?s.success(`Combo cloned`,`${e.combo.name} — skipped unresolvable member${t.length>1?`s`:``}: ${t.join(`, `)}`):s.success(`Combo cloned`,e.combo.name)},onError:e=>s.error(_(e,`Could not clone the combo.`))})},ge=e=>{e.preventDefault(),L.trim()&&$.length!==0&&(j?r.mutate({id:j.id,request:{name:L.trim(),members:$,strategy:q}},{onSuccess:()=>{A(!1),M(null),s.success(`Combo saved`)},onError:e=>s.error(_(e,`Could not save the combo.`))}):t.mutate({name:L.trim(),members:$,strategy:q},{onSuccess:()=>{A(!1),W(``),K([]),s.success(`Combo created`)},onError:e=>s.error(_(e,`Could not create the combo.`))}))},_e=(e,t)=>{r.mutate({id:e.id,request:{strategy:t}},{onSuccess:()=>s.success(`Combo strategy updated`),onError:e=>s.error(_(e,`Could not update the combo strategy.`))})},ve=(e,t)=>{le(e).then(e=>{if(!e){s.error(`Copy failed`);return}ce(t),ue(()=>ce(null),1500)})};return(0,H.jsxs)(ie,{children:[(0,H.jsx)(re,{title:`Combos`,subtitle:`Combine multiple models with fallback or round-robin rotation`,icon:(0,H.jsx)(d,{size:16}),action:(0,H.jsx)(oe,{children:(0,H.jsx)(o,{variant:`primary`,size:`sm`,icon:(0,H.jsx)(te,{size:13}),onClick:pe,children:`New Combo`})})}),(0,H.jsx)(b,{children:e.isPending?(0,H.jsx)(l,{label:`Loading combos...`}):e.isError?(0,H.jsx)(ee,{message:`Failed to load combos`,onRetry:()=>e.refetch()}):fe.length===0?(0,H.jsx)(u,{title:`No combos defined`,message:`Create a model combo to distribute requests across multiple models.`}):(0,H.jsx)(c,{items:fe,label:`Model combos`,disabled:h.isPending,onReorder:e=>h.mutate(e,{onError:e=>s.error(_(e,`Could not save the new order.`))}),renderItem:e=>(0,H.jsxs)(E,{className:`items-start flex-col sm:flex-row`,actions:(0,H.jsxs)(T,{gap:`8px`,className:`w-full justify-between sm:w-auto sm:justify-start`,children:[(0,H.jsx)(S,{value:e.strategy,onValueChange:t=>_e(e,t),options:V}),(0,H.jsxs)(T,{gap:`4px`,className:`flex-wrap`,children:[(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(a,{size:13}),onClick:()=>ve(e.name,e.id),title:se===e.id?`Copied!`:`Copy combo name`}),(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(z,{size:13}),onClick:()=>he(e),disabled:n.isPending,title:`Clone combo (same members and strategy)`}),(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(m,{size:13}),onClick:()=>me(e),title:`Edit combo`}),(0,H.jsx)(o,{variant:`ghost`,size:`sm`,icon:(0,H.jsx)(ne,{size:13}),onClick:()=>Q(e),title:`Delete combo`,className:`text-red`})]})]}),children:[(0,H.jsx)(`div`,{className:`flex items-center justify-between gap-6 flex-wrap`,children:(0,H.jsx)(`strong`,{className:`text-body`,children:e.name})}),(0,H.jsx)(T,{gap:`6px`,className:`w-full flex-wrap`,children:e.members.map(e=>(0,H.jsx)(y,{value:e},e))})]})})}),(0,H.jsx)(p,{open:k,onClose:()=>A(!1),title:j?`Edit Model Combo`:`New Model Combo`,footer:(0,H.jsxs)(H.Fragment,{children:[(0,H.jsx)(o,{variant:`secondary`,type:`button`,onClick:()=>A(!1),children:`Cancel`}),(0,H.jsx)(o,{variant:`primary`,type:`submit`,form:`combo-form`,disabled:t.isPending||r.isPending||!L.trim()||$.length===0,children:j?`Save Changes`:`Create Combo`})]}),children:(0,H.jsxs)(`form`,{id:`combo-form`,onSubmit:ge,className:`flex flex-col gap-6`,children:[(0,H.jsx)(x,{label:`Combo name`,id:`combo-name-input`,value:L,onChange:e=>W(e.target.value),placeholder:`e.g. smart-combo, fast-pool`,required:!0}),(0,H.jsx)(S,{label:`Strategy`,id:`combo-strategy-select`,value:q,onValueChange:e=>J(e),options:V}),(0,H.jsxs)(w,{gap:`6px`,children:[(0,H.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,H.jsx)(`label`,{className:`text-caption font-semibold text-text-secondary`,children:`Member models — use arrows or drag to reorder`}),(0,H.jsx)(o,{variant:`secondary`,size:`sm`,type:`button`,icon:(0,H.jsx)(g,{size:12}),onClick:()=>X(!0),children:`Browse models`})]}),(0,H.jsx)(`div`,{role:`list`,"aria-label":`Combo members`,"data-testid":`combo-members-list`,className:`flex min-h-22 flex-col gap-2 rounded-control border border-dashed border-inner-border ${G.length===0?`p-0`:`p-3`}`,children:G.length===0?(0,H.jsx)(`button`,{type:`button`,onClick:()=>X(!0),className:`flex-1 cursor-pointer font-inherit text-caption text-text-tertiary`,children:`Pick models to add`}):(0,H.jsx)(c,{items:G,label:`Combo members`,gap:`4px`,onReorder:e=>{let t=new Map(G.map(e=>[e.id,e]));K(e.map(e=>t.get(e)).filter(Boolean))},renderItem:e=>(0,H.jsx)(E,{density:`compact`,actions:(0,H.jsx)(`button`,{type:`button`,onClick:()=>de(e.value),"aria-label":`Remove ${e.value}`,className:`flex shrink-0 cursor-pointer text-text-tertiary`,children:(0,H.jsx)(f,{size:12})}),children:(0,H.jsx)(y,{value:e.value,tone:`accent`})})})})]}),(0,H.jsx)(C,{open:Y,onClose:()=>X(!1),selected:$,onToggle:de,title:`Select combo members`,multi:!0})]})}),(0,H.jsx)(p,{open:!!Z,onClose:()=>Q(null),title:`Delete Model Combo`,children:(0,H.jsxs)(w,{gap:`12px`,children:[(0,H.jsxs)(`p`,{className:`text-body text-text-secondary`,children:[`Are you sure you want to delete combo `,(0,H.jsx)(`strong`,{children:Z?.name}),`? Any aliases pointing to it will fail to resolve.`]}),(0,H.jsxs)(v,{children:[(0,H.jsx)(o,{variant:`secondary`,onClick:()=>Q(null),children:`Cancel`}),(0,H.jsx)(o,{variant:`danger`,onClick:()=>{Z&&i.mutate(Z.id,{onSuccess:()=>Q(null)})},disabled:i.isPending,children:i.isPending?`Deleting...`:`Delete Combo`})]})]})})]})}function K(){return(0,H.jsxs)(w,{gap:`16px`,children:[(0,H.jsx)(G,{}),(0,H.jsx)(W,{})]})}export{K as default};
@@ -1 +1 @@
1
- import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{l as r,r as i,s as a}from"./numbers-Bs4LOOuf.js";import{n as o,r as s,t as c}from"./state-DYdQmdAl.js";import{t as l}from"./refresh-cw-BqJFk4sU.js";import{t as u}from"./search-JOKus9rb.js";import{t as d}from"./shield-check-DVS0Foqh.js";import{t as f}from"./trash-Cppn5c3R.js";import{l as p,o as m,u as h}from"./query-keys-D7wX2vM5.js";import{A as g,R as _,it as v,k as y}from"./entry-CkryrIea.js";import{n as b,r as x,t as S}from"./card--AtFedAq.js";import{t as C}from"./stream-retry-5QnVuSSo.js";import{t as w}from"./badge-6uzDDvqs.js";import{n as T}from"./input-BG41et9G.js";import{t as E}from"./layout-C8mer_Ak.js";var D=e(t(),1),O=500,k=1500;function A(e){return h(e)&&typeof e.ts==`string`&&(e.level===`debug`||e.level===`info`||e.level===`warn`||e.level===`error`)&&typeof e.msg==`string`}function j(e){return!h(e)||!Array.isArray(e.lines)?[]:e.lines.filter(A)}function M(){let[e,t]=(0,D.useState)([]),[n,r]=(0,D.useState)(new Set),[i,a]=(0,D.useState)(`idle`),o=(0,D.useRef)(0),s=(0,D.useRef)(0),c=(0,D.useRef)(new Set),l=e=>({...e,id:`l${s.current+=1}`});return(0,D.useEffect)(()=>{let e=!1,n,i=o.current+=1,s=(e,t)=>{let n=window.setTimeout(()=>{c.current.delete(n),e()},t);c.current.add(n)},u=e=>{let n=l(e);r(e=>{let t=new Set(e);return t.add(n.id),t}),s(()=>{r(e=>{if(!e.has(n.id))return e;let t=new Set(e);return t.delete(n.id),t})},k),t(e=>{let t=[...e,n];return t.length>O?t.slice(t.length-O):t})},d=()=>{n=new EventSource(`/console/api/logs/stream`),n.addEventListener(`init`,n=>{if(!e)try{let e=JSON.parse(n.data);h(e)&&(t(j(e).slice(-500).map(l)),r(new Set)),a(`live`)}catch{}}),n.addEventListener(`line`,t=>{if(!e)try{let e=JSON.parse(t.data);A(e)&&(u(e),a(`live`))}catch{}}),n.addEventListener(`clear`,()=>{e||(t([]),r(new Set))}),n.onerror=()=>{n?.close(),!e&&(a(`reconnecting`),s(()=>{!e&&i===o.current&&f()},C))}},f=async()=>{try{let n=await m(`/logs?limit=200`);if(e||i!==o.current)return;t(j(n).slice(-500).map(l)),r(new Set),d()}catch{}};return f(),()=>{e=!0;for(let e of c.current)window.clearTimeout(e);c.current.clear(),n?.close()}},[]),{lines:e,newLineIds:n,status:i,clear:(0,D.useCallback)(async()=>{await m(`/logs`,{method:`DELETE`}),t([]),r(new Set)},[])}}var N={"api_key.created":`API key created`,"api_key.updated":`API key updated`,"api_key.revoked":`API key revoked`,"api_key.regenerated":`API key regenerated`,"api_key.shared":`API key shared`,"api_key.share_regenerated":`API key share link regenerated`,"api_key.share_revoked":`API key unshared`,"provider.created":`Provider created`,"provider.updated":`Provider updated`,"provider.deleted":`Provider deleted`,"provider.global.updated":`Global provider updated`,"provider.global.deleted":`Global provider deleted`,"provider.routing.updated":`Provider routing updated`,"provider.models.registered":`Provider models registered`,"provider.models.bulk_deleted":`Provider models bulk-deleted`,"provider.model.deleted":`Provider model deleted`,"provider.model.enabled":`Provider model enabled`,"provider.model.disabled":`Provider model disabled`,"provider_account.created":`Provider account connected`,"provider_account.updated":`Provider account updated`,"provider_account.recovered":`Provider account recovered`,"provider_account.revoked":`Provider account revoked`,"provider_account.circuit_force_closed":`Provider account circuit force-closed`,"provider_account.deleted":`Provider account deleted`,"provider_account.exported":`Provider accounts exported (plaintext)`,"provider_account.global.updated":`Global provider account updated`,"provider_account.global.refreshed":`Global provider account refreshed`,"provider_account.global.deleted":`Global provider account deleted`,"model_alias.created":`Model alias created`,"model_alias.updated":`Model alias updated`,"model_alias.deleted":`Model alias deleted`,"model_combo.created":`Model combo created`,"model_combo.updated":`Model combo updated`,"model_combo.cloned":`Model combo cloned`,"model_combo.deleted":`Model combo deleted`,"network_pool.created":`Network pool created`,"network_pool.updated":`Network pool updated`,"network_pool.deleted":`Network pool deleted`,"network_pool.recovered":`Network pool recovered`,"network_pool.strategy_updated":`Network pool strategy updated`,"network_pool.relay_deployed":`Network pool relay deployed`,"filter_rule.created":`Filter rule created`,"filter_rule.updated":`Filter rule updated`,"filter_rule.deleted":`Filter rule deleted`,"filter_rule.reordered":`Filter rules reordered`,"filter_rule.master_toggle":`Filter master switch toggled`,"settings.runtime.updated":`Runtime settings updated`,"cli_tool.mappings_saved":`CLI tool mappings saved`,"cli_tool.mappings_reset":`CLI tool mappings reset`,"cli_tool.applied":`CLI tool applied`,"console.password_changed":`Console password changed`,"console_logs.cleared":`Console logs cleared`,"security.ip_banned":`IP banned`,"backup.reset":`Backup reset`,"backup.delete_all":`Delete all configuration`},P={api:`API`,ip:`IP`,cli:`CLI`,oauth:`OAuth`};function F(e){return e.split(`.`).map(e=>e.split(/[_-]+/).filter(Boolean).map(e=>P[e.toLowerCase()]??e.charAt(0).toUpperCase()+e.slice(1)).join(` `)).join(` · `)}function I(e){return N[e]??F(e)}var L=n(),R=50,z=[{id:`all`,label:`All`},{id:`debug`,label:`Debug`},{id:`info`,label:`Info`},{id:`warn`,label:`Warn`},{id:`error`,label:`Error`}],B={debug:`var(--text-tertiary)`,info:`var(--accent)`,warn:`var(--orange)`,error:`var(--red)`},V={debug:`DBG`,info:`INF`,warn:`WRN`,error:`ERR`};function H(e){return e>=500?`err`:e>=400?`warn`:`ok`}function U(e,t,n){let r=n.trim().toLowerCase();return e.filter(e=>t!==`all`&&e.level!==t?!1:!r||`${e.msg} ${e.endpoint??``} ${e.model??``} ${e.routedModel??``} ${e.providerId??``} ${e.errorCode??``} ${e.userAgent??``} ${e.clientIp??``} ${e.accountLabel??``}`.toLowerCase().includes(r))}function W(){let[e,t]=(0,D.useState)(`logs`),n=g().data?.isPlatformAdmin??!1,i=e===`audit`&&!n?`logs`:e,a=(0,L.jsxs)(`div`,{className:`flex gap-4`,children:[(0,L.jsx)(r,{variant:i===`logs`?`primary`:`secondary`,size:`sm`,onClick:()=>t(`logs`),icon:(0,L.jsx)(v,{size:13}),"aria-pressed":i===`logs`,children:`Console Log`}),n?(0,L.jsx)(r,{variant:i===`audit`?`primary`:`secondary`,size:`sm`,onClick:()=>t(`audit`),icon:(0,L.jsx)(d,{size:13}),"aria-pressed":i===`audit`,children:`Admin Audit`}):null]});return(0,L.jsx)(`div`,{className:`flex flex-col flex-1 min-h-0`,children:i===`logs`?(0,L.jsx)(Q,{tabAction:a}):(0,L.jsx)($,{tabAction:a})})}function G(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString([],{hour12:!1})}function K(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function q(e){let t=e.details;if(!t)return null;let n=typeof t.inputTokens==`number`?t.inputTokens:void 0,r=typeof t.outputTokens==`number`?t.outputTokens:void 0,i=typeof t.cachedInputTokens==`number`?t.cachedInputTokens:void 0,a=typeof t.reasoningTokens==`number`?t.reasoningTokens:void 0;if(n===void 0&&r===void 0&&i===void 0&&a===void 0)return null;let o=[];return n!==void 0&&o.push(`${K(n)} in`),r!==void 0&&o.push(`${K(r)} out`),i!==void 0&&o.push(`${K(i)} cached`),a!==void 0&&a>0&&o.push(`${K(a)} reason`),o.join(` / `)}function J(e){let t=e.model,n=e.routedModel,r=e.providerId,i=n??t;if(!i&&!r)return null;let a=r&&i?`${r}/${i}`:i??r??``;return n&&t&&n!==t?`${a} ← ${t}`:a}var Y=(0,D.memo)(function({line:e,isNew:t}){let n=e.event!==void 0,r=e.level;return(0,L.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-4 px-8 py-1.5 font-mono text-caption leading-normal max-medium:gap-3 max-medium:px-5 max-medium:text-badge${r===`warn`?` bg-orange-soft`:r===`error`?` bg-red-soft`:``}${t?` bg-surface-muted`:``} hover:bg-surface-hover`,"data-log-tone":r,children:[(0,L.jsx)(`span`,{className:`max-medium:flex-none flex-none tabular-nums text-text-tertiary`,children:G(e.ts)}),(0,L.jsx)(`span`,{className:`flex-none w-13 text-left text-micro font-bold tracking-label`,style:{color:B[e.level]},title:e.level.toUpperCase(),children:V[e.level]}),n?(0,L.jsx)(X,{line:e}):(0,L.jsx)(`span`,{className:`min-w-0 flex-1 whitespace-pre-wrap wrap-anywhere break-words text-text-secondary`,children:e.msg})]})});function X({line:e}){let t=J(e),n=q(e),r=Z(e);return(0,L.jsxs)(`span`,{className:`min-w-0 flex-1 whitespace-pre-wrap wrap-anywhere`,children:[(0,L.jsxs)(`span`,{className:`font-bold tracking-label ${r.tone}`,"data-log-field":`badge`,children:[`[`,r.label,`]`]}),` `,(0,L.jsx)(`span`,{className:`text-text-tertiary`,children:e.method??`POST`}),` `,(0,L.jsx)(`span`,{className:`text-text-primary`,children:e.endpoint??``}),e.status===void 0?null:(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums ${H(e.status)===`ok`?`text-text-tertiary`:H(e.status)===`warn`?`text-orange font-semibold`:`text-red font-semibold`}`,children:e.status})]}),e.durationMs===void 0?null:(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-text-secondary`,children:i(e.durationMs)})]}),t?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-status-info`,"data-log-field":`route`,children:t})]}):null,e.accountLabel?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-purple`,"data-log-field":`account`,title:e.accountId??void 0,children:e.accountLabel})]}):null,e.clientIp?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-text-secondary`,"data-log-field":`ip`,children:e.clientIp})]}):null,n?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-orange`,"data-log-field":`tokens`,children:n})]}):null,e.errorCode?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsxs)(`span`,{className:`text-red`,title:e.msg,children:[e.msg,` (`,e.errorCode,`)`]})]}):null,e.requestId?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-micro text-text-tertiary`,"data-log-field":`id`,children:e.requestId.slice(0,8)})]}):null]})}function Z(e){return e.event===`request_start`||e.status===void 0?{label:`REQUEST`,tone:`text-text-tertiary`}:e.event===`request_error`||e.status>=400?{label:`FAILED`,tone:`text-red`}:{label:`SUCCESS`,tone:`text-status-info`}}function Q({tabAction:e}){let{lines:t,newLineIds:n,clear:r}=M(),[i,o]=(0,D.useState)(`all`),[s,l]=(0,D.useState)(``),[d,p]=(0,D.useState)(!1),[m,h]=(0,D.useState)(null),g=s.trim().toLowerCase(),y=(0,D.useMemo)(()=>U(t,i,g).slice().reverse(),[t,i,g]),C=(0,D.useMemo)(()=>{let e=new Map([[`all`,t.length]]);for(let n of t)e.set(n.level,(e.get(n.level)??0)+1);return e},[t]);return(0,L.jsxs)(S,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(x,{title:`Console Log`,subtitle:`${y.length} of ${t.length} lines`,icon:(0,L.jsx)(v,{size:16}),action:e}),(0,L.jsxs)(b,{className:`flex flex-row items-center justify-between gap-8 flex-none min-h-0 px-7 py-4 border-b border-inner-border max-medium:flex-col max-medium:items-start max-medium:gap-4`,children:[(0,L.jsx)(`div`,{className:`inline-flex items-center gap-1.5 flex-none max-medium:w-full max-medium:overflow-x-auto`,role:`group`,"aria-label":`Log level`,children:z.map(e=>{let t=C.get(e.id)??0;return(0,L.jsxs)(`button`,{className:`inline-flex items-center appearance-none border-0 rounded-tiny px-5 py-3.5 bg-transparent font-sans text-badge font-semibold leading-none cursor-pointer ${i===e.id?`bg-surface-muted text-text-primary`:`text-text-tertiary hover:bg-surface-muted hover:text-text-primary`}`,type:`button`,onClick:()=>o(e.id),"aria-pressed":i===e.id,children:[(0,L.jsx)(`span`,{children:e.label}),(0,L.jsx)(`span`,{className:`ml-2.5 text-inherit opacity-65 tabular-nums`,children:t})]},e.id)})}),(0,L.jsxs)(`div`,{className:`flex items-center gap-4 ml-auto max-medium:w-full max-medium:ml-0 max-medium:min-w-0`,children:[(0,L.jsxs)(`div`,{className:`relative w-140 min-w-0 max-w-full max-medium:flex-auto max-medium:w-auto`,children:[(0,L.jsx)(u,{size:13,"aria-hidden":`true`,className:`absolute left-5 top-1/2 -translate-y-1/2 text-text-tertiary pointer-events-none`}),(0,L.jsx)(T,{"aria-label":`Search console logs`,value:s,onChange:e=>l(e.target.value),placeholder:`Search logs...`,className:`pl-15 w-full min-w-0`})]}),(0,L.jsx)(`button`,{className:`inline-grid place-items-center w-16 h-16 border border-border-subtle rounded-control bg-transparent text-text-secondary cursor-pointer hover:border-red hover:text-red hover:bg-red-soft`,type:`button`,onClick:()=>p(!0),"aria-label":`Clear console logs`,title:`Clear logs`,children:(0,L.jsx)(f,{size:15,"aria-hidden":`true`})})]})]}),(0,L.jsxs)(b,{className:`p-0 flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(`div`,{className:`scroll-region flex-1 min-h-0 flex flex-col p-0 bg-code-surface text-text-primary`,children:y.length===0?(0,L.jsx)(c,{title:t.length===0?`No log lines yet`:g?`No lines match your search`:`No lines match this level`,message:t.length===0?`Server log output will stream here as the gateway runs.`:`Adjust the search or pick another level to widen the view.`,icon:(0,L.jsx)(v,{size:20})}):y.map(e=>(0,L.jsx)(Y,{line:e,isNew:n.has(e.id)},e.id))}),(0,L.jsx)(`div`,{className:`flex items-center justify-between gap-5 shrink-0 px-8 py-4 border-t border-inner-border bg-surface-2 text-micro text-text-tertiary`,"aria-live":`polite`,children:(0,L.jsxs)(`span`,{className:`min-w-0 overflow-hidden text-ellipsis whitespace-nowrap`,children:[y.length,` of `,t.length,` lines`,i===`all`?``:` · ${i}`,g?` · search: "${s.trim()}"`:``]})})]}),(0,L.jsx)(_,{open:d,onClose:()=>p(!1),onConfirm:async()=>{h(null);try{await r(),p(!1),a.success(`Console logs cleared`)}catch{h(`Failed to clear server logs.`)}},title:`Clear console logs`,message:`Clear the in-memory server log tail? New lines keep streaming afterwards.`,confirmLabel:`Clear`,danger:!0}),m?(0,L.jsx)(`span`,{className:`text-badge text-red pt-0 px-8 pb-4`,children:m}):null]})}function $({tabAction:e}){let[t,n]=(0,D.useState)(``),[i,a]=(0,D.useState)(``),[u,f]=(0,D.useState)(``),[m,h]=(0,D.useState)(``),[g,_]=(0,D.useState)(void 0),[v,C]=(0,D.useState)([]);(0,D.useEffect)(()=>{let e=setTimeout(()=>f(t),300);return()=>clearTimeout(e)},[t]),(0,D.useEffect)(()=>{let e=setTimeout(()=>h(i),300);return()=>clearTimeout(e)},[i]);let w=y({limit:R,...u?{action:u}:{},...m?{actor:m}:{},...g?{cursor:g}:{}}),O=w.data,k=O?.entries??[],A=O?.nextCursor,j=()=>{A&&(C(e=>[...e,g??``]),_(A))},M=()=>{C(e=>{let t=e[e.length-1];return _(t||void 0),e.slice(0,-1)})},N=()=>{_(void 0),C([])};return(0,L.jsxs)(S,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(x,{title:`Admin Audit Trail`,subtitle:`Every privileged console mutation, retained on its own lifecycle`,icon:(0,L.jsx)(d,{size:16}),action:(0,L.jsxs)(`div`,{className:`flex gap-4 items-center`,children:[e,(0,L.jsx)(r,{variant:`secondary`,size:`sm`,onClick:()=>void w.refetch(),disabled:w.isFetching,icon:(0,L.jsx)(l,{size:13,className:w.isFetching?`animate-spin`:``}),children:`Refresh`})]})}),(0,L.jsxs)(b,{className:`flex flex-row items-center justify-between gap-6 flex-none min-h-0 px-8 py-5 border-b border-inner-border items-end`,children:[(0,L.jsx)(T,{label:`Action`,placeholder:`e.g. provider updated`,value:t,onChange:e=>{n(e.target.value),N()}}),(0,L.jsx)(T,{label:`Actor`,placeholder:`e.g. alice or a user id`,value:i,onChange:e=>{a(e.target.value),N()}}),(0,L.jsxs)(`div`,{className:`ml-auto flex gap-4`,children:[(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:M,disabled:v.length===0,children:`← Newer`}),(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:j,disabled:!A,children:`Older →`})]})]}),(0,L.jsx)(b,{className:`p-0 flex-1 min-h-0 flex flex-col`,children:(0,L.jsx)(`div`,{className:`flex-1 min-h-0 flex flex-col overflow-y-auto p-0 bg-transparent text-inherit`,children:w.isPending&&k.length===0?(0,L.jsx)(s,{compact:!0,label:`Loading audit trail…`}):w.isError&&k.length===0?(0,L.jsx)(o,{compact:!0,message:p(w.error,`Unable to load audit trail.`),onRetry:()=>void w.refetch()}):k.length===0?(0,L.jsx)(c,{compact:!0,title:`No audit entries yet`,message:`Privileged mutations (provider changes, key rotations, backups, bans) will appear here.`,icon:(0,L.jsx)(d,{size:20})}):(0,L.jsx)(E,{headers:[`Timestamp`,`Actor`,`Action`,`Target`,`Detail`],children:k.map(e=>(0,L.jsx)(ee,{entry:e},e.id))})})})]})}function ee({entry:e}){return(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{className:`text-badge text-text-tertiary whitespace-nowrap`,children:new Date(e.createdAt).toLocaleString()}),(0,L.jsxs)(`td`,{className:`max-w-100`,children:[(0,L.jsx)(`div`,{className:`text-caption font-semibold`,children:e.actorName??e.actor}),e.actorName?(0,L.jsx)(`div`,{title:e.actor,className:`truncate font-mono tabular-nums text-micro text-text-tertiary`,children:e.actor}):null]}),(0,L.jsx)(`td`,{children:(0,L.jsx)(w,{tone:e.action.includes(`delete`)||e.action.includes(`revoked`)?`err`:`ok`,title:e.action,children:I(e.action)})}),(0,L.jsx)(`td`,{title:e.target,className:`truncate font-mono tabular-nums text-badge max-w-110`,children:e.target}),(0,L.jsx)(`td`,{className:`font-mono tabular-nums text-badge max-w-160 overflow-hidden truncate`,children:e.detail?JSON.stringify(e.detail):`—`})]})}export{W as default,U as filterLogLines,H as statusTone};
1
+ import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{c as r,r as i,s as a}from"./numbers-DkfMR5Qs.js";import{n as o,r as s,t as c}from"./state-mPDRlQkl.js";import{t as l}from"./refresh-cw-BqJFk4sU.js";import{t as u}from"./search-JOKus9rb.js";import{t as d}from"./shield-check-DVS0Foqh.js";import{t as f}from"./trash-Cppn5c3R.js";import{l as p,o as m,u as h}from"./query-keys-BFhGpwR1.js";import{A as g,at as _,j as v,z as y}from"./entry-DxBHnauy.js";import{n as b,r as x,t as S}from"./card-DS7CQEsO.js";import{t as C}from"./stream-retry-5QnVuSSo.js";import{t as w}from"./badge-CR72dasT.js";import{n as T}from"./input-V1umFiBk.js";import{t as E}from"./layout-BBOYycyS.js";var D=e(t(),1),O=500,k=1500;function A(e){return h(e)&&typeof e.ts==`string`&&(e.level===`debug`||e.level===`info`||e.level===`warn`||e.level===`error`)&&typeof e.msg==`string`}function j(e){return!h(e)||!Array.isArray(e.lines)?[]:e.lines.filter(A)}function M(){let[e,t]=(0,D.useState)([]),[n,r]=(0,D.useState)(new Set),[i,a]=(0,D.useState)(`idle`),o=(0,D.useRef)(0),s=(0,D.useRef)(0),c=(0,D.useRef)(new Set),l=e=>({...e,id:`l${s.current+=1}`});return(0,D.useEffect)(()=>{let e=!1,n,i=o.current+=1,s=(e,t)=>{let n=window.setTimeout(()=>{c.current.delete(n),e()},t);c.current.add(n)},u=e=>{let n=l(e);r(e=>{let t=new Set(e);return t.add(n.id),t}),s(()=>{r(e=>{if(!e.has(n.id))return e;let t=new Set(e);return t.delete(n.id),t})},k),t(e=>{let t=[...e,n];return t.length>O?t.slice(t.length-O):t})},d=()=>{n=new EventSource(`/console/api/logs/stream`),n.addEventListener(`init`,n=>{if(!e)try{let e=JSON.parse(n.data);h(e)&&(t(j(e).slice(-500).map(l)),r(new Set)),a(`live`)}catch{}}),n.addEventListener(`line`,t=>{if(!e)try{let e=JSON.parse(t.data);A(e)&&(u(e),a(`live`))}catch{}}),n.addEventListener(`clear`,()=>{e||(t([]),r(new Set))}),n.onerror=()=>{n?.close(),!e&&(a(`reconnecting`),s(()=>{!e&&i===o.current&&f()},C))}},f=async()=>{try{let n=await m(`/logs?limit=200`);if(e||i!==o.current)return;t(j(n).slice(-500).map(l)),r(new Set),d()}catch{}};return f(),()=>{e=!0;for(let e of c.current)window.clearTimeout(e);c.current.clear(),n?.close()}},[]),{lines:e,newLineIds:n,status:i,clear:(0,D.useCallback)(async()=>{await m(`/logs`,{method:`DELETE`}),t([]),r(new Set)},[])}}var N={"api_key.created":`API key created`,"api_key.updated":`API key updated`,"api_key.revoked":`API key revoked`,"api_key.regenerated":`API key regenerated`,"api_key.shared":`API key shared`,"api_key.share_regenerated":`API key share link regenerated`,"api_key.share_revoked":`API key unshared`,"provider.created":`Provider created`,"provider.updated":`Provider updated`,"provider.deleted":`Provider deleted`,"provider.global.updated":`Global provider updated`,"provider.global.deleted":`Global provider deleted`,"provider.routing.updated":`Provider routing updated`,"provider.models.registered":`Provider models registered`,"provider.models.bulk_deleted":`Provider models bulk-deleted`,"provider.model.deleted":`Provider model deleted`,"provider.model.enabled":`Provider model enabled`,"provider.model.disabled":`Provider model disabled`,"provider_account.created":`Provider account connected`,"provider_account.updated":`Provider account updated`,"provider_account.recovered":`Provider account recovered`,"provider_account.revoked":`Provider account revoked`,"provider_account.circuit_force_closed":`Provider account circuit force-closed`,"provider_account.deleted":`Provider account deleted`,"provider_account.exported":`Provider accounts exported (plaintext)`,"provider_account.global.updated":`Global provider account updated`,"provider_account.global.refreshed":`Global provider account refreshed`,"provider_account.global.deleted":`Global provider account deleted`,"model_alias.created":`Model alias created`,"model_alias.updated":`Model alias updated`,"model_alias.deleted":`Model alias deleted`,"model_combo.created":`Model combo created`,"model_combo.updated":`Model combo updated`,"model_combo.cloned":`Model combo cloned`,"model_combo.deleted":`Model combo deleted`,"network_pool.created":`Network pool created`,"network_pool.updated":`Network pool updated`,"network_pool.deleted":`Network pool deleted`,"network_pool.recovered":`Network pool recovered`,"network_pool.strategy_updated":`Network pool strategy updated`,"network_pool.relay_deployed":`Network pool relay deployed`,"filter_rule.created":`Filter rule created`,"filter_rule.updated":`Filter rule updated`,"filter_rule.deleted":`Filter rule deleted`,"filter_rule.reordered":`Filter rules reordered`,"filter_rule.master_toggle":`Filter master switch toggled`,"settings.runtime.updated":`Runtime settings updated`,"cli_tool.mappings_saved":`CLI tool mappings saved`,"cli_tool.mappings_reset":`CLI tool mappings reset`,"cli_tool.applied":`CLI tool applied`,"console.password_changed":`Console password changed`,"console_logs.cleared":`Console logs cleared`,"security.ip_banned":`IP banned`,"backup.reset":`Backup reset`,"backup.delete_all":`Delete all configuration`},P={api:`API`,ip:`IP`,cli:`CLI`,oauth:`OAuth`};function F(e){return e.split(`.`).map(e=>e.split(/[_-]+/).filter(Boolean).map(e=>P[e.toLowerCase()]??e.charAt(0).toUpperCase()+e.slice(1)).join(` `)).join(` · `)}function I(e){return N[e]??F(e)}var L=n(),R=50,z=[{id:`all`,label:`All`},{id:`debug`,label:`Debug`},{id:`info`,label:`Info`},{id:`warn`,label:`Warn`},{id:`error`,label:`Error`}],B={debug:`var(--text-tertiary)`,info:`var(--accent)`,warn:`var(--orange)`,error:`var(--red)`},V={debug:`DBG`,info:`INF`,warn:`WRN`,error:`ERR`};function H(e){return e>=500?`err`:e>=400?`warn`:`ok`}function U(e,t,n){let r=n.trim().toLowerCase();return e.filter(e=>t!==`all`&&e.level!==t?!1:!r||`${e.msg} ${e.endpoint??``} ${e.model??``} ${e.routedModel??``} ${e.providerId??``} ${e.errorCode??``} ${e.userAgent??``} ${e.clientIp??``} ${e.accountLabel??``}`.toLowerCase().includes(r))}function W(){let[e,t]=(0,D.useState)(`logs`),n=v().data?.isPlatformAdmin??!1,i=e===`audit`&&!n?`logs`:e,a=(0,L.jsxs)(`div`,{className:`flex gap-4`,children:[(0,L.jsx)(r,{variant:i===`logs`?`primary`:`secondary`,size:`sm`,onClick:()=>t(`logs`),icon:(0,L.jsx)(_,{size:13}),"aria-pressed":i===`logs`,children:`Console Log`}),n?(0,L.jsx)(r,{variant:i===`audit`?`primary`:`secondary`,size:`sm`,onClick:()=>t(`audit`),icon:(0,L.jsx)(d,{size:13}),"aria-pressed":i===`audit`,children:`Admin Audit`}):null]});return(0,L.jsx)(`div`,{className:`flex flex-col flex-1 min-h-0`,children:i===`logs`?(0,L.jsx)(Q,{tabAction:a}):(0,L.jsx)($,{tabAction:a})})}function G(e){let t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleTimeString([],{hour12:!1})}function K(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function q(e){let t=e.details;if(!t)return null;let n=typeof t.inputTokens==`number`?t.inputTokens:void 0,r=typeof t.outputTokens==`number`?t.outputTokens:void 0,i=typeof t.cachedInputTokens==`number`?t.cachedInputTokens:void 0,a=typeof t.reasoningTokens==`number`?t.reasoningTokens:void 0;if(n===void 0&&r===void 0&&i===void 0&&a===void 0)return null;let o=[];return n!==void 0&&o.push(`${K(n)} in`),r!==void 0&&o.push(`${K(r)} out`),i!==void 0&&o.push(`${K(i)} cached`),a!==void 0&&a>0&&o.push(`${K(a)} reason`),o.join(` / `)}function J(e){let t=e.model,n=e.routedModel,r=e.providerId,i=n??t;if(!i&&!r)return null;let a=r&&i?`${r}/${i}`:i??r??``;return n&&t&&n!==t?`${a} ← ${t}`:a}var Y=(0,D.memo)(function({line:e,isNew:t}){let n=e.event!==void 0,r=e.level;return(0,L.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-4 px-8 py-1.5 font-mono text-caption leading-normal max-medium:gap-3 max-medium:px-5 max-medium:text-badge${r===`warn`?` bg-orange-soft`:r===`error`?` bg-red-soft`:``}${t?` bg-surface-muted`:``} hover:bg-surface-hover`,"data-log-tone":r,children:[(0,L.jsx)(`span`,{className:`max-medium:flex-none flex-none tabular-nums text-text-tertiary`,children:G(e.ts)}),(0,L.jsx)(`span`,{className:`flex-none w-13 text-left text-micro font-bold tracking-label`,style:{color:B[e.level]},title:e.level.toUpperCase(),children:V[e.level]}),n?(0,L.jsx)(X,{line:e}):(0,L.jsx)(`span`,{className:`min-w-0 flex-1 whitespace-pre-wrap wrap-anywhere break-words text-text-secondary`,children:e.msg})]})});function X({line:e}){let t=J(e),n=q(e),r=Z(e);return(0,L.jsxs)(`span`,{className:`min-w-0 flex-1 whitespace-pre-wrap wrap-anywhere`,children:[(0,L.jsxs)(`span`,{className:`font-bold tracking-label ${r.tone}`,"data-log-field":`badge`,children:[`[`,r.label,`]`]}),` `,(0,L.jsx)(`span`,{className:`text-text-tertiary`,children:e.method??`POST`}),` `,(0,L.jsx)(`span`,{className:`text-text-primary`,children:e.endpoint??``}),e.status===void 0?null:(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums ${H(e.status)===`ok`?`text-text-tertiary`:H(e.status)===`warn`?`text-orange font-semibold`:`text-red font-semibold`}`,children:e.status})]}),e.durationMs===void 0?null:(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-text-secondary`,children:i(e.durationMs)})]}),t?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-status-info`,"data-log-field":`route`,children:t})]}):null,e.accountLabel?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-purple`,"data-log-field":`account`,title:e.accountId??void 0,children:e.accountLabel})]}):null,e.clientIp?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-text-secondary`,"data-log-field":`ip`,children:e.clientIp})]}):null,n?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`tabular-nums text-orange`,"data-log-field":`tokens`,children:n})]}):null,e.errorCode?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsxs)(`span`,{className:`text-red`,title:e.msg,children:[e.msg,` (`,e.errorCode,`)`]})]}):null,e.requestId?(0,L.jsxs)(L.Fragment,{children:[` `,(0,L.jsx)(`span`,{className:`text-micro text-text-tertiary`,"data-log-field":`id`,children:e.requestId.slice(0,8)})]}):null]})}function Z(e){return e.event===`request_start`||e.status===void 0?{label:`REQUEST`,tone:`text-text-tertiary`}:e.event===`request_error`||e.status>=400?{label:`FAILED`,tone:`text-red`}:{label:`SUCCESS`,tone:`text-status-info`}}function Q({tabAction:e}){let{lines:t,newLineIds:n,clear:r}=M(),[i,o]=(0,D.useState)(`all`),[s,l]=(0,D.useState)(``),[d,p]=(0,D.useState)(!1),[m,h]=(0,D.useState)(null),g=s.trim().toLowerCase(),v=(0,D.useMemo)(()=>U(t,i,g).slice().reverse(),[t,i,g]),C=(0,D.useMemo)(()=>{let e=new Map([[`all`,t.length]]);for(let n of t)e.set(n.level,(e.get(n.level)??0)+1);return e},[t]);return(0,L.jsxs)(S,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(x,{title:`Console Log`,subtitle:`${v.length} of ${t.length} lines`,icon:(0,L.jsx)(_,{size:16}),action:e}),(0,L.jsxs)(b,{className:`flex flex-row items-center justify-between gap-8 flex-none min-h-0 px-7 py-4 border-b border-inner-border max-medium:flex-col max-medium:items-start max-medium:gap-4`,children:[(0,L.jsx)(`div`,{className:`inline-flex items-center gap-1.5 flex-none max-medium:w-full max-medium:overflow-x-auto`,role:`group`,"aria-label":`Log level`,children:z.map(e=>{let t=C.get(e.id)??0;return(0,L.jsxs)(`button`,{className:`inline-flex items-center appearance-none border-0 rounded-tiny px-5 py-3.5 bg-transparent font-sans text-badge font-semibold leading-none cursor-pointer ${i===e.id?`bg-surface-muted text-text-primary`:`text-text-tertiary hover:bg-surface-muted hover:text-text-primary`}`,type:`button`,onClick:()=>o(e.id),"aria-pressed":i===e.id,children:[(0,L.jsx)(`span`,{children:e.label}),(0,L.jsx)(`span`,{className:`ml-2.5 text-inherit opacity-65 tabular-nums`,children:t})]},e.id)})}),(0,L.jsxs)(`div`,{className:`flex items-center gap-4 ml-auto max-medium:w-full max-medium:ml-0 max-medium:min-w-0`,children:[(0,L.jsxs)(`div`,{className:`relative w-140 min-w-0 max-w-full max-medium:flex-auto max-medium:w-auto`,children:[(0,L.jsx)(u,{size:13,"aria-hidden":`true`,className:`absolute left-5 top-1/2 -translate-y-1/2 text-text-tertiary pointer-events-none`}),(0,L.jsx)(T,{"aria-label":`Search console logs`,value:s,onChange:e=>l(e.target.value),placeholder:`Search logs...`,className:`pl-15 w-full min-w-0`})]}),(0,L.jsx)(`button`,{className:`inline-grid place-items-center w-16 h-16 border border-border-subtle rounded-control bg-transparent text-text-secondary cursor-pointer hover:border-red hover:text-red hover:bg-red-soft`,type:`button`,onClick:()=>p(!0),"aria-label":`Clear console logs`,title:`Clear logs`,children:(0,L.jsx)(f,{size:15,"aria-hidden":`true`})})]})]}),(0,L.jsxs)(b,{className:`p-0 flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(`div`,{className:`scroll-region flex-1 min-h-0 flex flex-col p-0 bg-code-surface text-text-primary`,children:v.length===0?(0,L.jsx)(c,{title:t.length===0?`No log lines yet`:g?`No lines match your search`:`No lines match this level`,message:t.length===0?`Server log output will stream here as the gateway runs.`:`Adjust the search or pick another level to widen the view.`,icon:(0,L.jsx)(_,{size:20})}):v.map(e=>(0,L.jsx)(Y,{line:e,isNew:n.has(e.id)},e.id))}),(0,L.jsx)(`div`,{className:`flex items-center justify-between gap-5 shrink-0 px-8 py-4 border-t border-inner-border bg-surface-2 text-micro text-text-tertiary`,"aria-live":`polite`,children:(0,L.jsxs)(`span`,{className:`min-w-0 overflow-hidden text-ellipsis whitespace-nowrap`,children:[v.length,` of `,t.length,` lines`,i===`all`?``:` · ${i}`,g?` · search: "${s.trim()}"`:``]})})]}),(0,L.jsx)(y,{open:d,onClose:()=>p(!1),onConfirm:async()=>{h(null);try{await r(),p(!1),a.success(`Console logs cleared`)}catch{h(`Failed to clear server logs.`)}},title:`Clear console logs`,message:`Clear the in-memory server log tail? New lines keep streaming afterwards.`,confirmLabel:`Clear`,danger:!0}),m?(0,L.jsx)(`span`,{className:`text-badge text-red pt-0 px-8 pb-4`,children:m}):null]})}function $({tabAction:e}){let[t,n]=(0,D.useState)(``),[i,a]=(0,D.useState)(``),[u,f]=(0,D.useState)(``),[m,h]=(0,D.useState)(``),[_,v]=(0,D.useState)(void 0),[y,C]=(0,D.useState)([]);(0,D.useEffect)(()=>{let e=setTimeout(()=>f(t),300);return()=>clearTimeout(e)},[t]),(0,D.useEffect)(()=>{let e=setTimeout(()=>h(i),300);return()=>clearTimeout(e)},[i]);let w=g({limit:R,...u?{action:u}:{},...m?{actor:m}:{},..._?{cursor:_}:{}}),O=w.data,k=O?.entries??[],A=O?.nextCursor,j=()=>{A&&(C(e=>[...e,_??``]),v(A))},M=()=>{C(e=>{let t=e[e.length-1];return v(t||void 0),e.slice(0,-1)})},N=()=>{v(void 0),C([])};return(0,L.jsxs)(S,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(x,{title:`Admin Audit Trail`,subtitle:`Every privileged console mutation, retained on its own lifecycle`,icon:(0,L.jsx)(d,{size:16}),action:(0,L.jsxs)(`div`,{className:`flex gap-4 items-center`,children:[e,(0,L.jsx)(r,{variant:`secondary`,size:`sm`,onClick:()=>void w.refetch(),disabled:w.isFetching,icon:(0,L.jsx)(l,{size:13,className:w.isFetching?`animate-spin`:``}),children:`Refresh`})]})}),(0,L.jsxs)(b,{className:`flex flex-row items-center justify-between gap-6 flex-none min-h-0 px-8 py-5 border-b border-inner-border items-end`,children:[(0,L.jsx)(T,{label:`Action`,placeholder:`e.g. provider updated`,value:t,onChange:e=>{n(e.target.value),N()}}),(0,L.jsx)(T,{label:`Actor`,placeholder:`e.g. alice or a user id`,value:i,onChange:e=>{a(e.target.value),N()}}),(0,L.jsxs)(`div`,{className:`ml-auto flex gap-4`,children:[(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:M,disabled:y.length===0,children:`← Newer`}),(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:j,disabled:!A,children:`Older →`})]})]}),(0,L.jsx)(b,{className:`p-0 flex-1 min-h-0 flex flex-col`,children:(0,L.jsx)(`div`,{className:`flex-1 min-h-0 flex flex-col overflow-y-auto p-0 bg-transparent text-inherit`,children:w.isPending&&k.length===0?(0,L.jsx)(s,{compact:!0,label:`Loading audit trail…`}):w.isError&&k.length===0?(0,L.jsx)(o,{compact:!0,message:p(w.error,`Unable to load audit trail.`),onRetry:()=>void w.refetch()}):k.length===0?(0,L.jsx)(c,{compact:!0,title:`No audit entries yet`,message:`Privileged mutations (provider changes, key rotations, backups, bans) will appear here.`,icon:(0,L.jsx)(d,{size:20})}):(0,L.jsx)(E,{headers:[`Timestamp`,`Actor`,`Action`,`Target`,`Detail`],children:k.map(e=>(0,L.jsx)(ee,{entry:e},e.id))})})})]})}function ee({entry:e}){return(0,L.jsxs)(`tr`,{children:[(0,L.jsx)(`td`,{className:`text-badge text-text-tertiary whitespace-nowrap`,children:new Date(e.createdAt).toLocaleString()}),(0,L.jsxs)(`td`,{className:`max-w-100`,children:[(0,L.jsx)(`div`,{className:`text-caption font-semibold`,children:e.actorName??e.actor}),e.actorName?(0,L.jsx)(`div`,{title:e.actor,className:`truncate font-mono tabular-nums text-micro text-text-tertiary`,children:e.actor}):null]}),(0,L.jsx)(`td`,{children:(0,L.jsx)(w,{tone:e.action.includes(`delete`)||e.action.includes(`revoked`)?`err`:`ok`,title:e.action,children:I(e.action)})}),(0,L.jsx)(`td`,{title:e.target,className:`truncate font-mono tabular-nums text-badge max-w-110`,children:e.target}),(0,L.jsx)(`td`,{className:`font-mono tabular-nums text-badge max-w-160 overflow-hidden truncate`,children:e.detail?JSON.stringify(e.detail):`—`})]})}export{W as default,U as filterLogLines,H as statusTone};
@@ -1 +1 @@
1
- import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{l as i,v as a}from"./numbers-Bs4LOOuf.js";import{t as o}from"./image-BPaouViG.js";import{t as s}from"./layers-2-glBbjl.js";import{t as c}from"./rotate-ccw-CufcqITi.js";import{B as l,G as u,H as d,J as f,K as p,V as m,W as h,X as g,Y as _,q as v,z as y}from"./entry-CkryrIea.js";import{n as b,r as x,t as S}from"./card--AtFedAq.js";import{t as C}from"./switch-CidSfbG7.js";import{t as w}from"./stack-DwLmjUFK.js";import{t as T}from"./inline-BcNGF8Gr.js";var E=e(`frame`,[[`line`,{x1:`22`,x2:`2`,y1:`6`,y2:`6`,key:`15w7dq`}],[`line`,{x1:`22`,x2:`2`,y1:`18`,y2:`18`,key:`1ip48p`}],[`line`,{x1:`6`,x2:`6`,y1:`2`,y2:`22`,key:`a2lnyx`}],[`line`,{x1:`18`,x2:`18`,y1:`2`,y2:`22`,key:`8vb6jd`}]]),D=e(`panel-top`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}]]),O=e(`rectangle-horizontal`,[[`rect`,{width:`20`,height:`12`,x:`2`,y:`6`,rx:`2`,key:`9lu3g6`}]]),k=t(n(),1),A=r(),j={cards:{label:`Cards`,description:`The card body on every page`,icon:(0,A.jsx)(O,{size:15})},chrome:{label:`Sidebar & topbar`,description:`The shell around the page`,icon:(0,A.jsx)(D,{size:15})}};function M(e){return e<1048576?`${Math.max(1,Math.round(e/1024))} KB`:`${(e/1048576).toFixed(1)} MB`}function N(){let[e,t]=d(),[n,r]=(0,k.useState)(!1),[u,f]=(0,k.useState)(null),C=async n=>{let i=n.target.files?.[0];if(n.target.value=``,!i)return;let o=v(i);if(!o){a.error(`Choose an image or a video.`);return}if(i.size>4294967296){a.error(`File too big. 4 GB is the limit.`);return}let s=i.size>h;r(!0);try{let n=o===`image`?await _(i):i;await g(n,o),f(n.size),t({backgroundSet:!0,backgroundEnabled:!0,backgroundRevision:e.backgroundRevision+1}),a.success(o===`video`?`Video background saved in this browser.`:`Background saved in this browser.`),s&&a.warning(`File too big. Your web performance and experience may be degraded.`)}catch{a.error(`Could not store that file. The browser may be out of space.`)}finally{r(!1)}},D=async()=>{r(!0);try{await p(),f(null),t({backgroundSet:!1,backgroundEnabled:!1})}catch{a.error(`Could not remove the background.`)}finally{r(!1)}};return(0,A.jsxs)(w,{gap:`16px`,children:[(0,A.jsxs)(S,{children:[(0,A.jsx)(x,{title:`Background`,subtitle:`Stored in this browser only. It never leaves the machine.`,icon:(0,A.jsx)(o,{size:16}),action:(0,A.jsx)(T,{children:(0,A.jsx)(i,{variant:`ghost`,size:`sm`,icon:(0,A.jsx)(c,{size:13}),onClick:()=>{m({backgroundOpacity:l.backgroundOpacity,backgroundScale:l.backgroundScale,backgroundX:l.backgroundX,backgroundY:l.backgroundY,backgroundBlur:l.backgroundBlur,backgroundEnabled:e.backgroundSet}),a.success(`Background reset to defaults.`)},children:`Reset`})})}),(0,A.jsx)(b,{children:(0,A.jsxs)(w,{gap:`14px`,children:[(0,A.jsx)(P,{settings:e,onBytes:f,bytes:u}),(0,A.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,A.jsxs)(`label`,{className:`btn btn-primary inline-flex items-center justify-center gap-3.5 rounded-control font-semibold text-caption px-7 py-2 cursor-pointer bg-accent text-accent-foreground`,children:[n?`Working…`:e.backgroundSet?`Replace`:`Upload image or video`,(0,A.jsx)(`input`,{type:`file`,accept:`image/*,video/*`,className:`sr-only`,onChange:e=>void C(e),disabled:n})]}),e.backgroundSet?(0,A.jsx)(i,{variant:`danger`,size:`sm`,onClick:()=>void D(),disabled:n,children:`Remove`}):null,(0,A.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Images are resized to 2560px. Videos play on desktop and show their first frame on mobile.`})]}),(0,A.jsx)(F,{settings:e,setSettings:t})]})})]}),(0,A.jsxs)(S,{children:[(0,A.jsx)(x,{title:`Blur`,subtitle:`Each surface keeps its own style. Dialogs are never blurred, so they stay readable.`,icon:(0,A.jsx)(s,{size:16}),action:(0,A.jsx)(T,{children:(0,A.jsx)(i,{variant:`ghost`,size:`sm`,icon:(0,A.jsx)(c,{size:13}),onClick:()=>{m({blurCardsAmount:l.blurCardsAmount,blurChromeAmount:l.blurChromeAmount,blurCardsEnabled:l.blurCardsEnabled,blurChromeEnabled:l.blurChromeEnabled,blurCardsDepth:l.blurCardsDepth,blurChromeDepth:l.blurChromeDepth}),a.success(`Blur reset to defaults.`)},children:`Reset`})})}),(0,A.jsx)(b,{children:(0,A.jsx)(`div`,{className:`grid gap-10 lg:grid-cols-2`,children:y.map(n=>{let r=n===`chrome`;return(0,A.jsx)(L,{target:n,enabled:r?e.blurChromeEnabled:e.blurCardsEnabled,onToggle:()=>t(r?{blurChromeEnabled:!e.blurChromeEnabled}:{blurCardsEnabled:!e.blurCardsEnabled}),clarity:r?e.blurChromeAmount:e.blurCardsAmount,onClarity:e=>t(r?{blurChromeAmount:e}:{blurCardsAmount:e}),depth:r?e.blurChromeDepth:e.blurCardsDepth,onDepth:e=>t(r?{blurChromeDepth:e}:{blurCardsDepth:e})},n)})})})]}),(0,A.jsxs)(S,{children:[(0,A.jsx)(x,{title:`Empty panels`,subtitle:`A dashed frame around a page that has nothing to show yet.`,icon:(0,A.jsx)(E,{size:16})}),(0,A.jsx)(b,{children:(0,A.jsxs)(`button`,{type:`button`,role:`switch`,"aria-checked":e.emptyOutline,onClick:()=>t({emptyOutline:!e.emptyOutline}),className:`flex w-full items-center justify-between gap-6 rounded-card border border-inner-border bg-surface-2 px-7 py-6 text-left`,children:[(0,A.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,A.jsx)(`span`,{className:`text-caption font-semibold text-text-primary`,children:`Dashed border`}),(0,A.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Off leaves the empty state sitting on the card.`})]}),(0,A.jsx)(`span`,{"aria-hidden":`true`,className:e.emptyOutline?`h-10 w-18 shrink-0 rounded-pill bg-accent p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1`,children:(0,A.jsx)(`span`,{className:e.emptyOutline?`block size-8 translate-x-8 rounded-full bg-accent-foreground transition-transform`:`block size-8 rounded-full bg-text-secondary transition-transform`})})]})})]})]})}function P({settings:e,bytes:t,onBytes:n}){let[r,i]=(0,k.useState)(null),[a,o]=(0,k.useState)(null);if((0,k.useEffect)(()=>{if(!e.backgroundSet){i(u),o(`image`);return}let t=!0,r=null;return f().then(e=>{if(e){if(!t){URL.revokeObjectURL(e.url);return}r=e.url,i(e.url),o(e.kind),n(e.blob.size)}}).catch(()=>{}),()=>{t=!1,r&&URL.revokeObjectURL(r)}},[e.backgroundSet,n]),!r)return(0,A.jsx)(`div`,{className:`flex h-60 items-center justify-center rounded-card border border-dashed border-inner-border bg-surface-2 text-caption text-text-tertiary`,children:`No background yet. The console uses its plain surface.`});let s={objectFit:`cover`,objectPosition:`${50+e.backgroundX/2}% ${50+e.backgroundY/2}%`,transform:`scale(${e.backgroundScale/100})`,opacity:e.backgroundOpacity/100};return(0,A.jsxs)(`div`,{className:`relative h-75 overflow-hidden rounded-card border border-inner-border bg-surface-2`,children:[a===`video`?(0,A.jsx)(`video`,{src:r,muted:!0,playsInline:!0,preload:`metadata`,className:`size-full`,style:s}):(0,A.jsx)(`img`,{src:r,alt:``,className:`size-full`,style:s}),(0,A.jsxs)(`span`,{className:`absolute bottom-4 left-5 rounded-control bg-surface-1 px-4 py-1 text-micro text-text-secondary`,children:[a===`video`?`Video`:`Image`,t===null?``:` · ${M(t)}`,e.backgroundEnabled?``:` · hidden`]})]})}function F({settings:e,setSettings:t}){return(0,A.jsxs)(`div`,{className:`flex flex-col gap-7`,children:[(0,A.jsxs)(`label`,{className:`flex min-h-18 items-center justify-between gap-6 text-body font-semibold text-text-primary`,children:[(0,A.jsx)(`span`,{children:`Show background`}),(0,A.jsx)(C,{checked:e.backgroundEnabled,onChange:e=>t({backgroundEnabled:e}),"aria-label":`Show background`})]}),(0,A.jsxs)(`div`,{className:`grid gap-7 sm:grid-cols-2`,children:[(0,A.jsx)(I,{label:`Visibility`,value:e.backgroundOpacity,defaultValue:l.backgroundOpacity,min:0,max:100,unit:`%`,onChange:e=>t({backgroundOpacity:e})}),(0,A.jsx)(I,{label:`Blur`,value:e.backgroundBlur,defaultValue:l.backgroundBlur,min:0,max:100,unit:`%`,onChange:e=>t({backgroundBlur:e})}),(0,A.jsx)(I,{label:`Zoom`,value:e.backgroundScale,defaultValue:l.backgroundScale,min:100,max:180,unit:`%`,onChange:e=>t({backgroundScale:e})}),(0,A.jsx)(I,{label:`Shift horizontal`,value:e.backgroundX,defaultValue:l.backgroundX,min:-100,max:100,onChange:e=>t({backgroundX:e})}),(0,A.jsx)(I,{label:`Shift vertical`,value:e.backgroundY,defaultValue:l.backgroundY,min:-100,max:100,onChange:e=>t({backgroundY:e})})]})]})}function I({label:e,value:t,defaultValue:n,min:r,max:i,unit:a,onChange:o}){return(0,A.jsxs)(`label`,{className:`flex flex-col gap-2 text-caption text-text-secondary`,children:[(0,A.jsxs)(`span`,{className:`flex items-center justify-between`,children:[e,(0,A.jsxs)(`span`,{className:`flex items-center gap-3`,children:[(0,A.jsxs)(`span`,{className:`font-mono tabular-nums text-badge text-text-tertiary`,children:[t,a??``]}),(0,A.jsx)(`button`,{type:`button`,onClick:()=>o(n),disabled:t===n,"aria-label":`Reset ${e}`,title:`Reset ${e} to ${n}${a??``}`,className:`flex size-9 items-center justify-center rounded-control text-text-tertiary hover:bg-hover hover:text-text-primary disabled:pointer-events-none disabled:opacity-30`,children:(0,A.jsx)(c,{size:11})})]})]}),(0,A.jsx)(`input`,{type:`range`,min:r,max:i,value:t,onChange:e=>o(Number(e.target.value)),"aria-label":e,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${(t-r)/(i-r)*100}%`}})]})}function L({target:e,enabled:t,onToggle:n,clarity:r,onClarity:i,depth:a,onDepth:o}){let s=j[e]??j.cards;return(0,A.jsxs)(`div`,{className:`flex flex-col gap-8 rounded-card border border-inner-border bg-surface-2 p-8`,children:[(0,A.jsxs)(`div`,{className:`flex items-center gap-5`,children:[(0,A.jsx)(`span`,{className:`flex size-16 shrink-0 items-center justify-center rounded-control bg-surface-1 text-text-secondary`,children:s.icon}),(0,A.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col`,children:[(0,A.jsx)(`span`,{className:`text-body font-semibold text-text-primary`,children:s.label}),(0,A.jsx)(`span`,{className:`text-micro text-text-tertiary`,children:s.description})]}),(0,A.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":t,"aria-label":`Toggle ${s.label} blur`,onClick:n,className:t?`h-10 w-18 shrink-0 rounded-pill bg-accent p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1`,children:(0,A.jsx)(`span`,{className:t?`block size-8 translate-x-8 rounded-full bg-accent-foreground`:`block size-8 rounded-full bg-text-secondary`})})]}),(0,A.jsxs)(`div`,{className:t?`flex flex-col gap-6`:`flex flex-col gap-6 opacity-40`,children:[(0,A.jsxs)(`label`,{className:`flex flex-col gap-3 text-caption text-text-secondary`,children:[(0,A.jsxs)(`span`,{className:`flex items-center justify-between`,children:[`Clarity`,(0,A.jsxs)(`span`,{className:`font-mono text-badge tabular-nums text-text-tertiary`,children:[r,`%`]})]}),(0,A.jsx)(`input`,{type:`range`,min:0,max:100,value:r,disabled:!t,onChange:e=>i(Number(e.target.value)),"aria-label":`${s.label} clarity. How see-through the surface is.`,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${r}%`}}),(0,A.jsxs)(`span`,{className:`flex justify-between text-badge text-text-tertiary`,children:[(0,A.jsx)(`span`,{children:`See-through`}),(0,A.jsx)(`span`,{children:`Solid`})]})]}),(0,A.jsxs)(`label`,{className:`flex flex-col gap-3 text-caption text-text-secondary`,children:[(0,A.jsxs)(`span`,{className:`flex items-center justify-between`,children:[`Blur`,(0,A.jsxs)(`span`,{className:`font-mono text-badge tabular-nums text-text-tertiary`,children:[a,`%`]})]}),(0,A.jsx)(`input`,{type:`range`,min:0,max:100,value:a,disabled:!t,onChange:e=>o(Number(e.target.value)),"aria-label":`${s.label} blur. How blurred whatever is behind it looks.`,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${a}%`}}),(0,A.jsxs)(`span`,{className:`flex justify-between text-badge text-text-tertiary`,children:[(0,A.jsx)(`span`,{children:`Sharp`}),(0,A.jsx)(`span`,{children:`Blurred`})]})]})]})]})}export{N as default};
1
+ import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{_ as i,c as a}from"./numbers-DkfMR5Qs.js";import{t as o}from"./image-BPaouViG.js";import{t as s}from"./layers-2-glBbjl.js";import{t as c}from"./rotate-ccw-CufcqITi.js";import{B as l,G as u,H as d,J as f,K as p,U as m,V as h,X as g,Y as _,Z as v,q as y}from"./entry-DxBHnauy.js";import{n as b,r as x,t as S}from"./card-DS7CQEsO.js";import{t as C}from"./switch-DOmJxg7H.js";import{t as w}from"./stack-BHTfXdz_.js";import{t as T}from"./inline-BhY2sSnO.js";var E=e(`frame`,[[`line`,{x1:`22`,x2:`2`,y1:`6`,y2:`6`,key:`15w7dq`}],[`line`,{x1:`22`,x2:`2`,y1:`18`,y2:`18`,key:`1ip48p`}],[`line`,{x1:`6`,x2:`6`,y1:`2`,y2:`22`,key:`a2lnyx`}],[`line`,{x1:`18`,x2:`18`,y1:`2`,y2:`22`,key:`8vb6jd`}]]),D=e(`panel-top`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}]]),O=e(`rectangle-horizontal`,[[`rect`,{width:`20`,height:`12`,x:`2`,y:`6`,rx:`2`,key:`9lu3g6`}]]),k=t(n(),1),A=r(),j={cards:{label:`Cards`,description:`The card body on every page`,icon:(0,A.jsx)(O,{size:15})},chrome:{label:`Sidebar & topbar`,description:`The shell around the page`,icon:(0,A.jsx)(D,{size:15})}};function M(e){return e<1048576?`${Math.max(1,Math.round(e/1024))} KB`:`${(e/1048576).toFixed(1)} MB`}function N(){let[e,t]=m(),[n,r]=(0,k.useState)(!1),[p,_]=(0,k.useState)(null),C=async n=>{let a=n.target.files?.[0];if(n.target.value=``,!a)return;let o=f(a);if(!o){i.error(`Choose an image or a video.`);return}if(a.size>4294967296){i.error(`File too big. 4 GB is the limit.`);return}let s=a.size>u;r(!0);try{let n=o===`image`?await g(a):a;await v(n,o),_(n.size),t({backgroundSet:!0,backgroundEnabled:!0,backgroundRevision:e.backgroundRevision+1}),i.success(o===`video`?`Video background saved in this browser.`:`Background saved in this browser.`),s&&i.warning(`File too big. Your web performance and experience may be degraded.`)}catch{i.error(`Could not store that file. The browser may be out of space.`)}finally{r(!1)}},D=async()=>{r(!0);try{await y(),_(null),t({backgroundSet:!1,backgroundEnabled:!1})}catch{i.error(`Could not remove the background.`)}finally{r(!1)}};return(0,A.jsxs)(w,{gap:`16px`,children:[(0,A.jsxs)(S,{children:[(0,A.jsx)(x,{title:`Background`,subtitle:`Stored in this browser only. It never leaves the machine.`,icon:(0,A.jsx)(o,{size:16}),action:(0,A.jsx)(T,{children:(0,A.jsx)(a,{variant:`ghost`,size:`sm`,icon:(0,A.jsx)(c,{size:13}),onClick:()=>{d({backgroundOpacity:h.backgroundOpacity,backgroundScale:h.backgroundScale,backgroundX:h.backgroundX,backgroundY:h.backgroundY,backgroundBlur:h.backgroundBlur,backgroundEnabled:e.backgroundSet}),i.success(`Background reset to defaults.`)},children:`Reset`})})}),(0,A.jsx)(b,{children:(0,A.jsxs)(w,{gap:`14px`,children:[(0,A.jsx)(P,{settings:e,onBytes:_,bytes:p}),(0,A.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,A.jsxs)(`label`,{className:`btn btn-primary inline-flex items-center justify-center gap-3.5 rounded-control font-semibold text-caption px-7 py-2 cursor-pointer bg-accent text-accent-foreground`,children:[n?`Working…`:e.backgroundSet?`Replace`:`Upload image or video`,(0,A.jsx)(`input`,{type:`file`,accept:`image/*,video/*`,className:`sr-only`,onChange:e=>void C(e),disabled:n})]}),e.backgroundSet?(0,A.jsx)(a,{variant:`danger`,size:`sm`,onClick:()=>void D(),disabled:n,children:`Remove`}):null,(0,A.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Images are resized to 2560px. Videos play on desktop and show their first frame on mobile.`})]}),(0,A.jsx)(F,{settings:e,setSettings:t})]})})]}),(0,A.jsxs)(S,{children:[(0,A.jsx)(x,{title:`Blur`,subtitle:`Each surface keeps its own style. Dialogs are never blurred, so they stay readable.`,icon:(0,A.jsx)(s,{size:16}),action:(0,A.jsx)(T,{children:(0,A.jsx)(a,{variant:`ghost`,size:`sm`,icon:(0,A.jsx)(c,{size:13}),onClick:()=>{d({blurCardsAmount:h.blurCardsAmount,blurChromeAmount:h.blurChromeAmount,blurCardsEnabled:h.blurCardsEnabled,blurChromeEnabled:h.blurChromeEnabled,blurCardsDepth:h.blurCardsDepth,blurChromeDepth:h.blurChromeDepth}),i.success(`Blur reset to defaults.`)},children:`Reset`})})}),(0,A.jsx)(b,{children:(0,A.jsx)(`div`,{className:`grid gap-10 lg:grid-cols-2`,children:l.map(n=>{let r=n===`chrome`;return(0,A.jsx)(L,{target:n,enabled:r?e.blurChromeEnabled:e.blurCardsEnabled,onToggle:()=>t(r?{blurChromeEnabled:!e.blurChromeEnabled}:{blurCardsEnabled:!e.blurCardsEnabled}),clarity:r?e.blurChromeAmount:e.blurCardsAmount,onClarity:e=>t(r?{blurChromeAmount:e}:{blurCardsAmount:e}),depth:r?e.blurChromeDepth:e.blurCardsDepth,onDepth:e=>t(r?{blurChromeDepth:e}:{blurCardsDepth:e})},n)})})})]}),(0,A.jsxs)(S,{children:[(0,A.jsx)(x,{title:`Empty panels`,subtitle:`A dashed frame around a page that has nothing to show yet.`,icon:(0,A.jsx)(E,{size:16})}),(0,A.jsx)(b,{children:(0,A.jsxs)(`button`,{type:`button`,role:`switch`,"aria-checked":e.emptyOutline,onClick:()=>t({emptyOutline:!e.emptyOutline}),className:`flex w-full items-center justify-between gap-6 rounded-card border border-inner-border bg-surface-2 px-7 py-6 text-left`,children:[(0,A.jsxs)(`span`,{className:`flex min-w-0 flex-col`,children:[(0,A.jsx)(`span`,{className:`text-caption font-semibold text-text-primary`,children:`Dashed border`}),(0,A.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:`Off leaves the empty state sitting on the card.`})]}),(0,A.jsx)(`span`,{"aria-hidden":`true`,className:e.emptyOutline?`h-10 w-18 shrink-0 rounded-pill bg-accent p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1`,children:(0,A.jsx)(`span`,{className:e.emptyOutline?`block size-8 translate-x-8 rounded-full bg-accent-foreground transition-transform`:`block size-8 rounded-full bg-text-secondary transition-transform`})})]})})]})]})}function P({settings:e,bytes:t,onBytes:n}){let[r,i]=(0,k.useState)(null),[a,o]=(0,k.useState)(null);if((0,k.useEffect)(()=>{if(!e.backgroundSet){i(p),o(`image`);return}let t=!0,r=null;return _().then(e=>{if(e){if(!t){URL.revokeObjectURL(e.url);return}r=e.url,i(e.url),o(e.kind),n(e.blob.size)}}).catch(()=>{}),()=>{t=!1,r&&URL.revokeObjectURL(r)}},[e.backgroundSet,n]),!r)return(0,A.jsx)(`div`,{className:`flex h-60 items-center justify-center rounded-card border border-dashed border-inner-border bg-surface-2 text-caption text-text-tertiary`,children:`No background yet. The console uses its plain surface.`});let s={objectFit:`cover`,objectPosition:`${50+e.backgroundX/2}% ${50+e.backgroundY/2}%`,transform:`scale(${e.backgroundScale/100})`,opacity:e.backgroundOpacity/100};return(0,A.jsxs)(`div`,{className:`relative h-75 overflow-hidden rounded-card border border-inner-border bg-surface-2`,children:[a===`video`?(0,A.jsx)(`video`,{src:r,muted:!0,playsInline:!0,preload:`metadata`,className:`size-full`,style:s}):(0,A.jsx)(`img`,{src:r,alt:``,className:`size-full`,style:s}),(0,A.jsxs)(`span`,{className:`absolute bottom-4 left-5 rounded-control bg-surface-1 px-4 py-1 text-micro text-text-secondary`,children:[a===`video`?`Video`:`Image`,t===null?``:` · ${M(t)}`,e.backgroundEnabled?``:` · hidden`]})]})}function F({settings:e,setSettings:t}){return(0,A.jsxs)(`div`,{className:`flex flex-col gap-7`,children:[(0,A.jsxs)(`label`,{className:`flex min-h-18 items-center justify-between gap-6 text-body font-semibold text-text-primary`,children:[(0,A.jsx)(`span`,{children:`Show background`}),(0,A.jsx)(C,{checked:e.backgroundEnabled,onChange:e=>t({backgroundEnabled:e}),"aria-label":`Show background`})]}),(0,A.jsxs)(`div`,{className:`grid gap-7 sm:grid-cols-2`,children:[(0,A.jsx)(I,{label:`Visibility`,value:e.backgroundOpacity,defaultValue:h.backgroundOpacity,min:0,max:100,unit:`%`,onChange:e=>t({backgroundOpacity:e})}),(0,A.jsx)(I,{label:`Blur`,value:e.backgroundBlur,defaultValue:h.backgroundBlur,min:0,max:100,unit:`%`,onChange:e=>t({backgroundBlur:e})}),(0,A.jsx)(I,{label:`Zoom`,value:e.backgroundScale,defaultValue:h.backgroundScale,min:100,max:180,unit:`%`,onChange:e=>t({backgroundScale:e})}),(0,A.jsx)(I,{label:`Shift horizontal`,value:e.backgroundX,defaultValue:h.backgroundX,min:-100,max:100,onChange:e=>t({backgroundX:e})}),(0,A.jsx)(I,{label:`Shift vertical`,value:e.backgroundY,defaultValue:h.backgroundY,min:-100,max:100,onChange:e=>t({backgroundY:e})})]})]})}function I({label:e,value:t,defaultValue:n,min:r,max:i,unit:a,onChange:o}){return(0,A.jsxs)(`label`,{className:`flex flex-col gap-2 text-caption text-text-secondary`,children:[(0,A.jsxs)(`span`,{className:`flex items-center justify-between`,children:[e,(0,A.jsxs)(`span`,{className:`flex items-center gap-3`,children:[(0,A.jsxs)(`span`,{className:`font-mono tabular-nums text-badge text-text-tertiary`,children:[t,a??``]}),(0,A.jsx)(`button`,{type:`button`,onClick:()=>o(n),disabled:t===n,"aria-label":`Reset ${e}`,title:`Reset ${e} to ${n}${a??``}`,className:`flex size-9 items-center justify-center rounded-control text-text-tertiary hover:bg-hover hover:text-text-primary disabled:pointer-events-none disabled:opacity-30`,children:(0,A.jsx)(c,{size:11})})]})]}),(0,A.jsx)(`input`,{type:`range`,min:r,max:i,value:t,onChange:e=>o(Number(e.target.value)),"aria-label":e,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${(t-r)/(i-r)*100}%`}})]})}function L({target:e,enabled:t,onToggle:n,clarity:r,onClarity:i,depth:a,onDepth:o}){let s=j[e]??j.cards;return(0,A.jsxs)(`div`,{className:`flex flex-col gap-8 rounded-card border border-inner-border bg-surface-2 p-8`,children:[(0,A.jsxs)(`div`,{className:`flex items-center gap-5`,children:[(0,A.jsx)(`span`,{className:`flex size-16 shrink-0 items-center justify-center rounded-control bg-surface-1 text-text-secondary`,children:s.icon}),(0,A.jsxs)(`span`,{className:`flex min-w-0 flex-1 flex-col`,children:[(0,A.jsx)(`span`,{className:`text-body font-semibold text-text-primary`,children:s.label}),(0,A.jsx)(`span`,{className:`text-micro text-text-tertiary`,children:s.description})]}),(0,A.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":t,"aria-label":`Toggle ${s.label} blur`,onClick:n,className:t?`h-10 w-18 shrink-0 rounded-pill bg-accent p-1`:`h-10 w-18 shrink-0 rounded-pill bg-surface-active p-1`,children:(0,A.jsx)(`span`,{className:t?`block size-8 translate-x-8 rounded-full bg-accent-foreground`:`block size-8 rounded-full bg-text-secondary`})})]}),(0,A.jsxs)(`div`,{className:t?`flex flex-col gap-6`:`flex flex-col gap-6 opacity-40`,children:[(0,A.jsxs)(`label`,{className:`flex flex-col gap-3 text-caption text-text-secondary`,children:[(0,A.jsxs)(`span`,{className:`flex items-center justify-between`,children:[`Clarity`,(0,A.jsxs)(`span`,{className:`font-mono text-badge tabular-nums text-text-tertiary`,children:[r,`%`]})]}),(0,A.jsx)(`input`,{type:`range`,min:0,max:100,value:r,disabled:!t,onChange:e=>i(Number(e.target.value)),"aria-label":`${s.label} clarity. How see-through the surface is.`,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${r}%`}}),(0,A.jsxs)(`span`,{className:`flex justify-between text-badge text-text-tertiary`,children:[(0,A.jsx)(`span`,{children:`See-through`}),(0,A.jsx)(`span`,{children:`Solid`})]})]}),(0,A.jsxs)(`label`,{className:`flex flex-col gap-3 text-caption text-text-secondary`,children:[(0,A.jsxs)(`span`,{className:`flex items-center justify-between`,children:[`Blur`,(0,A.jsxs)(`span`,{className:`font-mono text-badge tabular-nums text-text-tertiary`,children:[a,`%`]})]}),(0,A.jsx)(`input`,{type:`range`,min:0,max:100,value:a,disabled:!t,onChange:e=>o(Number(e.target.value)),"aria-label":`${s.label} blur. How blurred whatever is behind it looks.`,className:`blur-slider w-full h-11 m-0 border-0 rounded-pill cursor-pointer`,style:{"--fill":`${a}%`}}),(0,A.jsxs)(`span`,{className:`flex justify-between text-badge text-text-tertiary`,children:[(0,A.jsx)(`span`,{children:`Sharp`}),(0,A.jsx)(`span`,{children:`Blurred`})]})]})]})]})}export{N as default};
@@ -0,0 +1 @@
1
+ import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{i as r}from"./terminal-0_IjPWTk.js";import{c as i,s as a}from"./numbers-DkfMR5Qs.js";import{n as o,r as s,t as c}from"./state-mPDRlQkl.js";import{t as l}from"./dialog-k37exjNt.js";import{t as u}from"./rotate-ccw-CufcqITi.js";import{t as d}from"./trash-Cppn5c3R.js";import{C as f,T as p,v as m}from"./assert-C9FD_JwJ.js";import{o as h,t as g}from"./query-keys-BFhGpwR1.js";import{t as _}from"./useMutation-Dem0lXQj.js";import{k as v,n as y,v as b,y as x,z as S}from"./entry-DxBHnauy.js";import{t as C}from"./badge-CR72dasT.js";import{n as w}from"./inline-BhY2sSnO.js";import{t as T}from"./layout-BBOYycyS.js";async function E(e){return h(`/quota/overview`,e?{signal:e}:void 0)}function D(){return f({queryKey:g.quota.all,queryFn:e=>E(m(e)),staleTime:1/0,refetchInterval:!1,refetchIntervalInBackground:!1,refetchOnMount:!1,refetchOnWindowFocus:!1,placeholderData:e=>e})}function O(e){let t=p(),n=g.quota.account(e);return _({mutationFn:async()=>h(`/accounts/${encodeURIComponent(e)}/quota/refresh`,{method:`POST`}),onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:n,exact:!0}),t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}var k=100;function A(){let e=p();return _({mutationFn:async e=>{let t=[];for(let n=0;n<e.length;n+=k)t.push(e.slice(n,n+k));let n=await Promise.all(t.map(e=>h(`/quota/refresh`,{method:`POST`,body:JSON.stringify({accountIds:e})}))),r=n.flatMap(e=>e.failures);return{ok:r.length===0,queued:n.reduce((e,t)=>e+t.queued,0),succeeded:n.reduce((e,t)=>e+t.succeeded,0),failed:n.reduce((e,t)=>e+t.failed,0),failures:r}},onSuccess:async(t,n)=>{let r=new Set(t.failures.map(e=>e.accountId)),i=n.filter(e=>!r.has(e));await Promise.all([...i.map(t=>e.invalidateQueries({queryKey:g.quota.account(t),exact:!0})),e.invalidateQueries({queryKey:g.quota.all})])}})}function j(){let e=p();return _({mutationFn:({id:e,active:t})=>h(`/accounts/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({active:t})}),onSuccess:async()=>{await Promise.all([e.invalidateQueries({queryKey:g.quota.all}),e.invalidateQueries({queryKey:g.providers.all})])}})}function M(){let e=p();return _({mutationFn:async({ids:e,active:t})=>{e.length!==0&&await h(`/accounts/batch`,{method:`PATCH`,body:JSON.stringify({ids:e,active:t})})},onSuccess:async()=>{await Promise.all([e.invalidateQueries({queryKey:g.quota.all}),e.invalidateQueries({queryKey:g.providers.all})])}})}function N(){let e=p();return _({mutationFn:async e=>{await h(`/accounts/${encodeURIComponent(e)}`,{method:`DELETE`})},onSuccess:async(t,n)=>{e.removeQueries({queryKey:g.quota.account(n),exact:!0}),await Promise.all([e.invalidateQueries({queryKey:g.quota.all}),e.invalidateQueries({queryKey:g.providers.all})])}})}var P=new Set([`workbuddy`,`workbuddycn`,`cb`,`cbcn`]);function F(e){return P.has(e.trim().toLowerCase())}function I(e){let t=p();return _({mutationFn:async()=>{if(e.length===0)throw Error(`Select a provider first`);return h(`/quota/daily-growth`,{method:`POST`,body:JSON.stringify({providerId:e})})},onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}function L(e){let t=p();return _({mutationFn:async()=>{let t=await h(`/accounts/${encodeURIComponent(e)}/activity-report`,{method:`POST`}),n=t.message??`Activity reported`,r=await h(`/accounts/${encodeURIComponent(e)}/checkin`,{method:`POST`}),i=r.message??`Daily check-in done`;return{ok:t.ok,message:t.ok?`Report success · Check-in ${i}`:`Report failed: ${n} · Check-in ${i}`,checkin:r,report:t}},onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}var R=new Set([`codex`,`claude`,`anthropic`]);function z(e){return R.has(e.trim().toLowerCase())}function B(e,t){return f({queryKey:g.quota.resets(e),queryFn:({signal:t})=>h(`/accounts/${encodeURIComponent(e)}/resets`,t?{signal:t}:void 0),enabled:t,staleTime:3e4})}function V(e){let t=p();return _({mutationFn:async t=>h(`/accounts/${encodeURIComponent(e)}/reset`,{method:`POST`,body:JSON.stringify(t??{})}),onSettled:async()=>{await Promise.all([t.invalidateQueries({queryKey:g.quota.all}),t.invalidateQueries({queryKey:g.providers.all})])}})}var H=e(t(),1),U=n();function W(e){return e===`cooldown`}function G(e){return e===`active`?`ok`:e===`disabled`?`disabled`:`warn`}function K(e,t){return e?{title:`Enable static-token mode?`,message:`${t} will be used exactly as issued and will not be refreshed. Re-enable refresh before this token expires.`,confirmLabel:`Enable static mode`}:{title:`Re-enable credential refresh?`,message:`${t} will return to the OAuth refresh sweep. Use this only when a refresh token is available.`,confirmLabel:`Re-enable refresh`}}function q({summary:e,onClose:t}){let{providerId:n,accountId:f,title:p,status:m,errorCategory:h,errorMessage:g}=e,_=y(n,f),E=x(),D=_.data??[],O=v(),k=e.credentialKind===`oauth`||e.credentialMode===`jwt`||e.staticToken===!0,[A,j]=(0,H.useState)(e.staticToken===!0),[M,N]=(0,H.useState)(null),[P,F]=(0,H.useState)(!1);(0,H.useEffect)(()=>j(e.staticToken===!0),[e.staticToken]);let I=b();return(0,U.jsx)(l,{open:!0,onClose:t,title:`Health & Error Log — ${p}`,size:`lg`,children:(0,U.jsxs)(`div`,{className:`flex flex-col gap-7 min-w-0`,children:[(0,U.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-5 rounded-control border border-inner-border bg-surface-2 py-5 px-7`,children:[(0,U.jsxs)(`div`,{className:`min-w-0`,children:[(0,U.jsxs)(w,{gap:`8px`,className:`flex-wrap`,children:[(0,U.jsx)(`span`,{className:`text-body font-semibold`,children:`Account status:`}),(0,U.jsx)(C,{tone:G(m),dot:!0,children:m.toUpperCase()}),h?(0,U.jsx)(C,{tone:`warn`,title:g??void 0,children:h}):null]}),g?(0,U.jsx)(`p`,{className:`text-badge text-red mt-2 wrap-anywhere`,children:g}):null]}),W(m)?(0,U.jsx)(i,{size:`sm`,variant:`secondary`,icon:(0,U.jsx)(u,{size:12,className:E.isPending?`animate-spin`:``}),disabled:E.isPending,onClick:()=>E.mutate({providerId:n,accountId:f},{onSuccess:()=>void _.refetch()}),children:E.isPending?`Recovering...`:`Recover Now`}):null]}),k?(0,U.jsxs)(`div`,{className:`flex items-center justify-between gap-6 rounded-control border border-inner-border bg-surface-2 py-5 px-7`,children:[(0,U.jsxs)(`div`,{children:[(0,U.jsx)(`div`,{className:`text-caption font-semibold`,children:`Credential management`}),(0,U.jsx)(`div`,{className:`text-badge text-text-tertiary`,children:A?`Static mode: no refresh request will be sent.`:`OAuth refresh is enabled for this account.`})]}),(0,U.jsx)(i,{size:`sm`,variant:A?`primary`:`secondary`,disabled:O.isPending,onClick:()=>N(!A),children:A?`Static · no refresh`:`Enable static mode`})]}):null,(0,U.jsxs)(`div`,{className:`min-w-0`,children:[(0,U.jsxs)(`div`,{className:`flex items-center justify-between gap-5 mb-4`,children:[(0,U.jsxs)(`h4`,{className:`text-caption font-semibold text-text-secondary`,children:[`Transition Events & Audit (`,D.length,`)`]}),(0,U.jsx)(i,{size:`sm`,variant:`secondary`,icon:(0,U.jsx)(d,{size:12}),disabled:D.length===0||I.isPending,onClick:()=>F(!0),title:`Deletes this account's recorded transitions and audit entries.`,children:`Purge log`})]}),_.isPending?(0,U.jsx)(s,{compact:!0,label:`Loading health events...`}):_.isError?(0,U.jsx)(o,{compact:!0,message:`Failed to load health events`,onRetry:()=>void _.refetch()}):D.length===0?(0,U.jsx)(c,{compact:!0,title:`No health events recorded`,message:e.emptyMessage,icon:(0,U.jsx)(r,{size:20})}):(0,U.jsx)(`div`,{className:`rounded-inset border border-inner-border`,children:(0,U.jsx)(T,{maxHeight:480,scrollRegion:!0,headers:[`Timestamp`,`From → To`,`Model`,`Category`,`Reason / Details`],children:D.map(e=>(0,U.jsxs)(`tr`,{children:[(0,U.jsx)(`td`,{className:`text-badge text-text-tertiary whitespace-nowrap`,children:new Date(e.createdAt).toLocaleString()}),(0,U.jsxs)(`td`,{className:`whitespace-nowrap`,children:[(0,U.jsxs)(`span`,{className:`text-badge text-text-secondary`,children:[e.fromStatus??`new`,` →`,` `]}),(0,U.jsx)(C,{tone:G(e.toStatus),children:e.toStatus})]}),(0,U.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary wrap-anywhere`,children:e.modelId??`—`}),(0,U.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary`,children:e.errorCategory??`—`}),(0,U.jsx)(`td`,{className:`text-badge text-text-primary min-w-110 max-w-260 wrap-anywhere`,children:e.reason??`—`})]},e.id))})})]}),(0,U.jsx)(S,{open:M!==null,onClose:()=>N(null),onConfirm:()=>{let e=M===!0;O.mutate({providerId:n,accountId:f,request:{staticToken:e}},{onSuccess:()=>{j(e),N(null),a.success(e?`Static mode enabled`:`Credential refresh re-enabled`,p),_.refetch()},onError:e=>a.error(`Credential update failed`,e instanceof Error?e.message:`Unable to update credential mode`)})},title:K(M===!0,p).title,message:K(M===!0,p).message,confirmLabel:K(M===!0,p).confirmLabel,cancelLabel:`Cancel`}),(0,U.jsx)(S,{open:P,onClose:()=>F(!1),onConfirm:()=>{I.mutate({providerId:n,accountId:f,title:p},{onSuccess:()=>F(!1)})},title:`Purge the health & error log for ${p}?`,message:`Deletes every transition and audit entry recorded for this account. Its status, credentials, and counters are untouched. This cannot be undone.`,confirmLabel:`Purge log`,cancelLabel:`Cancel`}),(0,U.jsx)(w,{justify:`flex-end`,gap:`0px`,children:(0,U.jsx)(i,{variant:`secondary`,size:`sm`,onClick:t,children:`Close`})})]})})}export{N as a,A as c,L as d,I as f,B as i,M as l,F as n,D as o,j as p,z as r,O as s,q as t,V as u};
@@ -1 +1 @@
1
- import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{l as r}from"./numbers-Bs4LOOuf.js";import{t as i}from"./log-in-BmRjy60c.js";import{o as a,t as o}from"./query-keys-D7wX2vM5.js";import{I as s,Q as c,et as l}from"./entry-CkryrIea.js";import{n as u}from"./input-BG41et9G.js";var d=e(t(),1),f=n();function p(e){return e?.startsWith(`/`)&&!e.startsWith(`//`)?e:`/`}function m(){let e=c(),[t]=l(),[n,m]=(0,d.useState)(``),[h,g]=(0,d.useState)(``),[_,v]=(0,d.useState)(null),[y,b]=(0,d.useState)(!1),[x,S]=(0,d.useState)(!0);return(0,d.useEffect)(()=>{let t=!0;return a(`/auth/first-boot`).then(n=>{if(t){if(n.requires_setup){e(`/setup`,{replace:!0});return}S(!1)}}).catch(()=>{t&&S(!1)}),()=>{t=!1}},[e]),x?(0,f.jsx)(`main`,{className:`auth-viewport`,children:(0,f.jsx)(`div`,{className:`card-solid auth-window`,children:(0,f.jsxs)(`div`,{className:`auth-header`,children:[(0,f.jsx)(`div`,{className:`auth-logo`,"aria-hidden":`true`}),(0,f.jsx)(`h1`,{className:`auth-title`,children:`Cartethyia Console`}),(0,f.jsx)(`p`,{className:`auth-desc`,children:`Checking console setup...`})]})})}):(0,f.jsx)(`main`,{className:`auth-viewport`,children:(0,f.jsxs)(`div`,{className:`card-solid auth-window`,children:[(0,f.jsxs)(`div`,{className:`auth-header`,children:[(0,f.jsx)(`div`,{className:`auth-logo`,"aria-hidden":`true`}),(0,f.jsx)(`h1`,{className:`auth-title`,children:`Cartethyia Console`}),(0,f.jsx)(`p`,{className:`auth-desc`,children:`Sign in to manage AI Gateway routing and providers`})]}),(0,f.jsxs)(`form`,{onSubmit:async r=>{r.preventDefault(),b(!0),v(null);try{let r=await a(`/auth/login`,{method:`POST`,body:JSON.stringify({username:n.trim(),password:h})});if(r.status!==`success`){if(r.requires_setup){e(`/setup`,{replace:!0});return}g(``),v(r.message??`Authentication failed. Please check your credentials.`);return}s.removeQueries({queryKey:o.session.current}),e(r.requires_setup?`/setup`:p(t.get(`returnTo`)),{replace:!0})}catch(e){if(e&&typeof e==`object`&&`message`in e){let t=e.message;if(typeof t==`string`){g(``),v(t);return}}v(`An unexpected network error occurred.`)}finally{b(!1)}},className:`flex flex-col gap-7`,children:[(0,f.jsx)(u,{label:`Username`,id:`login-username`,value:n,onChange:e=>m(e.target.value),required:!0,autoComplete:`username`,placeholder:`admin`}),(0,f.jsx)(u,{label:`Password`,id:`login-password`,type:`password`,value:h,onChange:e=>g(e.target.value),required:!0,autoComplete:`current-password`}),_?(0,f.jsx)(`div`,{className:`py-5 px-7 rounded-control bg-red-soft text-red text-caption font-medium`,role:`alert`,children:_}):null,(0,f.jsx)(r,{variant:`primary`,type:`submit`,disabled:y,className:`w-full mt-3 h-20`,icon:(0,f.jsx)(i,{size:15}),children:y?`Authenticating…`:`Sign In`})]})]})})}export{m as default};
1
+ import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{c as r}from"./numbers-DkfMR5Qs.js";import{t as i}from"./log-in-BmRjy60c.js";import{o as a,t as o}from"./query-keys-BFhGpwR1.js";import{$ as s,L as c,tt as l}from"./entry-DxBHnauy.js";import{n as u}from"./input-V1umFiBk.js";var d=e(t(),1),f=n();function p(e){return e?.startsWith(`/`)&&!e.startsWith(`//`)?e:`/`}function m(){let e=s(),[t]=l(),[n,m]=(0,d.useState)(``),[h,g]=(0,d.useState)(``),[_,v]=(0,d.useState)(null),[y,b]=(0,d.useState)(!1),[x,S]=(0,d.useState)(!0);return(0,d.useEffect)(()=>{let t=!0;return a(`/auth/first-boot`).then(n=>{if(t){if(n.requires_setup){e(`/setup`,{replace:!0});return}S(!1)}}).catch(()=>{t&&S(!1)}),()=>{t=!1}},[e]),x?(0,f.jsx)(`main`,{className:`auth-viewport`,children:(0,f.jsx)(`div`,{className:`card-solid auth-window`,children:(0,f.jsxs)(`div`,{className:`auth-header`,children:[(0,f.jsx)(`div`,{className:`auth-logo`,"aria-hidden":`true`}),(0,f.jsx)(`h1`,{className:`auth-title`,children:`Cartethyia Console`}),(0,f.jsx)(`p`,{className:`auth-desc`,children:`Checking console setup...`})]})})}):(0,f.jsx)(`main`,{className:`auth-viewport`,children:(0,f.jsxs)(`div`,{className:`card-solid auth-window`,children:[(0,f.jsxs)(`div`,{className:`auth-header`,children:[(0,f.jsx)(`div`,{className:`auth-logo`,"aria-hidden":`true`}),(0,f.jsx)(`h1`,{className:`auth-title`,children:`Cartethyia Console`}),(0,f.jsx)(`p`,{className:`auth-desc`,children:`Sign in to manage AI Gateway routing and providers`})]}),(0,f.jsxs)(`form`,{onSubmit:async r=>{r.preventDefault(),b(!0),v(null);try{let r=await a(`/auth/login`,{method:`POST`,body:JSON.stringify({username:n.trim(),password:h})});if(r.status!==`success`){if(r.requires_setup){e(`/setup`,{replace:!0});return}g(``),v(r.message??`Authentication failed. Please check your credentials.`);return}c.removeQueries({queryKey:o.session.current}),e(r.requires_setup?`/setup`:p(t.get(`returnTo`)),{replace:!0})}catch(e){if(e&&typeof e==`object`&&`message`in e){let t=e.message;if(typeof t==`string`){g(``),v(t);return}}v(`An unexpected network error occurred.`)}finally{b(!1)}},className:`flex flex-col gap-7`,children:[(0,f.jsx)(u,{label:`Username`,id:`login-username`,value:n,onChange:e=>m(e.target.value),required:!0,autoComplete:`username`,placeholder:`admin`}),(0,f.jsx)(u,{label:`Password`,id:`login-password`,type:`password`,value:h,onChange:e=>g(e.target.value),required:!0,autoComplete:`current-password`}),_?(0,f.jsx)(`div`,{className:`py-5 px-7 rounded-control bg-red-soft text-red text-caption font-medium`,role:`alert`,children:_}):null,(0,f.jsx)(r,{variant:`primary`,type:`submit`,disabled:y,className:`w-full mt-3 h-20`,icon:(0,f.jsx)(i,{size:15}),children:y?`Authenticating…`:`Sign In`})]})]})})}export{m as default};
@@ -0,0 +1 @@
1
+ import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{O as r,c as i}from"./numbers-DkfMR5Qs.js";import{r as a}from"./use-modal-focus-By7oJoGd.js";import{t as o}from"./dialog-k37exjNt.js";import{t as s}from"./route-CNSNj9Zm.js";import{t as c}from"./search-JOKus9rb.js";import{C as l,v as u}from"./assert-C9FD_JwJ.js";import{o as d,t as f}from"./query-keys-BFhGpwR1.js";import{s as p}from"./tokens-COzario9.js";import{t as m}from"./badge-CR72dasT.js";import{t as h}from"./ProviderIcon-CmfzxpVM.js";var g=e(t(),1),_=n();function v(e){let t=l({queryKey:f.providers.flatAll,queryFn:e=>d(`/providers/models/flat`,{signal:u(e)}),enabled:e,staleTime:0});return{items:t.data??[],isLoading:t.isPending,isError:t.isError,refetch:()=>void t.refetch()}}function y(e){return e==null?`?`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(0)}k`:String(e)}function b(e){let t=e.toLowerCase();return t===`responses`?`Responses`:t===`messages`?`Messages`:`Chat`}function x(e){let t=e.toLowerCase();return t===`responses`?`var(--purple)`:t===`messages`?`var(--orange)`:`var(--teal)`}function S(e){return e===`systemone`?`System One decision model — not a chat model. Call it at POST /v1/systemone with {state, questions}; it answers {answers}. It cannot run in a chat playground.`:e===`websearch`?`Web-search model — not a chat model. Call it at POST /v1/search with {query, max_results}; it answers a normalized list of hits. It cannot run in a chat playground.`:`This model is served by a native '${e}' route, not the chat wire.`}function C({open:e,onClose:t,selected:n,onToggle:l,onSelectOne:u,size:d=`lg`,title:f=`Select model`,multi:C=!0,filter:w}){let[T,E]=(0,g.useState)(``),{items:D,isLoading:O,isError:k,refetch:A}=v(e),j=(0,g.useMemo)(()=>{let e=T.trim().toLowerCase();return D.filter(t=>w&&!w(t)?!1:!e||t.qualified.toLowerCase().includes(e)||t.modelId.toLowerCase().includes(e)||t.providerId.toLowerCase().includes(e))},[D,T,w]),M=(0,g.useMemo)(()=>{let e=new Map;for(let t of j){let n=t.kind===`model`?t.providerId:t.kind===`alias`?`Aliases`:`Combos`,r=e.get(n)??[];r.push(t),e.set(n,r)}let t=(e,t)=>{let n=t[0]?.kind;return n===`alias`?0:n===`combo`?1:2};return Array.from(e.entries()).sort(([e,n],[r,i])=>{let a=t(e,n),o=t(r,i);return a===o?e.localeCompare(r):a-o})},[j]),N=e=>n.includes(e),P=e=>{u&&!C?(u(e),t()):l(e)};return(0,_.jsx)(o,{open:e,onClose:t,title:f,size:d,footer:(0,_.jsx)(i,{variant:`secondary`,onClick:t,children:`Done`}),children:(0,_.jsxs)(`div`,{className:`flex max-w-full flex-col gap-6`,children:[(0,_.jsxs)(`div`,{className:`relative`,children:[(0,_.jsx)(c,{size:14,className:`absolute left-5 top-1/2 -translate-y-1/2 text-text-tertiary`}),(0,_.jsx)(`input`,{value:T,onChange:e=>E(e.target.value),placeholder:`Search models or providers (e.g. gpt-5.4, codex)`,className:`w-full max-w-full rounded-inset border border-inner-border bg-surface-2 py-4 pr-5 pl-16 text-caption text-text-primary`})]}),C&&n.length>0&&(0,_.jsx)(`div`,{className:`flex flex-wrap gap-3 rounded-inset border border-inner-border bg-surface-2 p-4`,children:n.map(e=>(0,_.jsxs)(`span`,{className:`font-mono tabular-nums inline-flex items-center gap-2 text-badge bg-accent-soft text-accent py-1 px-3 rounded-chip border border-accent max-w-full overflow-hidden break-all`,children:[(0,_.jsx)(`span`,{className:`overflow-hidden truncate whitespace-nowrap`,children:e}),(0,_.jsx)(`button`,{type:`button`,onClick:()=>l(e),className:`bg-transparent border-none cursor-pointer p-0 flex shrink-0`,children:(0,_.jsx)(a,{size:12})})]},e))}),(0,_.jsx)(`div`,{className:`flex min-h-160 max-h-210 flex-1 flex-col gap-8 overflow-x-hidden overflow-y-auto rounded-control border border-inner-border bg-surface-1 p-6`,children:O?(0,_.jsx)(`div`,{className:`p-16 text-center text-caption text-text-tertiary`,children:`Loading catalog…`}):k?(0,_.jsxs)(`div`,{className:`p-16 text-center text-caption`,children:[(0,_.jsx)(`p`,{className:`text-text-tertiary`,children:`Failed to load catalog.`}),(0,_.jsx)(`button`,{type:`button`,onClick:A,className:`mt-4`,children:`Retry`})]}):M.length===0?(0,_.jsx)(`div`,{className:`p-16 text-center text-caption text-text-tertiary`,children:`No models found.`}):M.map(([e,t])=>{let n=t[0]?.kind===`model`;return(0,_.jsxs)(`div`,{className:`flex flex-col gap-4 min-w-0`,children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-3 text-badge font-bold tracking-[0.05em] text-text-secondary uppercase`,children:[n?(0,_.jsx)(h,{name:e,icon:e,size:16}):(0,_.jsx)(s,{size:14}),e,(0,_.jsx)(m,{tone:`default`,children:t.length})]}),(0,_.jsx)(`div`,{className:`grid min-w-0 grid-cols-2 gap-4 max-small:gap-2`,children:t.map(e=>{let t=N(e.qualified);return(0,_.jsxs)(`button`,{type:`button`,onClick:()=>P(e.qualified),className:`relative flex w-full min-w-0 cursor-pointer flex-col gap-2 overflow-hidden rounded-control px-6 py-5 text-left max-small:px-3 max-small:py-4 ${t?`border border-accent bg-accent-soft`:`border border-inner-border bg-surface-2`}`,children:[t&&(0,_.jsx)(r,{size:12,className:`absolute top-4 right-4 text-accent`}),(0,_.jsxs)(`span`,{title:e.qualified,className:`font-mono tabular-nums w-full whitespace-normal break-all text-badge font-semibold ${t?`pr-8 text-accent`:`text-text-primary`}`,children:[e.modelId,e.kind===`model`&&e.entry.serviceKind!==`llm`&&(0,_.jsx)(`span`,{title:S(e.entry.serviceKind),className:`ml-3 inline-block cursor-help rounded-tiny border border-orange px-2.5 align-middle font-bold tracking-[0.04em] text-micro text-orange uppercase`,children:e.entry.serviceKind})]}),(0,_.jsx)(`span`,{title:e.qualified,className:`font-mono tabular-nums w-full truncate text-micro text-text-tertiary`,children:e.kind===`alias`||e.kind===`combo`?(0,_.jsx)(`span`,{title:e.providerLabel,children:e.providerLabel}):(0,_.jsxs)(_.Fragment,{children:[e.entry.contextLimit?`${y(e.entry.contextLimit)} ctx`:(0,_.jsx)(`span`,{title:p,className:`cursor-help`,children:`n/a ctx`}),` · `,e.entry.outputLimit?`${y(e.entry.outputLimit)} out`:(0,_.jsx)(`span`,{title:p,className:`cursor-help`,children:`n/a out`}),` · `,(0,_.jsx)(`span`,{style:{color:x(e.entry.wireFamily),fontWeight:700},children:b(e.entry.wireFamily)})]})})]},e.qualified)})})]},e)})})]})})}export{v as n,C as t};
@@ -0,0 +1 @@
1
+ import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{n as i}from"./terminal-0_IjPWTk.js";import{a,i as o,n as s,r as c}from"./model-bans-CmffjLuG.js";import{n as l,r as u,t as d}from"./concurrency-BDF0ok7y.js";import{C as f,E as p,O as m,T as h,c as g,s as _,v,x as y}from"./numbers-DkfMR5Qs.js";import{t as ee}from"./chevron-right-BXIy5l3h.js";import{t as b}from"./SortableList-BLujdX7N.js";import{t as x}from"./database-Dz9N3zGd.js";import{t as S}from"./eye-off-Bk5g2luF.js";import{t as C}from"./eye-C_hawfH4.js";import{t as te}from"./gauge-BbIMy7MB.js";import{n as w,r as T,t as E}from"./state-mPDRlQkl.js";import{t as ne}from"./key-round-UkavsGxp.js";import{n as re,r as ie,t as D}from"./clipboard-button-611pSsaX.js";import{t as O}from"./dialog-k37exjNt.js";import{t as k}from"./pencil-768ysRAr.js";import{t as A}from"./plus-DIdX_g-x.js";import{t as j}from"./refresh-cw-BqJFk4sU.js";import{t as M}from"./route-CNSNj9Zm.js";import{t as N}from"./search-JOKus9rb.js";import{t as ae}from"./shield-check-DVS0Foqh.js";import{n as oe,r as se,t as P}from"./settings-DNX9sydi.js";import{t as ce}from"./trash-Cppn5c3R.js";import{C as le,T as ue,b as de,x as fe}from"./assert-C9FD_JwJ.js";import{l as F,o as pe,t as I}from"./query-keys-BFhGpwR1.js";import{t as me}from"./useMutation-Dem0lXQj.js";import{it as he,j as ge,lt as _e,ot as ve,z as L}from"./entry-DxBHnauy.js";import{n as R,r as z,t as B}from"./card-DS7CQEsO.js";import{t as V}from"./use-clipboard-B0Sy03fE.js";import{n as ye}from"./download-dRFo5_Wu.js";import{c as H,d as U}from"./tokens-COzario9.js";import{t as W}from"./badge-CR72dasT.js";import{n as G,t as be}from"./input-V1umFiBk.js";import{t as K}from"./select-BYR_5K2c.js";import{t as xe}from"./ModelPicker-C7pDb41R.js";import{t as q}from"./switch-DOmJxg7H.js";import{t as J}from"./stack-BHTfXdz_.js";import{n as Y}from"./inline-BhY2sSnO.js";import{a as Se,c as Ce,d as X,f as we,i as Te,l as Z,n as Ee,o as De,r as Oe,s as ke,t as Ae,u as je}from"./api-keys-DQYLQxpW.js";import{a as Me,i as Ne,n as Pe,r as Fe}from"./cli-tools-CNqzrfdb.js";import{t as Ie}from"./layout-BBOYycyS.js";import{s as Le}from"./quota-DZGyp0N5.js";var Re=e(`lock-keyhole`,[[`circle`,{cx:`12`,cy:`16`,r:`1`,key:`1au0dj`}],[`rect`,{x:`3`,y:`10`,width:`18`,height:`12`,rx:`2`,key:`6s8ecr`}],[`path`,{d:`M7 10V7a5 5 0 0 1 10 0v3`,key:`1pqi11`}]]),ze=e(`radio-tower`,[[`path`,{d:`M4.9 16.1C1 12.2 1 5.8 4.9 1.9`,key:`s0qx1y`}],[`path`,{d:`M7.8 4.7a6.14 6.14 0 0 0-.8 7.5`,key:`1idnkw`}],[`circle`,{cx:`12`,cy:`9`,r:`2`,key:`1092wv`}],[`path`,{d:`M16.2 4.8c2 2 2.26 5.11.8 7.47`,key:`ojru2q`}],[`path`,{d:`M19.1 1.9a9.96 9.96 0 0 1 0 14.1`,key:`rhi7fg`}],[`path`,{d:`M9.5 18h5`,key:`mfy3pd`}],[`path`,{d:`m8 22 4-11 4 11`,key:`25yftu`}]]),Be=e(`repeat-2`,[[`path`,{d:`m2 9 3-3 3 3`,key:`1ltn5i`}],[`path`,{d:`M13 18H7a2 2 0 0 1-2-2V6`,key:`1r6tfw`}],[`path`,{d:`m22 15-3 3-3-3`,key:`4rnwn2`}],[`path`,{d:`M11 6h6a2 2 0 0 1 2 2v10`,key:`2f72bc`}]]),Ve=e(`rotate-cw`,[[`path`,{d:`M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8`,key:`1p45f6`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}]]),He=e(`scissors`,[[`circle`,{cx:`6`,cy:`6`,r:`3`,key:`1lh9wr`}],[`path`,{d:`M8.12 8.12 12 12`,key:`1alkpv`}],[`path`,{d:`M20 4 8.12 15.88`,key:`xgtan2`}],[`circle`,{cx:`6`,cy:`18`,r:`3`,key:`fqmcym`}],[`path`,{d:`M14.8 14.8 20 20`,key:`ptml3r`}]]),Ue=e(`share-2`,[[`circle`,{cx:`18`,cy:`5`,r:`3`,key:`gq8acd`}],[`circle`,{cx:`6`,cy:`12`,r:`3`,key:`w7nqdw`}],[`circle`,{cx:`18`,cy:`19`,r:`3`,key:`1xt0gg`}],[`line`,{x1:`8.59`,x2:`15.42`,y1:`13.51`,y2:`17.49`,key:`47mynk`}],[`line`,{x1:`15.41`,x2:`8.59`,y1:`6.51`,y2:`10.49`,key:`1n3mei`}]]),We=e(`shield-off`,[[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71`,key:`1jlk70`}],[`path`,{d:`M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264`,key:`18rp1v`}]]),Ge=e(`shield-x`,[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}],[`path`,{d:`m14.5 9.5-5 5`,key:`17q4r4`}],[`path`,{d:`m9.5 9.5 5 5`,key:`18nt4w`}]]),Ke=e(`undo-2`,[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]),qe=e(`user-round`,[[`circle`,{cx:`12`,cy:`8`,r:`5`,key:`1hypcn`}],[`path`,{d:`M20 21a8 8 0 0 0-16 0`,key:`rfgkzh`}]]),Je=e(`users-round`,[[`path`,{d:`M18 21a8 8 0 0 0-16 0`,key:`3ypg7q`}],[`circle`,{cx:`10`,cy:`8`,r:`5`,key:`o932ke`}],[`path`,{d:`M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3`,key:`10s06x`}]]),Ye=[`routing:invoke`,`routing:cli_mapping`,`search:invoke`,`dashboard:read`,`dashboard:write`,`providers:read`,`providers:write`,`models:read`,`models:write`],Xe=[`image/png`,`image/jpeg`,`image/webp`,`image/gif`],Q=t(n(),1),$=r(),Ze={"routing:invoke":`Call /v1/* gateway routes within this tenant.`,"routing:cli_mapping":`Resolve persisted CLI source→target model mappings.`,"search:invoke":`Call POST /v1/search with exa.`,"dashboard:read":`Read this tenant's configuration and usage.`,"dashboard:write":`Modify this tenant's configuration.`,"providers:read":`Read provider rows, including accounts.`,"providers:write":`Add, modify, or delete provider rows and their credentials.`,"models:read":`Read catalog model rows.`,"models:write":`Add, modify, or delete catalog model rows.`},Qe={"routing:invoke":M,"routing:cli_mapping":M,"search:invoke":N,"dashboard:read":C,"dashboard:write":k,"providers:read":he,"providers:write":Re,"models:read":u,"models:write":x},$e={k:1e3,m:1e6,b:1e9,t:0xe8d4a51000},et=[{label:`1M`,amount:1e6,description:`1 million`},{label:`100M`,amount:1e8,description:`100 million`},{label:`1B`,amount:1e9,description:`1 billion`},{label:`1T`,amount:0xe8d4a51000,description:`1 trillion`}];function tt(e){let t=e.trim().toLowerCase();if(!t)return;let n=t.match(/^([\d.]+)\s*([kmbt])?$/);if(!n)return;let r=Number(n[1]);if(!Number.isFinite(r)||r<=0)return;let i=n[2]?$e[n[2]]??1:1;return Math.round(r*i)}function nt(e){if(e==null)return``;let t=et.find(t=>t.amount===e);return t?t.label:e>=1e9?`${(e/1e9).toFixed(1).replace(/\.0$/,``)}B`:e>=1e6?`${(e/1e6).toFixed(1).replace(/\.0$/,``)}M`:e>=1e3?`${(e/1e3).toFixed(1).replace(/\.0$/,``)}K`:String(e)}function rt(e){let t=Number(e.trim());return Number.isFinite(t)&&t>0?Math.round(t):void 0}function it(e){let t=rt(e);return e.trim()===``?null:t}function at({label:e,value:t,onChange:n,disabled:r}){let i=tt(t),a=et.find(e=>e.amount===i)?.label;return(0,$.jsxs)(`div`,{children:[(0,$.jsx)(G,{label:e,value:t,onChange:e=>n(e.target.value),placeholder:`e.g. 1M, 500K`,disabled:r}),(0,$.jsx)(`div`,{className:`flex flex-wrap gap-2 mt-2`,role:`group`,"aria-label":`${e} presets`,children:et.map(e=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":a===e.label,"aria-label":`${e.label}, ${e.description} tokens`,onClick:()=>n(e.label),disabled:r,className:`py-0.5 px-3 rounded-chip text-micro font-semibold`,style:{cursor:r?`not-allowed`:`pointer`,border:`1px solid ${a===e.label?`var(--accent)`:`var(--inner-border)`}`,background:a===e.label?`var(--accent-soft)`:`transparent`,color:a===e.label?`var(--accent)`:`var(--text-tertiary)`},children:e.label},e.label))})]})}function ot({tool:e,keyId:t,busy:n,scopeGranted:r,onScopeChange:i}){let a=Ne(e.id,t),o=Fe(),s=Pe(),c=a.data?.enabled??!1,l=r&&c,u=a.data?.mappings.length??0,d=o.isPending||s.isPending;return(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4 py-1.5 px-4 rounded-inset`,style:{minHeight:`38px`,border:`1px solid var(--inner-border)`,background:l?`var(--accent-soft)`:`var(--surface-1)`},children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-start gap-3`,children:[(0,$.jsx)(M,{size:16,className:`mt-1 shrink-0 text-accent`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`div`,{className:`text-caption font-semibold text-text-primary`,children:e.name}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:l?`Remote routing on — ${u} route${u===1?``:`s`} active, routing:cli_mapping granted.`:`Remote routing off — this key's requests go straight to the provider.`})]})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,$.jsx)(q,{checked:l,disabled:n||d||a.isLoading,"aria-label":`Enable remote routing for ${e.name}`,onChange:n=>{n!==r&&i(n),o.mutate({toolId:e.id,keyId:t,input:{enabled:n,mappings:a.data?.mappings??[]}},{onSuccess:()=>_.success(`Saved remote routing for ${e.name}.`),onError:e=>_.error(F(e,`Could not save remote routing.`))})}}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,disabled:n||d||!c&&u===0,onClick:()=>s.mutate({toolId:e.id,keyId:t},{onSuccess:()=>_.success(`Cleared remote routes for ${e.name}.`),onError:e=>_.error(F(e,`Could not reset remote routes.`))}),children:s.isPending?`Resetting…`:`Reset`})]})]})}function st({keyId:e,busy:t,scopeGranted:n,onScopeChange:r,persistScope:i}){let a=(Me().data??[]).filter(e=>e.mappingSupported);return(0,$.jsxs)(`section`,{"aria-labelledby":`remote-routing-heading`,className:`flex flex-col gap-3`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`h4`,{id:`remote-routing-heading`,className:`inline-flex items-center gap-2 text-caption font-bold text-text-primary`,children:[(0,$.jsx)(M,{size:15,className:`text-accent`,"aria-hidden":`true`}),`Remote routing`]}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:`Route this key's CLI model calls through persisted mappings and grant routing:cli_mapping. Applies immediately — no save needed.`})]}),e.length===0?(0,$.jsx)(`p`,{className:`text-badge text-text-tertiary m-0`,children:`Save the key first to configure per-tool remote routing mappings.`}):a.length===0?(0,$.jsx)(`p`,{className:`text-badge text-text-tertiary m-0`,children:`No CLI tools with mapping support are currently registered.`}):(0,$.jsx)(`div`,{className:`flex flex-col gap-3`,children:a.map(a=>(0,$.jsx)(ot,{tool:a,keyId:e,busy:t,scopeGranted:n,onScopeChange:e=>{r(e),i(e)}},a.id))})]})}function ct(e,t,n){let r=e===`personal`?t.trim():``;return{keyMode:e,keyPrefix:n.trim()||void 0,...r?{key:r}:{}}}function lt(e,t){return e===`personal`?t??null:null}function ut(e){let t=e?.scopes;return e?.isDefault?t&&t.length>0?[...t]:[...Ye]:t&&t.length>0?[...t]:[`routing:invoke`,`search:invoke`]}function dt({mode:e,record:t,busy:n,onDone:r,onClose:i,actionsRef:o}){let[s,c]=(0,Q.useState)(t?.label??``),[d,f]=(0,Q.useState)(t?.keyPrefix??``),[p,m]=(0,Q.useState)(``),[h,v]=(0,Q.useState)(t?.requestsPerMinute?.toString()??``),[y,ee]=(0,Q.useState)(nt(t?.dailyTokenLimit??null)),[b,x]=(0,Q.useState)(nt(t?.monthlyTokenLimit??null)),[S,C]=(0,Q.useState)(nt(t?.lifetimeTokenBudget??null)),[w,T]=(0,Q.useState)(t?.lifetimeTokenBudget==null?`recurring`:`one-time`),[E,ie]=(0,Q.useState)(t?.maxConcurrentRequests?.toString()??``),[D,O]=(0,Q.useState)(()=>ut(t)),[k,A]=(0,Q.useState)(t?.modelAccessMode??`whitelist`),[j,N]=(0,Q.useState)(()=>{let e=t?.modelList;return e?[...e]:[]}),[oe,P]=(0,Q.useState)(!1),[ce,le]=(0,Q.useState)(()=>{let e=t?.clientRouterDenylist;return e?[...new Set(e.map(fe).filter(e=>e!==void 0))]:[]}),[ue,pe]=(0,Q.useState)(()=>t?.notesTitle??``),[I,me]=(0,Q.useState)(()=>t?.notesSubtitle??``),[he,ge]=(0,Q.useState)(()=>t?.notesBody??``),[L,R]=(0,Q.useState)(t?.sharePopupEnabled??!0),[z,B]=(0,Q.useState)(null),[V,ye]=(0,Q.useState)(!1),[H,U]=(0,Q.useState)(null),W=t?.sharePopupImageMime!==void 0,K=z??(W&&!V&&t!==null?`/console/api/api-keys/${t.id}/share-popup-image`:null);(0,Q.useEffect)(()=>{W||z!==null||V||fetch(`/donation/qris-risun-marke.png`).then(e=>e.ok?e.blob():Promise.reject(e.status)).then(e=>{let{promise:t,resolve:n,reject:r}=Promise.withResolvers(),i=new FileReader;return i.onload=()=>n(i.result),i.onerror=r,i.readAsDataURL(e),t}).then(e=>B(e)).catch(()=>{})},[]);let[J,Y]=(0,Q.useState)(t?.sharePopupTitle??`Support via QRIS`),[Se,Ce]=(0,Q.useState)(t?.sharePopupBody??`Scan the QR code above with any QRIS-compatible banking or e-wallet app to support this gateway's upkeep. Every contribution helps keep the service running — thank you! 🙏`),[X,Te]=(0,Q.useState)(t?.keyMode??`personal`),Z=w===`one-time`,Ee=e===`edit`,De=we(),Oe=e=>O(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e]),ke=()=>{r({label:s.trim(),...ct(X,p,d),scopes:D,modelAccessMode:k,modelList:j,clientRouterDenylist:ce,requestsPerMinute:it(h),maxConcurrentRequests:it(E),dailyTokenLimit:Z?null:tt(y)??null,monthlyTokenLimit:Z?null:tt(b)??null,lifetimeTokenBudget:Z?tt(S)??null:null,notesTitle:ue.trim(),notesSubtitle:I.trim(),notesBody:he.trim(),sharePopupEnabled:L,...z===null?V?{sharePopupImage:null}:{}:{sharePopupImage:z},sharePopupTitle:J.trim(),sharePopupBody:Se.trim()})};return(0,Q.useEffect)(()=>{o?.((0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(g,{variant:`secondary`,size:`sm`,onClick:i,disabled:n,children:`Cancel`}),(0,$.jsx)(g,{variant:`primary`,size:`sm`,disabled:n||e===`create`&&!s.trim(),onClick:ke,children:n?`Saving…`:e===`create`?`Create API key`:`Save changes`})]}))}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-3 min-w-0 pb-2`,children:[(0,$.jsxs)(`section`,{className:`flex flex-col gap-3 min-w-0 p-4 border border-inner-border rounded-card bg-surface-2 col-span-full`,children:[(0,$.jsxs)(`h3`,{className:`inline-flex items-center gap-2 text-caption font-bold text-text-primary`,children:[(0,$.jsx)(ne,{size:16,className:`text-accent`,"aria-hidden":`true`}),`Credential mode`]}),(0,$.jsx)(`div`,{role:`group`,"aria-label":`Credential mode`,className:`flex gap-4`,children:[`personal`,`share`].map(e=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":X===e,disabled:n||Ee,onClick:()=>Te(e),title:Ee?`Credential mode cannot change after creation`:void 0,className:`rounded-inset py-1.5 px-5`,style:{border:`1px solid var(--inner-border)`,color:X===e?`var(--accent)`:`var(--text-secondary)`,background:X===e?`var(--accent-soft)`:`var(--surface-2)`,cursor:Ee?`not-allowed`:`pointer`,opacity:Ee&&X!==e?.5:1},children:(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[e===`personal`?(0,$.jsx)(qe,{size:14,"aria-hidden":`true`}):(0,$.jsx)(Je,{size:14,"aria-hidden":`true`}),e===`personal`?`Personal`:`Share template`]})},e))}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:X===`share`?`A share template does not authenticate requests. Recipients generate their own child key from its public enrollment page.`:`A personal key authenticates requests directly; its secret is shown once when created or rotated.`})]}),(0,$.jsxs)(`div`,{className:`grid grid-cols-2 gap-3 min-w-0 max-medium:grid-cols-1`,children:[e===`create`&&(0,$.jsxs)(`section`,{className:`flex flex-col gap-3 min-w-0 p-4 border border-inner-border rounded-card bg-surface-2`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`h3`,{className:`inline-flex items-center gap-2 text-caption font-bold text-text-primary`,children:[(0,$.jsx)(l,{size:16,className:`text-accent`,"aria-hidden":`true`}),`Identity`]}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:`Give this credential a recognizable name.`})]}),(0,$.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,$.jsx)(G,{label:`Name`,value:s,onChange:e=>c(e.target.value),placeholder:`ci-key…`,disabled:n,autoFocus:!0}),(0,$.jsx)(G,{label:`Key prefix`,value:d,onChange:e=>f(e.target.value),placeholder:`pn-carte- (default)…`,disabled:n||p.trim().length>0})]}),X===`personal`&&(0,$.jsx)(G,{label:`Custom API key value (optional)`,value:p,onChange:e=>m(e.target.value),placeholder:`Leave blank to generate…`,disabled:n})]}),e===`edit`&&(0,$.jsxs)(`section`,{className:`flex flex-col gap-3 min-w-0 p-4 border border-inner-border rounded-card bg-surface-2`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`h3`,{className:`text-caption font-bold text-text-primary`,children:[(0,$.jsx)(l,{size:16,className:`mr-2 inline text-accent`,"aria-hidden":`true`}),`Identity`]}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:t?.isDefault?`The default key's name is fixed. Limits, access, and everything else can still change.`:`Update the label for this credential.`})]}),(0,$.jsx)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:(0,$.jsx)(G,{label:`Name`,value:s,onChange:e=>c(e.target.value),placeholder:`ci-key…`,disabled:n||t?.isDefault===!0,title:t?.isDefault?`The default gateway key keeps its name`:void 0,autoFocus:!0})})]}),(0,$.jsxs)(`section`,{className:`flex flex-col gap-3 min-w-0 p-4 border border-inner-border rounded-card bg-surface-2`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`h3`,{className:`text-caption font-bold text-text-primary`,children:[(0,$.jsx)(re,{size:16,className:`mr-2 inline text-accent`,"aria-hidden":`true`}),`Share notes`]}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:`Optional copy shown on the public share page.`})]}),(0,$.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,$.jsx)(G,{label:`Title`,value:ue,onChange:e=>pe(e.target.value),placeholder:`e.g. Bansos Token`,disabled:n}),(0,$.jsx)(G,{label:`Subtitle`,value:I,onChange:e=>me(e.target.value),placeholder:`e.g. Come and save your tokens`,disabled:n}),(0,$.jsx)(`div`,{className:`col-span-full`,children:(0,$.jsx)(G,{label:`Body`,value:he,onChange:e=>ge(e.target.value),placeholder:`Free-form notes for the recipient`,disabled:n})})]})]}),(0,$.jsxs)(`section`,{className:`flex flex-col gap-3 min-w-0 p-4 border border-inner-border rounded-card bg-surface-2 col-span-full`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`h3`,{className:`text-caption font-bold text-text-primary`,children:[(0,$.jsx)(te,{size:16,className:`mr-2 inline text-accent`,"aria-hidden":`true`}),`Limits`]}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:`Keep this credential predictable under load.`})]}),(0,$.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,$.jsx)(G,{label:`Requests per minute`,type:`number`,min:`0`,value:h,onChange:e=>v(e.target.value),placeholder:`Unlimited…`,disabled:n}),(0,$.jsx)(G,{label:`Max concurrent requests`,type:`number`,min:`0`,value:E,onChange:e=>ie(e.target.value),placeholder:`Unlimited…`,disabled:n})]}),(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4 rounded-panel border border-inner-border px-4 py-3 bg-surface-2`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`div`,{className:`text-caption font-bold text-text-primary`,children:[(0,$.jsx)(te,{size:14,className:`mr-2 inline text-accent`,"aria-hidden":`true`}),`Token budget`]}),(0,$.jsx)(`p`,{className:`mt-1 text-text-tertiary text-micro`,children:Z?`One-time cap; it does not reset.`:`Daily and monthly limits reset automatically.`})]}),(0,$.jsxs)(`div`,{className:`flex gap-2 rounded-inset border border-inner-border bg-surface-1 p-1`,children:[(0,$.jsx)(`button`,{type:`button`,onClick:()=>T(`recurring`),disabled:n,className:`py-1.5 px-4 rounded-chip font-semibold border-0 cursor-pointer`,style:{fontSize:`10px`,background:Z?`transparent`:`var(--accent-soft)`,color:Z?`var(--text-tertiary)`:`var(--accent)`},children:(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,$.jsx)(Be,{size:13,"aria-hidden":`true`}),`Recurring`]})}),(0,$.jsx)(`button`,{type:`button`,onClick:()=>T(`one-time`),disabled:n,className:`py-1.5 px-4 rounded-chip font-semibold border-0 cursor-pointer`,style:{fontSize:`10px`,background:Z?`var(--accent-soft)`:`transparent`,color:Z?`var(--accent)`:`var(--text-tertiary)`},children:(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2`,children:[(0,$.jsx)(Re,{size:13,"aria-hidden":`true`}),`One-time`]})})]})]}),Z?(0,$.jsx)(at,{label:`One-time token limit`,value:S,onChange:C,disabled:n}):(0,$.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 items-start min-w-0 max-medium:grid-cols-1`,children:[(0,$.jsx)(at,{label:`Daily token limit`,value:y,onChange:ee,disabled:n}),(0,$.jsx)(at,{label:`Monthly token limit`,value:b,onChange:x,disabled:n})]})]})]}),(0,$.jsxs)(`section`,{className:`flex flex-col gap-3 min-w-0 p-4 border border-inner-border rounded-card bg-surface-2 col-span-full`,"aria-labelledby":`share-popup-heading`,children:[(0,$.jsxs)(`div`,{className:`flex items-start justify-between gap-6`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`h3`,{id:`share-popup-heading`,className:`text-caption font-bold text-text-primary`,children:[(0,$.jsx)(Ue,{size:16,className:`mr-2 inline text-accent`,"aria-hidden":`true`}),`Share page popup`]}),(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:`Optional card visitors open from the Base URL card on your share page.`})]}),(0,$.jsx)(q,{checked:L,onChange:e=>R(e),disabled:n,label:`Enable popup`})]}),L?(0,$.jsxs)(`div`,{className:`flex gap-7 items-start mt-2 min-w-0 max-medium:flex-col max-medium:items-stretch`,children:[(0,$.jsxs)(`div`,{className:`flex flex-col gap-4 min-w-0 w-100 shrink-0 max-medium:w-auto`,children:[K?(0,$.jsx)(`img`,{className:`block w-full h-66 object-cover border border-inner-border rounded-control bg-surface-1 max-medium:h-80`,src:K,alt:`Popup image preview`}):(0,$.jsx)(`div`,{className:`flex items-center justify-center w-full h-66 object-cover border border-dashed border-inner-border rounded-control bg-surface-1 text-text-tertiary text-badge max-medium:h-80`,"aria-hidden":`true`,children:(0,$.jsx)(`span`,{children:`No image`})}),(0,$.jsx)(be,{id:`share-popup-image`,accept:Xe.join(`,`),"aria-label":`Popup image`,disabled:n,onChange:e=>{let t=e.target.files?.[0];if(e.target.value=``,!t)return;if(U(null),t.size>2097152){B(null),U(`Image must be 2 MB or smaller.`);return}let n=new FileReader;n.onload=()=>{B(String(n.result)),ye(!1)},n.onerror=()=>U(`Could not read that file.`),n.readAsDataURL(t)}}),K?(0,$.jsx)(g,{variant:`secondary`,size:`sm`,type:`button`,disabled:n,className:`h-14 px-5 text-badge self-start`,onClick:()=>{B(null),ye(!0),U(null)},children:`Remove image`}):null,H?(0,$.jsx)(`p`,{className:`form-error`,children:H}):null,(0,$.jsx)(`p`,{className:`m-0 text-text-tertiary text-badge leading-normal`,children:`PNG, JPEG, WebP, or GIF up to 2 MB.`})]}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-4 min-w-0 flex-1 [&_.form-group]:gap-2`,children:[(0,$.jsx)(G,{label:`Popup title`,value:J,onChange:e=>Y(e.target.value),maxLength:120,placeholder:`Support this gateway`,disabled:n}),(0,$.jsxs)(`div`,{className:`form-group`,children:[(0,$.jsx)(`label`,{className:`form-label`,htmlFor:`share-popup-copy`,children:`Message`}),(0,$.jsx)(`textarea`,{className:`form-textarea`,id:`share-popup-copy`,value:Se,onChange:e=>Ce(e.target.value),maxLength:1200,rows:3,placeholder:`If this service helps you, consider supporting its upkeep…`,disabled:n})]})]})]}):null]}),(0,$.jsxs)(`details`,{className:`group min-w-0 col-span-full rounded-card border border-inner-border bg-surface-2`,children:[(0,$.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center justify-between gap-3 p-4 [&::-webkit-details-marker]:hidden`,children:[(0,$.jsxs)(`span`,{className:`flex min-w-0 items-start gap-3`,children:[(0,$.jsx)(`span`,{className:`grid size-8 shrink-0 place-items-center rounded-inset bg-accent-soft text-accent`,children:(0,$.jsx)(se,{size:18,"aria-hidden":`true`})}),(0,$.jsxs)(`span`,{className:`min-w-0`,children:[(0,$.jsx)(`span`,{className:`block text-body font-bold text-text-primary`,children:`Access`}),(0,$.jsx)(`span`,{className:`mt-1 block text-badge text-text-tertiary`,children:t?.isDefault?`Default gateway key · all tenant permissions, including gateway routing and remote debugging.`:`Choose model, router, and dashboard permissions for this key.`})]})]}),(0,$.jsxs)(`span`,{className:`inline-flex shrink-0 items-center gap-2 rounded-control border border-inner-border bg-surface-1 px-3 py-2 text-micro font-semibold text-text-secondary`,children:[D.length,`/`,Ye.length,` grants`,(0,$.jsx)(_e,{size:14,className:`transition-transform group-open:rotate-180`,"aria-hidden":`true`})]})]}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-4 border-t border-inner-border p-4`,children:[t?.isDefault?(0,$.jsxs)(`div`,{className:`flex items-start gap-3 rounded-control border border-accent/30 bg-accent-soft p-4 text-badge text-text-secondary`,children:[(0,$.jsx)(ae,{size:16,className:`mt-0.5 shrink-0 text-accent`,"aria-hidden":`true`}),(0,$.jsxs)(`p`,{className:`m-0`,children:[`This default API key is provisioned with every tenant permission, including `,(0,$.jsx)(`code`,{children:`routing:invoke`}),` and`,` `,(0,$.jsx)(`code`,{children:`routing:cli_mapping`}),`. Those grant gateway access and authorization to use remote CLI mappings; each client's mapping toggle below still controls whether those routes are active. You can remove individual grants here.`]})]}):null,(0,$.jsxs)(`div`,{className:`grid grid-cols-access gap-5 min-w-0 max-medium:grid-cols-1`,children:[(0,$.jsxs)(`section`,{"aria-labelledby":`model-access-heading`,className:`flex flex-col gap-3 min-w-0 rounded-card border border-inner-border bg-surface-1 p-4`,children:[(0,$.jsxs)(`h4`,{id:`model-access-heading`,className:`inline-flex items-center gap-2 text-caption font-bold text-text-primary`,children:[(0,$.jsx)(u,{size:15,className:`text-accent`,"aria-hidden":`true`}),`Model access`]}),(0,$.jsx)(`div`,{role:`group`,"aria-label":`Model access mode`,className:`flex gap-2`,children:[`whitelist`,`blacklist`].map(e=>(0,$.jsxs)(`button`,{type:`button`,"aria-pressed":k===e,disabled:n,onClick:()=>A(e),title:e===`whitelist`?`Only the listed models may be used. An empty list allows every model.`:`The listed models are refused. Everything else is allowed.`,className:`flex-1 py-2 px-3 text-badge font-semibold`,style:{borderRadius:`7px`,border:`1px solid ${k===e?`var(--accent)`:`var(--inner-border)`}`,background:k===e?`var(--accent-soft)`:`var(--surface-2)`,color:k===e?`var(--accent)`:`var(--text-secondary)`,cursor:n?`not-allowed`:`pointer`,opacity:n?.6:1},children:[e===`whitelist`?`Whitelist`:`Blacklist`,e===`whitelist`?(0,$.jsx)(ae,{size:13,className:`ml-1.5 inline`,"aria-hidden":`true`}):(0,$.jsx)(Ge,{size:13,className:`ml-1.5 inline`,"aria-hidden":`true`})]},e))}),(0,$.jsx)(`p`,{className:`text-badge text-text-tertiary m-0`,children:k===`whitelist`?`Only these models may be called. Empty = all allowed.`:`These models are refused. Everything else is allowed.`}),(0,$.jsx)(`div`,{className:`flex gap-1.5 flex-wrap min-h-6`,children:j.length===0?(0,$.jsx)(`span`,{className:`text-badge text-text-tertiary`,children:k===`whitelist`?`All models allowed`:`No models blocked`}):j.map(e=>(0,$.jsxs)(`span`,{className:`font-mono tabular-nums inline-flex items-center gap-1.5 text-badge bg-accent-soft text-accent py-1 px-3 rounded-chip border border-accent`,children:[e,(0,$.jsx)(`button`,{type:`button`,"aria-label":`Remove ${e} from the model list`,onClick:()=>N(t=>t.filter(t=>t!==e)),disabled:n,className:`bg-transparent border-0 cursor-pointer p-0 flex`,children:`×`})]},e))}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,type:`button`,onClick:()=>P(!0),disabled:n,children:`Browse models`}),(0,$.jsx)(xe,{open:oe,onClose:()=>P(!1),selected:j,onToggle:e=>N(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e]),title:k===`whitelist`?`Select allowed models`:`Select blocked models`,multi:!0})]}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-4 min-w-0`,children:[(0,$.jsxs)(`section`,{"aria-labelledby":`routing-blocking-heading`,className:`flex flex-col gap-0 min-w-0 rounded-card border border-inner-border bg-surface-1 overflow-hidden`,children:[(0,$.jsxs)(`div`,{className:`px-4 pt-4 pb-3 border-b border-inner-border`,children:[(0,$.jsxs)(`h4`,{id:`routing-blocking-heading`,className:`inline-flex items-center gap-2 text-caption font-bold text-text-primary`,children:[(0,$.jsx)(M,{size:15,className:`text-accent`,"aria-hidden":`true`}),`Routing & Client Blocking`]}),(0,$.jsx)(`p`,{className:`mt-1 mb-0 text-badge text-text-tertiary`,children:`Control which gateway routes this key can call and which client apps are blocked before routing.`})]}),(0,$.jsxs)(`div`,{className:`flex flex-col divide-y divide-inner-border`,children:[(0,$.jsxs)(`div`,{className:`flex flex-col gap-2 px-4 py-3`,children:[(0,$.jsx)(`p`,{className:`text-badge font-semibold text-text-secondary m-0`,children:`Gateway routing`}),Ye.filter(e=>e===`routing:invoke`).map(e=>(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4 py-1.5 px-4 rounded-inset`,style:{minHeight:`38px`,border:`1px solid var(--inner-border)`,background:D.includes(e)?`var(--accent-soft)`:`var(--surface-2)`},children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,$.jsx)(M,{size:14,className:`mt-0.5 shrink-0 text-accent`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`div`,{className:`text-caption font-semibold text-text-primary`,children:e}),(0,$.jsx)(`p`,{className:`mt-0.5 mb-0 text-badge text-text-tertiary`,children:Ze[e]})]})]}),(0,$.jsx)(q,{checked:D.includes(e),onChange:()=>Oe(e),disabled:n,"aria-label":`Grant ${e}`})]},e))]}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-2 px-4 py-3`,children:[(0,$.jsx)(`p`,{className:`text-badge font-semibold text-text-secondary m-0`,children:`Blocked client apps`}),(0,$.jsx)(`div`,{className:`flex flex-col gap-2`,children:de.map(e=>(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4 py-1.5 px-4 rounded-inset`,style:{minHeight:`38px`,border:`1px solid var(--inner-border)`,background:ce.includes(e.id)?`var(--accent-soft)`:`var(--surface-2)`},children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-center gap-3`,children:[(0,$.jsx)(a,{size:14,className:`shrink-0 text-orange`,"aria-hidden":`true`}),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsxs)(`div`,{className:`text-caption font-semibold text-text-primary`,children:[`Block `,e.label,` Client`]}),(0,$.jsx)(`p`,{className:`mt-0.5 mb-0 text-badge text-text-tertiary`,children:e.id===`9router`?`9router, Omniroute, and Baazar Probes`:`Fingerprint-based detection — best-effort; unrecognised clients are never matched`})]})]}),(0,$.jsx)(q,{checked:ce.includes(e.id),onChange:t=>le(n=>t?[...n,e.id]:n.filter(t=>t!==e.id)),disabled:n,"aria-label":`Block ${e.label} client`})]},e.id))})]})]}),(0,$.jsx)(`div`,{className:`px-4 py-3`,children:(0,$.jsx)(st,{keyId:e===`edit`&&t?t.id:``,busy:n,scopeGranted:D.includes(`routing:cli_mapping`),onScopeChange:e=>{e!==D.includes(`routing:cli_mapping`)&&Oe(`routing:cli_mapping`)},persistScope:n=>{if(e!==`edit`||!t)return;let r=n?[...new Set([...D,`routing:cli_mapping`])]:D.filter(e=>e!==`routing:cli_mapping`);De.mutate({keyId:t.id,request:{scopes:r}},{onError:e=>_.error(F(e,`Could not update the key's routing scope.`))})}})})]}),(0,$.jsxs)(`section`,{"aria-labelledby":`dashboard-scopes-heading`,className:`flex flex-col gap-0 min-w-0 rounded-card border border-inner-border bg-surface-1 overflow-hidden`,children:[(0,$.jsxs)(`div`,{className:`px-4 pt-4 pb-3 border-b border-inner-border`,children:[(0,$.jsxs)(`h4`,{id:`dashboard-scopes-heading`,className:`inline-flex items-center gap-2 text-caption font-bold text-text-primary`,children:[(0,$.jsx)(ve,{size:15,className:`text-accent`,"aria-hidden":`true`}),`Dashboard / Resources`]}),(0,$.jsx)(`p`,{className:`mt-1 mb-0 text-badge text-text-tertiary`,children:`Grants read or write access to console data — providers, models, configuration, and usage stats. No routing is implied by these scopes.`})]}),(0,$.jsx)(`div`,{className:`flex flex-col gap-2 p-4`,children:Ye.filter(e=>!e.startsWith(`routing:`)).map(e=>(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4 py-1.5 px-4 rounded-inset`,style:{minHeight:`38px`,border:`1px solid var(--inner-border)`,background:D.includes(e)?`var(--accent-soft)`:`var(--surface-2)`},children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-3 min-w-0`,children:[(()=>{let t=Qe[e];return(0,$.jsx)(t,{size:14,className:`mt-0.5 shrink-0 text-accent`,"aria-hidden":`true`})})(),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`div`,{className:`text-caption font-semibold text-text-primary`,children:e}),(0,$.jsx)(`p`,{className:`mt-0.5 mb-0 text-badge text-text-tertiary`,children:Ze[e]})]})]}),(0,$.jsx)(q,{checked:D.includes(e),onChange:()=>Oe(e),disabled:n,"aria-label":`Grant ${e}`})]},e))})]})]})]})]})]})]})}function ft({secret:e,onClose:t}){return(0,$.jsx)(O,{open:e!==null,onClose:t,title:`New API key`,description:`Copy it now, or reveal it again later from the key's Share button.`,size:`md`,children:(0,$.jsxs)(`div`,{className:`flex flex-col gap-7`,children:[(0,$.jsx)(`p`,{className:`text-body text-text-secondary m-0 leading-normal`,children:`A personal key stays recoverable. Open the key's Share button and choose Reveal to see it again and copy it. Rotating the key replaces this secret, and any client still using it starts getting 401s.`}),(0,$.jsx)(`code`,{className:`block rounded-inset border border-inner-border bg-surface-1 py-5 px-6 text-caption text-text-primary break-all`,children:e}),(0,$.jsxs)(`div`,{className:`flex gap-4 flex-wrap`,children:[(0,$.jsx)(D,{value:e??``,size:`sm`,variant:`primary`,label:`Copy key`,copiedLabel:`Copied`}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(h,{size:13}),onClick:()=>{e!==null&&(ye(`cartethyia-api-key.txt`,`Cartethyia API key\n\n${e}\n\nKeep this secret. Reveal it again from the key's Share button.\n`,`text/plain;charset=utf-8`),_.success(`Key saved to your downloads.`))},children:`Save this key`})]})]})})}function pt(e,t){if(t)return`Permanent — lift manually`;let n=new Date(e);if(!Number.isFinite(n.getTime()))return`—`;let r=e-Date.now(),i=n.toLocaleString();if(r<=0)return`${i} (lapsed)`;let a=Math.ceil(r/6e4);if(a<60)return`${i} (in ${a}m)`;let o=Math.floor(a/60);return o<24?`${i} (in ${o}h)`:`${i} (in ${Math.floor(o/24)}d)`}function mt({onClose:e}){let t=s(!0),n=c(),[r,i]=(0,Q.useState)(null),a=t.data??[];return(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(O,{open:!0,onClose:e,title:`Banned Users`,description:`A caller is banned after repeated invalid-model requests. A ban is scoped to the API key that made them, so other keys used from the same address keep working — unless an operator banned the address outright.`,size:`lg`,children:(0,$.jsxs)(`div`,{className:`flex flex-col gap-7 min-w-0`,children:[(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsxs)(`h4`,{className:`text-caption font-semibold text-text-secondary mb-4`,children:[`Active bans (`,a.length,`)`]}),t.isPending?(0,$.jsx)(T,{compact:!0,label:`Loading banned users…`}):t.isError?(0,$.jsx)(w,{compact:!0,message:F(t.error,`Could not load banned users.`),onRetry:()=>void t.refetch()}):a.length===0?(0,$.jsx)(E,{compact:!0,title:`No banned users`,message:`No client address is currently banned for model abuse.`,icon:(0,$.jsx)(We,{size:20})}):(0,$.jsx)(`div`,{className:`rounded-inset border border-inner-border`,children:(0,$.jsx)(Ie,{maxHeight:480,scrollRegion:!0,headers:[`Client IP`,`API key`,`Reason`,`Applies to`,`Lapses`,``],children:a.map(e=>(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-primary whitespace-nowrap`,children:e.ip}),(0,$.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary whitespace-nowrap`,children:e.apiKeyId?`${e.apiKeyId.slice(0,8)}…`:`—`}),(0,$.jsx)(`td`,{className:`text-badge text-text-secondary`,children:e.reason===`repeated_invalid_model_requests`?`Repeated invalid-model requests`:e.reason}),(0,$.jsx)(`td`,{className:`text-badge text-text-secondary whitespace-nowrap`,children:e.apiKeyId?`This key only`:`All keys from this IP`}),(0,$.jsx)(`td`,{className:`text-badge text-text-secondary whitespace-nowrap`,children:pt(e.expiresAt,e.permanent===!0)}),(0,$.jsx)(`td`,{className:`text-right whitespace-nowrap`,children:(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(Ke,{size:13}),disabled:n.isPending,onClick:()=>i(e),children:`Unban`})})]},e.identity))})})]}),(0,$.jsx)(Y,{justify:`flex-end`,gap:`0px`,children:(0,$.jsx)(g,{variant:`secondary`,size:`sm`,onClick:e,children:`Close`})})]})}),(0,$.jsx)(L,{open:r!==null,onClose:()=>i(null),onConfirm:async()=>{r&&(await n.mutateAsync(r.identity),_.success(`Unbanned ${r.ip}.`),i(null))},title:`Lift this ban?`,message:r?`Lift the ban on ${r.ip}${r.apiKeyId?` for this API key`:``}? The caller can reach the gateway again immediately.`:`Lift this ban?`,confirmLabel:`Unban`,danger:!0})]})}var ht=e=>(e??0).toLocaleString(),gt=e=>e?new Date(e).toLocaleString():`—`;function _t({keyId:e}){let t=Se(),[n,r]=(0,Q.useState)(null),[i,a]=(0,Q.useState)(!1);return(0,$.jsxs)(`div`,{className:`flex min-w-0 items-center gap-4 rounded-control border border-inner-border bg-surface-2 px-5 py-4 text-text-tertiary`,children:[(0,$.jsx)(`code`,{title:i&&n?n:void 0,className:`min-w-0 flex-auto overflow-hidden font-mono text-caption text-text-primary text-ellipsis whitespace-nowrap`,children:i&&n?n:`••••••••••••••••`}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:i?(0,$.jsx)(S,{size:13}):(0,$.jsx)(C,{size:13}),loading:t.isPending,disabled:t.isPending,onClick:()=>{if(n!==null){a(e=>!e);return}t.mutate({keyId:e},{onSuccess:e=>{r(e.secret),a(!0)},onError:e=>_.error(F(e,`Could not reveal the key.`))})},children:i?`Hide`:`Reveal`}),i&&n?(0,$.jsx)(D,{value:n,size:`sm`,variant:`secondary`,label:`Copy`,copiedLabel:`Copied`}):null]})}function vt({label:e,value:t}){return(0,$.jsxs)(`div`,{className:`min-w-0 flex-1 basis-60 rounded-control border border-inner-border bg-surface-2 px-5 py-3`,children:[(0,$.jsx)(`dt`,{className:`text-badge font-normal tracking-label text-text-tertiary uppercase`,children:e}),(0,$.jsx)(`dd`,{className:`mt-1 text-caption font-normal text-text-primary tabular-nums`,children:t==null?`Unlimited`:ht(t)})]})}function yt(e){return e?{title:`Regenerate this key?`,message:`This rotates the key credential. Any client still using the current secret starts getting 401s immediately, and the old secret cannot be recovered. The handoff link is re-pointed to reveal the new key.`,confirmLabel:`Regenerate key`}:{title:`Regenerate this link?`,message:`This replaces the link URL; the current URL stops resolving immediately. Recipients keep the keys they already generated and keep working — but no one can enroll through the old link again.`,confirmLabel:`Regenerate link`}}function bt({consumed:e,budget:t}){let n=t==null||t<=0,r=n?100:Math.min(100,e/t*100),i=!n&&e>=t;return(0,$.jsxs)(`div`,{className:`grid flex-auto basis-full gap-2.5 rounded-control border border-inner-border bg-surface-2 px-5 py-3.5`,children:[(0,$.jsxs)(`div`,{className:`flex items-baseline justify-between gap-4 text-badge tracking-label text-text-tertiary uppercase`,children:[(0,$.jsx)(`span`,{children:`Lifetime budget`}),(0,$.jsx)(`span`,{className:`text-caption font-normal text-text-primary tabular-nums normal-case tracking-normal`,children:n?`${H(e)} · Unlimited`:`${H(e)} / ${H(t)}`})]}),(0,$.jsx)(`div`,{className:`h-3 overflow-hidden rounded bg-inner-border`,role:`progressbar`,"aria-label":`Lifetime token budget consumed`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(r),"aria-valuetext":n?`${H(e)} tokens consumed, no lifetime budget set`:`${H(e)} of ${H(t)} tokens consumed`,children:(0,$.jsx)(`div`,{className:i?`h-full rounded bg-status-danger`:`h-full rounded bg-status-success`,style:{width:`${r}%`}})})]})}var xt=6;function St(e){return e.filter(e=>e.revokedAt===null).length}function Ct(e){return e.reduce((e,t)=>e+t.allTime.totalTokens,0)}function wt({consumed:e,budget:t}){if(t==null)return(0,$.jsx)(`div`,{className:`grid flex-auto basis-full gap-2.5 rounded-control border border-inner-border bg-surface-2 px-5 py-3.5`,children:(0,$.jsxs)(`div`,{className:`flex items-baseline justify-between gap-4 text-badge tracking-label text-text-tertiary uppercase`,children:[(0,$.jsx)(`span`,{children:`Total quota used`}),(0,$.jsx)(`span`,{className:`text-caption font-normal text-text-primary tabular-nums normal-case tracking-normal`,children:H(e)})]})});let n=t>0?Math.min(100,e/t*100):0,r=t>0?Math.max(0,100-e/t*100):100,i=Math.max(0,t-e),a=Le(e>=t?0:r),o=e>=t;return(0,$.jsxs)(`div`,{className:`grid flex-auto basis-full gap-2.5 rounded-control border border-inner-border bg-surface-2 px-5 py-3.5`,children:[(0,$.jsxs)(`div`,{className:`flex items-baseline justify-between gap-4 text-badge tracking-label text-text-tertiary uppercase`,children:[(0,$.jsx)(`span`,{children:`Total quota`}),(0,$.jsxs)(`span`,{className:`text-caption font-normal text-text-primary tabular-nums normal-case tracking-normal`,children:[H(e),` / `,H(t)]}),(0,$.jsx)(`span`,{className:`border rounded-chip px-4 py-0.5 text-caption font-bold whitespace-nowrap tabular-nums`,style:{color:a.text,borderColor:a.text},children:o?`Exhausted`:`${H(i)} left`})]}),(0,$.jsx)(`div`,{className:`h-3 overflow-hidden rounded bg-inner-border`,role:`progressbar`,"aria-label":`Total quota consumed`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(n),"aria-valuetext":`${H(e)} of ${H(t)} tokens consumed`,children:(0,$.jsx)(`div`,{className:o?`h-full rounded bg-status-danger`:`h-full rounded`,style:{width:`${n}%`,background:o?void 0:a.bar}})})]})}function Tt({parentId:e,childId:t}){let n=je(e,t);if(n.isPending)return(0,$.jsx)(T,{label:`Loading activity…`,compact:!0});if(n.isError)return(0,$.jsx)(w,{compact:!0,message:F(n.error,`Could not load activity.`),onRetry:()=>void n.refetch()});let r=n.data;return r?(0,$.jsxs)(`div`,{className:`grid min-w-0 gap-6 border-t border-inner-border bg-surface-1 px-6 py-5`,children:[(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h4`,{className:`mb-3 text-caption font-bold text-text-primary`,children:`Top models`}),r.models.length?(0,$.jsx)(`div`,{className:`data-table-container`,children:(0,$.jsxs)(`table`,{className:`data-table text-caption`,children:[(0,$.jsx)(`thead`,{children:(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`th`,{scope:`col`,children:`Model`}),(0,$.jsx)(`th`,{scope:`col`,children:`Today`}),(0,$.jsx)(`th`,{scope:`col`,children:`Errors`}),(0,$.jsx)(`th`,{scope:`col`,children:`Tokens`})]})}),(0,$.jsx)(`tbody`,{children:r.models.map((e,t)=>(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`td`,{children:e.modelId}),(0,$.jsx)(`td`,{children:ht(e.todayRequests)}),(0,$.jsx)(`td`,{children:ht(e.todayErrors)}),(0,$.jsx)(`td`,{children:H(e.todayTokens)})]},`${e.providerId??``}-${e.modelId}-${t}`))})]})}):(0,$.jsx)(`p`,{className:`py-3 text-caption text-text-tertiary`,children:`No model activity yet.`})]}),(0,$.jsxs)(`section`,{children:[(0,$.jsx)(`h4`,{className:`mb-3 text-caption font-bold text-text-primary`,children:`Recent requests`}),r.requests.length?(0,$.jsx)(`div`,{className:`data-table-container`,children:(0,$.jsxs)(`table`,{className:`data-table text-caption`,children:[(0,$.jsx)(`thead`,{children:(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`th`,{scope:`col`,children:`Model`}),(0,$.jsx)(`th`,{scope:`col`,children:`Status`}),(0,$.jsx)(`th`,{scope:`col`,children:`Tokens`}),(0,$.jsx)(`th`,{scope:`col`,children:`Time`})]})}),(0,$.jsx)(`tbody`,{children:r.requests.map(e=>(0,$.jsxs)(`tr`,{children:[(0,$.jsxs)(`td`,{children:[e.providerId??`Provider`,`/`,e.modelId??`Model`]}),(0,$.jsxs)(`td`,{children:[e.status,e.httpStatus?` · ${e.httpStatus}`:``]}),(0,$.jsx)(`td`,{children:H(e.totalTokens)}),(0,$.jsx)(`td`,{children:gt(e.startedAt)})]},e.requestId))})]})}):(0,$.jsx)(`p`,{className:`py-3 text-caption text-text-tertiary`,children:`No recent requests.`})]})]}):null}function Et({parent:e,onSecretRevealed:t}){let[n,r]=(0,Q.useState)(null),[i,o]=(0,Q.useState)(`active`),[s,c]=(0,Q.useState)(null),l=ue(),u=Ce(),f=Oe(),p=ke(),m=Z(e.id),h=e.keyMode!==`share`,v=X(h?null:e.id),y=v.data??[],b=i===`active`?y.filter(e=>e.revokedAt===null):y.filter(e=>e.revokedAt!==null),x=y.filter(e=>e.revokedAt===null&&e.allTime.totalTokens===0);(0,Q.useEffect)(()=>{r(null)},[e.id]);let S=async(t,n)=>{let r=(await d(t,xt,t=>p.mutateAsync({parentKeyId:e.id,childKeyId:t.id,deferInvalidation:!0}))).filter(e=>e.status===`fulfilled`).length;await l.invalidateQueries({queryKey:I.apiKeys.sharedKeys(e.id)}),await l.invalidateQueries({queryKey:I.apiKeys.all}),await v.refetch();let i=t.length-r;i>0?_.error(`Revoked ${r} of ${t.length} ${n}; ${i} failed.`):_.success(`Revoked ${r} ${n}.`)},C=u.isPending||f.isPending,[te,ne]=(0,Q.useState)(!1),re=async()=>{if(h){let n=await f.mutateAsync({keyId:e.id});t?.(n.secret);return}await u.mutateAsync({keyId:e.id,regenerate:!0}),_.success(`Link regenerated; the previous URL no longer works.`)},O=()=>{u.mutate({keyId:e.id},{onError:e=>_.error(F(e,`Could not create link.`))})},k=m.data?.url??null,A=yt(h);return(0,$.jsxs)(`div`,{className:`grid min-w-0 gap-6`,children:[(0,$.jsx)(`section`,{"aria-label":`Link`,children:m.isPending?(0,$.jsx)(T,{label:`Loading link…`,compact:!0}):m.isError?(0,$.jsx)(w,{compact:!0,message:F(m.error,`Could not load the link.`),onRetry:()=>void m.refetch()}):k?(0,$.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-4 rounded-control border border-inner-border bg-surface-2 px-5 py-4 text-text-tertiary`,children:[(0,$.jsx)(ie,{size:14,"aria-hidden":`true`,className:`shrink-0`}),(0,$.jsx)(`code`,{title:k,className:`min-w-0 flex-auto overflow-hidden font-mono text-caption text-text-primary text-ellipsis whitespace-nowrap`,children:k}),(0,$.jsx)(D,{value:k,size:`sm`,variant:`secondary`,label:`Copy`,copiedLabel:`Copied`}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(Ve,{size:13}),loading:C,disabled:C,onClick:()=>ne(!0),children:`Regenerate`})]}):(0,$.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-4 rounded-control border border-inner-border bg-surface-2 px-5 py-4 text-text-tertiary`,children:[(0,$.jsx)(ie,{size:14,"aria-hidden":`true`,className:`shrink-0`}),(0,$.jsx)(`span`,{className:`flex-auto text-caption text-text-tertiary`,children:`No link yet.`}),(0,$.jsx)(g,{variant:`primary`,size:`sm`,loading:C,disabled:C,onClick:O,children:`Create link`})]})}),h?(0,$.jsxs)(`section`,{"aria-label":`API key`,className:`grid gap-3`,children:[(0,$.jsx)(`div`,{className:`flex items-center justify-between gap-4`,children:(0,$.jsx)(`strong`,{className:`text-caption`,children:`API key`})}),(0,$.jsx)(_t,{keyId:e.id})]}):null,h?(0,$.jsxs)(`section`,{"aria-label":`Usage`,className:`grid gap-3`,children:[(0,$.jsx)(`div`,{className:`flex items-center justify-between gap-4`,children:(0,$.jsx)(`strong`,{className:`text-caption`,children:`Usage`})}),(0,$.jsxs)(`dl`,{className:`m-0 flex flex-wrap gap-3`,children:[(0,$.jsxs)(`div`,{className:`min-w-0 flex-1 basis-60 rounded-control border border-inner-border bg-surface-2 px-5 py-3`,children:[(0,$.jsx)(`dt`,{className:`text-badge font-normal tracking-label text-text-tertiary uppercase`,children:`Lifetime tokens`}),(0,$.jsx)(`dd`,{className:`mt-1 text-caption font-normal text-text-primary tabular-nums`,children:H(e.tokensConsumed)})]}),(0,$.jsx)(vt,{label:`Requests / min`,value:e.requestsPerMinute}),(0,$.jsx)(vt,{label:`Daily tokens`,value:e.dailyTokenLimit}),(0,$.jsx)(vt,{label:`Monthly tokens`,value:e.monthlyTokenLimit}),(0,$.jsx)(bt,{consumed:e.tokensConsumed,budget:e.lifetimeTokenBudget})]})]}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`section`,{"aria-label":`Total quota`,className:`grid gap-3`,children:[(0,$.jsx)(`div`,{className:`flex items-center justify-between gap-4`,children:(0,$.jsx)(`strong`,{className:`text-caption`,children:`Total quota`})}),(0,$.jsx)(wt,{consumed:Ct(y),budget:e.lifetimeTokenBudget})]}),(0,$.jsxs)(`section`,{"aria-label":`Recipients`,className:`grid gap-3`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,$.jsx)(`strong`,{className:`text-caption`,children:`Recipients`}),(0,$.jsxs)(`span`,{className:`mr-2 ml-auto text-caption text-text-tertiary tabular-nums`,children:[`Active users: `,St(y)]}),(0,$.jsx)(`div`,{className:`inline-flex items-center gap-1 rounded-chip border border-inner-border p-0.5`,role:`group`,"aria-label":`Filter recipients by status`,children:[`active`,`revoked`].map(e=>(0,$.jsx)(`button`,{type:`button`,"aria-pressed":i===e,onClick:()=>o(e),className:`rounded-chip border-0 px-3 py-1 text-badge font-semibold capitalize cursor-pointer ${i===e?`bg-surface-1 text-text-primary`:`bg-transparent text-text-secondary hover:text-text-primary`}`,children:e},e))}),s===null?null:(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2 rounded-chip border border-danger-border bg-surface-2 px-3 py-1`,children:[(0,$.jsx)(`span`,{className:`text-badge text-text-secondary`,children:s===`all`?`Revoke ${b.length}?`:`Revoke ${x.length} unused?`}),(0,$.jsx)(g,{variant:`danger`,size:`sm`,loading:p.isPending,onClick:()=>{let e=s===`all`?b:x,t=s===`all`?`recipients`:`unused recipients`;c(null),S(e,t)},children:`Confirm`}),(0,$.jsx)(g,{variant:`ghost`,size:`sm`,onClick:()=>c(null),children:`Cancel`})]}),(0,$.jsx)(g,{variant:`ghost`,size:`sm`,disabled:x.length===0||p.isPending,title:x.length===0?`No active recipient has spent zero tokens`:`Revoke ${x.length} recipient${x.length===1?``:`s`} that never spent a token`,onClick:()=>c(`unused`),icon:(0,$.jsx)(a,{size:13}),children:`Revoke no-usage`}),(0,$.jsx)(g,{variant:`ghost`,size:`sm`,disabled:b.length===0||p.isPending,title:b.length===0?`Nothing to revoke in this view`:`Revoke all ${b.length} listed recipient${b.length===1?``:`s`}`,onClick:()=>c(`all`),icon:(0,$.jsx)(a,{size:13}),children:`Revoke all`}),(0,$.jsx)(g,{variant:`ghost`,size:`sm`,onClick:()=>void v.refetch(),icon:(0,$.jsx)(j,{size:13,className:v.isFetching?`animate-spin`:void 0}),children:`Refresh`})]}),v.isPending&&!v.data?(0,$.jsx)(T,{label:`Loading recipients…`,compact:!0}):v.isError?(0,$.jsx)(w,{compact:!0,message:F(v.error,`Could not load recipients.`),onRetry:()=>void v.refetch()}):b.length===0?(0,$.jsx)(E,{compact:!0,title:i===`revoked`?`No revoked recipients`:`No active recipients`,message:i===`revoked`?`Revoked keys appear here once a recipient's key is revoked.`:`Keys generated through this link appear here with their masked client IP and token usage.`}):(0,$.jsx)(`div`,{className:`data-table-container max-h-[46vh]`,children:(0,$.jsxs)(`table`,{className:`data-table text-caption`,children:[(0,$.jsx)(`thead`,{children:(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`th`,{scope:`col`,className:`w-12`,"aria-label":`Expand`}),(0,$.jsx)(`th`,{scope:`col`,children:`Key`}),(0,$.jsx)(`th`,{scope:`col`,children:`Status`}),(0,$.jsx)(`th`,{scope:`col`,children:`Today`}),(0,$.jsx)(`th`,{scope:`col`,children:`Lifetime`}),(0,$.jsx)(`th`,{scope:`col`,children:`Last activity`}),(0,$.jsx)(`th`,{scope:`col`,className:`text-right whitespace-nowrap`,children:`Actions`})]})}),(0,$.jsx)(`tbody`,{children:b.map(t=>{let i=n===t.id;return(0,$.jsxs)(Q.Fragment,{children:[(0,$.jsxs)(`tr`,{children:[(0,$.jsx)(`td`,{children:(0,$.jsx)(`button`,{type:`button`,className:`grid h-11 w-11 place-items-center rounded-chip border-0 bg-transparent p-0 text-text-secondary hover:bg-hover hover:text-text-primary`,"aria-expanded":i,"aria-label":i?`Collapse recipient`:`Expand recipient`,onClick:()=>r(i?null:t.id),children:i?(0,$.jsx)(_e,{size:14}):(0,$.jsx)(ee,{size:14})})}),(0,$.jsxs)(`td`,{children:[(0,$.jsxs)(`code`,{children:[t.label||t.keyPrefix||`key`,`…`]}),(0,$.jsx)(`div`,{className:`mt-1 text-badge text-text-tertiary wrap-anywhere`,children:t.issuedClientIp??`IP hidden`})]}),(0,$.jsx)(`td`,{children:t.revokedAt?`revoked`:`active`}),(0,$.jsx)(`td`,{children:H(t.today.totalTokens)}),(0,$.jsx)(`td`,{children:H(t.allTime.totalTokens)}),(0,$.jsx)(`td`,{children:gt(t.lastUsedAt)}),(0,$.jsx)(`td`,{className:`text-right whitespace-nowrap`,children:(0,$.jsx)(g,{variant:`danger`,size:`sm`,disabled:p.isPending||!!t.revokedAt,onClick:()=>p.mutate({parentKeyId:e.id,childKeyId:t.id},{onError:e=>_.error(F(e,`Could not revoke key.`))}),children:`Revoke`})})]}),i?(0,$.jsx)(`tr`,{children:(0,$.jsx)(`td`,{colSpan:7,className:`p-0`,children:(0,$.jsx)(Tt,{parentId:e.id,childId:t.id})})}):null]},t.id)})})]})})]})]}),(0,$.jsx)(L,{open:te,onClose:()=>ne(!1),onConfirm:re,title:A.title,message:A.message,confirmLabel:A.confirmLabel,danger:!0})]})}function Dt({parent:e,onClose:t,onSecretRevealed:n}){let r=e.keyMode!==`share`;return(0,$.jsx)(O,{open:!0,onClose:t,title:`Sharing — ${e.label||`API key`}`,description:r?`One stable handoff link for this key. Regenerating rotates the key itself.`:`One stable enrollment link. Regenerating replaces the URL; recipients keep the keys they already generated.`,size:`lg`,children:(0,$.jsx)(Et,{parent:e,onSecretRevealed:n})})}function Ot(){let e=Ae(),t=ge(),n=Ee(),r=we(),i=De(),a=Oe(),o=Se(),s=Te(),{copy:c}=V(),[l,u]=(0,Q.useState)(!1),[d,f]=(0,Q.useState)(null),[m,h]=(0,Q.useState)(null),[v,y]=(0,Q.useState)(null),[ee,x]=(0,Q.useState)(null),[S,C]=(0,Q.useState)(null),[te,re]=(0,Q.useState)(!1),[ie,D]=(0,Q.useState)(null),[j,M]=(0,Q.useState)(null),N=e.data??[],ae=t.data?.isPlatformAdmin??!1,oe=e=>{x(null),C(e)},se=async e=>{try{let{secret:t}=await o.mutateAsync({keyId:e.id});await c(t)?_.success(`API key copied`):_.error(`Clipboard unavailable on this origin`)}catch(e){_.error(F(e,`Could not reveal API key.`))}},P=yt(!0);return(0,$.jsxs)(B,{children:[(0,$.jsx)(z,{title:`API Credentials`,subtitle:`Manage tenant API keys, model access, budgets, and sharing.`,icon:(0,$.jsx)(ne,{size:16}),action:(0,$.jsxs)(`div`,{className:`flex items-center gap-4`,children:[ae?(0,$.jsx)(g,{variant:`secondary`,size:`sm`,onClick:()=>re(!0),icon:(0,$.jsx)(We,{size:13}),children:`Banned Users`}):null,(0,$.jsx)(g,{variant:`primary`,size:`sm`,onClick:()=>{x(null),u(!0)},icon:(0,$.jsx)(A,{size:13}),children:`Create Key`})]})}),(0,$.jsx)(R,{children:e.isPending&&!e.data?(0,$.jsx)(T,{label:`Loading API keys…`}):e.isError&&!e.data?(0,$.jsx)(w,{message:F(e.error,`Could not load credentials.`),onRetry:()=>void e.refetch()}):N.length===0?(0,$.jsx)(E,{title:`No API keys issued`,message:`Generate a secret key to authenticate your SDK or CLI client against the gateway.`,icon:(0,$.jsx)(ne,{size:20})}):(0,$.jsx)(`div`,{className:`scroll-region max-h-280 pr-1`,children:(0,$.jsx)(b,{items:N,label:`API credentials`,disabled:s.isPending,onReorder:e=>s.mutate(e,{onError:e=>_.error(F(e,`Could not save the new order.`))}),renderItem:e=>(0,$.jsxs)(`div`,{className:`api-key-card flex items-start justify-between gap-6 px-6 py-4 rounded-chip border border-inner-border bg-surface-2 max-medium:flex-col max-medium:items-stretch max-medium:gap-4 max-medium:p-5 [&>div:last-child]:flex-wrap`,children:[(0,$.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap`,children:[(0,$.jsx)(`strong`,{className:`text-body`,children:e.label||`Unnamed credential`}),(0,$.jsx)(W,{tone:e.revokedAt?`err`:e.enabled?`ok`:`warn`,children:e.revokedAt?`revoked`:e.enabled?`enabled`:`disabled`}),(0,$.jsx)(W,{tone:e.keyMode===`share`?`accent`:`default`,children:e.keyMode===`share`?`share template`:`personal`}),e.isDefault?(0,$.jsx)(W,{tone:`warn`,title:`Required by the gateway. Rotate it; it cannot be deleted.`,children:`default · rotate only`}):null]}),(0,$.jsxs)(`div`,{className:`api-key-facts flex items-center flex-wrap gap-2 mt-3 min-w-0 max-medium:grid max-medium:grid-cols-3 max-medium:gap-2 max-medium:mt-0`,children:[(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`Created`}),new Date(e.createdAt).toLocaleDateString()]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:e.keyMode===`share`?`Total usage`:`Usage`}),H(e.tokensConsumed)]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`RPM`}),U(e.requestsPerMinute)]})]}),(0,$.jsxs)(`div`,{className:`api-key-facts flex items-center flex-wrap gap-2 mt-3 min-w-0 max-medium:grid max-medium:grid-cols-3 max-medium:gap-2 max-medium:mt-0`,children:[(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`Daily`}),U(e.dailyTokenLimit)]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`Monthly`}),U(e.monthlyTokenLimit)]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`One-time`}),U(e.lifetimeTokenBudget)]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`Concurrent`}),U(e.maxConcurrentRequests)]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap max-medium:justify-between`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:e.modelAccessMode===`blacklist`?`Blocked`:`Models`}),e.modelAccessMode===`blacklist`?e.modelList?.length??0:e.modelList?.length?e.modelList.length:`All`]})]})]}),(0,$.jsxs)(`div`,{className:`flex gap-3 shrink-0 flex-wrap`,children:[e.revokedAt?null:(0,$.jsx)(q,{checked:e.enabled,disabled:r.isPending,id:`api-key-enabled-${e.id}`,label:``,"aria-label":`${e.enabled?`Disable`:`Enable`} ${e.label||`API credential`}`,onChange:t=>r.mutate({keyId:e.id,request:{enabled:t}},{onSuccess:()=>_.success(`${e.label||`API credential`} ${t?`enabled`:`disabled`}`),onError:e=>_.error(F(e,`Could not update credential state.`))})}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(k,{size:13}),onClick:()=>{x(null),f(e)},children:`Edit`}),!e.revokedAt&&e.keyMode!==`share`?(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(p,{size:13}),onClick:()=>void se(e),disabled:o.isPending,children:`Copy`}):null,!e.revokedAt&&(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(Ue,{size:13}),onClick:()=>oe(e),children:e.keyMode===`share`?`Recipients`:`Share`}),!e.revokedAt&&e.keyMode!==`share`&&(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(Ve,{size:13}),onClick:()=>{x(null),y(e)},disabled:a.isPending,children:`Rotate`}),!e.revokedAt&&!e.isDefault&&(0,$.jsx)(g,{variant:`danger`,size:`sm`,icon:(0,$.jsx)(ce,{size:13}),onClick:()=>h(e),disabled:i.isPending,children:`Revoke`})]})]})})})}),(0,$.jsx)(O,{open:l,onClose:()=>u(!1),title:`Create API Key`,description:`Create a tenant-scoped credential. Choose model access, permissions, limits, and optional blocked client routers.`,size:`lg`,footer:ie,children:(0,$.jsx)(dt,{mode:`create`,record:null,busy:n.isPending,onClose:()=>u(!1),actionsRef:D,onDone:e=>{n.mutate(e,{onSuccess:t=>{u(!1),x(lt(e.keyMode,t.secret)),_.success(`API key created`)},onError:e=>_.error(F(e,`Could not create API key.`))})}})}),(0,$.jsx)(O,{open:d!==null,onClose:()=>f(null),title:`Edit API Key`,description:`Update the key's model access, permissions, limits, share notes, and optional public popup.`,size:`lg`,footer:j,children:(0,$.jsx)(dt,{mode:`edit`,record:d,busy:r.isPending,onClose:()=>f(null),actionsRef:M,onDone:e=>{d&&r.mutate({keyId:d.id,request:e},{onSuccess:t=>{f(null),x(lt(e.keyMode,t.secret)),_.success(`API key updated`)},onError:e=>_.error(F(e,`Could not update API key.`))})}})}),S?(0,$.jsx)(Dt,{parent:S,onClose:()=>C(null),onSecretRevealed:e=>{C(null),x(e)}}):null,(0,$.jsx)(L,{open:v!==null,onClose:()=>y(null),onConfirm:async()=>{if(!v)return;let e=await a.mutateAsync({keyId:v.id});x(e.secret),_.success(`Rotated ${v.label||v.id}.`),y(null)},title:P.title,message:P.message,confirmLabel:P.confirmLabel,danger:!0}),(0,$.jsx)(L,{open:m!==null,onClose:()=>h(null),onConfirm:async()=>{m&&(await i.mutateAsync(m.id),_.success(`Revoked ${m.label||m.id}.`),h(null))},title:`Revoke API key?`,message:m?`Revoke ${m.label||m.id}? Clients using it will be rejected.${m.keyMode===`share`?` All child keys and enrollment links will also be revoked.`:``}`:`Revoke this API key?`,confirmLabel:`Revoke`,danger:!0}),te?(0,$.jsx)(mt,{onClose:()=>re(!1)}):null,(0,$.jsx)(ft,{secret:ee,onClose:()=>x(null)})]})}function kt(){let e=P(),t=oe(),n=e.data;if(e.isPending)return(0,$.jsx)(T,{label:`Loading compression settings…`});if(e.isError||!n)return(0,$.jsx)(w,{message:F(e.error,`Failed to load compression settings`),onRetry:()=>void e.refetch()});let r=n.rtkPruneEnabled,a=n.ponyTailEnabled;return(0,$.jsxs)(B,{children:[(0,$.jsx)(z,{title:`Compression`,subtitle:`Shrink requests before they reach the provider`,icon:(0,$.jsx)(o,{size:16})}),(0,$.jsx)(R,{children:(0,$.jsxs)(J,{gap:`14px`,children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-x-8 gap-y-5`,children:[(0,$.jsxs)(`div`,{className:`flex gap-5 min-w-0 flex-auto`,children:[(0,$.jsx)(He,{size:16,className:`shrink-0 mt-1 text-text-secondary`}),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`label`,{htmlFor:`compression-rtk`,children:(0,$.jsx)(Y,{gap:`6px`,className:`text-body font-semibold`,children:`Prune tool output (RTK)`})}),(0,$.jsx)(`div`,{className:`text-badge text-text-tertiary wrap-anywhere max-w-full`,children:`Compact bulky tool results (diffs, grep dumps, listings) in the message history so a long conversation stops re-sending megabytes of raw output. Higher strength compresses more aggressively.`})]})]}),(0,$.jsxs)(Y,{gap:`8px`,className:`shrink-0 items-center ml-auto`,children:[(0,$.jsx)(K,{id:`compression-rtk-level`,"aria-label":`RTK strength`,value:n.rtkPruneLevel,onValueChange:e=>t.mutate({rtkPruneLevel:e===`lite`||e===`full`||e===`ultra`?e:`full`},{onError:e=>_.error(F(e,`Could not update RTK strength.`))}),options:[{value:`lite`,label:`Lite`},{value:`full`,label:`Full`},{value:`ultra`,label:`Ultra`}]}),(0,$.jsx)(q,{id:`compression-rtk`,"aria-label":`Enable RTK prune`,checked:r,onChange:e=>t.mutate({rtkPruneEnabled:e},{onError:e=>_.error(F(e,`Could not update RTK prune.`))})})]})]}),(0,$.jsxs)(`div`,{className:`flex items-start gap-x-8 gap-y-5`,children:[(0,$.jsxs)(`div`,{className:`flex gap-5 min-w-0 flex-auto`,children:[(0,$.jsx)(i,{size:16,className:`shrink-0 mt-1 text-text-secondary`}),(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`label`,{htmlFor:`compression-ponytail`,children:(0,$.jsx)(Y,{gap:`6px`,className:`text-body font-semibold`,children:`PonyTail (system directive)`})}),(0,$.jsx)(`div`,{className:`text-badge text-text-tertiary wrap-anywhere max-w-full`,children:`Appends a minimal-code directive to the system content, biasing the model toward the smallest working change. Higher strength pushes harder toward deletion over addition.`})]})]}),(0,$.jsxs)(Y,{gap:`8px`,className:`shrink-0 items-center ml-auto`,children:[(0,$.jsx)(K,{id:`compression-ponytail-level`,"aria-label":`PonyTail strength`,value:n.ponyTailLevel,onValueChange:e=>t.mutate({ponyTailLevel:e===`lite`||e===`full`||e===`ultra`?e:`full`},{onError:e=>_.error(F(e,`Could not update PonyTail strength.`))}),options:[{value:`lite`,label:`Lite`},{value:`full`,label:`Full`},{value:`ultra`,label:`Ultra`}]}),(0,$.jsx)(q,{id:`compression-ponytail`,"aria-label":`Enable PonyTail`,checked:a,onChange:e=>t.mutate({ponyTailEnabled:e},{onError:e=>_.error(F(e,`Could not update PonyTail.`))})})]})]}),r||a?(0,$.jsxs)(`p`,{role:`note`,className:`flex gap-4 items-start m-0 py-4 px-5 rounded-inset border border-orange bg-orange-soft text-text-secondary text-badge`,children:[(0,$.jsx)(v,{size:14,className:`shrink-0 mt-0.5 text-orange`}),(0,$.jsx)(`span`,{children:`Your AI may produce degraded quality while compression is active: it sees a shortened history and a minimal-code directive, so fewer tokens but a chance of missing detail. Turn it off if answers get worse.`})]}):null]})})]})}function At(){return le({queryKey:I.remoteSupport.status,queryFn:()=>pe(`/remote-support/status`)})}function jt(){let e=ue();return me({mutationFn:e=>pe(`/remote-support/start`,{method:`POST`,body:JSON.stringify({tool:e})}),onSuccess:async()=>{await e.invalidateQueries({queryKey:I.remoteSupport.status})}})}function Mt(){let e=ue();return me({mutationFn:e=>pe(`/remote-support/stop`,{method:`POST`,body:JSON.stringify(e===void 0?{}:{tool:e})}),onSuccess:async()=>{await e.invalidateQueries({queryKey:I.remoteSupport.status})}})}var Nt={cloudflared:`cloudflared`,tailscale:`Tailscale`},Pt={cloudflared:`Publish a temporary public URL without opening a port.`,tailscale:`Give a helper a private address on your own tailnet.`};function Ft({tool:e}){return e===`cloudflared`?(0,$.jsxs)(`svg`,{viewBox:`0 0 24 24`,className:`size-8 shrink-0`,"aria-hidden":`true`,fill:`currentColor`,children:[(0,$.jsx)(`path`,{d:`M16.5 18.4a4.6 4.6 0 0 1-3.2-1.3l-6-5.9a2.4 2.4 0 0 0-3.3 0 2.3 2.3 0 0 0 0 3.3l5.4 5.3a.9.9 0 0 1-1.3 1.3L2.7 15.8a4.1 4.1 0 0 1 0-5.8 4.2 4.2 0 0 1 5.8 0l6 5.9a2.4 2.4 0 0 0 3.3 0 2.3 2.3 0 0 0 0-3.3l-4.2-4.1a.9.9 0 0 1 1.3-1.3l4.2 4.1a4.1 4.1 0 0 1 0 5.8 4.2 4.2 0 0 1-2.6 1.3Z`}),(0,$.jsx)(`path`,{d:`M7.6 18.4a4.5 4.5 0 0 1-3-1.1 5.4 5.4 0 0 1-1.5-3.5 6 6 0 0 1 .4-2 .9.9 0 0 1 1.7.6 4.2 4.2 0 0 0-.3 1.4 3.6 3.6 0 0 0 1 2.3 2.7 2.7 0 0 0 1.8.7.9.9 0 0 1 0 1.8Z`})]}):(0,$.jsxs)(`svg`,{viewBox:`0 0 24 24`,className:`size-8 shrink-0`,"aria-hidden":`true`,fill:`currentColor`,children:[(0,$.jsx)(`path`,{d:`M12 3.2a4.4 4.4 0 0 0-4.4 4.4v2.2H4.6a2.2 2.2 0 0 0 0 4.4h3v2.2a4.4 4.4 0 0 0 8.8 0v-2.2h1.1a3.3 3.3 0 0 0 0-6.6h-1.1V7.6A4.4 4.4 0 0 0 12 3.2Zm0 2.2a2.2 2.2 0 0 1 2.2 2.2v6.6a2.2 2.2 0 0 1-4.4 0V7.6A2.2 2.2 0 0 1 12 5.4Z`}),(0,$.jsx)(`path`,{d:`M6.6 11h4.2v2.2H6.6zM13.2 11h4.2v2.2h-4.2z`})]})}function It({tool:e}){let t=At(),n=jt(),r=Mt(),{copied:i,copy:a}=V(2e3),o=t.data?.active===e,s=n.isPending||r.isPending,c=o?t.data?.url??null:null,[l,u]=(0,Q.useState)(null),[d,f]=(0,Q.useState)(o);(0,Q.useEffect)(()=>{!n.isPending&&!r.isPending&&f(o)},[o,n.isPending,r.isPending]);let h=async t=>{f(t);try{let i=t?await n.mutateAsync(e):await r.mutateAsync(e);if(i.blocker!==null&&i.message!==null){u(i.message),_.error(i.message),f(!t);return}u(null),_.success(t?`${Nt[e]} started`:`${Nt[e]} stopped`)}catch{_.error(`Could not ${t?`start`:`stop`} ${Nt[e]}`),f(!t)}},v=async()=>{if(c!==null){if(await a(c)){_.success(`Remote URL copied`,c);return}_.error(`Clipboard unavailable on this origin`)}};return(0,$.jsxs)(`div`,{className:`rounded-control border border-inner-border bg-surface-2 p-5`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 items-center gap-3`,children:[(0,$.jsx)(Ft,{tool:e}),(0,$.jsx)(`h3`,{className:`text-caption font-semibold`,children:Nt[e]})]}),(0,$.jsx)(q,{checked:d,disabled:s,onChange:e=>void h(e),"aria-label":`Toggle ${Nt[e]} remote support`})]}),n.isPending?(0,$.jsxs)(`div`,{className:`mt-3 flex items-center justify-between gap-3`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2 text-badge text-text-secondary`,children:[(0,$.jsx)(y,{size:14,className:`animate-spin`,"aria-hidden":`true`}),(0,$.jsx)(`span`,{className:`animate-pulse`,children:`Waiting for address…`})]}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,onClick:()=>void h(!1),children:`Cancel`})]}):c===null?l===null?(0,$.jsx)(`p`,{className:`mt-2 text-badge leading-normal text-text-tertiary`,children:Pt[e]}):(0,$.jsxs)(`div`,{className:`mt-2 rounded-control border border-warning/30 bg-warning/10 p-3 text-badge leading-normal text-text-secondary`,children:[(0,$.jsx)(`p`,{className:`font-medium text-warning`,children:`Setup needed`}),(0,$.jsx)(`p`,{className:`mt-1 whitespace-pre-wrap break-words`,children:l}),(()=>{let e=l.match(/https:\/\/login\.tailscale\.com\/f\/serve\?[^\s]+/);return e?(0,$.jsx)(`a`,{href:e[0],target:`_blank`,rel:`noreferrer`,className:`mt-2 inline-block font-medium text-accent underline`,children:`Enable Tailscale Serve →`}):null})()]}):(0,$.jsxs)(`div`,{className:`mt-3 flex items-center gap-3`,children:[(0,$.jsx)(`code`,{className:`min-w-0 flex-1 truncate font-mono text-badge text-text-primary`,title:c,children:c}),(0,$.jsxs)(g,{variant:`secondary`,size:`sm`,onClick:()=>void v(),children:[i?(0,$.jsx)(m,{size:14}):(0,$.jsx)(p,{size:14}),i?`Copied`:`Copy`]})]})]})}function Lt(){let{copied:e,copy:t}=V(2e3),n=`${window.location.origin}/v1`,r=async()=>{if(await t(n)){_.success(`Gateway endpoint copied`,n);return}_.error(`Clipboard unavailable on this origin`)};return(0,$.jsxs)(B,{children:[(0,$.jsx)(z,{title:`Gateway Endpoint`,subtitle:`Universal OpenAI & Anthropic Wire API Endpoint Compatible`,icon:(0,$.jsx)(f,{size:16})}),(0,$.jsx)(R,{children:(0,$.jsxs)(J,{gap:`10px`,children:[(0,$.jsxs)(`div`,{className:`nested-panel flex items-center gap-4 rounded-control border border-inner-border bg-code-surface px-7 py-5 font-mono text-body font-semibold tabular-nums`,children:[(0,$.jsx)(`code`,{className:`min-w-0 flex-1 truncate`,title:n,children:n}),(0,$.jsx)(g,{variant:`secondary`,size:`sm`,icon:e?(0,$.jsx)(m,{size:13}):(0,$.jsx)(p,{size:13}),"aria-label":`Copy endpoint`,title:`Copy endpoint`,onClick:()=>void r(),className:`shrink-0`,children:e?`Copied`:`Copy`})]}),(0,$.jsxs)(`p`,{className:`text-caption leading-normal text-text-secondary`,children:[`Point any SDK, CLI, or agent (e.g. OpenCode, Pi, OMP, Kilo, Cline, Droid and more clients) to this same-origin base URL.`,(0,$.jsxs)(`span`,{className:`mt-1 block text-text-tertiary`,children:[`You may not put `,(0,$.jsx)(`code`,{className:`font-mono`,children:`/v1`}),` on Claude Code — the CLI appends it itself.`]})]})]})})]})}function Rt(){let e=At();return(0,$.jsxs)(B,{children:[(0,$.jsx)(z,{title:`Remote Support`,subtitle:`Reach this gateway from outside the local network`,icon:(0,$.jsx)(ze,{size:16})}),(0,$.jsx)(R,{children:(0,$.jsxs)(J,{gap:`10px`,children:[(0,$.jsxs)(`div`,{className:`grid grid-cols-2 gap-4 max-medium:grid-cols-1`,children:[(0,$.jsx)(It,{tool:`cloudflared`}),(0,$.jsx)(It,{tool:`tailscale`})]}),e.data?.blocker!==null&&e.data?.message!==null?(0,$.jsx)(`p`,{className:`text-badge leading-normal text-red-primary`,children:e.data?.message}):null,(0,$.jsxs)(`p`,{className:`text-caption leading-normal text-text-secondary`,children:[`Either way the gateway still sees the tunnel's address as the client, so set`,` `,(0,$.jsx)(`code`,{className:`font-mono`,children:`TRUSTED_PROXY_CIDRS`}),` to the edge that forwards to it — otherwise every remote caller is recorded as the loopback address.`]}),(0,$.jsx)(`p`,{className:`text-badge leading-normal text-text-tertiary`,children:`cloudflared and Tailscale are not installed by Cartethyia — install either one yourself first. The tunnel is launched detached from this process, so it survives a gateway restart.`})]})})]})}function zt(){return(0,$.jsxs)(J,{gap:`16px`,children:[(0,$.jsx)(Lt,{}),(0,$.jsx)(Rt,{}),(0,$.jsx)(kt,{}),(0,$.jsx)(Ot,{})]})}export{zt as default};