cartethyia 2.4.5 → 2.4.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 (303) hide show
  1. package/.env.example +4 -1
  2. package/README.md +18 -0
  3. package/dist/dashboard/assets/AccountCooldown-ChpdzxRH.js.gz +0 -0
  4. package/dist/dashboard/assets/{BannedPage-DUrXpp-X.js → BannedPage-QhvbJB9o.js} +1 -1
  5. package/dist/dashboard/assets/BannedPage-QhvbJB9o.js.gz +0 -0
  6. package/dist/dashboard/assets/{CliToolDetailPage-BzGevuql.js → CliToolDetailPage-Bcy150Jo.js} +1 -1
  7. package/dist/dashboard/assets/CliToolDetailPage-Bcy150Jo.js.gz +0 -0
  8. package/dist/dashboard/assets/{CliToolsPage-BaRM_7We.js → CliToolsPage-DyNXefph.js} +1 -1
  9. package/dist/dashboard/assets/CliToolsPage-DyNXefph.js.gz +0 -0
  10. package/dist/dashboard/assets/CombosPage-Cak0ljnO.js +1 -0
  11. package/dist/dashboard/assets/CombosPage-Cak0ljnO.js.gz +0 -0
  12. package/dist/dashboard/assets/ConsoleLogPage-CATpAEOz.js +1 -0
  13. package/dist/dashboard/assets/ConsoleLogPage-CATpAEOz.js.gz +0 -0
  14. package/dist/dashboard/assets/{CustomizationPage-DqUGcoH0.js → CustomizationPage-D6jEU7nL.js} +1 -1
  15. package/dist/dashboard/assets/CustomizationPage-D6jEU7nL.js.gz +0 -0
  16. package/dist/dashboard/assets/HealthEventsModal-CZkpn0a7.js +1 -0
  17. package/dist/dashboard/assets/HealthEventsModal-CZkpn0a7.js.gz +0 -0
  18. package/dist/dashboard/assets/{LoginPage-DbhTGfhb.js → LoginPage-BJlMVN4U.js} +1 -1
  19. package/dist/dashboard/assets/LoginPage-BJlMVN4U.js.gz +0 -0
  20. package/dist/dashboard/assets/ModelPicker-Br3CXEau.js +1 -0
  21. package/dist/dashboard/assets/ModelPicker-Br3CXEau.js.gz +0 -0
  22. package/dist/dashboard/assets/{OverviewPage-C3NIzsDx.js → OverviewPage-CQxXbo2g.js} +1 -1
  23. package/dist/dashboard/assets/OverviewPage-CQxXbo2g.js.gz +0 -0
  24. package/dist/dashboard/assets/ProviderDetailPage--0RBNh99.js +3 -0
  25. package/dist/dashboard/assets/ProviderDetailPage--0RBNh99.js.gz +0 -0
  26. package/dist/dashboard/assets/ProviderIcon-paOCq8I0.js.gz +0 -0
  27. package/dist/dashboard/assets/ProvidersPage-1M-C3mbu.js +1 -0
  28. package/dist/dashboard/assets/ProvidersPage-1M-C3mbu.js.gz +0 -0
  29. package/dist/dashboard/assets/ProxyPage-CXiumA53.js +7 -0
  30. package/dist/dashboard/assets/ProxyPage-CXiumA53.js.gz +0 -0
  31. package/dist/dashboard/assets/QuotaPage-BGDIfIYP.js +1 -0
  32. package/dist/dashboard/assets/QuotaPage-BGDIfIYP.js.gz +0 -0
  33. package/dist/dashboard/assets/{SettingsPage-YxRml8AT.js → SettingsPage-BHW4Zt06.js} +1 -1
  34. package/dist/dashboard/assets/SettingsPage-BHW4Zt06.js.gz +0 -0
  35. package/dist/dashboard/assets/SetupPage-VOYC_lIa.js +1 -0
  36. package/dist/dashboard/assets/SetupPage-VOYC_lIa.js.gz +0 -0
  37. package/dist/dashboard/assets/SortableList-DpOTnGuH.js +1 -0
  38. package/dist/dashboard/assets/SortableList-DpOTnGuH.js.gz +0 -0
  39. package/dist/dashboard/assets/StudioPage-BNIDLiU6.js +31 -0
  40. package/dist/dashboard/assets/StudioPage-BNIDLiU6.js.gz +0 -0
  41. package/dist/dashboard/assets/ToolIcon-K1ckcDKg.js.gz +0 -0
  42. package/dist/dashboard/assets/{UsagePage-Djes-Epy.js → UsagePage-BAFaSDQV.js} +14 -14
  43. package/dist/dashboard/assets/UsagePage-BAFaSDQV.js.gz +0 -0
  44. package/dist/dashboard/assets/api-keys-BETfaMYZ.js +1 -0
  45. package/dist/dashboard/assets/api-keys-BETfaMYZ.js.gz +0 -0
  46. package/dist/dashboard/assets/app-BLCvGdzb.css +2 -0
  47. package/dist/dashboard/assets/app-BLCvGdzb.css.gz +0 -0
  48. package/dist/dashboard/assets/{app-BDJWMThu.js → app-Cjq7nrwu.js} +3 -3
  49. package/dist/dashboard/assets/app-Cjq7nrwu.js.gz +0 -0
  50. package/dist/dashboard/assets/arrow-left-CpBxkoxI.js.gz +0 -0
  51. package/dist/dashboard/assets/arrow-right-Dl5yKnp8.js.gz +0 -0
  52. package/dist/dashboard/assets/{assert-Bwh6DJTK.js → assert-7J6_LVD3.js} +1 -1
  53. package/dist/dashboard/assets/assert-7J6_LVD3.js.gz +0 -0
  54. package/dist/dashboard/assets/backup-file-gdKIlg8U.js.gz +0 -0
  55. package/dist/dashboard/assets/{badge-BwmwEOgA.js → badge-BTyGk_DL.js} +1 -1
  56. package/dist/dashboard/assets/badge-BTyGk_DL.js.gz +0 -0
  57. package/dist/dashboard/assets/{banner-BKBfKTqn.js → banner-bujTWYM4.js} +1 -1
  58. package/dist/dashboard/assets/banner-bujTWYM4.js.gz +0 -0
  59. package/dist/dashboard/assets/brain-Cwed_72z.js.gz +0 -0
  60. package/dist/dashboard/assets/{card-BTdbRFFg.js → card-B0Bnx5CA.js} +1 -1
  61. package/dist/dashboard/assets/card-B0Bnx5CA.js.gz +0 -0
  62. package/dist/dashboard/assets/check-D69FzdvC.js.gz +0 -0
  63. package/dist/dashboard/assets/chevron-right-BXIy5l3h.js.gz +0 -0
  64. package/dist/dashboard/assets/circle-alert-CntYHV5v.js.gz +0 -0
  65. package/dist/dashboard/assets/circle-check-BU3v_mFW.js.gz +0 -0
  66. package/dist/dashboard/assets/cli-tools-DE2ug812.js +1 -0
  67. package/dist/dashboard/assets/cli-tools-DE2ug812.js.gz +0 -0
  68. package/dist/dashboard/assets/clipboard-button-R_rArH8S.js +1 -0
  69. package/dist/dashboard/assets/clipboard-button-R_rArH8S.js.gz +0 -0
  70. package/dist/dashboard/assets/cog-CdWhsajs.js.gz +0 -0
  71. package/dist/dashboard/assets/copy-ngmQ9zcZ.js.gz +0 -0
  72. package/dist/dashboard/assets/{dialog-iocKA3jr.js → dialog-BWIP_EvW.js} +1 -1
  73. package/dist/dashboard/assets/dialog-BWIP_EvW.js.gz +0 -0
  74. package/dist/dashboard/assets/dialog-actions-B1axpEg7.js.gz +0 -0
  75. package/dist/dashboard/assets/download-A0SW9OCW.js.gz +0 -0
  76. package/dist/dashboard/assets/download-dRFo5_Wu.js.gz +0 -0
  77. package/dist/dashboard/assets/{drawer-CDKOTZdY.js → drawer-BKcgVugF.js} +1 -1
  78. package/dist/dashboard/assets/drawer-BKcgVugF.js.gz +0 -0
  79. package/dist/dashboard/assets/entry-7dpgvpJ3.js +4 -0
  80. package/dist/dashboard/assets/entry-7dpgvpJ3.js.gz +0 -0
  81. package/dist/dashboard/assets/entry-CcWkGR4a.js +1 -0
  82. package/dist/dashboard/assets/entry-CcWkGR4a.js.gz +0 -0
  83. package/dist/dashboard/assets/entry-kTiTFrvh.js +1 -0
  84. package/dist/dashboard/assets/entry-kTiTFrvh.js.gz +0 -0
  85. package/dist/dashboard/assets/eye-C_hawfH4.js.gz +0 -0
  86. package/dist/dashboard/assets/eye-off-Bk5g2luF.js.gz +0 -0
  87. package/dist/dashboard/assets/fingerprint-pattern-BWuHtbW4.js.gz +0 -0
  88. package/dist/dashboard/assets/gauge-BbIMy7MB.js.gz +0 -0
  89. package/dist/dashboard/assets/github-badge-Booc5mNe.js +1 -0
  90. package/dist/dashboard/assets/github-badge-Booc5mNe.js.gz +0 -0
  91. package/dist/dashboard/assets/image-BPaouViG.js.gz +0 -0
  92. package/dist/dashboard/assets/{index-C4hXfAMs.js → index-D70pChfn.js} +2 -2
  93. package/dist/dashboard/assets/index-D70pChfn.js.gz +0 -0
  94. package/dist/dashboard/assets/{inline-DCejSLlA.js → inline-D1TCqM2D.js} +1 -1
  95. package/dist/dashboard/assets/inline-D1TCqM2D.js.gz +0 -0
  96. package/dist/dashboard/assets/{input-Bn4_kNav.js → input-B9oyU93y.js} +1 -1
  97. package/dist/dashboard/assets/input-B9oyU93y.js.gz +0 -0
  98. package/dist/dashboard/assets/jsx-runtime-CXUMngI_.js.gz +0 -0
  99. package/dist/dashboard/assets/key-round-UkavsGxp.js.gz +0 -0
  100. package/dist/dashboard/assets/layers-2-glBbjl.js.gz +0 -0
  101. package/dist/dashboard/assets/{layout-Bv-NxqZ5.js → layout-BArzXirQ.js} +1 -1
  102. package/dist/dashboard/assets/layout-BArzXirQ.js.gz +0 -0
  103. package/dist/dashboard/assets/{list-row-BLA0sldD.js → list-row-BVZzaoHF.js} +1 -1
  104. package/dist/dashboard/assets/list-row-BVZzaoHF.js.gz +0 -0
  105. package/dist/dashboard/assets/{live-YlifPYox.js → live-EmuIayqp.js} +1 -1
  106. package/dist/dashboard/assets/live-EmuIayqp.js.gz +0 -0
  107. package/dist/dashboard/assets/log-in-BmRjy60c.js.gz +0 -0
  108. package/dist/dashboard/assets/message-circle-CCxGwRvv.js.gz +0 -0
  109. package/dist/dashboard/assets/{model-bans-CVvHZ-qz.js → model-bans-CSPQ9xB0.js} +1 -1
  110. package/dist/dashboard/assets/model-bans-CSPQ9xB0.js.gz +0 -0
  111. package/dist/dashboard/assets/mutation-BkoLM5Ba.js +1 -0
  112. package/dist/dashboard/assets/mutation-BkoLM5Ba.js.gz +0 -0
  113. package/dist/dashboard/assets/numbers-CFL4_Dqc.js.gz +0 -0
  114. package/dist/dashboard/assets/pencil-768ysRAr.js.gz +0 -0
  115. package/dist/dashboard/assets/plus-DIdX_g-x.js.gz +0 -0
  116. package/dist/dashboard/assets/power-off-Yjw9GMJh.js +1 -0
  117. package/dist/dashboard/assets/power-off-Yjw9GMJh.js.gz +0 -0
  118. package/dist/dashboard/assets/privacy-mode-GM8bej85.js +1 -0
  119. package/dist/dashboard/assets/privacy-mode-GM8bej85.js.gz +0 -0
  120. package/dist/dashboard/assets/providers/agentrouter.svg.gz +0 -0
  121. package/dist/dashboard/assets/providers/aihubmix.svg.gz +0 -0
  122. package/dist/dashboard/assets/providers/alibaba-coding-plan.svg.gz +0 -0
  123. package/dist/dashboard/assets/providers/alibaba.svg.gz +0 -0
  124. package/dist/dashboard/assets/providers/antigravity.svg.gz +0 -0
  125. package/dist/dashboard/assets/providers/bai.svg.gz +0 -0
  126. package/dist/dashboard/assets/providers/blackbox.svg.gz +0 -0
  127. package/dist/dashboard/assets/providers/claude-code.svg.gz +0 -0
  128. package/dist/dashboard/assets/providers/exa.svg.gz +0 -0
  129. package/dist/dashboard/assets/providers/gmi-cloud.svg.gz +0 -0
  130. package/dist/dashboard/assets/providers/inferhub.svg.gz +0 -0
  131. package/dist/dashboard/assets/providers/muse.svg.gz +0 -0
  132. package/dist/dashboard/assets/providers/nous-research.svg.gz +0 -0
  133. package/dist/dashboard/assets/providers/openai-light.svg.gz +0 -0
  134. package/dist/dashboard/assets/providers/parallel.svg.gz +0 -0
  135. package/dist/dashboard/assets/providers/tokenharbor.svg.gz +0 -0
  136. package/dist/dashboard/assets/providers/zai-coding-plan.svg.gz +0 -0
  137. package/dist/dashboard/assets/{query-keys-ROf-g1Wi.js → query-keys-D7wX2vM5.js} +1 -1
  138. package/dist/dashboard/assets/query-keys-D7wX2vM5.js.gz +0 -0
  139. package/dist/dashboard/assets/quota-DZGyp0N5.js.gz +0 -0
  140. package/dist/dashboard/assets/refresh-cw-BqJFk4sU.js.gz +0 -0
  141. package/dist/dashboard/assets/rotate-ccw-CufcqITi.js.gz +0 -0
  142. package/dist/dashboard/assets/route-CNSNj9Zm.js.gz +0 -0
  143. package/dist/dashboard/assets/{routing-jntw9-Ui.js → routing-BExgxxBU.js} +1 -1
  144. package/dist/dashboard/assets/routing-BExgxxBU.js.gz +0 -0
  145. package/dist/dashboard/assets/scaling-nWE4Cx8f.js.gz +0 -0
  146. package/dist/dashboard/assets/search-JOKus9rb.js.gz +0 -0
  147. package/dist/dashboard/assets/{select-CGUuTQmj.js → select-C9mMoEpJ.js} +1 -1
  148. package/dist/dashboard/assets/select-C9mMoEpJ.js.gz +0 -0
  149. package/dist/dashboard/assets/settings-C4_Gn_wq.js +1 -0
  150. package/dist/dashboard/assets/settings-C4_Gn_wq.js.gz +0 -0
  151. package/dist/dashboard/assets/shield-check-DVS0Foqh.js.gz +0 -0
  152. package/dist/dashboard/assets/sliders-horizontal-ClG7dBeJ.js.gz +0 -0
  153. package/dist/dashboard/assets/sparkles-BRaRUxAU.js.gz +0 -0
  154. package/dist/dashboard/assets/{stack-C1kTcOmP.js → stack-Ca5HxI5i.js} +1 -1
  155. package/dist/dashboard/assets/stack-Ca5HxI5i.js.gz +0 -0
  156. package/dist/dashboard/assets/{state-DHKdg-pm.js → state-CzUPfLXo.js} +1 -1
  157. package/dist/dashboard/assets/state-CzUPfLXo.js.gz +0 -0
  158. package/dist/dashboard/assets/stream-retry-5QnVuSSo.js.gz +0 -0
  159. package/dist/dashboard/assets/{switch-DIDeAiz9.js → switch-DOUIky_i.js} +1 -1
  160. package/dist/dashboard/assets/switch-DOUIky_i.js.gz +0 -0
  161. package/dist/dashboard/assets/terminal-Bd4ee8TA.js +1 -0
  162. package/dist/dashboard/assets/terminal-Bd4ee8TA.js.gz +0 -0
  163. package/dist/dashboard/assets/toast-C76WrMhc.js +2 -0
  164. package/dist/dashboard/assets/toast-C76WrMhc.js.gz +0 -0
  165. package/dist/dashboard/assets/tokens-DDxMbSRL.js.gz +0 -0
  166. package/dist/dashboard/assets/trash-Cppn5c3R.js.gz +0 -0
  167. package/dist/dashboard/assets/use-clipboard-B0Sy03fE.js.gz +0 -0
  168. package/dist/dashboard/assets/use-presence-BSZEBx7U.js.gz +0 -0
  169. package/dist/dashboard/assets/use-reduced-motion-C4B0R6Sz.js.gz +0 -0
  170. package/dist/dashboard/assets/use-timeout-BwcBBRrT.js.gz +0 -0
  171. package/dist/dashboard/assets/{useMutation-DVmwOKU-.js → useMutation-D87FZwH0.js} +1 -1
  172. package/dist/dashboard/assets/useMutation-D87FZwH0.js.gz +0 -0
  173. package/dist/dashboard/assets/wrench-B6E1oEuY.js.gz +0 -0
  174. package/dist/dashboard/index.html +1 -1
  175. package/dist/dashboard/index.html.gz +0 -0
  176. package/dist/dashboard/precompressed-assets.json +123 -0
  177. package/migrations/full-postgres/0013_add_providers_tenant_id_index.sql +22 -0
  178. package/migrations/full-postgres/0014_add_provider_accounts_tenant_id_index.sql +21 -0
  179. package/migrations/lite-sqlite3/0000_baseline.sql +4 -2
  180. package/migrations/lite-sqlite3/0013_add_providers_tenant_id_index.sql +4 -0
  181. package/migrations/lite-sqlite3/0014_add_provider_accounts_tenant_id_index.sql +4 -0
  182. package/package.json +25 -30
  183. package/scripts/cli/{carte-launcher.cjs → bin/carte.cjs} +8 -8
  184. package/scripts/cli/{cli-launcher.cjs → bin/cartethyia.cjs} +167 -134
  185. package/scripts/cli/command/admin.ts +65 -0
  186. package/scripts/cli/command/console-menu.ts +227 -0
  187. package/scripts/cli/{doctor.ts → command/doctor.ts} +257 -258
  188. package/scripts/cli/{setup.ts → command/setup.ts} +8 -12
  189. package/scripts/cli/command/start.ts +13 -0
  190. package/scripts/cli/command/tray.ts +165 -0
  191. package/scripts/cli/command/update.ts +23 -0
  192. package/scripts/cli/{runtime-state.ts → gateway/drain-token.ts} +78 -78
  193. package/scripts/cli/gateway/spawn.ts +101 -0
  194. package/scripts/cli/gateway/stop.ts +51 -0
  195. package/scripts/cli/main.ts +94 -0
  196. package/scripts/cli/support/bun.ts +27 -0
  197. package/scripts/cli/support/env.ts +99 -0
  198. package/scripts/cli/support/platform.ts +64 -0
  199. package/scripts/cli/support/services.ts +88 -0
  200. package/scripts/cli/support/startup-signal.ts +23 -0
  201. package/scripts/cli/{version.ts → support/version.ts} +1 -1
  202. package/scripts/cli/tray/hidden-window.vbs +28 -0
  203. package/scripts/cli/{tray.ts → tray/index.ts} +3 -3
  204. package/scripts/cli/{tray.ps1 → tray/windows.ps1} +107 -98
  205. package/scripts/cli/ui/background.ts +49 -0
  206. package/src/boot/app.ts +3 -1
  207. package/src/boot/dependencies.ts +36 -13
  208. package/src/config/providers.ts +27 -1
  209. package/src/config/spec.ts +11 -0
  210. package/src/console/backup/routes.ts +8 -0
  211. package/src/console/cli-tools/contracts.ts +6 -6
  212. package/src/console/console-router.ts +5 -3
  213. package/src/console/dashboard-assets.ts +81 -11
  214. package/src/console/observability/contracts.ts +54 -22
  215. package/src/console/observability/routes.ts +31 -6
  216. package/src/console/observability/store.ts +68 -28
  217. package/src/console/providers/catalog/public-model-store.ts +91 -60
  218. package/src/console/providers/catalog/store.ts +5 -1
  219. package/src/console/quota/account-quota-tenant.ts +9 -6
  220. package/src/console/response-compression.ts +69 -2
  221. package/src/console/routing/pools/probe-verdict.ts +72 -0
  222. package/src/console/share/share-router.ts +7 -4
  223. package/src/console/share/share-stats.ts +12 -5
  224. package/src/console/shared/read-through-cache.ts +133 -7
  225. package/src/console/updates/repository-updates.ts +39 -34
  226. package/src/network/outbound-fetch.ts +113 -25
  227. package/src/network/tls/bun-client-hello.ts +112 -0
  228. package/src/observability/event-log.ts +29 -8
  229. package/src/observability/metrics.ts +40 -13
  230. package/src/observability/runtime-metrics.ts +7 -0
  231. package/src/persistence/schema.ts +40 -2
  232. package/src/protocol/response/codex.ts +9 -75
  233. package/src/protocol/tool-identity.ts +43 -9
  234. package/src/providers/authentication/jwt-validator.ts +130 -187
  235. package/src/providers/authentication/oauth-flow-store.ts +16 -9
  236. package/src/providers/default-registry.ts +4 -0
  237. package/src/providers/discovery/catalog/catalog-format.ts +20 -0
  238. package/src/providers/discovery/models-dev-catalog.ts +39 -22
  239. package/src/providers/discovery/probe-wire.ts +29 -5
  240. package/src/providers/integrations/buddy/buddy-catalog-shared.ts +3 -2
  241. package/src/providers/integrations/buddy/buddy-cli-headers.ts +88 -0
  242. package/src/providers/integrations/buddy/buddy-conversation-headers.ts +4 -0
  243. package/src/providers/integrations/buddy/buddy-discovery-shared.ts +33 -1
  244. package/src/providers/integrations/buddy/buddy-identity.ts +46 -0
  245. package/src/providers/integrations/buddy/buddy-oauth-shared.ts +37 -1
  246. package/src/providers/integrations/buddy/buddy-usage-store.ts +40 -5
  247. package/src/providers/integrations/buddy/codebuddy/provider.ts +2 -2
  248. package/src/providers/integrations/buddy/codebuddy/shared.ts +106 -73
  249. package/src/providers/integrations/buddy/workbuddy/cn-provider.ts +5 -2
  250. package/src/providers/integrations/buddy/workbuddy/quota.ts +172 -159
  251. package/src/providers/integrations/buddy/workbuddy/shared.ts +200 -171
  252. package/src/providers/integrations/codex/codex.ts +5 -8
  253. package/src/providers/integrations/factory/factory-oauth.ts +7 -11
  254. package/src/providers/integrations/opencode/opencode-go-quota.ts +130 -0
  255. package/src/providers/integrations/opencode/provider.ts +42 -3
  256. package/src/providers/integrations/qoder/qoder-oauth.ts +3 -9
  257. package/src/providers/integrations/shared/install-id.ts +29 -2
  258. package/src/providers/operations/client-versions.ts +11 -1
  259. package/src/providers/operations/model-catalog-cache.ts +18 -3
  260. package/src/providers/operations/provider-catalog-service.ts +76 -0
  261. package/src/transport/dispatch/attempt-finalize.ts +7 -1
  262. package/src/transport/dispatch/attempt-loop.ts +9 -7
  263. package/src/transport/dispatch/empty-stream.ts +17 -26
  264. package/src/transport/failure-policy.ts +20 -0
  265. package/src/transport/routing/route-catalog.ts +42 -3
  266. package/src/transport/surface/chat/encode.ts +18 -31
  267. package/src/transport/surface/messages/stream.ts +3 -2
  268. package/src/transport/translation/tool-repair.ts +37 -16
  269. package/src/workers/account-identity-sweep.ts +14 -12
  270. package/src/workers/daily-checkin.ts +62 -0
  271. package/src/workers/quota-refresh-sweep.ts +27 -2
  272. package/dist/dashboard/assets/CombosPage-B7ETkfVH.js +0 -1
  273. package/dist/dashboard/assets/ConsoleLogPage-AisQzCI1.js +0 -1
  274. package/dist/dashboard/assets/HealthEventsModal-BNflDm_f.js +0 -1
  275. package/dist/dashboard/assets/ModelPicker-CAiPR5Vd.js +0 -1
  276. package/dist/dashboard/assets/ProviderDetailPage-BK8i5B5X.js +0 -3
  277. package/dist/dashboard/assets/ProvidersPage-CvCVgm1e.js +0 -1
  278. package/dist/dashboard/assets/ProxyPage-DjabkuzP.js +0 -7
  279. package/dist/dashboard/assets/QuotaPage-Dxe0B0iu.js +0 -1
  280. package/dist/dashboard/assets/SetupPage-BaD4P_jW.js +0 -1
  281. package/dist/dashboard/assets/SortableList-Bol1ASmI.js +0 -1
  282. package/dist/dashboard/assets/StudioPage-CLP4le3U.js +0 -31
  283. package/dist/dashboard/assets/api-keys-CjIGQhe7.js +0 -1
  284. package/dist/dashboard/assets/app-Cjgo4-Lf.css +0 -2
  285. package/dist/dashboard/assets/cli-tools-DccaOfhX.js +0 -1
  286. package/dist/dashboard/assets/clipboard-button-DQmMikNQ.js +0 -1
  287. package/dist/dashboard/assets/entry-Cpi0rph1.js +0 -4
  288. package/dist/dashboard/assets/entry-Dm3PpDCO.js +0 -1
  289. package/dist/dashboard/assets/entry-keNDZ_Wz.js +0 -1
  290. package/dist/dashboard/assets/github-badge-BuAJr8oU.js +0 -1
  291. package/dist/dashboard/assets/mutation-BIizFZav.js +0 -1
  292. package/dist/dashboard/assets/privacy-mode-CQjbZ3xk.js +0 -1
  293. package/dist/dashboard/assets/settings-BAS6QbmJ.js +0 -1
  294. package/dist/dashboard/assets/terminal-C9mZ4Ugm.js +0 -1
  295. package/dist/dashboard/assets/toast-DKAdP2mo.js +0 -2
  296. package/scripts/cli/cli.ts +0 -771
  297. package/scripts/operations/probe-egress.ts +0 -335
  298. package/scripts/operations/restart.ts +0 -120
  299. package/scripts/shared/env.ts +0 -269
  300. /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.ico +0 -0
  301. /package/{tray-assets → scripts/cli/tray/assets}/cartethyia.png +0 -0
  302. /package/scripts/cli/{menu.ts → ui/prompt.ts} +0 -0
  303. /package/scripts/cli/{wordmark.ts → ui/wordmark.ts} +0 -0
@@ -9,16 +9,31 @@ import { canContainToolResult } from "../../protocol/canonical-model";
9
9
 
10
10
  const MISSING_TOOL_OUTPUT = "<missing tool output>";
11
11
 
12
- /** True when any tool/user turn carries a `toolResult` part for `callId`. */
13
- function findToolResult(
14
- turns: readonly CanonicalMessage[],
15
- callId: string,
16
- ): boolean {
17
- return turns.some(
18
- (turn) =>
19
- canContainToolResult(turn) &&
20
- turn.content.some((part) => part.kind === "toolResult" && part.call_id === callId),
21
- );
12
+ /**
13
+ * Maps each answered call id to the LAST message index carrying its result.
14
+ *
15
+ * A call is answered iff some result appears at an index greater than the
16
+ * call's own, so the highest index is sufficient — no per-call scan of the
17
+ * remaining messages is needed. Built in one forward sweep, O(n·p) overall.
18
+ *
19
+ * The previous implementation sliced the remaining array per assistant turn
20
+ * and scanned it per call id: O(n²·p) plus O(n) array allocations on every
21
+ * request carrying tools, which a 200-turn agentic conversation turned into
22
+ * ~20 000 part scans of pure synchronous CPU before the upstream was ever
23
+ * contacted.
24
+ */
25
+ function lastResultIndexByCallId(
26
+ messages: readonly CanonicalMessage[],
27
+ ): Map<string, number> {
28
+ const lastIndex = new Map<string, number>();
29
+ for (let index = 0; index < messages.length; index += 1) {
30
+ const message = messages[index] as CanonicalMessage;
31
+ if (!canContainToolResult(message)) continue;
32
+ for (const part of message.content) {
33
+ if (part.kind === "toolResult") lastIndex.set(part.call_id, index);
34
+ }
35
+ }
36
+ return lastIndex;
22
37
  }
23
38
 
24
39
  /**
@@ -40,18 +55,24 @@ export function repairMissingToolResponses(
40
55
  messages: readonly CanonicalMessage[],
41
56
  ): CanonicalMessage[] {
42
57
  const repaired: CanonicalMessage[] = [];
58
+ // Answered-by-a-later-message, resolved once instead of per assistant turn.
59
+ const lastResultIndex = lastResultIndexByCallId(messages);
43
60
  for (let index = 0; index < messages.length; index += 1) {
44
61
  const message = messages[index] as CanonicalMessage;
45
62
  repaired.push(message);
46
63
  if (message.role !== "assistant") continue;
47
- const callIds = message.content
48
- .filter((part) => part.kind === "toolCall")
49
- .map((part) => (part as Extract<typeof part, { kind: "toolCall" }>).call_id);
64
+ const callIds = toolCallIdsIn(message);
50
65
  if (callIds.length === 0) continue;
51
66
 
52
- // Answered = a later tool message carrying a matching toolResult part.
53
- const later = messages.slice(index + 1);
54
- const orphanIds = callIds.filter((id) => !findToolResult(later, id));
67
+ // Positional: a result answers only calls in EARLIER messages, so the
68
+ // answering index must be strictly greater than this one. That is also
69
+ // what stops a result for batch N from silencing a same-id call the
70
+ // client reuses in batch N+1, and stops a replayed stale turn from
71
+ // satisfying the call declared beside it.
72
+ const orphanIds = callIds.filter((id) => {
73
+ const answeredAt = lastResultIndex.get(id);
74
+ return answeredAt === undefined || answeredAt <= index;
75
+ });
55
76
  if (orphanIds.length === 0) continue;
56
77
 
57
78
  for (const callId of orphanIds) {
@@ -21,6 +21,12 @@ export interface UnenrichedAccount {
21
21
  readonly id: string;
22
22
  readonly providerId: string;
23
23
  readonly label: string;
24
+ /**
25
+ * The stored credential, carried from the listing query. It is what the
26
+ * sweep exists to parse, so fetching it a second time per account was a
27
+ * redundant read of the row's widest column.
28
+ */
29
+ readonly credentialCiphertext: Buffer | Uint8Array | null;
24
30
  }
25
31
 
26
32
  export interface AccountIdentityEnrichmentSweepDeps {
@@ -76,11 +82,17 @@ export async function accountIdentitySweep(
76
82
  await runSweep<UnenrichedAccount>({
77
83
  name: "account-enrichment",
78
84
  list: async () => {
85
+ // `credentialCiphertext` is selected here, not re-read per account: the
86
+ // sweep ran one listing query and then a second SELECT for every account
87
+ // in it, to fetch the one column the listing had already matched on. The
88
+ // credential is the widest column on the row, so this is also the row
89
+ // that most needed to be fetched once.
79
90
  const rows = await deps.db
80
91
  .select({
81
92
  id: providerAccounts.id,
82
93
  providerId: providerAccounts.providerId,
83
94
  label: providerAccounts.label,
95
+ credentialCiphertext: providerAccounts.credentialCiphertext,
84
96
  })
85
97
  .from(providerAccounts)
86
98
  .where(
@@ -94,22 +106,12 @@ export async function accountIdentitySweep(
94
106
  return rows;
95
107
  },
96
108
  run: async (account) => {
97
- const rows = await deps.db
98
- .select({
99
- credentialCiphertext: providerAccounts.credentialCiphertext,
100
- })
101
- .from(providerAccounts)
102
- .where(eq(providerAccounts.id, account.id))
103
- .limit(1);
104
- const row = rows[0];
105
- if (row === undefined) return;
106
-
107
109
  let secret: string | undefined;
108
110
  try {
109
111
  secret =
110
- row.credentialCiphertext === null || row.credentialCiphertext === undefined
112
+ account.credentialCiphertext === null || account.credentialCiphertext === undefined
111
113
  ? undefined
112
- : decryptCredentialToString(row.credentialCiphertext);
114
+ : decryptCredentialToString(account.credentialCiphertext);
113
115
  } catch (error) {
114
116
  // An undecryptable credential is a real problem, but not one this sweep
115
117
  // can fix. Stamp it so the pass stops retrying and the account's own
@@ -252,6 +252,68 @@ export async function markCheckinAttempted(args: {
252
252
  * Absent or unreadable means unknown, never "not claimed": the sweep may
253
253
  * simply not have reached the account yet.
254
254
  */
255
+ /**
256
+ * The same question as {@link checkinAttemptedToday}, asked once for many
257
+ * accounts.
258
+ *
259
+ * The console answers it for every account on the page, and doing that one
260
+ * account at a time cost a round trip per account — one `GET` to Redis, or one
261
+ * `SELECT` to Postgres — on the route the dashboard polls. This is one `MGET`
262
+ * when Redis is present, or one `SELECT ... WHERE day_key = ? AND account_id
263
+ * IN (...)` when it is not, which is the same shape the release path already
264
+ * uses.
265
+ *
266
+ * An account absent from the result was not attempted, matching the single
267
+ * read's "absent means unknown, never claimed".
268
+ */
269
+ export async function checkinAttemptedTodayBatch(args: {
270
+ readonly db: CartethyiaDatabase | undefined;
271
+ readonly redis: RedisClient | undefined;
272
+ readonly accountIds: readonly string[];
273
+ readonly now?: () => Date;
274
+ }): Promise<Map<string, boolean>> {
275
+ const attempted = new Map<string, boolean>();
276
+ if (args.accountIds.length === 0) return attempted;
277
+ const dayKey = checkinDayKey(args.now?.() ?? new Date());
278
+ // A client without MGET (the memory backend) takes the DB path below, or
279
+ // reports unknown when there is no DB either.
280
+ if (args.redis !== undefined && typeof args.redis.mget === "function") {
281
+ try {
282
+ // One command for every account: one key per account is small, and a
283
+ // single `MGET` keeps the cost flat instead of linear in the count.
284
+ const values = (await args.redis.mget(
285
+ ...args.accountIds.map((id) => ledgerKey(dayKey, id)),
286
+ )) as Array<string | null>;
287
+ args.accountIds.forEach((accountId, index) => {
288
+ attempted.set(accountId, values[index] != null);
289
+ });
290
+ return attempted;
291
+ } catch {
292
+ // Fall through: an unreadable ledger means unknown, and the DB path is
293
+ // the only other place the marker could be.
294
+ }
295
+ }
296
+ if (args.db === undefined) return attempted;
297
+ try {
298
+ const rows = await args.db
299
+ .select({ accountId: dailyCheckinLedger.accountId })
300
+ .from(dailyCheckinLedger)
301
+ .where(
302
+ and(
303
+ eq(dailyCheckinLedger.dayKey, dayKey),
304
+ inArray(dailyCheckinLedger.accountId, [...args.accountIds]),
305
+ ),
306
+ );
307
+ const present = new Set(rows.map((row) => row.accountId));
308
+ for (const accountId of args.accountIds) {
309
+ attempted.set(accountId, present.has(accountId));
310
+ }
311
+ } catch {
312
+ // Unknown, per account, as above.
313
+ }
314
+ return attempted;
315
+ }
316
+
255
317
  export async function checkinAttemptedToday(args: {
256
318
  readonly db: CartethyiaDatabase | undefined;
257
319
  readonly redis: RedisClient | undefined;
@@ -113,10 +113,25 @@ export function checkinSlotAvailable(
113
113
  * An account is re-announced only when its outcome actually changes.
114
114
  *
115
115
  * Module scope, not per-call: suppression must survive across passes, and one
116
- * `quotaRefreshSweep` call is one pass.
116
+ * `quotaRefreshSweep` call is one pass. Bounded because it is keyed by account
117
+ * id and was never pruned, so accounts deleted years ago still held an entry;
118
+ * the oldest keys are the ones least likely to be announced again.
117
119
  */
120
+ const LAST_SWEEP_LINE_MAX = 512;
118
121
  const lastSweepLine = new Map<string, string>();
119
122
 
123
+ /** Drops the oldest entries once the suppression map reaches its cap. */
124
+ function trimLastSweepLine(): void {
125
+ if (lastSweepLine.size <= LAST_SWEEP_LINE_MAX) return;
126
+ const excess = lastSweepLine.size - LAST_SWEEP_LINE_MAX;
127
+ let dropped = 0;
128
+ for (const key of lastSweepLine.keys()) {
129
+ if (dropped >= excess) break;
130
+ lastSweepLine.delete(key);
131
+ dropped += 1;
132
+ }
133
+ }
134
+
120
135
  function getErrorMessage(error: unknown): string {
121
136
  return error instanceof Error ? error.message : String(error);
122
137
  }
@@ -201,6 +216,7 @@ function logSweepAccounts(
201
216
 
202
217
  if (lastSweepLine.get(target.accountId) === line) continue;
203
218
  lastSweepLine.set(target.accountId, line);
219
+ trimLastSweepLine();
204
220
 
205
221
  // A failed quota fetch or a failed check-in is operator-actionable.
206
222
  if (outcome.failure !== null || result?.state === "error") {
@@ -219,7 +235,16 @@ function logSweepAccounts(
219
235
  }
220
236
  }
221
237
 
222
- const DEFAULT_MIN_AGE_MS = 4 * 60_000;
238
+ /**
239
+ * How stale a cached quota reading must be before it is refreshed again.
240
+ *
241
+ * Half the cache TTL. The sweep runs every 60 s, so at the old 4 min every
242
+ * account was refreshed roughly three times per 15 min TTL window — two of
243
+ * those three passes hit the provider and learned nothing the cache did not
244
+ * already know. 8 min is still comfortably inside the TTL, so a reading never
245
+ * goes stale while it waits.
246
+ */
247
+ const DEFAULT_MIN_AGE_MS = 8 * 60_000;
223
248
  const DEFAULT_MAX_PER_PASS = 40;
224
249
  const DEFAULT_PASS_BUDGET_MS = 90_000;
225
250
 
@@ -1 +0,0 @@
1
- import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{o as i}from"./app-BDJWMThu.js";import{t as a}from"./arrow-right-Dl5yKnp8.js";import{t as o}from"./select-CGUuTQmj.js";import{t as s}from"./SortableList-Bol1ASmI.js";import{i as c,n as l,t as u}from"./toast-DKAdP2mo.js";import{t as d}from"./copy-ngmQ9zcZ.js";import{n as ee,r as te,t as f}from"./state-DHKdg-pm.js";import{t as p}from"./layers-2-glBbjl.js";import{t as m}from"./dialog-iocKA3jr.js";import{t as h}from"./pencil-768ysRAr.js";import{t as g}from"./plus-DIdX_g-x.js";import{t as ne}from"./route-CNSNj9Zm.js";import{t as _}from"./search-JOKus9rb.js";import{t as v}from"./trash-Cppn5c3R.js";import{c as y}from"./query-keys-ROf-g1Wi.js";import{t as b}from"./dialog-actions-B1axpEg7.js";import{n as x,r as re,t as ie}from"./card-BTdbRFFg.js";import{t as ae}from"./use-clipboard-B0Sy03fE.js";import{n as S}from"./input-Bn4_kNav.js";import{t as C}from"./ModelPicker-CAiPR5Vd.js";import{t as w}from"./stack-C1kTcOmP.js";import{n as T,t as E}from"./inline-DCejSLlA.js";import{t as D}from"./list-row-BLA0sldD.js";import{a as O,d as k,f as A,i as j,n as M,o as N,p as P,r as F,s as I,t as oe,u as L}from"./routing-jntw9-Ui.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=r(),H={plain:`code-chip-plain`,muted:`code-chip-muted text-text-secondary bg-surface-muted border border-inner-border px-4 py-1 rounded-chip`,accent:`code-chip-accent text-accent bg-accent-soft px-4 py-1.5 rounded-chip font-bold`};function U({value:e,tone:t=`muted`,action:n,className:r=``,children:i,...a}){return(0,V.jsxs)(`span`,{className:c(`code-chip inline-flex items-center gap-3 min-w-0 max-w-full font-mono text-caption tabular-nums`,H[t],r),...a,children:[(0,V.jsx)(`code`,{className:`code-chip-value min-w-0 overflow-hidden text-ellipsis whitespace-nowrap`,title:a.title??e,children:e}),n?(0,V.jsx)(`span`,{className:`code-chip-action inline-flex shrink-0`,children:n}):null,i]})}var W=[{value:`fallback`,label:`Fallback (try in order)`},{value:`round_robin`,label:`Round Robin (rotate)`}],G=()=>`m${Date.now().toString(36)}${Math.random().toString(36).slice(2,8)}`;function K(){let e=N(),t=M(),n=A(),r=j(),i=L(),[o,c]=(0,B.useState)(!1),[p,O]=(0,B.useState)(null),[k,P]=(0,B.useState)(``),[F,I]=(0,B.useState)(``),[oe,z]=(0,B.useState)(!1),[H,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(``),c(!0)},Z=e=>{O(e),P(e.alias),I(e.targetModel),c(!0)},Q=e=>{e.preventDefault(),k.trim()&&F.trim()&&(p?n.mutate({id:p.id,request:{alias:k.trim(),targetModel:F.trim()}},{onSuccess:()=>{c(!1),O(null),u.success(`Alias updated`)},onError:e=>u.error(y(e,`Could not save the alias.`))}):t.mutate({alias:k.trim(),targetModel:F.trim()},{onSuccess:()=>{c(!1),P(``),I(``),u.success(`Alias created`)},onError:e=>u.error(y(e,`Could not create the alias.`))}))},se=(e,t)=>{q(e).then(e=>{if(!e){u.error(`Copy failed`);return}K(t),J(()=>K(null),1500)})};return(0,V.jsxs)(ie,{children:[(0,V.jsx)(re,{title:`Model Aliases`,subtitle:`Map readable names to real models (e.g. claude-mythos-5 → claude-opus-5)`,icon:(0,V.jsx)(ne,{size:16}),action:(0,V.jsx)(E,{children:(0,V.jsx)(l,{variant:`primary`,size:`sm`,icon:(0,V.jsx)(g,{size:13}),onClick:X,children:`New Alias`})})}),(0,V.jsx)(x,{children:e.isPending?(0,V.jsx)(te,{label:`Loading aliases...`}):e.isError?(0,V.jsx)(ee,{message:`Failed to load aliases`,onRetry:()=>e.refetch()}):Y.length===0?(0,V.jsx)(f,{title:`No aliases defined`,message:`Create an alias to route short or friendly names to real provider model IDs.`}):(0,V.jsx)(s,{items:Y,label:`Model aliases`,gap:`8px`,disabled:i.isPending,onReorder:e=>i.mutate(e,{onError:e=>u.error(y(e,`Could not save the new order.`))}),renderItem:e=>(0,V.jsx)(D,{className:`items-start flex-col sm:flex-row`,actions:(0,V.jsxs)(T,{gap:`4px`,className:`w-full justify-start sm:w-auto sm:justify-end`,children:[(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(d,{size:13}),onClick:()=>se(e.alias,e.id),title:G===e.id?`Copied!`:`Copy alias`}),(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(h,{size:13}),onClick:()=>Z(e),title:`Edit target model`}),(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(v,{size:13}),onClick:()=>W(e),title:`Delete alias`,className:`text-red`})]}),children:(0,V.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap min-w-0`,children:[(0,V.jsx)(U,{value:e.alias,tone:`accent`}),(0,V.jsx)(a,{size:13,className:`text-text-tertiary shrink-0`}),(0,V.jsx)(U,{value:e.targetModel,tone:`plain`})]})})})}),(0,V.jsx)(m,{open:o,onClose:()=>c(!1),title:p?`Edit Model Alias`:`New Model Alias`,footer:(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(l,{variant:`secondary`,type:`button`,onClick:()=>c(!1),children:`Cancel`}),(0,V.jsx)(l,{variant:`primary`,type:`submit`,form:`alias-form`,disabled:t.isPending||n.isPending||!k.trim()||!F.trim(),children:p?`Save Changes`:`Create Alias`})]}),children:(0,V.jsxs)(`form`,{id:`alias-form`,onSubmit:Q,className:`flex flex-col gap-6`,children:[(0,V.jsx)(S,{label:`Alias name`,id:`alias-name-input`,value:k,onChange:e=>P(e.target.value),placeholder:`e.g. fast, sonnet, smart`,required:!0}),(0,V.jsxs)(T,{gap:`8px`,align:`flex-end`,children:[(0,V.jsx)(`div`,{className:`flex-1`,children:(0,V.jsx)(S,{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,V.jsx)(l,{variant:`secondary`,size:`sm`,type:`button`,onClick:()=>z(!0),icon:(0,V.jsx)(_,{size:13}),children:`Browse`})]}),(0,V.jsx)(C,{open:oe,onClose:()=>z(!1),selected:F?[F]:[],onToggle:()=>{},onSelectOne:e=>I(e),title:`Select target model`,multi:!1})]})}),(0,V.jsx)(m,{open:!!H,onClose:()=>W(null),title:`Delete Model Alias`,children:(0,V.jsxs)(w,{gap:`12px`,children:[(0,V.jsxs)(`p`,{className:`text-body text-text-secondary`,children:[`Are you sure you want to delete alias `,(0,V.jsx)(`strong`,{children:H?.alias}),`? Clients requesting this name will need their full model path.`]}),(0,V.jsxs)(b,{children:[(0,V.jsx)(l,{variant:`secondary`,onClick:()=>W(null),children:`Cancel`}),(0,V.jsx)(l,{variant:`danger`,onClick:()=>{H&&r.mutate(H.id,{onSuccess:()=>W(null)})},disabled:r.isPending,children:r.isPending?`Deleting...`:`Delete Alias`})]})]})})]})}function q(){let e=I(),t=F(),n=oe(),r=P(),a=O(),c=k(),[ne,A]=(0,B.useState)(!1),[j,M]=(0,B.useState)(null),[N,L]=(0,B.useState)(``),[H,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)(()=>H.map(e=>e.value),[H]),de=e=>{$.includes(e)?K(H.filter(t=>t.value!==e)):K([...H,{id:G(),value:e.trim()}])},fe=e.data??[],pe=()=>{M(null),L(``),K([]),J(`fallback`),A(!0)},me=e=>{M(e),L(e.name),K(e.members.map(e=>({id:G(),value:e}))),A(!0)},he=e=>{n.mutate(e.id,{onSuccess:e=>{let t=e.skippedMembers;t.length>0?u.success(`Combo cloned`,`${e.combo.name} — skipped unresolvable member${t.length>1?`s`:``}: ${t.join(`, `)}`):u.success(`Combo cloned`,e.combo.name)},onError:e=>u.error(y(e,`Could not clone the combo.`))})},ge=e=>{e.preventDefault(),N.trim()&&$.length!==0&&(j?r.mutate({id:j.id,request:{name:N.trim(),members:$,strategy:q}},{onSuccess:()=>{A(!1),M(null),u.success(`Combo saved`)},onError:e=>u.error(y(e,`Could not save the combo.`))}):t.mutate({name:N.trim(),members:$,strategy:q},{onSuccess:()=>{A(!1),L(``),K([]),u.success(`Combo created`)},onError:e=>u.error(y(e,`Could not create the combo.`))}))},_e=(e,t)=>{r.mutate({id:e.id,request:{strategy:t}},{onSuccess:()=>u.success(`Combo strategy updated`),onError:e=>u.error(y(e,`Could not update the combo strategy.`))})},ve=(e,t)=>{le(e).then(e=>{if(!e){u.error(`Copy failed`);return}ce(t),ue(()=>ce(null),1500)})};return(0,V.jsxs)(ie,{children:[(0,V.jsx)(re,{title:`Combos`,subtitle:`Combine multiple models with fallback or round-robin rotation`,icon:(0,V.jsx)(p,{size:16}),action:(0,V.jsx)(E,{children:(0,V.jsx)(l,{variant:`primary`,size:`sm`,icon:(0,V.jsx)(g,{size:13}),onClick:pe,children:`New Combo`})})}),(0,V.jsx)(x,{children:e.isPending?(0,V.jsx)(te,{label:`Loading combos...`}):e.isError?(0,V.jsx)(ee,{message:`Failed to load combos`,onRetry:()=>e.refetch()}):fe.length===0?(0,V.jsx)(f,{title:`No combos defined`,message:`Create a model combo to distribute requests across multiple models.`}):(0,V.jsx)(s,{items:fe,label:`Model combos`,disabled:c.isPending,onReorder:e=>c.mutate(e,{onError:e=>u.error(y(e,`Could not save the new order.`))}),renderItem:e=>(0,V.jsxs)(D,{className:`items-start flex-col sm:flex-row`,actions:(0,V.jsxs)(T,{gap:`8px`,className:`w-full justify-between sm:w-auto sm:justify-start`,children:[(0,V.jsx)(o,{value:e.strategy,onValueChange:t=>_e(e,t),options:W}),(0,V.jsxs)(T,{gap:`4px`,className:`flex-wrap`,children:[(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(d,{size:13}),onClick:()=>ve(e.name,e.id),title:se===e.id?`Copied!`:`Copy combo name`}),(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(z,{size:13}),onClick:()=>he(e),disabled:n.isPending,title:`Clone combo (same members and strategy)`}),(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(h,{size:13}),onClick:()=>me(e),title:`Edit combo`}),(0,V.jsx)(l,{variant:`ghost`,size:`sm`,icon:(0,V.jsx)(v,{size:13}),onClick:()=>Q(e),title:`Delete combo`,className:`text-red`})]})]}),children:[(0,V.jsx)(`div`,{className:`flex items-center justify-between gap-6 flex-wrap`,children:(0,V.jsx)(`strong`,{className:`text-body`,children:e.name})}),(0,V.jsx)(T,{gap:`6px`,className:`w-full flex-wrap`,children:e.members.map(e=>(0,V.jsx)(U,{value:e},e))})]})})}),(0,V.jsx)(m,{open:ne,onClose:()=>A(!1),title:j?`Edit Model Combo`:`New Model Combo`,footer:(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(l,{variant:`secondary`,type:`button`,onClick:()=>A(!1),children:`Cancel`}),(0,V.jsx)(l,{variant:`primary`,type:`submit`,form:`combo-form`,disabled:t.isPending||r.isPending||!N.trim()||$.length===0,children:j?`Save Changes`:`Create Combo`})]}),children:(0,V.jsxs)(`form`,{id:`combo-form`,onSubmit:ge,className:`flex flex-col gap-6`,children:[(0,V.jsx)(S,{label:`Combo name`,id:`combo-name-input`,value:N,onChange:e=>L(e.target.value),placeholder:`e.g. smart-combo, fast-pool`,required:!0}),(0,V.jsx)(o,{label:`Strategy`,id:`combo-strategy-select`,value:q,onValueChange:e=>J(e),options:W}),(0,V.jsxs)(w,{gap:`6px`,children:[(0,V.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,V.jsx)(`label`,{className:`text-caption font-semibold text-text-secondary`,children:`Member models — use arrows or drag to reorder`}),(0,V.jsx)(l,{variant:`secondary`,size:`sm`,type:`button`,icon:(0,V.jsx)(_,{size:12}),onClick:()=>X(!0),children:`Browse models`})]}),(0,V.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 ${H.length===0?`p-0`:`p-3`}`,children:H.length===0?(0,V.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,V.jsx)(s,{items:H,label:`Combo members`,gap:`4px`,onReorder:e=>{let t=new Map(H.map(e=>[e.id,e]));K(e.map(e=>t.get(e)).filter(Boolean))},renderItem:e=>(0,V.jsx)(D,{density:`compact`,actions:(0,V.jsx)(`button`,{type:`button`,onClick:()=>de(e.value),"aria-label":`Remove ${e.value}`,className:`flex shrink-0 cursor-pointer text-text-tertiary`,children:(0,V.jsx)(i,{size:12})}),children:(0,V.jsx)(U,{value:e.value,tone:`accent`})})})})]}),(0,V.jsx)(C,{open:Y,onClose:()=>X(!1),selected:$,onToggle:de,title:`Select combo members`,multi:!0})]})}),(0,V.jsx)(m,{open:!!Z,onClose:()=>Q(null),title:`Delete Model Combo`,children:(0,V.jsxs)(w,{gap:`12px`,children:[(0,V.jsxs)(`p`,{className:`text-body text-text-secondary`,children:[`Are you sure you want to delete combo `,(0,V.jsx)(`strong`,{children:Z?.name}),`? Any aliases pointing to it will fail to resolve.`]}),(0,V.jsxs)(b,{children:[(0,V.jsx)(l,{variant:`secondary`,onClick:()=>Q(null),children:`Cancel`}),(0,V.jsx)(l,{variant:`danger`,onClick:()=>{Z&&a.mutate(Z.id,{onSuccess:()=>Q(null)})},disabled:a.isPending,children:a.isPending?`Deleting...`:`Delete Combo`})]})]})})]})}function J(){return(0,V.jsxs)(w,{gap:`16px`,children:[(0,V.jsx)(q,{}),(0,V.jsx)(K,{})]})}export{J as default};
@@ -1 +0,0 @@
1
- import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{n as r,t as i}from"./toast-DKAdP2mo.js";import{n as a,r as o,t as s}from"./state-DHKdg-pm.js";import{t as c}from"./refresh-cw-BqJFk4sU.js";import{t as l}from"./search-JOKus9rb.js";import{t as u}from"./shield-check-DVS0Foqh.js";import{t as d}from"./trash-Cppn5c3R.js";import{a as f,c as p,l as m}from"./query-keys-ROf-g1Wi.js";import{D as h,F as g,O as _,tt as v}from"./entry-Cpi0rph1.js";import{n as y,r as b,t as x}from"./card-BTdbRFFg.js";import{r as S}from"./numbers-CFL4_Dqc.js";import{t as C}from"./stream-retry-5QnVuSSo.js";import{t as w}from"./badge-BwmwEOgA.js";import{n as T}from"./input-Bn4_kNav.js";import{t as E}from"./layout-Bv-NxqZ5.js";var D=e(t(),1),O=500,k=1500;function A(e){return m(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!m(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);m(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&&p()},C))}},p=async()=>{try{let n=await f(`/logs?limit=200`);if(e||i!==o.current)return;t(j(n).slice(-500).map(l)),r(new Set),d()}catch{}};return p(),()=>{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 f(`/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=_().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)(u,{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:S(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(),[a,o]=(0,D.useState)(`all`),[c,u]=(0,D.useState)(``),[f,p]=(0,D.useState)(!1),[m,h]=(0,D.useState)(null),_=c.trim().toLowerCase(),S=(0,D.useMemo)(()=>U(t,a,_).slice().reverse(),[t,a,_]),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)(x,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(b,{title:`Console Log`,subtitle:`${S.length} of ${t.length} lines`,icon:(0,L.jsx)(v,{size:16}),action:e}),(0,L.jsxs)(y,{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 ${a===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":a===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)(l,{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:c,onChange:e=>u(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)(d,{size:15,"aria-hidden":`true`})})]})]}),(0,L.jsxs)(y,{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:S.length===0?(0,L.jsx)(s,{title:t.length===0?`No log lines yet`:_?`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})}):S.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:[S.length,` of `,t.length,` lines`,a===`all`?``:` · ${a}`,_?` · search: "${c.trim()}"`:``]})})]}),(0,L.jsx)(g,{open:f,onClose:()=>p(!1),onConfirm:async()=>{h(null);try{await r(),p(!1),i.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,l]=(0,D.useState)(``),[d,f]=(0,D.useState)(``),[m,g]=(0,D.useState)(``),[_,v]=(0,D.useState)(void 0),[S,C]=(0,D.useState)([]);(0,D.useEffect)(()=>{let e=setTimeout(()=>f(t),300);return()=>clearTimeout(e)},[t]),(0,D.useEffect)(()=>{let e=setTimeout(()=>g(i),300);return()=>clearTimeout(e)},[i]);let w=h({limit:R,...d?{action:d}:{},...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)(x,{className:`flex-1 min-h-0 flex flex-col`,children:[(0,L.jsx)(b,{title:`Admin Audit Trail`,subtitle:`Every privileged console mutation, retained on its own lifecycle`,icon:(0,L.jsx)(u,{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)(c,{size:13,className:w.isFetching?`animate-spin`:``}),children:`Refresh`})]})}),(0,L.jsxs)(y,{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=>{l(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:S.length===0,children:`← Newer`}),(0,L.jsx)(r,{size:`sm`,variant:`secondary`,onClick:j,disabled:!A,children:`Older →`})]})]}),(0,L.jsx)(y,{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)(o,{label:`Loading audit trail…`}):w.isError&&k.length===0?(0,L.jsx)(a,{message:p(w.error,`Unable to load audit trail.`),onRetry:()=>void w.refetch()}):k.length===0?(0,L.jsx)(s,{title:`No audit entries yet`,message:`Privileged mutations (provider changes, key rotations, backups, bans) will appear here.`,icon:(0,L.jsx)(u,{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 +0,0 @@
1
- import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{i as r}from"./terminal-C9mZ4Ugm.js";import{n as i,t as a}from"./toast-DKAdP2mo.js";import{n as o,r as s,t as c}from"./state-DHKdg-pm.js";import{t as l}from"./dialog-iocKA3jr.js";import{t as u}from"./rotate-ccw-CufcqITi.js";import{S as d,_ as f,w as p}from"./assert-Bwh6DJTK.js";import{a as m,t as h}from"./query-keys-ROf-g1Wi.js";import{t as g}from"./useMutation-DVmwOKU-.js";import{E as _,F as v,_ as y,n as b}from"./entry-Cpi0rph1.js";import{t as x}from"./badge-BwmwEOgA.js";import{n as S}from"./inline-DCejSLlA.js";import{t as C}from"./layout-Bv-NxqZ5.js";async function w(e){return m(`/quota/overview`,e?{signal:e}:void 0)}function T(){return d({queryKey:h.quota.all,queryFn:e=>w(f(e)),staleTime:1/0,refetchInterval:!1,refetchIntervalInBackground:!1,refetchOnMount:!1,refetchOnWindowFocus:!1,placeholderData:e=>e})}function E(e){let t=p(),n=h.quota.account(e);return g({mutationFn:async()=>m(`/accounts/${encodeURIComponent(e)}/quota/refresh`,{method:`POST`}),onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:n,exact:!0}),t.invalidateQueries({queryKey:h.quota.all}),t.invalidateQueries({queryKey:h.providers.all})])}})}var D=100;function O(){let e=p();return g({mutationFn:async e=>{let t=[];for(let n=0;n<e.length;n+=D)t.push(e.slice(n,n+D));let n=await Promise.all(t.map(e=>m(`/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:h.quota.account(t),exact:!0})),e.invalidateQueries({queryKey:h.quota.all})])}})}function k(){let e=p();return g({mutationFn:({id:e,active:t})=>m(`/accounts/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify({active:t})}),onSuccess:async()=>{await Promise.all([e.invalidateQueries({queryKey:h.quota.all}),e.invalidateQueries({queryKey:h.providers.all})])}})}function A(){let e=p();return g({mutationFn:async({ids:e,active:t})=>{e.length!==0&&await m(`/accounts/batch`,{method:`PATCH`,body:JSON.stringify({ids:e,active:t})})},onSuccess:async()=>{await Promise.all([e.invalidateQueries({queryKey:h.quota.all}),e.invalidateQueries({queryKey:h.providers.all})])}})}function j(){let e=p();return g({mutationFn:async e=>{await m(`/accounts/${encodeURIComponent(e)}`,{method:`DELETE`})},onSuccess:async(t,n)=>{e.removeQueries({queryKey:h.quota.account(n),exact:!0}),await Promise.all([e.invalidateQueries({queryKey:h.quota.all}),e.invalidateQueries({queryKey:h.providers.all})])}})}var M=new Set([`workbuddy`,`workbuddycn`,`cb`,`cbcn`]);function N(e){return M.has(e.trim().toLowerCase())}function P(e){let t=p();return g({mutationFn:async()=>{if(e.length===0)throw Error(`Select a provider first`);return m(`/quota/daily-growth`,{method:`POST`,body:JSON.stringify({providerId:e})})},onSuccess:async()=>{await Promise.all([t.invalidateQueries({queryKey:h.quota.all}),t.invalidateQueries({queryKey:h.providers.all})])}})}function F(e){let t=p();return g({mutationFn:async()=>{let t=await m(`/accounts/${encodeURIComponent(e)}/activity-report`,{method:`POST`}),n=t.message??`Activity reported`,r=await m(`/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:h.quota.all}),t.invalidateQueries({queryKey:h.providers.all})])}})}var I=new Set([`codex`,`claude`,`anthropic`]);function L(e){return I.has(e.trim().toLowerCase())}function R(e,t){return d({queryKey:h.quota.resets(e),queryFn:({signal:t})=>m(`/accounts/${encodeURIComponent(e)}/resets`,t?{signal:t}:void 0),enabled:t,staleTime:3e4})}function z(e){let t=p();return g({mutationFn:async t=>m(`/accounts/${encodeURIComponent(e)}/reset`,{method:`POST`,body:JSON.stringify(t??{})}),onSettled:async()=>{await Promise.all([t.invalidateQueries({queryKey:h.quota.all}),t.invalidateQueries({queryKey:h.providers.all})])}})}var B=e(t(),1),V=n();function H(e){return e===`cooldown`}function U(e){return e===`active`?`ok`:e===`disabled`?`disabled`:`warn`}function W(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 G({summary:e,onClose:t}){let{providerId:n,accountId:d,title:f,status:p,errorCategory:m,errorMessage:h}=e,g=b(n,d),w=y(),T=g.data??[],E=_(),D=e.credentialKind===`oauth`||e.credentialMode===`jwt`||e.staticToken===!0,[O,k]=(0,B.useState)(e.staticToken===!0),[A,j]=(0,B.useState)(null);return(0,B.useEffect)(()=>k(e.staticToken===!0),[e.staticToken]),(0,V.jsx)(l,{open:!0,onClose:t,title:`Health & Error Log — ${f}`,size:`lg`,children:(0,V.jsxs)(`div`,{className:`flex flex-col gap-7 min-w-0`,children:[(0,V.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,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(S,{gap:`8px`,className:`flex-wrap`,children:[(0,V.jsx)(`span`,{className:`text-body font-semibold`,children:`Account status:`}),(0,V.jsx)(x,{tone:U(p),dot:!0,children:p.toUpperCase()}),m?(0,V.jsx)(x,{tone:`warn`,title:h??void 0,children:m}):null]}),h?(0,V.jsx)(`p`,{className:`text-badge text-red mt-2 wrap-anywhere`,children:h}):null]}),H(p)?(0,V.jsx)(i,{size:`sm`,variant:`secondary`,icon:(0,V.jsx)(u,{size:12,className:w.isPending?`animate-spin`:``}),disabled:w.isPending,onClick:()=>w.mutate({providerId:n,accountId:d},{onSuccess:()=>void g.refetch()}),children:w.isPending?`Recovering...`:`Recover Now`}):null]}),D?(0,V.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,V.jsxs)(`div`,{children:[(0,V.jsx)(`div`,{className:`text-caption font-semibold`,children:`Credential management`}),(0,V.jsx)(`div`,{className:`text-badge text-text-tertiary`,children:O?`Static mode: no refresh request will be sent.`:`OAuth refresh is enabled for this account.`})]}),(0,V.jsx)(i,{size:`sm`,variant:O?`primary`:`secondary`,disabled:E.isPending,onClick:()=>j(!O),children:O?`Static · no refresh`:`Enable static mode`})]}):null,(0,V.jsxs)(`div`,{className:`min-w-0`,children:[(0,V.jsxs)(`h4`,{className:`text-caption font-semibold text-text-secondary mb-4`,children:[`Transition Events & Audit (`,T.length,`)`]}),g.isPending?(0,V.jsx)(s,{label:`Loading health events...`}):g.isError?(0,V.jsx)(o,{message:`Failed to load health events`,onRetry:()=>void g.refetch()}):T.length===0?(0,V.jsx)(c,{title:`No health events recorded`,message:e.emptyMessage,icon:(0,V.jsx)(r,{size:20})}):(0,V.jsx)(`div`,{className:`rounded-inset border border-inner-border`,children:(0,V.jsx)(C,{maxHeight:480,scrollRegion:!0,headers:[`Timestamp`,`From → To`,`Model`,`Category`,`Reason / Details`],children:T.map(e=>(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`td`,{className:`text-badge text-text-tertiary whitespace-nowrap`,children:new Date(e.createdAt).toLocaleString()}),(0,V.jsxs)(`td`,{className:`whitespace-nowrap`,children:[(0,V.jsxs)(`span`,{className:`text-badge text-text-secondary`,children:[e.fromStatus??`new`,` →`,` `]}),(0,V.jsx)(x,{tone:U(e.toStatus),children:e.toStatus})]}),(0,V.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary wrap-anywhere`,children:e.modelId??`—`}),(0,V.jsx)(`td`,{className:`font-mono tabular-nums text-badge text-text-secondary`,children:e.errorCategory??`—`}),(0,V.jsx)(`td`,{className:`text-badge text-text-primary min-w-110 max-w-260 wrap-anywhere`,children:e.reason??`—`})]},e.id))})})]}),(0,V.jsx)(v,{open:A!==null,onClose:()=>j(null),onConfirm:()=>{let e=A===!0;E.mutate({providerId:n,accountId:d,request:{staticToken:e}},{onSuccess:()=>{k(e),j(null),a.success(e?`Static mode enabled`:`Credential refresh re-enabled`,f),g.refetch()},onError:e=>a.error(`Credential update failed`,e instanceof Error?e.message:`Unable to update credential mode`)})},title:W(A===!0,f).title,message:W(A===!0,f).message,confirmLabel:W(A===!0,f).confirmLabel,cancelLabel:`Cancel`}),(0,V.jsx)(S,{justify:`flex-end`,gap:`0px`,children:(0,V.jsx)(i,{variant:`secondary`,size:`sm`,onClick:t,children:`Close`})})]})})}export{j as a,O as c,F as d,P as f,R as i,A as l,N as n,T as o,k as p,L as r,E as s,G as t,z as u};
@@ -1 +0,0 @@
1
- import{o as e,r as t,t as n}from"./jsx-runtime-CXUMngI_.js";import{o as r}from"./app-BDJWMThu.js";import{t as i}from"./check-D69FzdvC.js";import{n as a}from"./toast-DKAdP2mo.js";import{t as o}from"./dialog-iocKA3jr.js";import{t as s}from"./route-CNSNj9Zm.js";import{t as c}from"./search-JOKus9rb.js";import{S as l,_ as u}from"./assert-Bwh6DJTK.js";import{a as d,t as f}from"./query-keys-ROf-g1Wi.js";import{s as p}from"./tokens-DDxMbSRL.js";import{t as m}from"./badge-BwmwEOgA.js";import{t as h}from"./ProviderIcon-paOCq8I0.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)(a,{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)(r,{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)(i,{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};
@@ -1,3 +0,0 @@
1
- import{n as e,o as t,r as n,t as r}from"./jsx-runtime-CXUMngI_.js";import{i}from"./terminal-C9mZ4Ugm.js";import{t as a}from"./arrow-left-CpBxkoxI.js";import{n as o,t as s}from"./brain-Cwed_72z.js";import{n as c,t as l}from"./fingerprint-pattern-BWuHtbW4.js";import{t as u}from"./check-D69FzdvC.js";import{n as d,t as f}from"./select-CGUuTQmj.js";import{t as p}from"./circle-alert-CntYHV5v.js";import{t as m}from"./circle-check-BU3v_mFW.js";import{g as h,h as g,i as _,m as v,n as y,r as b,t as x}from"./toast-DKAdP2mo.js";import{t as S}from"./cog-CdWhsajs.js";import{t as C}from"./copy-ngmQ9zcZ.js";import{t as w}from"./download-A0SW9OCW.js";import{t as T}from"./eye-off-Bk5g2luF.js";import{t as E}from"./eye-C_hawfH4.js";import{t as D}from"./gauge-BbIMy7MB.js";import{t as O}from"./image-BPaouViG.js";import{a as ee,n as k,r as A,t as j}from"./state-DHKdg-pm.js";import{t as M}from"./key-round-UkavsGxp.js";import{t as te}from"./layers-2-glBbjl.js";import{n as N,t as P}from"./dialog-iocKA3jr.js";import{t as F}from"./pencil-768ysRAr.js";import{t as ne}from"./plus-DIdX_g-x.js";import{i as re,n as I}from"./privacy-mode-CQjbZ3xk.js";import{t as ie}from"./refresh-cw-BqJFk4sU.js";import{t as ae}from"./rotate-ccw-CufcqITi.js";import{t as oe}from"./search-JOKus9rb.js";import{t as se}from"./trash-Cppn5c3R.js";import{t as ce}from"./wrench-B6E1oEuY.js";import{w as le}from"./assert-Bwh6DJTK.js";import{a as ue,t as L}from"./query-keys-ROf-g1Wi.js";import{E as de,F as fe,S as pe,T as me,X as he,Y as ge,Z as _e,_ as ve,a as ye,b as be,c as R,d as xe,f as Se,g as Ce,h as we,l as Te,m as Ee,o as De,p as Oe,r as ke,t as Ae,u as z,v as je,w as Me,x as Ne,y as Pe}from"./entry-Cpi0rph1.js";import{n as B,r as Fe,t as V}from"./card-BTdbRFFg.js";import{n as Ie}from"./download-dRFo5_Wu.js";import{f as Le,i as H,l as Re,n as U,r as ze,s as Be}from"./tokens-DDxMbSRL.js";import{a as W}from"./numbers-CFL4_Dqc.js";import{t as G}from"./badge-BwmwEOgA.js";import{n as K}from"./input-Bn4_kNav.js";import{t as Ve}from"./ProviderIcon-paOCq8I0.js";import{t as q}from"./switch-DIDeAiz9.js";import{t as J}from"./stack-C1kTcOmP.js";import{n as Y,t as He}from"./inline-DCejSLlA.js";import{i as X}from"./quota-DZGyp0N5.js";import{t as Ue}from"./list-row-BLA0sldD.js";import{c as We,l as Ge,m as Z}from"./routing-jntw9-Ui.js";import{o as Ke,s as qe,t as Je}from"./HealthEventsModal-BNflDm_f.js";import{n as Ye,t as Xe}from"./AccountCooldown-ChpdzxRH.js";import{t as Ze}from"./use-timeout-BwcBBRrT.js";import{t as Qe}from"./banner-BKBfKTqn.js";var $e=e(`cable`,[[`path`,{d:`M17 19a1 1 0 0 1-1-1v-2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2a1 1 0 0 1-1 1z`,key:`trhst0`}],[`path`,{d:`M17 21v-2`,key:`ds4u3f`}],[`path`,{d:`M19 14V6.5a1 1 0 0 0-7 0v11a1 1 0 0 1-7 0V10`,key:`1mo9zo`}],[`path`,{d:`M21 21v-2`,key:`eo0ou`}],[`path`,{d:`M3 5V3`,key:`1k5hjh`}],[`path`,{d:`M4 10a2 2 0 0 1-2-2V6a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2z`,key:`1dd30t`}],[`path`,{d:`M7 5V3`,key:`1t1388`}]]),et=e(`external-link`,[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]),tt=e(`info`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]),nt=e(`lock-open`,[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 9.9-1`,key:`1mm8w8`}]]),rt=e(`package-x`,[[`path`,{d:`M12 22V12`,key:`d0xqtd`}],[`path`,{d:`m16.5 14.5 5 5`,key:`ozpm51`}],[`path`,{d:`m16.5 19.5 5-5`,key:`syf6b9`}],[`path`,{d:`M21 10.5V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.729l7 4a2 2 0 0 0 2 .001l.13-.074`,key:`isw6gs`}],[`path`,{d:`M3.29 7 12 12l8.71-5`,key:`19ckod`}],[`path`,{d:`m7.5 4.27 8.997 5.148`,key:`9yrvtv`}]]),it=e(`repeat`,[[`path`,{d:`m17 2 4 4-4 4`,key:`nntrym`}],[`path`,{d:`M3 11v-1a4 4 0 0 1 4-4h14`,key:`84bu3i`}],[`path`,{d:`m7 22-4-4 4-4`,key:`1wqhfi`}],[`path`,{d:`M21 13v1a4 4 0 0 1-4 4H3`,key:`1rx37r`}]]),at=e(`video`,[[`path`,{d:`m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5`,key:`ftymec`}],[`rect`,{x:`2`,y:`6`,width:`14`,height:`12`,rx:`2`,key:`158x01`}]]),ot=e(`waypoints`,[[`path`,{d:`m10.586 5.414-5.172 5.172`,key:`4mc350`}],[`path`,{d:`m18.586 13.414-5.172 5.172`,key:`8c96vv`}],[`path`,{d:`M6 12h12`,key:`8npq4p`}],[`circle`,{cx:`12`,cy:`20`,r:`2`,key:`144qzu`}],[`circle`,{cx:`12`,cy:`4`,r:`2`,key:`muu5ef`}],[`circle`,{cx:`20`,cy:`12`,r:`2`,key:`1xzzfp`}],[`circle`,{cx:`4`,cy:`12`,r:`2`,key:`1hvhnz`}]]),st=[`auto`,`minimal`,`low`,`medium`,`high`,`xhigh`,`max`];function ct(e,t){return t===null?e:`${e}(${t})`}var Q=t(n(),1),$=r();function lt({to:e,label:t}){let n=ge();return(0,$.jsxs)(`button`,{type:`button`,onClick:()=>{window.history.length>1?n(-1):n(e)},className:`inline-flex items-center gap-3 text-accent text-caption bg-transparent border-0 p-0 cursor-pointer`,children:[(0,$.jsx)(a,{size:14,"aria-hidden":`true`}),t]})}function ut({title:e,description:t,icon:n,badges:r,actions:i,back:a}){return(0,$.jsxs)(`div`,{className:`flex flex-col gap-5`,children:[a?(0,$.jsx)(lt,{...a}):null,(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-6 flex-wrap`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-5 min-w-0`,children:[n?(0,$.jsx)(`div`,{className:`card-header-icon`,children:n}):null,(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-4 flex-wrap`,children:[(0,$.jsx)(`h1`,{className:`text-lead font-bold`,children:e}),r]}),t?(0,$.jsx)(`p`,{className:`mt-1 text-badge text-text-tertiary`,children:t}):null]})]}),i?(0,$.jsx)(`div`,{className:_(`flex items-center gap-4 flex-wrap min-w-0 max-w-full`),children:i}):null]})]})}function dt(e){return e.isBuiltIn&&e.requiresAccount&&e.oauthFlows===void 0&&!e.hasAdapterUserAgent}function ft(e,t=600){let n=(0,Q.useRef)(void 0);return(0,Q.useEffect)(()=>()=>clearTimeout(n.current),[]),r=>{clearTimeout(n.current),n.current=setTimeout(()=>e(r),t)}}var pt={fallback:`Failover`,roundRobin:`Round robin`},mt=new Set([`inferhub`,`cline`]);function ht(e,t){let n=Ge(e),r=Z(),[i,a]=(0,Q.useState)(`fallback`),[o,s]=(0,Q.useState)(1),[c,l]=(0,Q.useState)(null),[u,d]=(0,Q.useState)(null),[f,p]=(0,Q.useState)(null),[m,h]=(0,Q.useState)(`percent`),[g,_]=(0,Q.useState)(!1),[v,y]=(0,Q.useState)(``);(0,Q.useEffect)(()=>{n.data&&(a(n.data.strategy),s(n.data.rotateCount),l(n.data.maxInflight),d(n.data.maxInflightPerProxy??null),p(n.data.usageFloor),h(n.data.usageFloorUnit),_(n.data.skipProxy),y(n.data.userAgent))},[n.data]);let b=i=>{r.mutate({providerId:e,request:{enabled:!0,strategy:i.strategy,rotateCount:i.rotateCount,maxInflight:i.maxInflight,maxInflightPerProxy:i.maxInflightPerProxy,usageFloor:i.usageFloor,usageFloorUnit:i.usageFloorUnit,skipProxy:i.skipProxy,...t?{userAgent:i.userAgent}:{}}},{onError:()=>{n.data&&(a(n.data.strategy),s(n.data.rotateCount),l(n.data.maxInflight),d(n.data.maxInflightPerProxy??null),p(n.data.usageFloor),h(n.data.usageFloorUnit),_(n.data.skipProxy),y(n.data.userAgent))}})},x=ft(e=>b({strategy:i,rotateCount:o,maxInflight:e,maxInflightPerProxy:u,usageFloor:f,usageFloorUnit:m,skipProxy:g,userAgent:v})),S=ft(e=>b({strategy:i,rotateCount:o,maxInflight:c,maxInflightPerProxy:e,usageFloor:f,usageFloorUnit:m,skipProxy:g,userAgent:v})),C=ft(e=>b({strategy:i,rotateCount:e,maxInflight:c,maxInflightPerProxy:u,usageFloor:f,usageFloorUnit:m,skipProxy:g,userAgent:v})),w=ft(e=>b({strategy:i,rotateCount:o,maxInflight:c,maxInflightPerProxy:u,usageFloor:f,usageFloorUnit:m,skipProxy:g,userAgent:e}));return{strategy:i,maxInflight:c,maxInflightPerProxy:u,usageFloor:f,usageFloorUnit:m,setUsageFloor:(e,t)=>{p(e),h(t),b({strategy:i,rotateCount:o,maxInflight:c,maxInflightPerProxy:u,usageFloor:e,usageFloorUnit:t,skipProxy:g,userAgent:v})},skipProxy:g,userAgent:v,isLoading:n.isPending,isError:n.isError,isSaving:r.isPending,saveFailed:r.isError,refetch:()=>n.refetch(),setMaxInflight:e=>{l(e),x(e)},setMaxInflightPerProxy:e=>{d(e),S(e)},setUserAgent:e=>{y(e),w(e)},setSkipProxy:e=>{_(e),b({strategy:i,rotateCount:o,maxInflight:c,maxInflightPerProxy:u,usageFloor:f,usageFloorUnit:m,skipProxy:e,userAgent:v})},roundRobinEnabled:i===`round_robin`,setRoundRobinEnabled:e=>{let t=e?`round_robin`:`fallback`;a(t),b({strategy:t,rotateCount:o,maxInflight:c,maxInflightPerProxy:u,usageFloor:f,usageFloorUnit:m,skipProxy:g,userAgent:v})},rotateCount:o,setRotateCount:e=>{s(e),C(e)}}}var gt=50,_t=100;function vt(e,t,n){return[{value:``,label:`None`},{value:`Cartethyia/${e}`,label:`Cartethyia ${e}`},{value:`codex_cli_rs/${t}`,label:`Codex`},{value:`claude-cli/${n} (external, cli)`,label:`Claude Code`}]}function yt({children:e,action:t}){return(0,$.jsx)(Ue,{actions:t,children:e})}function bt({providerId:e,clientVersion:t,routeIdentityVersions:n,userAgentEditable:r}){let i=ht(e,r),[a,o]=(0,Q.useState)(!1),s=mt.has(e),c=vt(Ae,n.codex,n.claude),u=c.some(e=>e.value===i.userAgent)?c:[...c,{value:i.userAgent,label:`Custom`}];if(i.isLoading)return(0,$.jsx)(A,{label:`Loading routing...`});if(i.isError)return(0,$.jsx)(k,{message:`Failed to load routing`,onRetry:i.refetch});let d=i.roundRobinEnabled?`${pt.roundRobin} · ${i.rotateCount} account${i.rotateCount===1?``:`s`} per rotation`:pt.fallback,p=i.isSaving?`Saving...`:i.saveFailed?`Save failed — reverted to last saved value`:`Active: ${d}`,m=i.maxInflight===null,h=m?51:Math.min(51,Math.max(1,i.maxInflight)),g=m?`∞`:String(i.maxInflight),_=i.maxInflightPerProxy===null,v=_?51:Math.min(51,Math.max(1,i.maxInflightPerProxy)),b=_?`∞`:String(i.maxInflightPerProxy),S=i.skipProxy,C=e=>{i.setRotateCount(Math.min(1e3,Math.max(1,i.rotateCount+e)))},w=e=>{if(e===i.userAgent)return;i.setUserAgent(e);let t=u.find(t=>t.value===e)?.label??e;x.success(`Client identity updated`,t)},T=t?`${t.client} ${t.version}`:`Provider default`;return(0,$.jsxs)(V,{children:[(0,$.jsx)(Fe,{title:`Routing Strategy`,subtitle:p,icon:(0,$.jsx)(te,{size:16})}),(0,$.jsx)(B,{children:(0,$.jsxs)(`div`,{className:`grid gap-5 w-full min-w-0`,children:[(0,$.jsx)(yt,{action:(0,$.jsxs)($.Fragment,{children:[i.roundRobinEnabled?(0,$.jsxs)(`div`,{role:`group`,"aria-label":`Accounts per rotation`,className:`inline-flex items-center gap-1 rounded-control border border-inner-border bg-surface-1 p-1`,children:[(0,$.jsx)(`span`,{className:`px-2 text-badge text-text-secondary`,children:`Accounts/rotation`}),(0,$.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-9 rounded-tiny`,"aria-label":`Decrease accounts per rotation`,disabled:i.rotateCount<=1,icon:(0,$.jsx)(N,{size:14}),onClick:()=>C(-1)}),(0,$.jsx)(`output`,{className:`min-w-8 text-center text-body font-semibold tabular-nums`,"aria-live":`polite`,children:i.rotateCount}),(0,$.jsx)(y,{variant:`ghost`,size:`icon`,className:`size-9 rounded-tiny`,"aria-label":`Increase accounts per rotation`,disabled:i.rotateCount>=1e3,icon:(0,$.jsx)(ne,{size:14}),onClick:()=>C(1)})]}):null,(0,$.jsx)(q,{checked:i.roundRobinEnabled,onChange:i.setRoundRobinEnabled,id:`routing-round-robin`})]}),children:(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`label`,{htmlFor:`routing-round-robin`,children:(0,$.jsxs)(Y,{gap:`6px`,className:`text-body font-semibold`,children:[(0,$.jsx)(it,{size:15,"aria-hidden":`true`,className:`shrink-0 ${i.roundRobinEnabled?`text-accent`:`text-text-tertiary`}`}),`Round robin`]})}),(0,$.jsx)(`div`,{className:`mt-1 text-badge text-text-tertiary`,children:`Off uses priority order with failover. On rotates requests across this provider's accounts.`})]})}),(0,$.jsx)(yt,{action:(0,$.jsx)(q,{checked:i.skipProxy,onChange:i.setSkipProxy,id:`routing-skip-proxy`}),children:(0,$.jsxs)(`div`,{className:`min-w-0`,children:[(0,$.jsx)(`label`,{htmlFor:`routing-skip-proxy`,children:(0,$.jsxs)(Y,{gap:`6px`,className:`text-body font-semibold`,children:[(0,$.jsx)($e,{size:15,"aria-hidden":`true`,className:`shrink-0 ${i.skipProxy?`text-accent`:`text-text-tertiary`}`}),`Always direct`]})}),(0,$.jsx)(`div`,{className:`mt-1 text-badge text-text-tertiary`,children:`Bypass automatic proxy-pool routing for this provider and always dial direct`})]})}),(0,$.jsxs)(`div`,{className:`routing-controls-grid grid gap-5 min-w-0 w-full`,children:[(0,$.jsxs)(`div`,{className:`px-6 py-5 rounded-control border border-inner-border bg-surface-2 min-w-0`,children:[(0,$.jsxs)(Y,{gap:`6px`,className:`text-body font-semibold mb-3`,children:[(0,$.jsx)(l,{size:15,"aria-hidden":`true`,className:`text-text-tertiary shrink-0`}),`Client identity`]}),r?(0,$.jsx)(f,{id:`routing-user-agent-preset`,"aria-label":`Client identity`,value:i.userAgent,options:u,onValueChange:w}):(0,$.jsx)(f,{id:`routing-user-agent-fixed`,"aria-label":`Client identity`,disabled:!0,value:T,options:[{value:T,label:T}]}),(0,$.jsx)(`div`,{className:`text-badge text-text-tertiary mt-2`,children:r?`Sent when the provider has no identity of its own.`:`Set by the provider. It cannot be changed.`})]}),(0,$.jsxs)(`div`,{className:`px-6 py-5 rounded-control border border-inner-border bg-surface-2 min-w-0`,children:[(0,$.jsx)(`label`,{htmlFor:`routing-max-inflight`,className:`form-label`,children:(0,$.jsxs)(Y,{gap:`6px`,className:`text-body font-semibold`,children:[(0,$.jsx)(D,{size:15,"aria-hidden":`true`,className:`text-text-tertiary shrink-0`}),`Max inflight / account`]})}),(0,$.jsxs)(`div`,{className:`text-badge text-text-tertiary mb-3`,children:[`Shared provider ceiling. One step past `,gt,` is unlimited.`]}),(0,$.jsxs)(Y,{gap:`10px`,className:`mt-3`,children:[(0,$.jsx)(`input`,{id:`routing-max-inflight`,type:`range`,className:`routing-slider flex-1 min-w-0`,"data-unlimited":m?`true`:void 0,min:1,max:51,step:1,value:h,"aria-valuetext":m?`Unlimited`:String(i.maxInflight),onChange:e=>{let t=Number(e.target.value);Number.isFinite(t)&&i.setMaxInflight(t>gt?null:Math.round(t))},style:{"--slider-pct":`${h/51*100}%`}}),(0,$.jsx)(`input`,{type:`text`,inputMode:`numeric`,"aria-label":`Max inflight per account`,value:g,onChange:e=>{let t=e.target.value.trim();if(t===``||t===`∞`){i.setMaxInflight(null);return}let n=Number(t);Number.isFinite(n)&&n>=1&&i.setMaxInflight(Math.min(_t,Math.round(n)))},className:`form-input w-26 shrink-0 px-2 py-3 text-center text-body ${m?`text-status-success`:``}`})]})]})]}),(0,$.jsxs)(`div`,{className:`px-6 py-5 rounded-control border border-inner-border bg-surface-2 min-w-0${S?` opacity-60`:``}`,children:[(0,$.jsxs)(`div`,{className:`flex items-start justify-between gap-4`,children:[(0,$.jsxs)(`label`,{htmlFor:`routing-max-inflight-per-proxy`,className:`min-w-0`,children:[(0,$.jsxs)(Y,{gap:`6px`,className:`text-body font-semibold`,children:[(0,$.jsx)(ot,{size:15,"aria-hidden":`true`,className:`text-text-tertiary shrink-0`}),`Max inflight / proxy`]}),(0,$.jsx)(`div`,{className:`mt-1 text-badge text-text-tertiary`,children:`Each proxy pool carries at most this many concurrent requests for this provider. Other providers on the same pool are unaffected.`})]}),(0,$.jsx)(y,{variant:`ghost`,size:`sm`,className:`shrink-0`,"aria-label":`How per-proxy limits work`,onClick:()=>o(!0),children:`How it works`})]}),(0,$.jsxs)(Y,{gap:`10px`,className:`mt-3`,children:[(0,$.jsx)(`input`,{id:`routing-max-inflight-per-proxy`,type:`range`,className:`routing-slider flex-1 min-w-0`,"data-unlimited":_?`true`:void 0,min:1,max:51,step:1,disabled:S,value:v,"aria-valuetext":_?`Unlimited`:String(i.maxInflightPerProxy),onChange:e=>{let t=Number(e.target.value);Number.isFinite(t)&&i.setMaxInflightPerProxy(t>gt?null:Math.round(t))},style:{"--slider-pct":`${v/51*100}%`}}),(0,$.jsx)(`input`,{type:`text`,inputMode:`numeric`,"aria-label":`Max inflight per proxy`,disabled:S,value:b,onChange:e=>{let t=e.target.value.trim();if(t===``||t===`∞`){i.setMaxInflightPerProxy(null);return}let n=Number(t);Number.isFinite(n)&&n>=1&&i.setMaxInflightPerProxy(Math.min(_t,Math.round(n)))},className:`form-input w-26 shrink-0 px-2 py-3 text-center text-body ${_?`text-status-success`:``}`})]}),(0,$.jsx)(`div`,{className:`mt-2 text-badge text-text-tertiary`,children:S?`Always direct is on, so this provider never dials a pool. The limit is kept for when a pool is used again.`:`One step past ${gt} is unlimited.`})]}),(0,$.jsx)(P,{open:a,onClose:()=>o(!1),title:`How concurrency limits stack`,size:`md`,children:(0,$.jsxs)(`div`,{className:`grid gap-4 text-body`,children:[(0,$.jsx)(`p`,{className:`text-text-secondary`,children:`Three limits apply at once. Each one bounds a different thing; none replaces another.`}),(0,$.jsxs)(`dl`,{className:`grid gap-3`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{className:`font-semibold`,children:`Max inflight / account`}),(0,$.jsx)(`dd`,{className:`text-badge text-text-tertiary`,children:`One account of this provider, across every proxy. Set here, above.`})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{className:`font-semibold`,children:`Max inflight / proxy`}),(0,$.jsxs)(`dd`,{className:`text-badge text-text-tertiary`,children:[`One proxy pool's concurrent requests `,(0,$.jsx)(`em`,{children:`for this provider`}),`. The same number applies to every pool; each pool counts separately. This is the field above.`]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`dt`,{className:`font-semibold`,children:`Pool capacity`}),(0,$.jsx)(`dd`,{className:`text-badge text-text-tertiary`,children:`Everything through one pool, all providers combined. Set on the proxy itself, on the Proxies page.`})]})]}),(0,$.jsxs)(`p`,{className:`text-badge text-text-tertiary`,children:[`A request must clear all three. When a pool is full for this provider, the request moves to another pool that still has room; it only fails with`,` `,(0,$.jsx)(`code`,{children:`429`}),` when every pool is full.`]}),(0,$.jsx)(`p`,{className:`text-badge text-text-tertiary`,children:`Unlimited means no counter is kept for this provider, so the limit costs nothing until you set one.`})]})}),s&&(0,$.jsxs)(Y,{gap:`6px`,align:`flex-start`,className:`mt-1 text-badge text-text-tertiary`,children:[(0,$.jsx)(tt,{size:12,className:`shrink-0 mt-0.5`}),(0,$.jsx)(`span`,{children:`This provider doesn't reliably work through a plain HTTP/S proxy — use a SOCKS5 or proxy pool instead if you need to route it.`})]})]})})]})}function xt({providerId:e}){let t=ht(e,!1),n=Ke(),r=We(e),i=(0,Q.useMemo)(()=>Ct(n.data?.accounts??[],e),[n.data,e]),a=(0,Q.useRef)(null),o=(0,Q.useMemo)(()=>[...r.data?.values()??[]].reduce((e,t)=>e+t,0),[r.data]);(0,Q.useEffect)(()=>{if(a.current===null){a.current=o;return}a.current!==o&&(a.current=o,n.refetch())},[o,n]);let[s,c]=(0,Q.useState)(`40`),[l,u]=(0,Q.useState)(`percent`),d=t.usageFloor!==null;(0,Q.useEffect)(()=>{t.usageFloor!==null&&c(String(t.usageFloor)),u(t.usageFloorUnit)},[t.usageFloor,t.usageFloorUnit]);let f=Number(s),p=Number.isInteger(f)&&f>=0&&f<=1e6,m=i===null||i.remaining<=0?`text-status-danger`:i.percent<=10?`text-status-warning`:`text-status-success`,h=(e,n)=>{(e===null||p)&&t.setUsageFloor(e,n)};return(0,$.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,$.jsxs)(`section`,{className:`usage-floor-panel flex flex-col gap-4 px-5 py-4 border border-inner-border rounded-narrow bg-surface-2`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-3 text-body font-semibold text-text-primary`,children:[(0,$.jsx)(D,{size:14}),(0,$.jsx)(`span`,{children:`Usage floor`}),(0,$.jsx)(`span`,{className:`badge border border-warning-line bg-surface-2 text-micro tracking-label text-status-warning`,children:`BETA`})]}),(0,$.jsx)(`p`,{className:`mt-0.5 text-badge leading-normal text-text-tertiary`,children:`Per account. Skip an account once its remaining allowance reaches this, and send the request to the next one.`})]}),(0,$.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[i!==null&&(0,$.jsxs)(`div`,{className:`flex min-h-24 min-w-0 flex-[1_1_20rem] flex-col justify-center gap-2 py-2`,children:[(0,$.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-2 gap-y-1 text-micro font-semibold tracking-label uppercase text-text-tertiary`,children:[(0,$.jsx)(`span`,{children:`Pooled credits`}),(0,$.jsx)(`span`,{className:`text-text-primary`,children:i.accounts}),(0,$.jsx)(`span`,{children:i.accounts===1?`active account`:`active accounts`})]}),(0,$.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2 gap-y-1 text-caption font-semibold tabular-nums text-text-primary`,title:`Combined allowance across active accounts; the usage floor is evaluated per account`,children:[(0,$.jsx)(`strong`,{className:`font-bold ${m}`,children:wt(i.remaining)}),(0,$.jsx)(`span`,{className:`font-medium text-text-secondary`,children:`credits available`}),(0,$.jsxs)(`span`,{className:`font-medium opacity-75`,children:[`of `,wt(i.total)]}),(0,$.jsxs)(`span`,{className:`font-bold ${m}`,children:[i.percent,`%`]})]}),(0,$.jsx)(`p`,{className:`text-micro leading-normal text-text-tertiary`,children:t.usageFloor===null?`Floor off · exhausted quota windows are still skipped`:`Floor ${wt(t.usageFloor)} ${t.usageFloorUnit===`credit`?`credits`:`%`} per account`})]}),i===null&&(0,$.jsxs)(`p`,{className:`flex min-h-24 min-w-0 flex-[1_1_20rem] flex-col justify-center gap-2 py-2 text-badge leading-normal text-text-tertiary`,children:[(0,$.jsx)(`span`,{children:`No combined credit balance is available. Separate quota windows are not added together, and exhausted windows are still skipped.`}),(0,$.jsx)(`span`,{className:`text-micro`,children:t.usageFloor===null?`Floor off · exhausted quota windows are still skipped`:`Floor ${wt(t.usageFloor)} ${t.usageFloorUnit===`credit`?`credits`:`%`} per account`})]}),(0,$.jsxs)(`div`,{className:`ml-auto flex max-w-full shrink-0 flex-col items-end justify-center gap-2`,children:[(0,$.jsxs)(`div`,{className:`flex flex-wrap items-center justify-end gap-x-3 gap-y-2`,children:[(0,$.jsx)(`span`,{className:`text-micro font-semibold tracking-label uppercase text-text-tertiary`,children:`Floor threshold`}),(0,$.jsxs)(`label`,{className:`flex h-12 max-w-full items-center overflow-hidden rounded-tiny border border-inner-border bg-surface-1 focus-within:border-text-tertiary`,children:[(0,$.jsx)(`input`,{type:`number`,min:0,max:1e6,value:d?s:``,placeholder:`40`,disabled:!d,"aria-label":`Usage floor amount`,className:`h-full w-24 border-0 bg-transparent px-3 text-right font-mono text-body font-semibold tabular-nums text-text-primary disabled:text-text-tertiary`,onChange:e=>c(e.target.value),onBlur:()=>{d&&h(f,l)}}),(0,$.jsxs)(`select`,{value:l,disabled:!d,"aria-label":`Usage floor unit`,className:`h-full border-0 border-l border-inner-border bg-hover px-3 text-body font-semibold text-text-secondary disabled:cursor-default disabled:opacity-60`,onChange:e=>{let t=e.target.value===`credit`?`credit`:`percent`;u(t),d&&h(f,t)},children:[(0,$.jsx)(`option`,{value:`percent`,children:`%`}),(0,$.jsx)(`option`,{value:`credit`,children:`credits`})]})]}),(0,$.jsx)(q,{checked:d,label:`Enabled`,"aria-label":`Usage floor`,className:`usage-floor-switch`,onChange:e=>h(e?p?f:40:null,l)})]}),t.saveFailed?(0,$.jsx)(`p`,{role:`alert`,className:`text-right text-micro leading-normal text-status-danger`,children:`Usage floor save failed. The last saved setting has been restored.`}):null]})]})]}),(0,$.jsx)(St,{providerId:e})]})}function St({providerId:e}){let{enabled:t,setEnabled:n}=I(e);return(0,$.jsxs)(`div`,{className:`flex items-center justify-between flex-wrap gap-6 px-6 py-5 border border-inner-border rounded-control bg-surface-2`,children:[(0,$.jsxs)(`div`,{className:`min-w-0 flex-auto basis-110`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-3 text-body font-semibold text-text-primary`,children:[(0,$.jsx)(T,{size:14}),(0,$.jsx)(`span`,{children:`Mysterious accounts`})]}),(0,$.jsx)(`p`,{className:`mt-0.5 text-badge leading-normal text-text-tertiary`,children:`Hide this provider's emails and usernames. Stored in this browser only.`})]}),(0,$.jsx)(`div`,{className:`flex items-center gap-4 shrink-0`,children:(0,$.jsx)(q,{checked:t,"aria-label":`Mysterious accounts`,onChange:n})})]})}function Ct(e,t){let n=0,r=0,i=0,a=!1;for(let o of e)if(o.provider===t&&o.active&&(i+=1,o.quota!==null))for(let e of o.quota.windows){if(e.accounting!==`pooled`)continue;let t=typeof e.limit==`number`&&Number.isFinite(e.limit)?e.limit:null;if(t===null)continue;let i=typeof e.remaining==`number`&&Number.isFinite(e.remaining)?e.remaining:typeof e.used==`number`&&Number.isFinite(e.used)?t-e.used:null;i!==null&&(n+=Math.min(t,Math.max(0,i)),r+=t,a=!0)}return i>0&&a?{accounts:i,remaining:n,total:r,percent:r>0?Math.round(n/r*100):0}:null}function wt(e){return e.toLocaleString(void 0,{maximumFractionDigits:1})}function Tt({provider:e}){let t=e.credentialUrl,n=e.credentialHint,r=e.operatorNotice;if(!t&&!n&&!r)return null;let i=e.oauthFlows?.browser===!0||e.oauthFlows?.device===!0,a=n??(i?`This provider authorizes through its own login flow; there is no key to paste.`:e.requiresAccount?`Create a credential on the provider site, then add it as an account below.`:`This provider needs no credential.`);return(0,$.jsx)(V,{density:`compact`,children:(0,$.jsx)(B,{children:(0,$.jsxs)(Y,{gap:`12px`,className:`items-center flex-wrap`,children:[(0,$.jsxs)(`span`,{className:`min-w-110 flex-1 text-caption text-text-secondary`,children:[a,r?(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`br`,{}),r]}):null]}),t?(0,$.jsxs)(`a`,{href:t,target:`_blank`,rel:`noreferrer`,title:t,className:b({size:`sm`,className:`shrink-0 no-underline`}),children:[(0,$.jsx)(`span`,{className:`btn-icon-wrapper`,"aria-hidden":`true`,children:(0,$.jsx)(et,{size:13})}),i?`Sign in`:`Get API Key`]}):null]})})})}var Et={quota_fetch_failed:`Quota unreachable`,quota_exhausted:`Quota exhausted`,policy_blocked:`Policy blocked`,rate_limit_transient:`Rate limited`,missing_credential:`No credential`},Dt=new Set([`quota_fetch_failed`]);function Ot(e){return e===void 0||e.length===0?!1:!Dt.has(e)}function kt(e){return e===`oauth`?`Re-login required`:`Replace API key`}function At(e,t){return e===`auth_invalidated`?kt(t):Et[e]??e}async function jt(e,t,n){let r=Array(e.length),i=Math.max(1,Math.min(t,e.length)),a=0;return await Promise.all(Array.from({length:i},async()=>{for(;;){let t=a;if(t>=e.length)return;a+=1;try{r[t]={status:`fulfilled`,value:await n(e[t],t)}}catch(e){r[t]={status:`rejected`,reason:e}}}})),r}var Mt=[`access`,`accessToken`,`access_token`,`sessionToken`,`session_token`,`token`,`apiKey`,`api_key`,`key`,`credential`,`pat`,`secret`],Nt=[`refresh`,`refreshToken`,`refresh_token`],Pt=[`credentialKind`,`providerId`,`accessToken`],Ft=[`accounts`,`items`,`connections`],It=[`email`,`name`,`accountId`,`account_id`,`id`,`login`,`username`];function Lt(e){if(typeof e==`object`&&e&&!Array.isArray(e))return Object.fromEntries(Object.entries(e))}function Rt(e){let t=e.data;if(typeof t==`string`)try{return Lt(JSON.parse(t))}catch{return}return Lt(t)}function zt(e){for(let t of Mt){let n=e[t];if(typeof n==`string`&&n.trim().length>0)return{value:n.trim(),extracted:!0,source:t}}let t=Rt(e);if(t)for(let e of Mt){let n=t[e];if(typeof n==`string`&&n.trim().length>0)return{value:n.trim(),extracted:!0,source:`data.${e}`}}}function Bt(e){for(let t of It){let n=e[t];if(typeof n==`string`&&n.trim().length>0)return n.trim()}let t=Rt(e);if(t)for(let e of It){let n=t[e];if(typeof n==`string`&&n.trim().length>0)return n.trim()}}function Vt(e){let t=e=>Nt.some(t=>typeof e[t]==`string`||typeof e[t]==`number`);if(t(e))return!0;let n=Rt(e);return n?t(n):!1}function Ht(e){let t=e.trim().split(`.`);if(t.length===3)try{let e=t[1].replaceAll(`-`,`+`).replaceAll(`_`,`/`),n=e.padEnd(e.length+(4-e.length%4)%4,`=`);return Lt(JSON.parse(atob(n)))}catch{return}}function Ut(e){let t=Ht(e)?.exp;if(typeof t!=`number`||!Number.isFinite(t))return;let n=new Date(t*1e3);return Number.isFinite(n.getTime())?n.toISOString():void 0}function Wt(e){let t={},n=0;for(let r of e.split(/\r?\n/)){let e=/^\s*([A-Za-z_][\w-]*)\s*:\s*(.*)$/.exec(r),i=e?.[1],a=e?.[2];i!==void 0&&a!==void 0&&(t[i]=a.trim(),n+=1)}return n>0?t:void 0}function Gt(e){if(e.startsWith(`{`)||e.startsWith(`[`))try{return JSON.parse(e)}catch{return}}function Kt(e){let t=e.trim(),n=Lt(Gt(t))??Wt(t);return n&&Vt(n)?`oauth`:Ht((n?zt(n)?.value:void 0)??t)===void 0?`api_key`:`jwt`}function qt(e){return e.length!==0&&!!(e.some(e=>Array.isArray(e.cookies)&&(typeof e.domain==`string`||typeof e.originalUrl==`string`))||e.every(e=>typeof e.name==`string`&&typeof e.value==`string`&&(e.domain!==void 0||e.path!==void 0||e.expirationDate!==void 0)))}function Jt(e,t){let n,r=!1,i=(e,t)=>{let i=e.toLowerCase();(i===`userid`||i===`uid`||i===`accountid`||i===`cuserid`)&&(n||=t.replace(/^"|"$/g,``).trim()),(i.includes(`token`)||i.includes(`ph`)||i.includes(`auth`)||i.includes(`session`))&&(r=!0)};for(let e of t)if(Array.isArray(e.cookies)){for(let t of e.cookies)if(t&&typeof t==`object`){let e=t;typeof e.name==`string`&&typeof e.value==`string`&&i(e.name,e.value)}}else typeof e.name==`string`&&typeof e.value==`string`&&i(e.name,e.value);return{value:e,kind:r?`oauth`:`api_key`,...n?{identity:n}:{}}}function Yt(e){let t=e.credentialKind;if(typeof t==`string`&&typeof e.accessToken==`string`&&Pt.every(t=>t in e)){let n=typeof e.label==`string`&&e.label.trim().length>0?e.label.trim():void 0,r=e.accessToken,i=t===`oauth`&&Vt(e);return{value:i?JSON.stringify(e):r,kind:i?`oauth`:`api_key`,...n?{identity:n}:{}}}let n=zt(e),r=Vt(e)?`oauth`:Kt(n?.value??JSON.stringify(e)),i=r===`oauth`?JSON.stringify(e):n?.value??JSON.stringify(e),a=Bt(e);return a?{value:i,kind:r,identity:a}:{value:i,kind:r}}function Xt(e){for(let t of Ft){let n=e[t];if(!Array.isArray(n))continue;let r=n.map(e=>Lt(e)).filter(e=>e!==void 0);if(r.length>0)return r}}function Zt(e){let t=e.trim();if(!t)return[];let n=Gt(t);if(Array.isArray(n)){let e=n.map(e=>Lt(e)).filter(e=>e!==void 0);if(e.length>0)return qt(e)?[Jt(t,e)]:e.map(Yt)}else{let e=Lt(n);if(e){let t=Xt(e);return t?t.map(Yt):[Yt(e)]}}let r=t.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.length>0);if(r.length===0)return[];if(r.length===1)return Qt(r[0]);let i=Wt(t);return i&&(zt(i)||Object.keys(i).length===r.length)?[Yt(i)]:r.flatMap(Qt)}function Qt(e){let t=Lt(Gt(e));if(t){let e=Xt(t);return e?e.map(Yt):[Yt(t)]}return[{value:e,kind:Kt(e)}]}function $t(e,t,n){let r=new Set(n),i=1;return e.map(e=>{let n=e.identity;if(!n){for(;r.has(`${t}-${i}`);)i+=1;n=`${t}-${i}`,i+=1}let a=n,o=2;for(;r.has(a);)a=`${n} (${o++})`;return r.add(a),a})}function en(e){return e===`active`?0:e===`cooldown`?2:3}function tn(e){if(e===void 0)return;let t=new Date(e).getTime();if(Number.isFinite(t))return t<=Date.now()?`Expired ${new Date(e).toLocaleDateString()}`:X(e,!1)}function nn({cooldowns:e,reason:t}){if(!e)return null;let n=X(e.until),r=`Soonest: ${e.modelId} — ${n}`;return(0,$.jsxs)(G,{tone:`warn`,dot:!0,title:t?`${t} — ${r}`:r,children:[e.count,` model`,e.count===1?``:`s`,` cooling · `,n]})}function rn(e){if(e.credentialKind===`oauth`)return`OAuth`;if(e.credentialMode===`jwt`)return`JWT`}function an(e){return e.credentialKind===`oauth`?`blue`:`ok`}function on({account:e}){let t=e.cooldownUntil?new Date(e.cooldownUntil).getTime():NaN,n=Number.isFinite(t)&&t>Date.now(),r=Xe(e);if(e.status===`disabled`){let t=rn(e),n=e.lastErrorCategory===`auth_invalidated`;return(0,$.jsxs)(Y,{gap:`4px`,children:[(0,$.jsxs)(G,{tone:`disabled`,dot:!0,title:e.lastError,children:[`Disabled`,t?` - ${t}`:``]}),n?(0,$.jsx)(G,{tone:`warn`,title:e.lastError,children:kt(e.credentialKind)}):Ot(e.lastErrorCategory)&&!(e.lastErrorCategory===`quota_exhausted`&&r)?(0,$.jsx)(G,{tone:`warn`,title:e.lastError??e.lastErrorCategory,children:At(e.lastErrorCategory,e.credentialKind)}):null,(0,$.jsx)(nn,{cooldowns:r,reason:e.lastErrorCategory===`quota_exhausted`?e.lastError:void 0})]})}return e.status===`active`?(0,$.jsxs)(Y,{gap:`4px`,children:[(0,$.jsxs)(G,{tone:an(e),dot:!0,children:[`Active`,rn(e)?` - ${rn(e)}`:``]}),Ot(e.lastErrorCategory)&&!(e.lastErrorCategory===`quota_exhausted`&&r)?(0,$.jsx)(G,{tone:`warn`,title:e.lastError??e.lastErrorCategory,children:At(e.lastErrorCategory,e.credentialKind)}):null,(0,$.jsx)(nn,{cooldowns:r,reason:e.lastErrorCategory===`quota_exhausted`?e.lastError:void 0})]}):e.status===`cooldown`||n?(0,$.jsxs)(Y,{gap:`4px`,children:[(0,$.jsxs)(G,{tone:`warn`,dot:!0,children:[`Cooldown`,rn(e)?` - ${rn(e)}`:``,` `,e.cooldownUntil?`(${X(e.cooldownUntil)})`:``]}),Ot(e.lastErrorCategory)&&!(e.lastErrorCategory===`quota_exhausted`&&r)?(0,$.jsx)(G,{tone:`warn`,title:e.lastError??e.lastErrorCategory,children:At(e.lastErrorCategory,e.credentialKind)}):null,(0,$.jsx)(nn,{cooldowns:r,reason:e.lastErrorCategory===`quota_exhausted`?e.lastError:void 0})]}):(0,$.jsx)(G,{tone:`disabled`,children:`Disabled`})}function sn({windows:e}){if(e===void 0||e.length===0)return null;let t=0,n=0,r=!1,i=null;for(let a of e){if(a.accounting!==`pooled`){typeof a.remainingPercent==`number`&&Number.isFinite(a.remainingPercent)&&(i=i===null?a.remainingPercent:Math.min(i,a.remainingPercent));continue}let e=typeof a.limit==`number`&&Number.isFinite(a.limit)?a.limit:null,o=typeof a.remaining==`number`&&Number.isFinite(a.remaining)?a.remaining:e!==null&&typeof a.used==`number`&&Number.isFinite(a.used)?e-a.used:null;o!==null&&e!==null&&(t+=Math.max(0,o),n+=e,r=!0)}let a=null;return r?a=`${cn(t)} of ${cn(n)}`:i!==null&&(a=`${Math.round(i)}% left`),a===null?null:(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 max-w-full px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap`,"data-tone":r&&t<=0||(i??100)<=10?`warn`:void 0,title:r?`${cn(t)} credits available of ${cn(n)}`:`Lowest remaining percent across this account's quota windows`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`Quota`}),a]})}function cn(e){return e.toLocaleString(void 0,{maximumFractionDigits:1})}function ln({providerId:e,account:t,onClose:n}){let r=de(),[i,a]=(0,Q.useState)(``),o=t.label||t.id.slice(0,8),s=r.isPending,c=i.trim().length>0&&!s,l=async()=>{try{a(await navigator.clipboard.readText())}catch{x.error(`Clipboard access denied`)}};return(0,$.jsx)(P,{open:!0,onClose:n,title:`Replace API key — ${o}`,width:560,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:n,disabled:s,children:`Cancel`}),(0,$.jsx)(y,{size:`sm`,variant:`primary`,disabled:!c,onClick:()=>{let a=i.trim();a&&r.mutate({providerId:e,accountId:t.id,request:{secret:a}},{onSuccess:()=>{x.success(`API key replaced`,o),n()},onError:e=>{let t=e instanceof Error?e.message:`Unable to update account`;x.error(`Failed to replace key`,t)}})},children:s?`Saving…`:`Replace key`})]}),children:(0,$.jsxs)(`div`,{className:`flex flex-col gap-5`,children:[(0,$.jsx)(`p`,{className:`m-0 text-caption text-text-secondary`,children:`Paste the new key for this account. The old key stops working immediately; the account keeps its label, history, and routing.`}),(0,$.jsxs)(J,{gap:`6px`,className:`min-w-0`,children:[(0,$.jsx)(`label`,{className:`text-caption font-semibold text-text-secondary`,children:`New API key`}),(0,$.jsx)(`textarea`,{value:i,onChange:e=>a(e.target.value),placeholder:`Paste the replacement key…`,rows:4,spellCheck:!1,autoFocus:!0,className:`font-mono tabular-nums w-full min-w-0 min-h-65 rounded-control border border-inner-border bg-input-bg px-6 py-5 text-caption text-text-primary resize-y box-border`}),(0,$.jsx)(Y,{gap:`8px`,className:`justify-end`,children:(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:()=>void l(),children:`Paste`})})]})]})})}function un({providerId:e,account:t,inflight:n,quota:r,selected:a,onToggleSelect:o,onDelete:s}){let c=de(),l=ve(),u=qe(t.id),d=t.status===`disabled`,f=t.cooldownUntil?new Date(t.cooldownUntil).getTime():NaN,p=Number.isFinite(f)&&f>Date.now(),m=t.status===`cooldown`||p,[g,_]=(0,Q.useState)(!1),[b,S]=(0,Q.useState)(!1),[,C]=(0,Q.useState)(0),[w,T]=(0,Q.useState)(!1),[E,D]=(0,Q.useState)(``),O=I(e),ee=(t.label?.match(/[^\s@]+@[^\s@]+/)?.[0]??t.label)||t.id.slice(0,8),k=O.enabled?`Mysterious accounts`:ee,A=tn(t.tokenExpiresAt),j=Ye(t),te=Math.max(p&&t.cooldownUntil?f:0,j??0);(0,Q.useEffect)(()=>{if(te<=Date.now())return;let e=setInterval(()=>C(e=>e+1),1e3);return()=>clearInterval(e)},[te]);let N=()=>{let n=E.trim();T(!1),n&&n!==(t.label??``)&&c.mutate({providerId:e,accountId:t.id,request:{label:n}},{onSuccess:()=>x.success(`Account renamed`,n),onError:e=>x.error(`Rename failed`,e.message??`Unable to rename account`)})};return(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`div`,{className:`account-row account-row-grid grid items-center gap-5 px-5 py-4 border rounded-control bg-surface-2 ${a?`border-accent`:`border-inner-border`} hover:bg-hover`,role:`listitem`,"data-selected":a?`true`:void 0,style:{opacity:d?.62:1},children:[(0,$.jsx)(`div`,{className:`flex items-center`,children:(0,$.jsx)(`input`,{type:`checkbox`,checked:a,onChange:e=>o(t.id,e.target.checked),"aria-label":`Select ${k}`,className:`cursor-pointer`})}),(0,$.jsxs)(`div`,{className:`min-w-0 flex flex-col gap-1.5`,children:[(0,$.jsx)(`div`,{className:`flex items-center gap-3 min-w-0`,children:w?(0,$.jsx)(K,{value:E,onChange:e=>D(e.target.value),onKeyDown:e=>{e.key===`Enter`&&N(),e.key===`Escape`&&T(!1)},onBlur:N,autoFocus:!0,"aria-label":`Account label`,className:`text-body max-w-120`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(`span`,{className:`text-body font-semibold text-text-primary min-w-0 overflow-hidden text-ellipsis whitespace-nowrap`,title:t.label||t.id,children:k}),(0,$.jsx)(`button`,{type:`button`,className:`shrink-0 grid place-items-center w-10 h-10 p-0 border-0 bg-transparent text-text-tertiary cursor-pointer rounded-tiny hover:bg-inner-border hover:text-text-primary`,title:`Rename account`,"aria-label":`Rename ${k}`,onClick:()=>{D(t.label??``),T(!0)},children:(0,$.jsx)(F,{size:11})})]})}),(0,$.jsxs)(`div`,{className:`flex items-center flex-nowrap gap-2 min-w-0 overflow-hidden`,children:[(0,$.jsx)(on,{account:t}),A?(0,$.jsx)(`span`,{className:`inline-flex items-center gap-2.5 max-w-full px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap`,title:A,children:A}):null]}),(0,$.jsxs)(`div`,{className:`flex items-center flex-wrap gap-2 min-w-0`,children:[(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 max-w-full px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap`,title:`Today: ${t.usageToday.totalTokens.toLocaleString()} tokens, ${t.usageToday.requests.toLocaleString()} requests`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`Today`}),t.usageToday.totalTokens.toLocaleString(),` tok · `,t.usageToday.requests.toLocaleString(),` req`]}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 max-w-full px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap`,title:`Lifetime totals are backfilled from telemetry still retained when tracking starts; new totals survive telemetry cleanup.`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`All time`}),t.usageAllTime.totalTokens.toLocaleString(),` tok · `,t.usageAllTime.requests.toLocaleString(),` req`]}),(0,$.jsx)(sn,{windows:r}),(0,$.jsxs)(`span`,{className:`inline-flex items-center gap-2.5 max-w-full px-3.5 py-1 border border-inner-border rounded-chip bg-surface-1 text-text-secondary text-badge leading-normal whitespace-nowrap`,title:`Concurrency comes from this provider’s Routing Strategy; accounts no longer carry manual ceilings.`,children:[(0,$.jsx)(`span`,{className:`text-text-tertiary text-micro font-semibold uppercase tracking-label`,children:`In flight`}),n?.toLocaleString()??`—`]})]})]}),(0,$.jsxs)(`div`,{className:`account-row-actions flex items-center justify-end gap-3 flex-wrap`,children:[(0,$.jsx)(y,{size:`icon`,variant:`secondary`,icon:(0,$.jsx)(i,{size:12}),label:`Health`,"aria-label":`Health for ${k}`,onClick:()=>_(!0),title:`View Health & Error History`}),(0,$.jsx)(y,{size:`icon`,variant:`secondary`,icon:u.isPending?(0,$.jsx)(v,{size:12,className:`animate-spin`}):(0,$.jsx)(h,{size:12}),label:u.isPending?`Testing…`:`Test`,"aria-label":`Test ${k}`,disabled:u.isPending,onClick:()=>{u.mutate(void 0,{onSuccess:e=>{e?.ok?x.success(`Account test passed`,k):x.error(`Account test failed`,e?.message??`Provider reported an error`)},onError:e=>x.error(`Account test failed`,e.message??`Unable to test account`)})},title:`Refresh quota and health for this account`}),(0,$.jsx)(y,{size:`icon`,variant:`secondary`,icon:(0,$.jsx)(M,{size:12}),label:`Edit key`,"aria-label":`Replace API key for ${k}`,onClick:()=>S(!0),title:`Replace API key`}),(0,$.jsx)(y,{size:`icon`,variant:`secondary`,icon:d?(0,$.jsx)(nt,{size:12}):(0,$.jsx)(re,{size:12}),label:d?`Enable`:`Disable`,"aria-label":d?`Enable ${k}`:`Disable ${k}`,disabled:c.isPending,onClick:()=>{let n=d;c.mutate({providerId:e,accountId:t.id,request:{status:n?`active`:`disabled`}},{onSuccess:()=>x.success(n?`Account enabled`:`Account disabled`,k),onError:e=>x.error(`Update failed`,e.message??`Unable to update account`)})},title:d?`Enable account`:`Disable account`}),m?(0,$.jsx)(y,{size:`icon`,variant:`secondary`,icon:(0,$.jsx)(ae,{size:12,className:l.isPending?`animate-spin`:``}),label:l.isPending?`Recovering…`:`Recover`,"aria-label":`Recover ${k}`,disabled:l.isPending,onClick:()=>l.mutate({providerId:e,accountId:t.id}),title:`Clear cooldown / restore active status`}):null,(0,$.jsx)(y,{size:`icon`,variant:`danger`,icon:(0,$.jsx)(se,{size:12}),label:`Delete`,"aria-label":`Delete ${k}`,onClick:()=>s(t),title:`Delete account`})]})]}),g&&(0,$.jsx)(Je,{summary:{providerId:e,accountId:t.id,title:t.label||t.id.slice(0,8),status:t.status,errorCategory:t.lastErrorCategory??void 0,errorMessage:t.lastError??void 0,emptyMessage:`Status transitions, rate limits, and auto-recoveries will appear here.`,staticToken:t.staticToken===!0,credentialKind:t.credentialKind,credentialMode:t.credentialMode},onClose:()=>_(!1)}),b&&(0,$.jsx)(ln,{providerId:e,account:t,onClose:()=>S(!1)})]})}var dn=[{value:`added-asc`,label:`Added · oldest`},{value:`added-desc`,label:`Added · newest`},{value:`label-asc`,label:`Name · A–Z`},{value:`label-desc`,label:`Name · Z–A`},{value:`status-asc`,label:`Status · active first`},{value:`status-desc`,label:`Status · disabled first`},{value:`lastCheck-desc`,label:`Last check · newest`},{value:`lastCheck-asc`,label:`Last check · oldest`}];function fn(e,t,n){let r=(e,t)=>(e.label||e.id).localeCompare(t.label||t.id)||e.createdAt.localeCompare(t.createdAt)||e.id.localeCompare(t.id);if(n===`added`)return e.sortIndex-t.sortIndex||e.createdAt.localeCompare(t.createdAt)||e.id.localeCompare(t.id);if(n===`label`)return r(e,t);if(n===`status`){let n=en(e.status)-en(t.status);return n===0?r(e,t):n}let i=new Date(e.lastSuccessAt??e.createdAt).getTime();return new Date(t.lastSuccessAt??t.createdAt).getTime()-i||r(e,t)}function pn({providerId:e,accounts:t,onDelete:n,showGrokProbe:r=!1,grokProbePending:i=!1,onGrokProbe:a}){let o=le(),s=de(),c=ve(),l=Te(),u=We(e).data??new Map,p=Ke(),m=(0,Q.useMemo)(()=>{let t=new Map;for(let n of p.data?.accounts??[])n.provider===e&&n.quota&&t.set(n.id,n.quota.windows);return t},[p.data,e]),[g,_]=(0,Q.useState)(``),[v,b]=(0,Q.useState)(new Set),[S,C]=(0,Q.useState)(`added-asc`),[T,E]=(0,Q.useState)(!1),[D,O]=(0,Q.useState)(!1),[ee,k]=(0,Q.useState)(!1),A=(0,Q.useRef)(null);(0,Q.useEffect)(()=>{if(!ee)return;let e=e=>{A.current&&!A.current.contains(e.target)&&k(!1)},t=e=>{e.key===`Escape`&&k(!1)};return document.addEventListener(`mousedown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`mousedown`,e),document.removeEventListener(`keydown`,t)}},[ee]);let j=g.trim().toLowerCase(),M=(0,Q.useMemo)(()=>j?t.filter(e=>{let t=`${e.label??``} ${e.id} ${e.credentialKind} ${e.status}`.toLowerCase();return j.split(/\s+/).every(e=>t.includes(e))}):t,[t,j]),te=(0,Q.useMemo)(()=>{let e=S.slice(0,S.lastIndexOf(`-`)),t=S.endsWith(`-desc`)?-1:1,n=[...M];return n.sort((n,r)=>t*fn(n,r,e)),n},[M,S]),N=(0,Q.useMemo)(()=>t.filter(e=>v.has(e.id)),[t,v]),P=M.length>0&&M.every(e=>v.has(e.id)),F=N.some(e=>e.status===`disabled`),ne=N.some(e=>e.status!==`disabled`),I=N.length===0,ie=(e,t)=>{b(n=>{let r=new Set(n);return t?r.add(e):r.delete(e),r})},ce=()=>{b(e=>{let t=new Set(e);if(P)for(let e of M)t.delete(e.id);else for(let e of M)t.add(e.id);return t})},pe=async(e,t)=>{if(N.length===0)return;E(!0);let n=await Promise.allSettled(N.map(e=>t(e))),r=n.filter(e=>e.status===`rejected`).length,i=n.length-r;E(!1),r===0?x.success(`${e} complete`,`${i} account${i===1?``:`s`}`):x.error(`${e} partially failed`,`${i} succeeded, ${r} failed`)},me=()=>pe(`Recover`,t=>c.mutateAsync({providerId:e,accountId:t.id})),he=async()=>{if(t.length===0)return;E(!0);let e=await jt(t,3,e=>ue(`/accounts/${encodeURIComponent(e.id)}/quota/refresh`,{method:`POST`})),n=0,r=0;for(let t of e)t.status===`fulfilled`&&t.value?.ok?n+=1:r+=1;await Promise.all([o.invalidateQueries({queryKey:L.quota.all}),o.invalidateQueries({queryKey:L.providers.all})]),E(!1),r===0?x.success(`Test complete`,`${n} passed`):n===0?x.error(`Test failed`,`${r} account${r===1?``:`s`} failed`):x.error(`Test partially failed`,`${n} passed, ${r} failed`)},ge=t=>pe(t?`Enable`:`Disable`,n=>s.mutateAsync({providerId:e,accountId:n.id,request:{status:t?`active`:`disabled`}})),_e=async()=>{if(N.length!==0){E(!0);try{let t=await l.mutateAsync({providerId:e,accountIds:N.map(e=>e.id)}),n=new Date().toISOString().replace(/[:.]/g,`-`);Ie(`${e}-accounts-${n}.json`,JSON.stringify(t,null,2),`application/json`),x.success(`Accounts exported`,`${t.accounts.length} account${t.accounts.length===1?``:`s`} — contains plaintext credentials`)}catch(e){x.error(`Export failed`,e.message??`Unable to export accounts`)}finally{E(!1)}}};return(0,$.jsxs)(J,{gap:`8px`,children:[(0,$.jsxs)(`div`,{className:`flex min-w-0 flex-wrap items-center gap-2 p-3 border border-inner-border rounded-control bg-surface-2`,children:[(0,$.jsxs)(`label`,{className:`relative min-w-20 flex-[1_1_10rem]`,children:[(0,$.jsx)(oe,{size:13,"aria-hidden":`true`,className:`pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-text-tertiary`}),(0,$.jsx)(K,{id:`accounts-search`,value:g,onChange:e=>_(e.target.value),placeholder:`Search accounts...`,"aria-label":`Search accounts`,className:`pl-9`})]}),(0,$.jsx)(y,{size:`sm`,variant:`primary`,icon:(0,$.jsx)(h,{size:12}),disabled:T||t.length===0,onClick:he,"aria-label":`Test all accounts`,title:`Test every account, regardless of selection or filters`,children:`Test all`}),(0,$.jsxs)(`div`,{ref:A,className:`relative`,children:[(0,$.jsxs)(y,{size:`sm`,variant:`secondary`,disabled:T||I,"aria-expanded":ee,"aria-haspopup":`menu`,"aria-label":I?`Select accounts to enable bulk actions`:`Bulk actions for ${N.length} selected accounts`,onClick:()=>k(e=>!e),children:[`Actions`,I?``:` (${N.length})`,(0,$.jsx)(d,{size:12,"aria-hidden":`true`,className:`transition-transform ${ee?`rotate-180`:``}`})]}),ee&&!I?(0,$.jsxs)(`div`,{role:`menu`,"aria-label":`Selected account actions`,className:`absolute left-0 top-full z-50 mt-1 flex w-64 popover-max flex-col gap-1 rounded-control border border-inner-border bg-popover-bg p-2 shadow-popout sm:left-auto sm:right-0`,children:[(0,$.jsx)(y,{role:`menuitem`,size:`sm`,variant:`ghost`,className:`w-full justify-start`,icon:(0,$.jsx)(ae,{size:12}),disabled:T,onClick:()=>{k(!1),me()},children:`Recover`}),F?(0,$.jsx)(y,{role:`menuitem`,size:`sm`,variant:`ghost`,className:`w-full justify-start`,icon:(0,$.jsx)(nt,{size:12}),disabled:T,onClick:()=>{k(!1),ge(!0)},children:`Enable`}):null,ne?(0,$.jsx)(y,{role:`menuitem`,size:`sm`,variant:`ghost`,className:`w-full justify-start`,icon:(0,$.jsx)(re,{size:12}),disabled:T,onClick:()=>{k(!1),ge(!1)},children:`Disable`}):null,(0,$.jsx)(y,{role:`menuitem`,size:`sm`,variant:`ghost`,className:`w-full justify-start`,icon:(0,$.jsx)(w,{size:12}),disabled:T,onClick:()=>{k(!1),_e()},children:`Export JSON`}),(0,$.jsx)(y,{role:`menuitem`,size:`sm`,variant:`danger`,className:`w-full justify-start`,icon:(0,$.jsx)(se,{size:12}),disabled:T,onClick:()=>{k(!1),O(!0)},children:`Delete`}),(0,$.jsx)(y,{role:`menuitem`,size:`sm`,variant:`ghost`,className:`w-full justify-start`,disabled:T,onClick:()=>{b(new Set),k(!1)},children:`Clear selection`})]}):null]}),(0,$.jsx)(`label`,{className:`inline-flex h-15 shrink-0 items-center gap-2 text-caption font-semibold text-text-secondary [&_.radix-select-trigger]:font-semibold [&_.radix-select-trigger]:bg-hover [&_.radix-select-trigger]:text-text-primary`,children:(0,$.jsx)(f,{size:`sm`,value:S,onValueChange:e=>C(e),options:dn,"aria-label":`Sort accounts by`})}),(0,$.jsxs)(`label`,{className:`inline-flex h-15 shrink-0 items-center gap-2 text-caption font-semibold text-text-secondary`,children:[(0,$.jsx)(`input`,{type:`checkbox`,checked:P,onChange:ce,"aria-label":`Select accounts`}),(0,$.jsx)(`span`,{children:`Select`})]}),r?(0,$.jsx)(y,{size:`sm`,variant:`secondary`,icon:(0,$.jsx)(h,{size:12,className:i?`animate-spin`:``}),disabled:i||t.length===0,onClick:a,title:`Probe every Grok account with the live 407 streaming request`,children:i?`Testing…`:`Test 407`}):null]}),(0,$.jsx)(`div`,{className:`account-list flex flex-col gap-3 max-h-230 overflow-y-auto pr-1 [container-type:inline-size] [container-name:account-list]`,role:`list`,"aria-label":`Provider accounts`,children:te.map(t=>(0,$.jsx)(un,{providerId:e,account:t,inflight:u.get(t.id)??t.inflight,quota:m.get(t.id),selected:v.has(t.id),onToggleSelect:ie,onDelete:n},t.id))}),(0,$.jsx)(`div`,{className:`flex items-center justify-between text-badge text-text-tertiary`,children:(0,$.jsxs)(`span`,{children:[`Showing `,M.length,` account`,M.length===1?``:`s`,j?` (filtered from ${t.length})`:``]})}),(0,$.jsx)(fe,{open:D,onClose:()=>{T||O(!1)},onConfirm:async()=>{await pe(`Delete`,async e=>{let t=e.tenantId===null?`/global/accounts/${encodeURIComponent(e.id)}`:`/accounts/${encodeURIComponent(e.id)}`;await ue(t,{method:`DELETE`}),o.removeQueries({queryKey:L.quota.account(e.id),exact:!0})}),b(new Set),O(!1),await Promise.all([o.invalidateQueries({queryKey:L.providers.accounts(e)}),o.invalidateQueries({queryKey:L.providers.all}),o.invalidateQueries({queryKey:L.quota.all})])},title:`Delete ${N.length} account${N.length===1?``:`s`}?`,message:`This permanently removes the selected accounts and their credentials. This cannot be undone.`,confirmLabel:`Delete`,danger:!0})]})}var mn=2097152,hn=mn/1048576;function gn({providerId:e,accounts:t,onClose:n}){let r=ye(),i=De(),[a,o]=(0,Q.useState)(``),[s,c]=(0,Q.useState)(``),[l,u]=(0,Q.useState)(!1),[d,p]=(0,Q.useState)(`auto`),m=Zt(s),h=m.length>1,g=m.length===1?m[0]:void 0,_=d===`auto`?g?.kind:d,v=g&&_===`jwt`?Ut(g.value):void 0,S=t.map(e=>e.label),C=h?$t(m,e,S):[],w=e=>{let t=d===`auto`?e.kind===`jwt`?`jwt`:`auto`:d;return{credentialKind:t===`auto`&&e.kind===`oauth`?`oauth`:`api_key`,credentialMode:t,secret:e.value}},T=r.isPending||l,E=async()=>{try{let e=await navigator.clipboard.readText();c(e);let t=Zt(e);if(t.length>1)x.success(`Pasted from clipboard`,`Detected ${t.length} credentials`);else{let e=t[0]?.kind??`api_key`,n=e===`oauth`?`OAuth export`:e===`jwt`?`Static JWT`:`API key`;x.success(`Pasted from clipboard`,`Detected: ${n}`)}}catch{x.error(`Clipboard access denied`)}},D=e=>{if(e.size>mn){x.error(`File too large`,`Credential files must be ${hn} MB or smaller.`);return}let t=new FileReader;t.onload=()=>{let n=typeof t.result==`string`?t.result:``;c(n);let r=Zt(n);if(r.length===0){x.error(`Nothing to import`,`That file held no credential the gateway recognises.`);return}x.success(`Imported ${e.name}`,r.length>1?`Detected ${r.length} credentials`:r[0]?.kind===`oauth`?`Detected: OAuth export`:`Detected: API key`)},t.onerror=()=>x.error(`Could not read that file`),t.readAsText(e)},O=async()=>{if(m.length!==0){if(m.length===1){let t=m[0];r.mutate({providerId:e,request:{label:(a.trim()||t.identity)??void 0,...w(t)}},{onSuccess:()=>{x.success(`Account connected`,`New ${t.kind===`oauth`?`OAuth`:t.kind===`jwt`?`Static JWT`:`API key`} account registered successfully`),n()},onError:e=>x.error(`Failed to add account`,e.message??`Invalid credentials`)});return}u(!0);try{let t=await i.mutateAsync({providerId:e,accounts:m.map((e,t)=>({label:C[t],...w(e)}))}),r=t.results.filter(e=>!e.ok),a=t.created;if(a>0&&x.success(`${a} account${a===1?``:`s`} added`,r.length>0?`${r.length} skipped`:void 0),r.length>0){let e=r.slice(0,5).map(e=>`${C[e.index]??e.index}: ${e.error??`rejected`}`).join(`
2
- `);x.error(`${r.length} account${r.length===1?``:`s`} skipped`,e+(r.length>5?`\n…and ${r.length-5} more`:``))}a>0&&n()}finally{u(!1)}}};return(0,$.jsx)(P,{open:!0,onClose:n,title:`Add Account (API key / JSON)`,width:560,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:n,disabled:T,children:`Cancel`}),(0,$.jsx)(y,{size:`sm`,variant:`primary`,disabled:T||m.length===0,onClick:()=>void O(),children:T?`Connecting...`:h?`Add ${m.length} Accounts`:`Add Account`})]}),children:(0,$.jsxs)(`div`,{className:`flex flex-col gap-5`,children:[!h&&(0,$.jsx)(K,{label:`Account label (optional)`,value:a,onChange:e=>o(e.target.value),placeholder:g?.identity??`${e} account`}),(0,$.jsx)(f,{label:`Credential type`,id:`credential-mode`,value:d,onValueChange:e=>p(e===`jwt`||e===`api_key`?e:`auto`),options:[{value:`auto`,label:`Auto — detect JWT, OAuth, or API key`},{value:`jwt`,label:`JWT — static, no refresh`},{value:`api_key`,label:`API key — do not decode as JWT`}]}),(0,$.jsxs)(J,{gap:`6px`,className:`min-w-0`,children:[(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,$.jsx)(`label`,{className:`text-caption font-semibold text-text-secondary`,children:`API key, OAuth token, or exported JSON — one or many`}),h?(0,$.jsxs)(G,{tone:`accent`,children:[`Detected: `,m.length,` accounts`]}):g?(0,$.jsxs)(G,{tone:_===`oauth`||_===`jwt`?`accent`:`default`,children:[`Detected:`,` `,_===`oauth`?`OAuth`:_===`jwt`?`Static JWT`:`API key`,g.identity?` · ${g.identity}`:``]}):null,g&&_===`jwt`?(0,$.jsxs)(`p`,{className:`text-micro text-text-tertiary`,children:[`Static JWT · no refresh token`,v?` · expires ${new Date(v).toLocaleString()}`:` · no expiry claim`]}):null]}),(0,$.jsx)(`textarea`,{value:s,onChange:e=>c(e.target.value),placeholder:`Paste one credential, or many — one per line, a JSON array, or newline-delimited OAuth exports. Kind and account naming are detected automatically…`,rows:6,spellCheck:!1,className:`font-mono tabular-nums w-full min-w-0 min-h-65 rounded-control border border-inner-border bg-input-bg px-6 py-5 text-caption text-text-primary resize-y box-border`}),(0,$.jsxs)(Y,{gap:`8px`,className:`justify-end`,children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:()=>void E(),children:`Paste`}),(0,$.jsxs)(`label`,{className:b({size:`sm`,className:`cursor-pointer`}),children:[(0,$.jsx)(`input`,{type:`file`,accept:`.json,.txt,.jsonl,.ndjson,application/json,text/plain`,"aria-label":`Import credentials from a file`,className:`hidden`,onChange:e=>{let t=e.target.files?.[0];e.target.value=``,t&&D(t)}}),`Import file`]})]})]}),h&&(0,$.jsx)(`div`,{className:`flex flex-col gap-2 max-h-75 overflow-y-auto rounded-control border border-inner-border bg-surface-2 px-4 py-5`,children:m.map((e,t)=>(0,$.jsxs)(`div`,{className:`flex items-center justify-between gap-4 text-badge`,children:[(0,$.jsx)(`span`,{className:`truncate min-w-0`,children:C[t]}),(0,$.jsx)(G,{tone:e.kind===`oauth`?`accent`:`default`,children:e.kind===`oauth`?`OAuth`:`API key`})]},t))})]})})}function _n(e){let t=e.trim(),n=e=>{try{return new URL(e).searchParams}catch{return}},r=n(t)??new URLSearchParams(t.startsWith(`?`)?t.slice(1):t),i=r.get(`code`);if(i)return{code:i};let a=r.get(`error_description`)??r.get(`error`);return a?{error:`The provider refused the login: ${a}`}:n(t)!==void 0||t.startsWith(`?`)?{error:`That redirect URL carries no authorization code — copy the full URL from the address bar.`}:{code:t}}function vn({providerId:e,authorizeUrl:t,state:n,popup:r,onClose:i}){let[a,o]=(0,Q.useState)(!1),[s,c]=(0,Q.useState)(``),l=ke(),d=Ze(),f=le(),p=Ee(e),m=(0,Q.useRef)(null),h=(0,Q.useRef)(!1);(0,Q.useEffect)(()=>{let t=setInterval(()=>{f.invalidateQueries({queryKey:L.providers.accounts(e)})},1500);return()=>clearInterval(t)},[f,e]),(0,Q.useEffect)(()=>{let e=p.data?.map(e=>e.id)??null;if(e!==null){if(m.current===null){m.current=new Set(e);return}h.current||e.find(e=>!m.current.has(e))!==void 0&&(h.current=!0,r.close(),x.success(`Account connected`,`OAuth login completed successfully`),i(!0))}},[p.data,r,i]);let g=()=>{r.close(),i(!1)},[_,b]=(0,Q.useState)(!1),S=()=>{b(!0),f.invalidateQueries({queryKey:L.providers.accounts(e)}).finally(()=>b(!1))},w=async()=>{try{let e=await navigator.clipboard.readText();if(!e.trim()){x.error(`Clipboard is empty`);return}c(e),x.success(`Pasted redirect URL`)}catch{x.error(`Clipboard unavailable on this origin`)}};return(0,$.jsx)(P,{open:!0,onClose:g,title:`Connect via OAuth`,size:`sm`,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:g,disabled:l.isPending,children:`Cancel`}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:S,disabled:l.isPending||_,title:`You already approved in the popup — check now instead of waiting`,children:_?`Checking…`:`Complete`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,disabled:l.isPending||s.trim().length===0,onClick:()=>{let t=_n(s);if(`error`in t){x.error(`OAuth callback failed`,t.error);return}l.mutate({providerId:e,code:t.code,state:n},{onSuccess:()=>{r.close(),x.success(`Account connected`,`OAuth login completed successfully`),i(!0)},onError:e=>x.error(`OAuth callback failed`,e.message??`Invalid or expired authorization code`)})},children:l.isPending?`Connecting…`:`Connect`})]}),children:(0,$.jsxs)(J,{gap:`14px`,children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2.5 px-3.5 py-2.5 rounded-card border border-inner-border bg-surface-2`,children:[(0,$.jsx)(v,{size:16,className:`animate-spin text-accent shrink-0`}),(0,$.jsx)(`span`,{className:`text-body font-semibold`,children:`Waiting for popup authorization…`})]}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,$.jsx)(`div`,{className:`text-body font-semibold text-text-primary`,children:`Step 1: Open this URL in your browser`}),(0,$.jsxs)(Y,{gap:`8px`,children:[(0,$.jsx)(`a`,{className:`min-w-0 flex-1 font-mono text-badge text-accent overflow-hidden text-ellipsis whitespace-nowrap px-2.5 py-2 rounded-control bg-input-bg border border-inner-border`,href:t,target:`_blank`,rel:`noreferrer`,title:t,children:t}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:a?(0,$.jsx)(u,{size:12}):(0,$.jsx)(C,{size:12}),onClick:()=>{navigator.clipboard?.writeText(t),o(!0),d(()=>o(!1),1500)},className:`shrink-0`,children:a?`Copied`:`Copy`})]}),(0,$.jsx)(`p`,{className:`text-badge leading-snug text-text-tertiary`,children:`A popup should open automatically. If it was blocked, open the URL above manually.`})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-2.5 text-micro font-bold uppercase tracking-label text-text-tertiary`,children:[(0,$.jsx)(`span`,{"aria-hidden":`true`,className:`flex-1 h-px bg-inner-border`}),(0,$.jsx)(`span`,{children:`Or complete manually`}),(0,$.jsx)(`span`,{"aria-hidden":`true`,className:`flex-1 h-px bg-inner-border`})]}),(0,$.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,$.jsx)(`div`,{className:`text-body font-semibold text-text-primary`,children:`Step 2: Paste the redirect URL here`}),(0,$.jsx)(`p`,{className:`text-badge leading-snug text-text-tertiary`,children:`If the redirect lands on an unreachable address, copy that page's full URL from your browser and paste it below — this works from any machine, not just localhost.`}),(0,$.jsxs)(Y,{gap:`8px`,align:`flex-start`,children:[(0,$.jsx)(`textarea`,{value:s,onChange:e=>c(e.target.value),placeholder:`http://127.0.0.1:59653/callback?code=…&state=… (or just the code)`,rows:2,spellCheck:!1,className:`w-full min-h-16 resize-y rounded-control border border-inner-border bg-input-bg px-2.5 py-2 font-mono text-badge text-text-primary box-border focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-1 flex-1`}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:()=>void w(),className:`shrink-0`,children:`Paste`})]})]})]})})}function yn(e){try{return new URL(e).host}catch{return e}}function bn({providerId:e,parameters:t,onClose:n}){let r=Ne(),i=xe(),[a,o]=(0,Q.useState)(null),[s,c]=(0,Q.useState)(!1),[l,d]=(0,Q.useState)(!1),f=Ze();(0,Q.useEffect)(()=>{let i=!1;return r.mutate({providerId:e,...t===void 0||Object.keys(t).length===0?{}:{parameters:t}},{onSuccess:e=>{i||o(e)},onError:e=>{i||(x.error(`Failed to start device login`,e.message??`Unable to start device authorization`),n())}}),()=>{i=!0}},[]);let p=(0,Q.useRef)(null),[m,h]=(0,Q.useState)(!1);return(0,Q.useEffect)(()=>{if(!a)return;let e=window.open(a.verificationUri,`cartethyia-device`,`popup,width=720,height=820`);return e?p.current=e:h(!0),()=>{let e=p.current;p.current=null,e&&!e.closed&&e.close()}},[a]),(0,Q.useEffect)(()=>{if(!a)return;let t=Date.now(),r=Math.max(1,a.expiresInSeconds)*1e3,o=!1,s=Math.max(1,a.intervalSeconds)*1e3,c=!1,l=0,u=()=>window.clearTimeout(l),d=e=>{u(),l=window.setTimeout(f,e)},f=()=>{if(!c){if(Date.now()-t>r){u(),x.error(`Device login expired`,`Please try again.`),n();return}o||(o=!0,i.mutate({providerId:e,deviceAuthId:a.deviceAuthId},{onSuccess:e=>{if(o=!1,!c){if(e.status===`complete`){u();let e=p.current;e&&!e.closed&&e.close(),x.success(`OAuth account connected`,`Device authorization complete`),n()}else e.status===`failed`?(u(),x.error(`Device login failed`,e.reason),n()):e.status===`slow_down`?(s=(e.retryAfterSeconds===void 0?s+5e3:Math.max(1,e.retryAfterSeconds)*1e3)+1e3,d(s)):(e.status===`pending`&&e.retryAfterSeconds!==void 0&&(s=Math.max(1,e.retryAfterSeconds)*1e3+1e3),d(s))}},onError:()=>{o=!1,c||d(s)}}))}};return d(s+1e3),()=>{c=!0,u()}},[a]),(0,$.jsx)(P,{open:!0,onClose:n,title:`Login with OAuth (device code)`,size:`sm`,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:n,children:`Cancel`}),null]}),children:(0,$.jsx)(J,{gap:`14px`,children:a?(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`div`,{className:`flex items-center gap-2.5 px-3.5 py-2.5 rounded-card border border-inner-border bg-surface-2`,children:[(0,$.jsx)(v,{size:16,className:`animate-spin text-accent shrink-0`}),(0,$.jsx)(`span`,{className:`text-body font-semibold`,children:`Waiting for authorization…`})]}),a.userCode?(0,$.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,$.jsx)(`div`,{className:`text-body font-semibold text-text-primary`,children:`Step 1: Enter this code`}),(0,$.jsxs)(`div`,{className:`rounded-card border border-inner-border bg-surface-2 p-3.5 flex flex-col gap-1.5 items-center text-center`,children:[(0,$.jsx)(`div`,{className:`text-micro font-bold uppercase tracking-label text-text-tertiary`,children:`Device code`}),(0,$.jsx)(`div`,{className:`font-mono text-display font-bold tracking-code text-text-primary`,children:a.userCode}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:l?(0,$.jsx)(u,{size:12}):(0,$.jsx)(C,{size:12}),onClick:()=>{navigator.clipboard?.writeText(a.userCode),d(!0),f(()=>d(!1),1500)},children:l?`Copied`:`Copy code`})]})]}):null,(0,$.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[(0,$.jsx)(`div`,{className:`text-body font-semibold text-text-primary`,children:a.userCode?`Step 2: Open the verification page`:`Open the verification page to authorize`}),(0,$.jsxs)(Y,{gap:`8px`,children:[(0,$.jsx)(`a`,{className:`min-w-0 flex-1 font-mono text-badge text-accent overflow-hidden text-ellipsis whitespace-nowrap px-2.5 py-2 rounded-control bg-input-bg border border-inner-border`,href:a.verificationUri,target:`_blank`,rel:`noreferrer`,title:a.verificationUri,children:yn(a.verificationUri)}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,icon:(0,$.jsx)(et,{size:12}),onClick:()=>window.open(a.verificationUri,`_blank`,`noopener`),className:`shrink-0`,children:`Open`}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:s?(0,$.jsx)(u,{size:12}):(0,$.jsx)(C,{size:12}),onClick:()=>{navigator.clipboard?.writeText(a.verificationUri),c(!0),f(()=>c(!1),1500)},className:`shrink-0`,children:s?`Copied`:`Copy`})]}),(0,$.jsx)(`p`,{className:`text-badge leading-snug text-text-tertiary`,children:m?`The popup was blocked — open the page with Open above, finish signing in there, then press Check now.`:`The page opened in a popup. Finish signing in there — this dialog closes automatically once the account connects, or press Check now.`})]})]}):(0,$.jsxs)(`div`,{className:`flex items-center gap-2.5 px-3.5 py-2.5 rounded-card border border-inner-border bg-surface-2`,children:[(0,$.jsx)(v,{size:16,className:`animate-spin text-accent shrink-0`}),(0,$.jsx)(`span`,{className:`text-body font-semibold`,children:`Starting device authorization…`})]})})})}function xn(e){let t={};for(let n of e)t[n.key]=n.defaultValue??``;return t}function Sn(e,t){return e.filter(e=>e.required===!0&&(t[e.key]??``).trim().length===0).map(e=>e.key)}function Cn({fields:e,values:t,onChange:n,idPrefix:r}){return e.length===0?null:(0,$.jsx)(J,{gap:`10px`,children:e.map(e=>{let i=`${r}-${e.key}`,a=t[e.key]??``;return e.options&&e.options.length>0?(0,$.jsx)(f,{id:i,label:e.label,value:a,onValueChange:t=>n(e.key,t),options:e.options.map(e=>({value:e.value,label:e.label}))},e.key):(0,$.jsx)(K,{id:i,label:e.label,value:a,placeholder:e.placeholder??``,type:e.secret===!0?`password`:`text`,autoComplete:`off`,onChange:t=>n(e.key,t.target.value)},e.key)})})}function wn({providerId:e,providerName:t,fields:n,onClose:r}){let i=z(),[a,o]=(0,Q.useState)(``),[s,c]=(0,Q.useState)(``),[l,u]=(0,Q.useState)(()=>xn(n)),d=(0,Q.useMemo)(()=>Sn(n,l),[n,l]);return(0,$.jsx)(P,{open:!0,onClose:r,title:`Import a ${t} credential`,size:`sm`,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:r,disabled:i.isPending,children:`Cancel`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,onClick:()=>{if(a.trim().length===0){x.error(`Credential required`,`Paste the token, key or exported JSON to import.`);return}if(d.length>0){x.error(`Missing required fields`,`Fill in: ${d.join(`, `)}`);return}i.mutate({providerId:e,credential:a.trim(),...Object.keys(l).length>0?{fields:l}:{},...s.trim().length>0?{accountLabel:s.trim()}:{}},{onSuccess:()=>{x.success(`Account imported`,`The credential was validated and saved`),r()},onError:e=>x.error(`Import failed`,e.message??`The provider rejected this credential`)})},disabled:i.isPending,icon:i.isPending?(0,$.jsx)(v,{size:13,className:`animate-spin`}):void 0,children:i.isPending?`Validating…`:`Import`})]}),children:(0,$.jsxs)(J,{gap:`12px`,children:[(0,$.jsxs)(`p`,{className:`text-badge leading-snug text-text-tertiary`,children:[`The credential is checked against `,t,` before it is saved, so one that no longer works is reported here instead of being stored.`]}),(0,$.jsx)(Cn,{fields:n,values:l,idPrefix:`import`,onChange:(e,t)=>u(n=>({...n,[e]:t}))}),(0,$.jsx)(K,{id:`import-account-label`,label:`Account label`,hint:`optional`,value:s,placeholder:e,onChange:e=>c(e.target.value)}),(0,$.jsx)(K,{id:`import-credential`,label:`Credential`,value:a,placeholder:`Paste the token, key, or exported JSON`,type:`password`,autoComplete:`off`,onChange:e=>o(e.target.value)})]})})}function Tn(e,t,n){let r=n?.trim()??``,i=r.indexOf(` — `),a=i>0?r.slice(0,i):``,o=i>0?r.slice(i+3):r;return{title:`${e}/${t} probe failed${a.length>0?` via ${a}`:``}`,detail:o.length>0?o:`Unknown error`}}function En(e,t,n){let{title:r,detail:i}=Tn(e,t,n);return[r,i]}function Dn(e){return e===`builtin`?`Built-in model`:e===`auto_free`?`Free tier, discovered from the provider`:e===`discovered`?`Fetched from provider`:`Added manually`}function On(e){return e===`auto_free`?`Free tier`:e===`discovered`?`Fetched`:`Manual`}var kn=[{key:`builtin`,label:`Built-in models`,hint:`Compiled catalog — can be disabled, not deleted`,matches:e=>e===null||e===`builtin`},{key:`auto_free`,label:`Free models (auto)`,hint:`Discovered from the provider's free tier`,matches:e=>e===`auto_free`},{key:`manual`,label:`Manually added`,hint:`Added by hand from the Add Model dialog`,matches:e=>e===`manual`},{key:`fetched`,label:`Fetched from provider`,hint:`Listed by the provider's /v1/models`,matches:e=>e!==null&&e!==`builtin`&&e!==`auto_free`&&e!==`manual`}],An={key:`disabled`,label:`Disabled models`,hint:`Turned off — not routable until re-enabled`};function jn(){return st.map(e=>({value:e,label:e===`auto`?`Thinking: auto`:e.charAt(0).toUpperCase()+e.slice(1)}))}function Mn({value:e,onChange:t,disabled:n,id:r=`probe-thinking-effort`}){return(0,$.jsx)(`div`,{title:`Reasoning effort every test in this section sends. Auto leaves the model's own reasoning default in place.`,className:`min-w-74 shrink-0`,children:(0,$.jsx)(f,{id:r,"aria-label":`Thinking effort`,value:e,disabled:n,onValueChange:e=>t(e),options:jn()})})}function Nn({providerId:e,provider:t,onClose:n}){let r=Oe(),i=je(),[a,o]=(0,Q.useState)(``),s=t?.supportedWireFamilies,c=t?.wireFamilyDefault!==void 0&&(s===void 0||s.includes(t.wireFamilyDefault))?t.wireFamilyDefault:s?.[0],l=(0,Q.useMemo)(()=>{let e=[`chat`,`responses`,`messages`],t=(s??[]).filter(t=>e.includes(t));return[...t,...e.filter(e=>!t.includes(e))]},[s]),[u,d]=(0,Q.useState)(c??`chat`),[p,m]=(0,Q.useState)(`auto`),[g,_]=(0,Q.useState)(`idle`),[b,S]=(0,Q.useState)(``),[C,w]=(0,Q.useState)(Ln),T=a.trim(),E=T.toLowerCase().startsWith(`${e.toLowerCase()}/`)&&T.length>e.length+1?T.slice(e.length+1):T,D=E!==T,O=()=>{E&&(_(`testing`),S(``),r.mutate({providerId:e,request:{modelId:E,wireFamily:u,reasoningEffort:p,serviceKind:`llm`}},{onSuccess:e=>{e.ok?_(`passed`):(_(`failed`),S(e.error??`Model probe failed`))},onError:e=>{_(`failed`),S(e.message??`Model probe failed`)}}))};return(0,$.jsx)(P,{open:!0,onClose:n,title:`Add Custom Model`,size:`sm`,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:n,disabled:i.isPending,children:`Cancel`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,disabled:i.isPending||E.length===0,onClick:()=>{if(!E)return;let t=Le(C.contextLimit),r=Le(C.outputLimit);if(t===null||r===null){x.error(`Invalid limits`,`Use a token count such as 512k, 200000, or 1.5m.`);return}i.mutate({providerId:e,modelIds:[E],wireFamily:u,metadata:{contextLimit:t??null,outputLimit:r??null,passthrough:C.passthrough,image:C.passthrough?!0:C.image,reasoning:C.passthrough?!0:C.reasoning,toolCall:C.passthrough?!0:C.toolCall}},{onSuccess:()=>{x.success(`Custom model added`,`Sent to ${e}/${E}`),n()},onError:e=>x.error(`Failed to add model`,e.message??`Unable to register model`)})},children:i.isPending?`Adding...`:`Add Model`})]}),children:(0,$.jsxs)(J,{gap:`10px`,children:[(0,$.jsxs)(Y,{gap:`8px`,align:`flex-end`,children:[(0,$.jsx)(K,{label:`Model ID`,autoFocus:!0,placeholder:`e.g. gpt-4o, free-model-id`,value:a,onChange:e=>{o(e.target.value),_(`idle`),S(``)},onKeyDown:e=>{e.key===`Enter`&&E.length>0&&O()},className:`flex-1`}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:g===`testing`?(0,$.jsx)(v,{size:13,className:`animate-spin`}):(0,$.jsx)(h,{size:13}),disabled:r.isPending||E.length===0,onClick:O,className:`shrink-0`,children:g===`testing`?`Testing...`:`Test`})]}),D&&(0,$.jsxs)(`div`,{className:`mt-1 text-badge text-text-tertiary`,children:[`Using `,(0,$.jsx)(`span`,{className:`font-mono tabular-nums`,children:E}),` (provider prefix removed).`]}),(0,$.jsx)(f,{label:`Wire family`,id:`add-model-wire-family`,value:u,onValueChange:e=>{d(e),_(`idle`),S(``)},options:l.map(e=>({value:e,label:Un(e)}))}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`div`,{className:`text-badge font-semibold text-text-secondary mb-2`,children:`Thinking`}),(0,$.jsx)(Mn,{id:`add-model-thinking-effort`,value:p,onChange:e=>{m(e),_(`idle`),S(``)},disabled:r.isPending}),(0,$.jsx)(`div`,{className:`text-badge text-text-tertiary mt-2`,children:`Sent with the test. Auto leaves the model's own reasoning default in place.`})]}),(0,$.jsx)(Rn,{draft:C,onChange:w,idPrefix:`add-model`,disabled:i.isPending}),s!==void 0&&!s.includes(u)&&(0,$.jsxs)(`div`,{className:`mt-1 text-badge text-text-tertiary`,children:[`This provider does not declare the`,` `,(0,$.jsx)(`span`,{className:`font-mono tabular-nums`,children:Un(u)}),` wire. The request is sent as chosen; the upstream decides whether it answers.`]}),g===`passed`&&(0,$.jsx)(Qe,{tone:`success`,live:`status`,children:`Model test passed — ready to add.`}),g===`failed`&&(0,$.jsx)(Qe,{tone:`danger`,live:`alert`,children:b||`Model test failed.`})]})})}function Pn(){return{contextLimit:``,outputLimit:``,passthrough:!1,image:!0,reasoning:!0,toolCall:!0}}var Fn=String(ze),In=String(H);function Ln(){return{...Pn(),contextLimit:Fn,outputLimit:In}}function Rn({draft:e,onChange:t,idPrefix:n,disabled:r=!1}){let i=e.passthrough;return(0,$.jsxs)(J,{gap:`10px`,children:[(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`div`,{className:`text-badge font-semibold text-text-secondary mb-2`,children:`Limits`}),(0,$.jsxs)(Y,{gap:`8px`,children:[(0,$.jsx)(K,{label:`Context`,id:`${n}-context`,placeholder:Fn,value:e.contextLimit,disabled:r,onChange:n=>t({...e,contextLimit:n.target.value}),className:`flex-1`}),(0,$.jsx)(K,{label:`Output`,id:`${n}-output`,placeholder:In,value:e.outputLimit,disabled:r,onChange:n=>t({...e,outputLimit:n.target.value}),className:`flex-1`})]}),(0,$.jsxs)(`label`,{className:`inline-flex items-center gap-2 mt-2 text-badge text-text-secondary cursor-pointer`,children:[(0,$.jsx)(`input`,{type:`checkbox`,id:`${n}-fallback-limits`,checked:e.contextLimit===Fn&&e.outputLimit===In,disabled:r,onChange:n=>t(n.target.checked?{...e,contextLimit:Fn,outputLimit:In}:{...e,contextLimit:``,outputLimit:``})}),`Use fallback — `,Re(ze),` ctx ·`,` `,Re(H),` out`]})]}),(0,$.jsxs)(`div`,{children:[(0,$.jsx)(`div`,{className:`text-badge font-semibold text-text-secondary mb-2`,children:`Capabilities`}),(0,$.jsx)(J,{gap:`6px`,children:[[`image`,`Can image`,e.image],[`reasoning`,`Reasoning`,e.reasoning],[`toolCall`,`Tools`,e.toolCall]].map(([a,o,s])=>(0,$.jsxs)(`label`,{className:`inline-flex items-center gap-2 text-badge text-text-secondary`,style:i?{opacity:.5}:void 0,children:[(0,$.jsx)(`input`,{type:`checkbox`,id:`${n}-${a}`,checked:i?!0:s,disabled:r||i,onChange:n=>t({...e,[a]:n.target.checked})}),o]},a))}),(0,$.jsxs)(`label`,{className:`inline-flex items-center gap-2 mt-2 text-badge text-text-secondary cursor-pointer`,children:[(0,$.jsx)(`input`,{type:`checkbox`,id:`${n}-passthrough`,checked:e.passthrough,disabled:r,onChange:n=>t({...e,passthrough:n.target.checked})}),`Passthrough — accept every capability`]}),i?(0,$.jsx)(`div`,{className:`text-badge text-text-tertiary mt-2`,children:`Passthrough grants all of the above, so they are locked on. Uncheck it to restore your own choices.`}):null]})]})}function zn({providerId:e,model:t,onClose:n}){let r=me(),[i,a]=(0,Q.useState)(()=>({contextLimit:t.contextLimit?String(t.contextLimit):``,outputLimit:t.outputLimit?String(t.outputLimit):``,passthrough:!1,image:t.vision===!0,reasoning:t.reasoning===!0,toolCall:t.toolCall===!0}));return(0,$.jsx)(P,{open:!0,onClose:n,title:`Edit Model`,size:`sm`,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:n,disabled:r.isPending,children:`Cancel`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,disabled:r.isPending,onClick:()=>{let a=Le(i.contextLimit),o=Le(i.outputLimit);if(a===null||o===null){x.error(`Invalid limits`,`Use a token count such as 512k, 200000, or 1.5m.`);return}r.mutate({providerId:e,modelId:t.modelId,route:t.route??``,metadata:{contextLimit:a??null,outputLimit:o??null,passthrough:i.passthrough,image:i.passthrough?!0:i.image,reasoning:i.passthrough?!0:i.reasoning,toolCall:i.passthrough?!0:i.toolCall}},{onSuccess:()=>n(),onError:e=>x.error(`Failed to update model`,e.message??`Unable to update model`)})},children:r.isPending?`Saving...`:`Save`})]}),children:(0,$.jsxs)(J,{gap:`10px`,children:[(0,$.jsxs)(`div`,{className:`text-badge text-text-tertiary`,children:[`Editing `,(0,$.jsx)(`span`,{className:`font-mono tabular-nums`,children:t.modelId})]}),(0,$.jsx)(Rn,{draft:i,onChange:a,idPrefix:`edit-model`,disabled:r.isPending})]})})}function Bn({providerId:e,model:t,serviceKind:n,searchCapable:r,thinkingEffort:i,onDeleteRequest:a,onEditRequest:c,deletePending:l}){let d=Oe(),f=Pe(),[_,b]=(0,Q.useState)(!1),[w,T]=(0,Q.useState)(null),D=Ze(),O=n===`llm`?ct(t.modelId,i===`auto`?null:i):t.modelId,k=`${e}/${O}`,A=n===`websearch`?`Searching…`:`Thinking…`,j=()=>{d.mutate({providerId:e,request:{modelId:t.modelId,route:t.route,...n===`llm`?{reasoningEffort:i}:{},serviceKind:n}},{onSuccess:t=>{if(T({ok:t.ok,latencyMs:t.latencyMs}),!t.ok){let{title:n,detail:r}=Tn(e,O,t.error);x.error(n,r);return}let n=t.sample?.trim()??``,r=t.reportedModel?.trim()??``;x.successRich(`${O} · END ${W(t.latencyMs)}`,(0,$.jsxs)(`span`,{className:`grid gap-2 min-w-0`,children:[r?(0,$.jsxs)(Y,{gap:`6px`,align:`center`,className:`min-w-0`,children:[(0,$.jsx)(S,{size:12,"aria-hidden":`true`,className:`shrink-0 text-text-tertiary`}),(0,$.jsx)(`span`,{className:`truncate font-mono text-badge text-text-secondary`,title:r,children:r})]}):null,(0,$.jsx)(`span`,{children:n||`No sample text in the response.`})]}),[r,n].filter(Boolean).join(`
3
- `)||`No sample text in the response.`)},onError:t=>{T({ok:!1,latencyMs:0}),x.error(...En(e,O,t.message))}})},M=()=>{let n=!t.enabled;f.mutate({providerId:e,request:{modelId:t.modelId,route:t.route,enabled:n}},{onSuccess:()=>x.success(n?`Model enabled`:`Model disabled`,t.modelId),onError:e=>x.error(`Failed to update model`,e.message??`Unable to update model`)})};return(0,$.jsx)($.Fragment,{children:(0,$.jsxs)(`div`,{className:`model-card box-border flex w-full min-w-0 flex-1-auto flex-col gap-5 rounded-panel border border-inner-border p-6 ${t.enabled?`bg-surface-2`:`bg-surface-1 opacity-72`}`,children:[(0,$.jsxs)(`div`,{className:`flex items-start gap-4 min-w-0`,children:[(0,$.jsx)(`span`,{className:`inline-flex items-center justify-center w-13 h-13 rounded-inset bg-teal-soft text-teal shrink-0`,children:(0,$.jsx)(o,{size:14})}),(0,$.jsxs)(`div`,{className:`flex-1 min-w-0 flex flex-col gap-1`,children:[(0,$.jsx)(`div`,{title:k,className:`font-mono tabular-nums min-w-0 truncate text-caption font-semibold leading-[1.35]`,children:O}),(0,$.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0 text-micro text-text-tertiary`,children:[(0,$.jsx)(`span`,{title:`${t.wireFamily} · ${t.route??e}`,className:`shrink-0 rounded-pill px-3 py-0.5 text-micro font-bold tracking-[0.04em]`,style:{...Hn(t.wireFamily)},children:Un(t.wireFamily)}),t.source!==null&&t.source!==`builtin`?(0,$.jsx)(`span`,{title:Dn(t.source),className:`shrink-0 rounded-pill border border-teal-soft px-3 py-0.5 text-micro font-bold tracking-[0.04em] text-teal`,children:On(t.source)}):null,t.enabled?null:(0,$.jsx)(`span`,{className:`shrink-0 rounded-pill bg-red-soft px-3 py-0.5 text-micro font-bold tracking-[0.04em] text-red`,children:`Off`})]})]}),(0,$.jsx)(y,{variant:`ghost`,size:`sm`,icon:_?(0,$.jsx)(u,{size:12}):(0,$.jsx)(C,{size:12}),"aria-label":`Copy ${k}`,title:`Copy ${k}`,onClick:()=>{navigator.clipboard?.writeText(k),b(!0),D(()=>b(!1),1500)},className:`shrink-0 p-2 opacity-70`})]}),(0,$.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0 text-badge text-text-secondary`,children:[(0,$.jsxs)(`span`,{className:`inline-flex gap-2.5`,children:[t.reasoning?(0,$.jsx)(`span`,{title:`Reasoning`,"aria-label":`Reasoning`,className:`inline-flex text-purple`,children:(0,$.jsx)(s,{size:12})}):null,t.vision?(0,$.jsx)(`span`,{title:`Vision`,"aria-label":`Vision`,className:`inline-flex text-status-info`,children:(0,$.jsx)(E,{size:12})}):null,t.toolCall?(0,$.jsx)(`span`,{title:`Tool calling`,"aria-label":`Tool calling`,className:`inline-flex text-orange`,children:(0,$.jsx)(ce,{size:12})}):null,r?(0,$.jsx)(`span`,{title:`Web search`,"aria-label":`Web search`,className:`inline-flex text-teal`,children:(0,$.jsx)(g,{size:12})}):null]}),(0,$.jsxs)(`span`,{className:`whitespace-nowrap`,children:[t.limitsEstimated?(0,$.jsx)(`span`,{title:U,"aria-label":`Limits are a fallback estimate`,className:`estimate-dot inline-flex items-center justify-center rounded-full border border-inner-border bg-surface-2 text-orange cursor-help mr-1 align-middle`,children:(0,$.jsx)(p,{size:9,"aria-hidden":`true`})}):null,t.contextLimit?`${Re(t.contextLimit)} ctx`:(0,$.jsx)(`span`,{title:Be,className:`cursor-help`,children:`n/a ctx`}),t.outputLimit?` · ${Re(t.outputLimit)} out`:(0,$.jsx)(`span`,{title:Be,className:`cursor-help`,children:` · n/a out`})]}),c?(0,$.jsx)(`button`,{type:`button`,className:`shrink-0 grid place-items-center w-6 h-6 p-0 border-0 bg-transparent text-text-tertiary cursor-pointer rounded-tiny hover:bg-inner-border hover:text-text-primary`,title:`Edit limits and capabilities`,"aria-label":`Edit ${t.modelId} limits and capabilities`,onClick:()=>c(t),children:(0,$.jsx)(F,{size:11})}):null]}),(0,$.jsxs)(`div`,{className:`flex gap-3 items-center flex-wrap`,children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,disabled:d.isPending,onClick:j,"aria-label":`Test ${O}`,title:d.isPending?`Probing ${O}…`:w?.ok?`Last probe OK in ${W(w.latencyMs)} — click to re-test`:w?`Last probe failed — click to retry`:`Test ${O}`,className:`flex-1 justify-center`,icon:d.isPending?(0,$.jsx)(v,{size:12,className:`animate-spin`}):w?w.ok?(0,$.jsx)(`span`,{className:`inline-flex text-green`,children:(0,$.jsx)(m,{size:12})}):(0,$.jsx)(`span`,{className:`inline-flex text-red`,children:(0,$.jsx)(ee,{size:12})}):(0,$.jsx)(h,{size:12}),children:d.isPending?A:w?.ok?W(w.latencyMs):w?`Fail`:`Test`}),(0,$.jsx)(y,{variant:`ghost`,size:`sm`,disabled:f.isPending,onClick:M,icon:t.enabled?(0,$.jsx)(re,{size:12}):(0,$.jsx)(nt,{size:12}),"aria-label":t.enabled?`Disable ${t.modelId}`:`Enable ${t.modelId}`,title:t.enabled?`Disable model`:`Enable model`,className:`flex-1 justify-center ${t.enabled?`text-red`:`text-green`}`,children:t.enabled?`Disable`:`Enable`}),t.source===`builtin`?null:(0,$.jsx)(y,{variant:`ghost`,size:`sm`,disabled:l,onClick:()=>a(t),icon:(0,$.jsx)(se,{size:12}),"aria-label":`Delete ${t.modelId}`,title:`Delete model`,className:`model-card-delete shrink-0 px-4 py-3 text-text-tertiary`})]})]})})}var Vn=(0,Q.memo)(Bn);function Hn(e){return e===`responses`?{color:`var(--purple)`,background:`var(--purple-soft)`}:e===`messages`?{color:`var(--orange)`,background:`color-mix(in srgb, var(--orange) 14%, transparent)`}:{color:`var(--teal)`,background:`var(--teal-soft)`}}function Un(e){let t=e.toLowerCase();return t===`responses`?`Responses`:t===`messages`?`Messages`:`Chat`}function Wn({providerId:e,models:t,thinkingEffort:n,serviceKind:r=`llm`,searchCapable:i=!1}){let a=R(),[o,s]=(0,Q.useState)(null),[c,l]=(0,Q.useState)(null),u=e=>e.enabled!==!1,d=kn.map(e=>({...e,rows:t.filter(t=>u(t)&&e.matches(t.source))})).filter(e=>e.rows.length>0),f=t.filter(e=>!u(e)),p=t=>(0,$.jsx)(Vn,{providerId:e,model:t,serviceKind:r,searchCapable:i,thinkingEffort:n,deletePending:a.isPending,onDeleteRequest:s,onEditRequest:t.source===`builtin`?void 0:l},`${t.modelId}::${t.route}`);return(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(J,{gap:`16px`,children:[d.map(e=>(0,$.jsxs)(`section`,{className:`flex flex-col gap-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-baseline gap-4 min-w-0`,children:[(0,$.jsx)(`span`,{className:`text-caption font-bold text-text-secondary`,children:e.label}),(0,$.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:e.rows.length}),(0,$.jsxs)(`span`,{title:e.hint,className:`text-micro text-text-tertiary overflow-hidden truncate`,children:[`· `,e.hint]})]}),(0,$.jsx)(`div`,{className:`provider-grid grid gap-4 items-stretch`,children:e.rows.map(p)})]},e.key)),f.length===0?null:(0,$.jsxs)(`section`,{className:`flex flex-col gap-4`,children:[(0,$.jsxs)(`div`,{className:`flex items-baseline gap-4 min-w-0`,children:[(0,$.jsx)(`span`,{className:`text-caption font-bold text-text-secondary`,children:An.label}),(0,$.jsx)(`span`,{className:`mt-1 text-badge text-text-tertiary`,children:f.length}),(0,$.jsxs)(`span`,{title:An.hint,className:`text-micro text-text-tertiary overflow-hidden truncate`,children:[`· `,An.hint]})]}),(0,$.jsx)(`div`,{className:`provider-grid grid gap-4 items-stretch`,children:f.map(p)})]})]}),(0,$.jsx)(fe,{open:o!==null,onClose:()=>{a.isPending||s(null)},onConfirm:async()=>{o!==null&&(await a.mutateAsync({providerId:e,request:{modelId:o.modelId,route:o.route}}),x.success(`Model deleted`,`${e}/${o.modelId}`),s(null))},title:`Delete model?`,message:`Delete ${e}/${o?.modelId??``} from the provider catalog?`,confirmLabel:`Delete`,danger:!0}),c===null?null:(0,$.jsx)(zn,{providerId:e,model:c,onClose:()=>l(null)})]})}function Gn(e){return e===`llm`?`LLM`:e===`websearch`?`Search`:e===`imageGeneration`?`Image`:e===`videoGeneration`?`Video`:e}function Kn(e){let t=e.serviceKinds;return Array.isArray(t)&&t.length>0?t:[`llm`]}function qn(){let{providerId:e}=he(),[t]=_e(),n=e??``,r=t.get(`service`),[i,a]=(0,Q.useState)(r===`websearch`||r===`imageGeneration`||r===`videoGeneration`?r:`llm`),o=Ce(),s=we(n),l=Ee(n),u=pe(),d=pe({silent:!0}),[f,p]=(0,Q.useState)(!1),m=Se(),h=Me(),_=be(),v=le(),[b,S]=(0,Q.useState)(!1),[C,T]=(0,Q.useState)(!1),E=Oe(),[D,ee]=(0,Q.useState)(``),[te,N]=(0,Q.useState)(``),[F,I]=(0,Q.useState)(null),ae=e=>`cartethyia:provider:${e}:thinking-effort`,oe=e=>{if(typeof window>`u`||!window.localStorage)return`auto`;let t=window.localStorage.getItem(ae(e));if(t===null)return`auto`;let n=t.trim().toLowerCase();return st.includes(n)?n:`auto`},[ce,de]=(0,Q.useState)(()=>oe(n));(0,Q.useEffect)(()=>{if(!n)return;let e=oe(n);e!==ce&&de(e)},[n]),(0,Q.useEffect)(()=>{typeof window>`u`||!window.localStorage||!n||window.localStorage.setItem(ae(n),ce)},[n,ce]);let[me,ge]=(0,Q.useState)(!1),[ve,ye]=(0,Q.useState)(!1),[R,xe]=(0,Q.useState)(null),[Te,De]=(0,Q.useState)({}),[ke,Ae]=(0,Q.useState)({}),[z,je]=(0,Q.useState)(null),[Ne,Pe]=(0,Q.useState)(!1),[Ie,Le]=(0,Q.useState)(null),H=(0,Q.useRef)(null),Re=(0,Q.useRef)(null);(0,Q.useEffect)(()=>()=>{let e=H.current;H.current=null,e&&!e.closed&&e.close()},[]);let U=(o.data??[]).find(e=>e.providerId===n),ze=n===`opencode`||n===`cline`,Be=U===void 0?[`llm`]:Kn(U),W=[];for(let e of Be)(e===`llm`||e===`websearch`||e===`imageGeneration`||e===`videoGeneration`)&&W.push(e);(0,Q.useEffect)(()=>{if(U===void 0)return;let e=r===`websearch`||r===`imageGeneration`||r===`videoGeneration`||r===`llm`?r:void 0,t=W[0];if(e!==void 0&&W.includes(e)){i!==e&&a(e);return}!W.includes(i)&&t!==void 0&&a(t)},[U,r,i,W.join(`|`)]),(0,Q.useEffect)(()=>{ze&&U!==void 0&&U.supportsModelDiscovery!==!1&&Re.current!==n&&(Re.current=n,d.mutate(n))},[ze,d,n,U?.supportsModelDiscovery]);let G=l.data??[],K=s.data??[],q=(()=>{let e=new Map;for(let t of K){let n=`${t.serviceKind??`llm`}:${t.modelId}`,r=e.get(n);if(!r)e.set(n,t);else{let i=r.contextLimit??0;(t.contextLimit??0)>i&&e.set(n,t)}}return[...e.values()].sort((e,t)=>e.modelId.localeCompare(t.modelId))})(),X=q.filter(e=>e.serviceKind===`llm`||e.serviceKind===void 0),Ue=q.filter(e=>e.serviceKind===`websearch`),We=q.filter(e=>e.serviceKind===`imageGeneration`),Ge=q.filter(e=>e.serviceKind===`videoGeneration`),Z=W.includes(i)?i:W[0],Ke=te||Ue[0]?.modelId||``,qe=()=>{let e=D.trim();Ke&&e&&(I(null),E.mutate({providerId:n,request:{modelId:Ke,serviceKind:`websearch`,prompt:e}},{onSuccess:e=>I({ok:e.ok,latencyMs:e.latencyMs,...e.searchResults?{results:e.searchResults,count:e.searchResults.length}:{},...e.error?{error:e.error}:{}}),onError:e=>I({ok:!1,error:e instanceof Error?e.message:`Search test failed`})}))};if(o.isPending)return(0,$.jsx)(A,{label:`Loading provider...`});if(o.isError)return(0,$.jsx)(k,{title:`Unable to load providers`,message:`The provider catalog could not be read, so this page cannot resolve its provider.`,onRetry:()=>void o.refetch(),retrying:o.isFetching,action:(0,$.jsx)(lt,{to:`/providers`,label:`Back to providers`})});if(!U)return(0,$.jsx)(j,{icon:(0,$.jsx)(rt,{size:20}),title:`Provider not found`,message:`No provider named “${n}”. It may have been removed, or the link is stale.`,action:(0,$.jsx)(lt,{to:`/providers`,label:`Back to providers`})});let Je=G.filter(e=>e.status===`active`).length,Ye=e=>{let t=e===`browser`?U?.oauthFlows?.browserLoginFields??[]:U?.oauthFlows?.deviceLoginFields??[];if(t.length===0){e===`browser`?Ze():ge(!0);return}De(xn(t)),xe(e)},Xe=()=>{if(R===null)return;let e=Sn(R===`browser`?U?.oauthFlows?.browserLoginFields??[]:U?.oauthFlows?.deviceLoginFields??[],Te);if(e.length>0){x.error(`Missing required fields`,`Fill in: ${e.join(`, `)}`);return}let t=R;xe(null),t===`browser`?Ze(Te):(Ae(Te),ge(!0))},Ze=e=>{let t=window.open(`about:blank`,`cartethyia-oauth`,`popup,width=720,height=820`);t&&(t.opener=null,H.current=t),_.mutate({providerId:n,...e===void 0?{}:{parameters:e}},{onSuccess:({authorizeUrl:e,state:n})=>{let r=null;if(t&&!t.closed?(t.location.href=e,r=t):(r=window.open(e,`cartethyia-oauth`,`popup,width=720,height=820`),r&&(r.opener=null,H.current=r)),!r){x.error(`Popup blocked`,`Allow popups to complete OAuth login.`);return}Le({authorizeUrl:e,state:n,popup:r})},onError:e=>{t&&!t.closed&&t.close(),H.current===t&&(H.current=null),x.error(`Failed to start OAuth`,e.message??`Unable to start authorization`)}})};return(0,$.jsxs)(J,{gap:`16px`,children:[(0,$.jsx)(ut,{title:`${U.label||U.displayName}${Z?` (${Gn(Z)})`:``}`,description:`${U.providerId}/${U.baseUrl?` · ${U.baseUrl}`:``}`,icon:(0,$.jsx)(Ve,{icon:U.providerId,name:U.label||U.displayName,size:28}),back:{to:`/providers`,label:`Back to Providers`},actions:(0,$.jsx)(Y,{gap:`8px`,className:`flex-wrap w-full max-w-full min-w-0`,children:U.isBuiltIn?(0,$.jsx)(y,{variant:U.enabled?`danger`:`secondary`,icon:U.enabled?(0,$.jsx)(re,{size:13}):(0,$.jsx)(nt,{size:13}),loading:h.isPending,onClick:()=>h.mutate({providerId:n,enabled:!U.enabled},{onSuccess:e=>x.success(e.enabled?`Provider enabled`:`Provider disabled`,U.label||U.displayName),onError:e=>x.error(`Provider update failed`,e.message??`Unable to change provider availability`)}),title:U.enabled?`Disable provider globally`:`Enable provider globally`,children:U.enabled?`Disable`:`Enable`}):null})}),(0,$.jsx)(Tt,{provider:U}),Z===`llm`?(0,$.jsx)(bt,{providerId:n,clientVersion:U.clientVersion,routeIdentityVersions:U.routeIdentityVersions,userAgentEditable:dt(U)}):null,U.requiresAccount===!1?(0,$.jsxs)(V,{children:[(0,$.jsx)(Fe,{title:`Accounts`,icon:(0,$.jsx)($e,{size:16})}),(0,$.jsx)(B,{children:(0,$.jsx)(`p`,{className:`text-caption text-text-secondary`,children:`This provider is a public, unauthenticated route — no account or credential is needed. Routing already works without any setup here.`})})]}):(0,$.jsxs)(V,{children:[(0,$.jsx)(Fe,{title:`Accounts`,subtitle:`${G.length} total · ${Je} active · ${G.length-Je} disabled`,icon:(0,$.jsx)($e,{size:16}),action:(0,$.jsxs)(He,{children:[U.oauthFlows?.browser&&(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(et,{size:13}),disabled:_.isPending,onClick:()=>Ye(`browser`),title:`Browser OAuth login — opens the provider authorize page in a popup`,children:_.isPending?`Starting...`:`Login with browser`}),U.oauthFlows?.device&&(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(M,{size:13}),onClick:()=>Ye(`device`),title:`Device-code login — enter the shown code on the provider site`,children:`Login with device code`}),U.oauthFlows?.import&&(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(w,{size:13}),onClick:()=>ye(!0),title:U.oauthFlows.browser||U.oauthFlows.device?`Import a credential you already hold — a refresh token, an exported auth blob, or an API key`:`Add and validate an API key`,children:U.oauthFlows.browser||U.oauthFlows.device?`Import credential`:`Add API key`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,icon:(0,$.jsx)(ne,{size:13}),onClick:()=>S(!0),children:`Add Account`})]})}),(0,$.jsxs)(B,{className:`flex flex-col gap-5`,children:[(0,$.jsx)(xt,{providerId:n}),l.isPending?(0,$.jsx)(A,{label:`Loading accounts...`}):l.isError?(0,$.jsx)(k,{message:`Failed to load accounts`,onRetry:()=>l.refetch()}):G.length===0?(0,$.jsx)(j,{title:`No accounts connected`,message:`Add an API key or OAuth credential to route requests to this provider.`}):(0,$.jsx)(pn,{providerId:n,accounts:G,onDelete:e=>je(e),showGrokProbe:Z===`llm`&&n===`grok`,grokProbePending:m.isPending,onGrokProbe:()=>{m.mutate({providerId:n,request:{modelId:`grok-4.6`,prompt:`reply my message with exact number 407`,stream:!0,serviceKind:`llm`}},{onSuccess:e=>{let t=e.results.filter(e=>e.ok).length,n=e.results.filter(e=>e.statusCode===202).length,r=e.results.length-t-n;x.success(`Grok account probe complete`,`${t} passed · ${n} returned 202 and were parked in cooldown · ${r} other failures`)},onError:e=>x.error(`Grok account probe failed`,e.message??`Unable to probe Grok accounts`)})}})]})]}),Z===`llm`?(0,$.jsx)($.Fragment,{children:(0,$.jsxs)(V,{children:[(0,$.jsx)(Fe,{title:`Models`,subtitle:`${X.length} model${X.length===1?``:`s`} registered`,icon:(0,$.jsx)(c,{size:16}),action:(0,$.jsxs)(Y,{gap:`6px`,className:`flex-wrap items-center`,children:[(0,$.jsx)(Mn,{id:`models-section-thinking-effort`,value:ce,onChange:de}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(ie,{size:13,className:u.isPending||d.isPending?`animate-spin`:``}),disabled:u.isPending||d.isPending,onClick:()=>u.mutate(n),children:u.isPending||d.isPending?`Fetching...`:`Fetch models`}),(0,$.jsx)(y,{variant:`secondary`,size:`sm`,icon:(0,$.jsx)(se,{size:13,className:f?`animate-spin`:``}),disabled:u.isPending||d.isPending||f||X.filter(e=>e.source!==`builtin`&&e.source!==null).length===0,onClick:async()=>{let e=X.filter(e=>e.source!==`builtin`&&e.source!==null);if(e.length!==0&&confirm(`Delete ${e.length} fetched/manual model(s) for ${n}?`)){p(!0);try{let t=await ue(`/providers/${encodeURIComponent(n)}/models/bulk`,{method:`DELETE`,body:JSON.stringify({items:e.map(e=>({modelId:e.modelId,route:e.route}))})});await Promise.all([v.invalidateQueries({queryKey:L.providers.models(n)}),v.invalidateQueries({queryKey:L.providers.all})]);let r=t.failures.length;x.success(`Fetched models deleted`,r>0?`${t.deleted}/${t.total} removed, ${r} failed`:`${t.deleted}/${t.total} removed`)}catch(e){x.error(`Failed to delete fetched models`,e.message??`Unable to delete models`)}finally{p(!1)}}},children:f?`Deleting…`:`Delete fetched`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,icon:(0,$.jsx)(ne,{size:13}),onClick:()=>T(!0),children:`Add Model`})]})}),(0,$.jsx)(B,{className:`flex flex-col gap-8`,children:s.isPending?(0,$.jsx)(A,{label:`Loading models...`}):s.isError?(0,$.jsx)(k,{message:`Failed to load models`,onRetry:()=>s.refetch()}):X.length===0?(0,$.jsx)(j,{title:`No LLM models found`,message:`No LLM models published by this provider yet. Sync or add a custom model above.`}):(0,$.jsx)(Wn,{providerId:n,models:X,serviceKind:`llm`,thinkingEffort:ce,searchCapable:U?.supportsWebSearch===!0})})]})}):Z===`websearch`?(0,$.jsxs)(V,{children:[(0,$.jsx)(Fe,{title:`Web Search`,subtitle:`Run a real search request through the selected provider.`,icon:(0,$.jsx)(g,{size:16})}),(0,$.jsx)(B,{className:`flex flex-col gap-6`,children:s.isPending?(0,$.jsx)(A,{label:`Loading search models...`}):s.isError?(0,$.jsx)(k,{message:`Failed to load search models`,onRetry:()=>s.refetch()}):Ue.length===0?(0,$.jsx)(j,{title:`No Search models found`,message:`This provider advertises Search, but no websearch model is registered yet.`}):(0,$.jsxs)($.Fragment,{children:[(0,$.jsxs)(`label`,{className:`flex flex-col gap-2.5 text-badge text-text-secondary`,children:[`Search model`,(0,$.jsx)(`select`,{value:Ke,onChange:e=>{N(e.target.value),I(null)},className:`w-full min-h-17 rounded-inset border border-inner-border bg-surface-1 text-text-primary px-4.5 py-0`,children:Ue.map(e=>(0,$.jsx)(`option`,{value:e.modelId,children:e.modelId},`${e.modelId}:${e.route}`))})]}),(0,$.jsxs)(`label`,{className:`flex flex-col gap-2.5 text-badge text-text-secondary`,children:[`Query`,(0,$.jsx)(`input`,{value:D,onChange:e=>ee(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),qe())},placeholder:`What is the latest news about AI?`,className:`w-full min-h-17 rounded-inset border border-inner-border bg-surface-1 text-text-primary px-4.5 py-0`})]}),(0,$.jsxs)(Y,{gap:`8px`,className:`items-center flex-wrap`,children:[(0,$.jsx)(y,{variant:`primary`,size:`sm`,disabled:E.isPending||D.trim().length===0,loading:E.isPending,onClick:qe,children:`Test search`}),F?(0,$.jsx)(`span`,{className:`text-badge`,style:{color:F.ok?`var(--green)`:`var(--red)`},children:F.ok?`Search ok · ${F.latencyMs}ms · ${F.count??0} result(s)`:F.error??`Search failed.`}):null]}),F&&F.results&&F.results.length>0?(0,$.jsx)(`div`,{className:`flex max-h-110 flex-col gap-4 overflow-y-auto rounded-inset border border-inner-border bg-surface-1 p-4`,children:F.results.map((e,t)=>(0,$.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,$.jsx)(`a`,{href:e.url,target:`_blank`,rel:`noreferrer`,className:`text-caption text-text-primary font-semibold`,children:e.title||e.url}),(0,$.jsx)(`span`,{className:`text-badge text-text-tertiary break-all`,children:e.url}),e.snippet?(0,$.jsx)(`span`,{className:`text-badge text-text-secondary`,children:e.snippet}):null]},`${e.url}:${t}`))}):null]})})]}):Z===`imageGeneration`||Z===`videoGeneration`?(0,$.jsxs)(V,{children:[(0,$.jsx)(Fe,{title:Gn(Z),subtitle:Z===`imageGeneration`?`Models that return an image rather than text.`:`Models that return a video. Wired and routable; not yet verified against a live account.`,icon:Z===`imageGeneration`?(0,$.jsx)(O,{size:16}):(0,$.jsx)(at,{size:16})}),(0,$.jsx)(B,{className:`flex flex-col gap-6`,children:s.isPending?(0,$.jsx)(A,{label:`Loading ${Gn(Z).toLowerCase()} models...`}):s.isError?(0,$.jsx)(k,{message:`Failed to load ${Gn(Z).toLowerCase()} models`,onRetry:()=>s.refetch()}):(Z===`imageGeneration`?We:Ge).length===0?(0,$.jsx)(j,{title:`No ${Gn(Z)} models found`,message:`This provider advertises ${Gn(Z)}, but no ${Z} model is registered yet.`}):(0,$.jsx)(Wn,{providerId:n,models:Z===`imageGeneration`?We:Ge,serviceKind:`llm`,searchCapable:!1,thinkingEffort:`auto`})})]}):(0,$.jsx)(V,{children:(0,$.jsx)(B,{children:(0,$.jsx)(j,{title:`Service not available`,message:`This provider advertises ${Be.map(Gn).join(`, `)}, but the dashboard has no controls for the selected service yet.`})})}),b&&(0,$.jsx)(gn,{providerId:n,accounts:G,onClose:()=>S(!1)}),Z===`llm`&&C?(0,$.jsx)(Nn,{providerId:n,provider:U,onClose:()=>T(!1)}):null,(0,$.jsx)(fe,{open:z!==null,onClose:()=>{Ne||je(null)},onConfirm:async()=>{if(z){Pe(!0);try{let e=z.tenantId===null?`/global/accounts/${encodeURIComponent(z.id)}`:`/accounts/${encodeURIComponent(z.id)}`;await ue(e,{method:`DELETE`}),v.removeQueries({queryKey:L.quota.account(z.id),exact:!0}),await Promise.all([v.invalidateQueries({queryKey:L.providers.accounts(n)}),v.invalidateQueries({queryKey:L.providers.healthEvents(n,z.id)}),v.invalidateQueries({queryKey:L.providers.all}),v.invalidateQueries({queryKey:L.quota.all})]),x.success(`Account deleted`,z.label||z.id.slice(0,8)),je(null)}catch(e){throw x.error(`Failed to delete account`,e.message??`Unable to delete account`),e}finally{Pe(!1)}}},title:`Delete account?`,message:`Delete "${z?.label||z?.id.slice(0,8)}"? This cannot be undone.`,confirmLabel:`Delete`,danger:!0}),me&&(0,$.jsx)(bn,{providerId:n,parameters:ke,onClose:()=>{ge(!1),Ae({})}}),R!==null&&(0,$.jsx)(P,{open:!0,onClose:()=>xe(null),title:R===`browser`?`Sign in with`:`Device sign-in details`,size:`sm`,footer:(0,$.jsxs)($.Fragment,{children:[(0,$.jsx)(y,{variant:`secondary`,size:`sm`,onClick:()=>xe(null),children:`Cancel`}),(0,$.jsx)(y,{variant:`primary`,size:`sm`,onClick:Xe,children:`Continue`})]}),children:(0,$.jsxs)(J,{gap:`12px`,children:[(0,$.jsx)(`p`,{className:`text-badge leading-snug text-text-tertiary`,children:R===`browser`?`Choose how ${U.label||U.displayName} should identify you, then continue to its sign-in page.`:`These decide which organization the device code is issued for.`}),(0,$.jsx)(Cn,{fields:R===`browser`?U?.oauthFlows?.browserLoginFields??[]:U?.oauthFlows?.deviceLoginFields??[],values:Te,idPrefix:`flow-${R}`,onChange:(e,t)=>De(n=>({...n,[e]:t}))})]})}),ve&&U?.oauthFlows?.import===!0&&(0,$.jsx)(wn,{providerId:n,providerName:U.label||U.displayName,fields:U.oauthFlows.importFields,onClose:()=>ye(!1)}),Ie&&(0,$.jsx)(vn,{providerId:n,authorizeUrl:Ie.authorizeUrl,state:Ie.state,popup:Ie.popup,onClose:e=>{H.current=null,Le(null),e&&v.invalidateQueries({queryKey:L.providers.accounts(n)})}})]})}export{qn as default};