aigetwey 1.3.8 → 1.4.0

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 (299) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +125 -211
  3. package/assets/screenshot-accesskey.png +0 -0
  4. package/assets/screenshot-budgets.png +0 -0
  5. package/assets/screenshot-endpoint.png +0 -0
  6. package/dashboard/.next/BUILD_ID +1 -1
  7. package/dashboard/.next/app-path-routes-manifest.json +1 -0
  8. package/dashboard/.next/build-manifest.json +3 -3
  9. package/dashboard/.next/diagnostics/route-bundle-stats.json +55 -38
  10. package/dashboard/.next/fallback-build-manifest.json +3 -3
  11. package/dashboard/.next/prerender-manifest.json +24 -0
  12. package/dashboard/.next/routes-manifest.json +6 -0
  13. package/dashboard/.next/server/app/(console)/combos/page.js.nft.json +1 -1
  14. package/dashboard/.next/server/app/(console)/combos/page_client-reference-manifest.js +1 -1
  15. package/dashboard/.next/server/app/(console)/config/page.js.nft.json +1 -1
  16. package/dashboard/.next/server/app/(console)/config/page_client-reference-manifest.js +1 -1
  17. package/dashboard/.next/server/app/(console)/console/page.js.nft.json +1 -1
  18. package/dashboard/.next/server/app/(console)/console/page_client-reference-manifest.js +1 -1
  19. package/dashboard/.next/server/app/(console)/endpoint/page.js.nft.json +1 -1
  20. package/dashboard/.next/server/app/(console)/endpoint/page_client-reference-manifest.js +1 -1
  21. package/dashboard/.next/server/app/(console)/keys/page/app-paths-manifest.json +3 -0
  22. package/dashboard/.next/server/app/(console)/keys/page/build-manifest.json +18 -0
  23. package/dashboard/.next/server/app/(console)/keys/page/next-font-manifest.json +11 -0
  24. package/dashboard/.next/server/app/(console)/keys/page/react-loadable-manifest.json +1 -0
  25. package/dashboard/.next/server/app/(console)/keys/page/server-reference-manifest.json +4 -0
  26. package/dashboard/.next/server/app/(console)/keys/page.js +15 -0
  27. package/dashboard/.next/server/app/(console)/keys/page.js.map +5 -0
  28. package/dashboard/.next/server/app/(console)/keys/page.js.nft.json +1 -0
  29. package/dashboard/.next/server/app/(console)/keys/page_client-reference-manifest.js +3 -0
  30. package/dashboard/.next/server/app/(console)/page.js.nft.json +1 -1
  31. package/dashboard/.next/server/app/(console)/page_client-reference-manifest.js +1 -1
  32. package/dashboard/.next/server/app/(console)/providers/[id]/page.js.nft.json +1 -1
  33. package/dashboard/.next/server/app/(console)/providers/[id]/page_client-reference-manifest.js +1 -1
  34. package/dashboard/.next/server/app/(console)/providers/page.js.nft.json +1 -1
  35. package/dashboard/.next/server/app/(console)/providers/page_client-reference-manifest.js +1 -1
  36. package/dashboard/.next/server/app/(console)/quota/page.js.nft.json +1 -1
  37. package/dashboard/.next/server/app/(console)/quota/page_client-reference-manifest.js +1 -1
  38. package/dashboard/.next/server/app/(console)/tools/[id]/page.js.nft.json +1 -1
  39. package/dashboard/.next/server/app/(console)/tools/[id]/page_client-reference-manifest.js +1 -1
  40. package/dashboard/.next/server/app/(console)/tools/page.js.nft.json +1 -1
  41. package/dashboard/.next/server/app/(console)/tools/page_client-reference-manifest.js +1 -1
  42. package/dashboard/.next/server/app/(console)/usage/page.js.nft.json +1 -1
  43. package/dashboard/.next/server/app/(console)/usage/page_client-reference-manifest.js +1 -1
  44. package/dashboard/.next/server/app/_global-error/page.js.nft.json +1 -1
  45. package/dashboard/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  46. package/dashboard/.next/server/app/_global-error.html +1 -1
  47. package/dashboard/.next/server/app/_global-error.rsc +1 -1
  48. package/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  49. package/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  50. package/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  51. package/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  52. package/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  53. package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -1
  54. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  55. package/dashboard/.next/server/app/_not-found.html +1 -1
  56. package/dashboard/.next/server/app/_not-found.rsc +2 -2
  57. package/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  58. package/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  59. package/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  60. package/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  61. package/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  62. package/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  63. package/dashboard/.next/server/app/combos.html +1 -1
  64. package/dashboard/.next/server/app/combos.rsc +5 -5
  65. package/dashboard/.next/server/app/combos.segments/!KGNvbnNvbGUp/combos/__PAGE__.segment.rsc +2 -2
  66. package/dashboard/.next/server/app/combos.segments/!KGNvbnNvbGUp/combos.segment.rsc +1 -1
  67. package/dashboard/.next/server/app/combos.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  68. package/dashboard/.next/server/app/combos.segments/_full.segment.rsc +5 -5
  69. package/dashboard/.next/server/app/combos.segments/_head.segment.rsc +1 -1
  70. package/dashboard/.next/server/app/combos.segments/_index.segment.rsc +2 -2
  71. package/dashboard/.next/server/app/combos.segments/_tree.segment.rsc +2 -2
  72. package/dashboard/.next/server/app/config.html +1 -1
  73. package/dashboard/.next/server/app/config.rsc +5 -5
  74. package/dashboard/.next/server/app/config.segments/!KGNvbnNvbGUp/config/__PAGE__.segment.rsc +2 -2
  75. package/dashboard/.next/server/app/config.segments/!KGNvbnNvbGUp/config.segment.rsc +1 -1
  76. package/dashboard/.next/server/app/config.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  77. package/dashboard/.next/server/app/config.segments/_full.segment.rsc +5 -5
  78. package/dashboard/.next/server/app/config.segments/_head.segment.rsc +1 -1
  79. package/dashboard/.next/server/app/config.segments/_index.segment.rsc +2 -2
  80. package/dashboard/.next/server/app/config.segments/_tree.segment.rsc +2 -2
  81. package/dashboard/.next/server/app/console.html +1 -1
  82. package/dashboard/.next/server/app/console.rsc +5 -5
  83. package/dashboard/.next/server/app/console.segments/!KGNvbnNvbGUp/console/__PAGE__.segment.rsc +2 -2
  84. package/dashboard/.next/server/app/console.segments/!KGNvbnNvbGUp/console.segment.rsc +1 -1
  85. package/dashboard/.next/server/app/console.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  86. package/dashboard/.next/server/app/console.segments/_full.segment.rsc +5 -5
  87. package/dashboard/.next/server/app/console.segments/_head.segment.rsc +1 -1
  88. package/dashboard/.next/server/app/console.segments/_index.segment.rsc +2 -2
  89. package/dashboard/.next/server/app/console.segments/_tree.segment.rsc +2 -2
  90. package/dashboard/.next/server/app/endpoint.html +1 -1
  91. package/dashboard/.next/server/app/endpoint.rsc +5 -5
  92. package/dashboard/.next/server/app/endpoint.segments/!KGNvbnNvbGUp/endpoint/__PAGE__.segment.rsc +2 -2
  93. package/dashboard/.next/server/app/endpoint.segments/!KGNvbnNvbGUp/endpoint.segment.rsc +1 -1
  94. package/dashboard/.next/server/app/endpoint.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  95. package/dashboard/.next/server/app/endpoint.segments/_full.segment.rsc +5 -5
  96. package/dashboard/.next/server/app/endpoint.segments/_head.segment.rsc +1 -1
  97. package/dashboard/.next/server/app/endpoint.segments/_index.segment.rsc +2 -2
  98. package/dashboard/.next/server/app/endpoint.segments/_tree.segment.rsc +2 -2
  99. package/dashboard/.next/server/app/index.html +1 -1
  100. package/dashboard/.next/server/app/index.rsc +5 -5
  101. package/dashboard/.next/server/app/index.segments/!KGNvbnNvbGUp/__PAGE__.segment.rsc +2 -2
  102. package/dashboard/.next/server/app/index.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  103. package/dashboard/.next/server/app/index.segments/_full.segment.rsc +5 -5
  104. package/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  105. package/dashboard/.next/server/app/index.segments/_index.segment.rsc +2 -2
  106. package/dashboard/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  107. package/dashboard/.next/server/app/keys.html +1 -0
  108. package/dashboard/.next/server/app/keys.meta +16 -0
  109. package/dashboard/.next/server/app/keys.rsc +25 -0
  110. package/dashboard/.next/server/app/keys.segments/!KGNvbnNvbGUp/keys/__PAGE__.segment.rsc +6 -0
  111. package/dashboard/.next/server/app/keys.segments/!KGNvbnNvbGUp/keys.segment.rsc +5 -0
  112. package/dashboard/.next/server/app/keys.segments/!KGNvbnNvbGUp.segment.rsc +6 -0
  113. package/dashboard/.next/server/app/keys.segments/_full.segment.rsc +25 -0
  114. package/dashboard/.next/server/app/keys.segments/_head.segment.rsc +6 -0
  115. package/dashboard/.next/server/app/keys.segments/_index.segment.rsc +9 -0
  116. package/dashboard/.next/server/app/keys.segments/_tree.segment.rsc +5 -0
  117. package/dashboard/.next/server/app/login/page.js.nft.json +1 -1
  118. package/dashboard/.next/server/app/login/page_client-reference-manifest.js +1 -1
  119. package/dashboard/.next/server/app/login.html +1 -1
  120. package/dashboard/.next/server/app/login.rsc +2 -2
  121. package/dashboard/.next/server/app/login.segments/_full.segment.rsc +2 -2
  122. package/dashboard/.next/server/app/login.segments/_head.segment.rsc +1 -1
  123. package/dashboard/.next/server/app/login.segments/_index.segment.rsc +2 -2
  124. package/dashboard/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  125. package/dashboard/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  126. package/dashboard/.next/server/app/login.segments/login.segment.rsc +1 -1
  127. package/dashboard/.next/server/app/providers.html +1 -1
  128. package/dashboard/.next/server/app/providers.rsc +5 -5
  129. package/dashboard/.next/server/app/providers.segments/!KGNvbnNvbGUp/providers/__PAGE__.segment.rsc +2 -2
  130. package/dashboard/.next/server/app/providers.segments/!KGNvbnNvbGUp/providers.segment.rsc +1 -1
  131. package/dashboard/.next/server/app/providers.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  132. package/dashboard/.next/server/app/providers.segments/_full.segment.rsc +5 -5
  133. package/dashboard/.next/server/app/providers.segments/_head.segment.rsc +1 -1
  134. package/dashboard/.next/server/app/providers.segments/_index.segment.rsc +2 -2
  135. package/dashboard/.next/server/app/providers.segments/_tree.segment.rsc +2 -2
  136. package/dashboard/.next/server/app/quota.html +1 -1
  137. package/dashboard/.next/server/app/quota.rsc +5 -5
  138. package/dashboard/.next/server/app/quota.segments/!KGNvbnNvbGUp/quota/__PAGE__.segment.rsc +2 -2
  139. package/dashboard/.next/server/app/quota.segments/!KGNvbnNvbGUp/quota.segment.rsc +1 -1
  140. package/dashboard/.next/server/app/quota.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  141. package/dashboard/.next/server/app/quota.segments/_full.segment.rsc +5 -5
  142. package/dashboard/.next/server/app/quota.segments/_head.segment.rsc +1 -1
  143. package/dashboard/.next/server/app/quota.segments/_index.segment.rsc +2 -2
  144. package/dashboard/.next/server/app/quota.segments/_tree.segment.rsc +2 -2
  145. package/dashboard/.next/server/app/tools.html +1 -1
  146. package/dashboard/.next/server/app/tools.rsc +5 -5
  147. package/dashboard/.next/server/app/tools.segments/!KGNvbnNvbGUp/tools/__PAGE__.segment.rsc +2 -2
  148. package/dashboard/.next/server/app/tools.segments/!KGNvbnNvbGUp/tools.segment.rsc +1 -1
  149. package/dashboard/.next/server/app/tools.segments/!KGNvbnNvbGUp.segment.rsc +3 -3
  150. package/dashboard/.next/server/app/tools.segments/_full.segment.rsc +5 -5
  151. package/dashboard/.next/server/app/tools.segments/_head.segment.rsc +1 -1
  152. package/dashboard/.next/server/app/tools.segments/_index.segment.rsc +2 -2
  153. package/dashboard/.next/server/app/tools.segments/_tree.segment.rsc +2 -2
  154. package/dashboard/.next/server/app-paths-manifest.json +1 -0
  155. package/dashboard/.next/server/chunks/[root-of-the-server]__0das32e._.js +1 -1
  156. package/dashboard/.next/server/chunks/[root-of-the-server]__0das32e._.js.map +1 -1
  157. package/dashboard/.next/server/chunks/ssr/[root-of-the-server]__006jvp_._.js +3 -0
  158. package/dashboard/.next/server/chunks/ssr/[root-of-the-server]__006jvp_._.js.map +1 -0
  159. package/dashboard/.next/server/chunks/ssr/{[root-of-the-server]__0x-617o._.js → [root-of-the-server]__1eeunp8._.js} +2 -2
  160. package/dashboard/.next/server/chunks/ssr/{[root-of-the-server]__0x-617o._.js.map → [root-of-the-server]__1eeunp8._.js.map} +1 -1
  161. package/dashboard/.next/server/chunks/ssr/{[root-of-the-server]__09pxn-h._.js → [root-of-the-server]__1t7z0yw._.js} +2 -2
  162. package/dashboard/.next/server/chunks/ssr/{[root-of-the-server]__09pxn-h._.js.map → [root-of-the-server]__1t7z0yw._.js.map} +1 -1
  163. package/dashboard/.next/server/chunks/ssr/_0p90gyy._.js +3 -0
  164. package/dashboard/.next/server/chunks/ssr/_0p90gyy._.js.map +1 -0
  165. package/dashboard/.next/server/chunks/ssr/_next-internal_server_app_(console)_keys_page_actions_1--ho2b.js +3 -0
  166. package/dashboard/.next/server/chunks/ssr/_next-internal_server_app_(console)_keys_page_actions_1--ho2b.js.map +1 -0
  167. package/dashboard/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-auga4.js +4 -0
  168. package/dashboard/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-auga4.js.map +1 -0
  169. package/dashboard/.next/server/chunks/ssr/src_13mfqac._.js +3 -0
  170. package/dashboard/.next/server/chunks/ssr/src_13mfqac._.js.map +1 -0
  171. package/dashboard/.next/server/chunks/ssr/src_16zsfd3._.js +3 -0
  172. package/dashboard/.next/server/chunks/ssr/src_16zsfd3._.js.map +1 -0
  173. package/dashboard/.next/server/chunks/ssr/src_components_0-kkrr9._.js +3 -0
  174. package/dashboard/.next/server/chunks/ssr/src_components_0-kkrr9._.js.map +1 -0
  175. package/dashboard/.next/server/chunks/ssr/src_components_0dgasfb._.js +3 -0
  176. package/dashboard/.next/server/chunks/ssr/src_components_0dgasfb._.js.map +1 -0
  177. package/dashboard/.next/server/chunks/ssr/src_components_0q5pldo._.js +3 -0
  178. package/dashboard/.next/server/chunks/ssr/src_components_0q5pldo._.js.map +1 -0
  179. package/dashboard/.next/server/chunks/ssr/src_components_10h9ide._.js +1 -1
  180. package/dashboard/.next/server/chunks/ssr/src_components_10h9ide._.js.map +1 -1
  181. package/dashboard/.next/server/chunks/ssr/src_components_11ckzq_._.js +1 -1
  182. package/dashboard/.next/server/chunks/ssr/src_components_11ckzq_._.js.map +1 -1
  183. package/dashboard/.next/server/chunks/ssr/src_components_11dtfns._.js +3 -0
  184. package/dashboard/.next/server/chunks/ssr/src_components_11dtfns._.js.map +1 -0
  185. package/dashboard/.next/server/chunks/ssr/src_components_1e6kjgr._.js +3 -0
  186. package/dashboard/.next/server/chunks/ssr/src_components_1e6kjgr._.js.map +1 -0
  187. package/dashboard/.next/server/chunks/ssr/src_components_1eg_jit._.js +3 -0
  188. package/dashboard/.next/server/chunks/ssr/src_components_1eg_jit._.js.map +1 -0
  189. package/dashboard/.next/server/chunks/ssr/src_components_1pu8z89._.js +3 -0
  190. package/dashboard/.next/server/chunks/ssr/src_components_1pu8z89._.js.map +1 -0
  191. package/dashboard/.next/server/chunks/ssr/src_components_1z4akp5._.js +3 -0
  192. package/dashboard/.next/server/chunks/ssr/src_components_1z4akp5._.js.map +1 -0
  193. package/dashboard/.next/server/chunks/ssr/src_components_KeyManager_tsx_0r7iyz8._.js +3 -0
  194. package/dashboard/.next/server/chunks/ssr/src_components_KeyManager_tsx_0r7iyz8._.js.map +1 -0
  195. package/dashboard/.next/server/chunks/ssr/src_components_ProviderManager_tsx_09d2dzw._.js +3 -0
  196. package/dashboard/.next/server/chunks/ssr/src_components_ProviderManager_tsx_09d2dzw._.js.map +1 -0
  197. package/dashboard/.next/server/chunks/ssr/src_components_ToolDetail_tsx_0qperd-._.js +1 -1
  198. package/dashboard/.next/server/chunks/ssr/src_components_ToolDetail_tsx_0qperd-._.js.map +1 -1
  199. package/dashboard/.next/server/middleware-build-manifest.js +3 -3
  200. package/dashboard/.next/server/next-font-manifest.js +1 -1
  201. package/dashboard/.next/server/next-font-manifest.json +4 -0
  202. package/dashboard/.next/server/pages/404.html +1 -1
  203. package/dashboard/.next/server/pages/500.html +1 -1
  204. package/dashboard/.next/static/chunks/0-qqj0_fg6ef0.js +1 -0
  205. package/dashboard/.next/static/chunks/0347y27liw05t.js +1 -0
  206. package/dashboard/.next/static/chunks/0iv69e64f1ywa.css +3 -0
  207. package/dashboard/.next/static/chunks/0mou1p6uwiu19.js +1 -0
  208. package/dashboard/.next/static/chunks/0pf-u__m67vld.js +1 -0
  209. package/dashboard/.next/static/chunks/0zdns9uijk264.js +1 -0
  210. package/dashboard/.next/static/chunks/19nfww990cvv7.js +1 -0
  211. package/dashboard/.next/static/chunks/1t87-rpltg53e.js +1 -0
  212. package/dashboard/.next/static/chunks/1wn1c2w4ibyg_.js +1 -0
  213. package/dashboard/.next/static/chunks/29bgf5j_v6h2z.js +1 -0
  214. package/dashboard/.next/static/chunks/2uvgdots59tjl.js +1 -0
  215. package/dashboard/.next/static/chunks/3chs_cdkdx2h9.js +1 -0
  216. package/dashboard/.next/static/chunks/3y0b8yet0vgwr.js +1 -0
  217. package/dashboard/.next/trace +1 -1
  218. package/dashboard/.next/trace-build +1 -1
  219. package/dashboard/.next/types/routes.d.ts +2 -1
  220. package/dashboard/.next/types/validator.ts +9 -0
  221. package/dashboard/package-lock.json +56 -0
  222. package/dashboard/package.json +3 -0
  223. package/dashboard/src/app/(console)/keys/page.tsx +5 -0
  224. package/dashboard/src/app/api/cli-detect/[tool]/route.ts +0 -1
  225. package/dashboard/src/app/globals.css +1 -0
  226. package/dashboard/src/components/Badge.tsx +2 -1
  227. package/dashboard/src/components/EndpointView.tsx +49 -373
  228. package/dashboard/src/components/KeyManager.tsx +252 -0
  229. package/dashboard/src/components/KeyReveal.tsx +11 -11
  230. package/dashboard/src/components/KeyScopeModal.tsx +184 -0
  231. package/dashboard/src/components/LogTable.tsx +1 -1
  232. package/dashboard/src/components/ProviderManager.tsx +136 -44
  233. package/dashboard/src/components/Rail.tsx +2 -1
  234. package/dashboard/src/components/ToolDetail.tsx +0 -1
  235. package/dashboard/src/components/TopBar.tsx +102 -28
  236. package/dashboard/src/lib/client.ts +2 -0
  237. package/dist/appDirs.js +11 -0
  238. package/dist/appDirs.js.map +1 -0
  239. package/dist/cli.js +35 -7
  240. package/dist/cli.js.map +1 -1
  241. package/dist/config.js +14 -0
  242. package/dist/config.js.map +1 -1
  243. package/dist/core/handler.js +3 -3
  244. package/dist/core/handler.js.map +1 -1
  245. package/dist/db.js +18 -11
  246. package/dist/db.js.map +1 -1
  247. package/dist/headroom/process.js +2 -1
  248. package/dist/headroom/process.js.map +1 -1
  249. package/dist/routes/admin.js +8 -1
  250. package/dist/routes/admin.js.map +1 -1
  251. package/dist/server.js +4 -4
  252. package/dist/server.js.map +1 -1
  253. package/dist/stream/anthropic-stream.js +6 -3
  254. package/dist/stream/anthropic-stream.js.map +1 -1
  255. package/package.json +1 -1
  256. package/src/appDirs.ts +12 -0
  257. package/src/cli.ts +36 -7
  258. package/src/config.ts +12 -0
  259. package/src/core/handler.ts +3 -3
  260. package/src/db.ts +27 -9
  261. package/src/headroom/process.ts +2 -1
  262. package/src/routes/admin.ts +9 -0
  263. package/src/server.ts +3 -3
  264. package/src/stream/anthropic-stream.ts +6 -3
  265. package/assets/screenshot.png +0 -0
  266. package/dashboard/.next/server/chunks/ssr/_1jt-_lv._.js +0 -3
  267. package/dashboard/.next/server/chunks/ssr/_1jt-_lv._.js.map +0 -1
  268. package/dashboard/.next/server/chunks/ssr/src_02ocd5c._.js +0 -3
  269. package/dashboard/.next/server/chunks/ssr/src_02ocd5c._.js.map +0 -1
  270. package/dashboard/.next/server/chunks/ssr/src_0az41dg._.js +0 -3
  271. package/dashboard/.next/server/chunks/ssr/src_0az41dg._.js.map +0 -1
  272. package/dashboard/.next/server/chunks/ssr/src_components_0nuo5yx._.js +0 -3
  273. package/dashboard/.next/server/chunks/ssr/src_components_0nuo5yx._.js.map +0 -1
  274. package/dashboard/.next/server/chunks/ssr/src_components_12gk6sc._.js +0 -3
  275. package/dashboard/.next/server/chunks/ssr/src_components_12gk6sc._.js.map +0 -1
  276. package/dashboard/.next/server/chunks/ssr/src_components_17nnhsa._.js +0 -3
  277. package/dashboard/.next/server/chunks/ssr/src_components_17nnhsa._.js.map +0 -1
  278. package/dashboard/.next/server/chunks/ssr/src_components_1kc5vh2._.js +0 -3
  279. package/dashboard/.next/server/chunks/ssr/src_components_1kc5vh2._.js.map +0 -1
  280. package/dashboard/.next/server/chunks/ssr/src_components_1zwow63._.js +0 -3
  281. package/dashboard/.next/server/chunks/ssr/src_components_1zwow63._.js.map +0 -1
  282. package/dashboard/.next/server/chunks/ssr/src_components_EndpointView_tsx_0awdzb5._.js +0 -3
  283. package/dashboard/.next/server/chunks/ssr/src_components_EndpointView_tsx_0awdzb5._.js.map +0 -1
  284. package/dashboard/.next/server/chunks/ssr/src_components_ModelPicker_tsx_1jisxh6._.js +0 -3
  285. package/dashboard/.next/server/chunks/ssr/src_components_ModelPicker_tsx_1jisxh6._.js.map +0 -1
  286. package/dashboard/.next/static/chunks/063d_vdu_m-g_.js +0 -1
  287. package/dashboard/.next/static/chunks/0tq5u12liycmg.js +0 -1
  288. package/dashboard/.next/static/chunks/1-r9spn081_wo.js +0 -1
  289. package/dashboard/.next/static/chunks/13824732j7-dk.js +0 -1
  290. package/dashboard/.next/static/chunks/16vbdc0g5xea0.js +0 -1
  291. package/dashboard/.next/static/chunks/22r7w355mazs8.js +0 -1
  292. package/dashboard/.next/static/chunks/2zho1fpijk0fu.js +0 -1
  293. package/dashboard/.next/static/chunks/30uw-uiehs39o.js +0 -1
  294. package/dashboard/.next/static/chunks/3mhsmb2ks1vev.js +0 -1
  295. package/dashboard/.next/static/chunks/3nrz6v06gppob.js +0 -1
  296. package/dashboard/.next/static/chunks/452cgglyyo7hp.css +0 -3
  297. /package/dashboard/.next/static/{l0QkSM6jT0jiUc4m4dh6K → WxqdtupTIrBh47rvaXxLB}/_buildManifest.js +0 -0
  298. /package/dashboard/.next/static/{l0QkSM6jT0jiUc4m4dh6K → WxqdtupTIrBh47rvaXxLB}/_clientMiddlewareManifest.js +0 -0
  299. /package/dashboard/.next/static/{l0QkSM6jT0jiUc4m4dh6K → WxqdtupTIrBh47rvaXxLB}/_ssgManifest.js +0 -0
@@ -1,3 +0,0 @@
1
- module.exports=[47444,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(93026),e=a.i(52065);a.s(["ModelPicker",0,function({title:a="Add models",note:f="Click to add, click again to remove.",searchPlaceholder:g="Search models…",groups:h,selected:i,onToggle:j,onClose:k,showThinkingHint:l=!0}){let[m,n]=(0,c.useState)(""),o=m.trim().toLowerCase(),p=h.map(a=>({...a,items:o?a.items.filter(a=>a.value.toLowerCase().includes(o)):a.items})).filter(a=>a.items.length>0),q=new Set(i);return(0,b.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/60 p-6 sm:p-10",onClick:k,children:(0,b.jsxs)("div",{className:"flex max-h-[80vh] w-full max-w-lg flex-col rounded-brand-lg border border-border bg-surface shadow-elevated",onClick:a=>a.stopPropagation(),children:[(0,b.jsxs)("div",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-3",children:[(0,b.jsx)("h2",{className:"text-[14px] font-semibold text-text",children:a}),(0,b.jsx)("button",{onClick:k,className:"text-text-subtle hover:text-text","aria-label":"Close",children:(0,b.jsx)(d.Icon,{name:"close",size:18})})]}),(0,b.jsxs)("div",{className:"border-b border-border-subtle px-4 py-3",children:[(0,b.jsx)("p",{className:"mb-2 text-[12px] text-text-muted",children:f}),(0,b.jsxs)("div",{className:"relative",children:[(0,b.jsx)(d.Icon,{name:"search",size:15,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle"}),(0,b.jsx)("input",{autoFocus:!0,value:m,onChange:a=>n(a.target.value),placeholder:g,className:"w-full rounded-brand border border-border bg-bg py-2 pl-8 pr-3 text-[13px] text-text placeholder:text-text-subtle focus:border-accent focus:outline-none"})]})]}),(0,b.jsx)("div",{className:"flex-1 overflow-y-auto px-4 py-3",children:0===p.length?(0,b.jsxs)("p",{className:"py-6 text-center text-[12.5px] text-text-subtle",children:["No models match “",m,"”."]}):(0,b.jsx)("div",{className:"space-y-4",children:p.map(a=>(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-text-subtle",children:[a.label," ",(0,b.jsxs)("span",{className:"tnum text-text-subtle/70",children:["(",a.items.length,")"]})]}),(0,b.jsx)("div",{className:"flex flex-wrap gap-1.5",children:a.items.map(a=>{let c=q.has(a.value);return(0,b.jsxs)("button",{type:"button",onClick:()=>j(a.value),className:`inline-flex items-center gap-1 rounded-brand border px-2 py-1 text-[12px] transition-colors ${c?"border-accent bg-accent-soft text-accent":"border-border bg-bg text-text-muted hover:border-text-subtle hover:text-text"}`,children:[c&&(0,b.jsx)(d.Icon,{name:"check",size:12}),(0,b.jsx)("span",{className:"tnum",children:a.label}),(0,b.jsx)(e.CapacityBadges,{model:a.value,size:13}),a.tag&&(0,b.jsx)("span",{className:"rounded bg-surface-2 px-1 text-[10px] text-text-subtle",children:a.tag})]},a.value)})})]},a.label))})}),l&&(0,b.jsxs)("div",{className:"border-t border-border-subtle px-4 py-2 text-[11px] text-text-subtle",children:[(0,b.jsx)(d.Icon,{name:"neurology",size:12,className:"mr-1 inline align-text-bottom text-warning"}),"Reasoning models accept a thinking suffix — call"," ",(0,b.jsx)("code",{className:"rounded bg-surface-2 px-1 text-text-muted",children:"model(high)"})," or"," ",(0,b.jsx)("code",{className:"rounded bg-surface-2 px-1 text-text-muted",children:"model(none)"})," (high·low·medium·minimal·auto·none·or a token budget)."]}),(0,b.jsxs)("div",{className:"flex items-center justify-between border-t border-border-subtle px-4 py-3",children:[(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-subtle",children:[i.length," selected"]}),(0,b.jsx)("button",{onClick:k,className:"rounded-brand bg-accent px-3.5 py-1.5 text-[13px] font-semibold text-accent-ink hover:bg-accent-hover",children:"Done"})]})]})})}])},70200,a=>{"use strict";let b=[{id:"claude-code",name:"Claude Code",icon:"smart_toy",format:"anthropic",blurb:"Anthropic CLI. Point its base URL + key at the gateway.",autoConfig:!0,install:"npm i -g @anthropic-ai/claude-code",slots:[{label:"Opus · heavy",alias:"claude-opus-4-1"},{label:"Sonnet · default",alias:"claude-sonnet-4-6"},{label:"Haiku · fast",alias:"claude-haiku-4-5"}],env:(a,b)=>[{name:"ANTHROPIC_BASE_URL",value:a},{name:"ANTHROPIC_API_KEY",value:b||"<your-gateway-key>"}],steps:["Export the two variables in the shell you run `claude` from.","Create a combo named like each slot above so Claude Code's model ids resolve.","The gateway translates Anthropic ↔ provider format, so any provider works behind it."]},{id:"opencode",name:"opencode",icon:"code_blocks",format:"openai",blurb:"OpenAI-compatible provider. Set base_url to /v1.",autoConfig:!0,install:"curl -fsSL https://opencode.ai/install | bash",slots:[{label:"Model",alias:"gpt-5"}],env:(a,b)=>[{name:"OPENAI_BASE_URL",value:`${a}/v1`},{name:"OPENAI_API_KEY",value:b||"<your-gateway-key>"}],steps:["Add an OpenAI-compatible provider with the gateway /v1 base URL.","Pick a combo alias as the model."]}];a.s(["CLI_TOOLS",0,b,"toolById",0,function(a){return b.find(b=>b.id===a)}])}];
2
-
3
- //# sourceMappingURL=src_0az41dg._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/ModelPicker.tsx","../../../../src/lib/cliTools.ts"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Icon } from \"@/components/Icon\";\nimport { CapacityBadges } from \"@/components/CapacityBadges\";\n\nexport interface ModelGroup {\n label: string;\n items: { value: string; label: string; tag?: string }[];\n}\n\n/**\n * aigetwey-style model picker: a search box + provider-grouped chips you click to\n * toggle in/out of a selection. Used by the combo form and the CLI-tool model\n * selection so both add models the same way (click to add, click again to drop).\n */\nexport function ModelPicker({\n title = \"Add models\",\n note = \"Click to add, click again to remove.\",\n searchPlaceholder = \"Search models…\",\n groups,\n selected,\n onToggle,\n onClose,\n showThinkingHint = true,\n}: {\n title?: string;\n note?: string;\n searchPlaceholder?: string;\n groups: ModelGroup[];\n selected: string[];\n onToggle: (value: string) => void;\n onClose: () => void;\n /** The \"reasoning models accept a thinking suffix\" footer only makes sense when\n * picking MODELS. Provider/key pickers reuse this component, so they hide it. */\n showThinkingHint?: boolean;\n}) {\n const [q, setQ] = useState(\"\");\n const needle = q.trim().toLowerCase();\n const filtered = groups\n .map((g) => ({\n ...g,\n items: needle ? g.items.filter((i) => i.value.toLowerCase().includes(needle)) : g.items,\n }))\n .filter((g) => g.items.length > 0);\n const sel = new Set(selected);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/60 p-6 sm:p-10\" onClick={onClose}>\n <div\n className=\"flex max-h-[80vh] w-full max-w-lg flex-col rounded-brand-lg border border-border bg-surface shadow-elevated\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-border-subtle px-4 py-3\">\n <h2 className=\"text-[14px] font-semibold text-text\">{title}</h2>\n <button onClick={onClose} className=\"text-text-subtle hover:text-text\" aria-label=\"Close\">\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n\n <div className=\"border-b border-border-subtle px-4 py-3\">\n <p className=\"mb-2 text-[12px] text-text-muted\">{note}</p>\n <div className=\"relative\">\n <Icon name=\"search\" size={15} className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle\" />\n <input\n autoFocus\n value={q}\n onChange={(e) => setQ(e.target.value)}\n placeholder={searchPlaceholder}\n className=\"w-full rounded-brand border border-border bg-bg py-2 pl-8 pr-3 text-[13px] text-text placeholder:text-text-subtle focus:border-accent focus:outline-none\"\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-3\">\n {filtered.length === 0 ? (\n <p className=\"py-6 text-center text-[12.5px] text-text-subtle\">No models match “{q}”.</p>\n ) : (\n <div className=\"space-y-4\">\n {filtered.map((g) => (\n <div key={g.label}>\n <div className=\"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-text-subtle\">\n {g.label} <span className=\"tnum text-text-subtle/70\">({g.items.length})</span>\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {g.items.map((it) => {\n const on = sel.has(it.value);\n return (\n <button\n key={it.value}\n type=\"button\"\n onClick={() => onToggle(it.value)}\n className={`inline-flex items-center gap-1 rounded-brand border px-2 py-1 text-[12px] transition-colors ${\n on ? \"border-accent bg-accent-soft text-accent\" : \"border-border bg-bg text-text-muted hover:border-text-subtle hover:text-text\"\n }`}\n >\n {on && <Icon name=\"check\" size={12} />}\n <span className=\"tnum\">{it.label}</span>\n <CapacityBadges model={it.value} size={13} />\n {it.tag && <span className=\"rounded bg-surface-2 px-1 text-[10px] text-text-subtle\">{it.tag}</span>}\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {showThinkingHint && (\n <div className=\"border-t border-border-subtle px-4 py-2 text-[11px] text-text-subtle\">\n <Icon name=\"neurology\" size={12} className=\"mr-1 inline align-text-bottom text-warning\" />\n Reasoning models accept a thinking suffix — call{\" \"}\n <code className=\"rounded bg-surface-2 px-1 text-text-muted\">model(high)</code> or{\" \"}\n <code className=\"rounded bg-surface-2 px-1 text-text-muted\">model(none)</code> (high·low·medium·minimal·auto·none·or a token budget).\n </div>\n )}\n\n <div className=\"flex items-center justify-between border-t border-border-subtle px-4 py-3\">\n <span className=\"tnum text-[12px] text-text-subtle\">{selected.length} selected</span>\n <button onClick={onClose} className=\"rounded-brand bg-accent px-3.5 py-1.5 text-[13px] font-semibold text-accent-ink hover:bg-accent-hover\">\n Done\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * CLI tool setup definitions. Each tool talks to the gateway in either OpenAI or\n * Anthropic wire format; the gateway exposes both on the same port, so setup is\n * just pointing the tool's base_url + key at us. `env` builders take the live\n * gateway base URL + a gateway key and return ready-to-copy environment lines.\n *\n * `slots` are the model names this tool calls. Because our gateway routes by the\n * combo alias (the alias IS the model name), the detail page checks whether a\n * combo with each slot's alias exists, and prompts to create the missing ones.\n */\nexport type ToolFormat = \"openai\" | \"anthropic\";\n\nexport interface CliTool {\n id: string;\n name: string;\n /** Material Symbols ligature shown on the tool card + detail header. */\n icon: string;\n format: ToolFormat;\n blurb: string;\n /** true when the dashboard can detect + write this tool's local config file. */\n autoConfig?: boolean;\n /** one-line install command, when the tool ships via a package manager. */\n install?: string;\n /** model names the tool sends — pair each with a combo of the same name. */\n slots: { label: string; alias: string }[];\n /** environment variables to set, given the gateway base + a key. */\n env: (base: string, key: string) => Array<{ name: string; value: string }>;\n /** extra free-form steps shown on the detail page. */\n steps: string[];\n}\n\nconst KEY = (k: string) => k || \"<your-gateway-key>\";\n\nexport const CLI_TOOLS: CliTool[] = [\n {\n id: \"claude-code\",\n name: \"Claude Code\",\n icon: \"smart_toy\",\n format: \"anthropic\",\n blurb: \"Anthropic CLI. Point its base URL + key at the gateway.\",\n autoConfig: true,\n install: \"npm i -g @anthropic-ai/claude-code\",\n slots: [\n { label: \"Opus · heavy\", alias: \"claude-opus-4-1\" },\n { label: \"Sonnet · default\", alias: \"claude-sonnet-4-6\" },\n { label: \"Haiku · fast\", alias: \"claude-haiku-4-5\" },\n ],\n env: (base, key) => [\n { name: \"ANTHROPIC_BASE_URL\", value: base },\n { name: \"ANTHROPIC_API_KEY\", value: KEY(key) },\n ],\n steps: [\n \"Export the two variables in the shell you run `claude` from.\",\n \"Create a combo named like each slot above so Claude Code's model ids resolve.\",\n \"The gateway translates Anthropic ↔ provider format, so any provider works behind it.\",\n ],\n },\n {\n id: \"opencode\",\n name: \"opencode\",\n icon: \"code_blocks\",\n format: \"openai\",\n blurb: \"OpenAI-compatible provider. Set base_url to /v1.\",\n autoConfig: true,\n install: \"curl -fsSL https://opencode.ai/install | bash\",\n slots: [{ label: \"Model\", alias: \"gpt-5\" }],\n env: (base, key) => [\n { name: \"OPENAI_BASE_URL\", value: `${base}/v1` },\n { name: \"OPENAI_API_KEY\", value: KEY(key) },\n ],\n steps: [\"Add an OpenAI-compatible provider with the gateway /v1 base URL.\", \"Pick a combo alias as the model.\"],\n },\n];\n\nexport function toolById(id: string): CliTool | undefined {\n return CLI_TOOLS.find((t) => t.id === id);\n}\n"],"names":["ModelPicker","title","note","searchPlaceholder","groups","selected","onToggle","onClose","showThinkingHint","q","setQ","needle","trim","toLowerCase","filtered","map","g","items","filter","i","value","includes","length","sel","Set","className","onClick","e","stopPropagation","name","size","autoFocus","onChange","target","placeholder","label","it","on","has","type","model","tag","KEY","k","CLI_TOOLS","id","icon","format","blurb","autoConfig","install","slots","alias","env","base","key","steps","toolById","find","t"],"mappings":"wDAEA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,OACA,EAAA,EAAA,CAAA,CAAA,4BAYO,SAASA,AAAY,OAC1BC,EAAQ,YAAY,MACpBC,EAAO,sCAAsC,mBAC7CC,EAAoB,gBAAgB,QACpCC,CAAM,UACNC,CAAQ,UACRC,CAAQ,CACRC,SAAO,kBACPC,GAAmB,CAAI,CAYxB,EACC,GAAM,CAACC,EAAGC,EAAK,CAAG,CAAA,EAAA,EAAA,QAAA,AAAQ,EAAC,IACrBC,EAASF,EAAEG,IAAI,GAAGC,WAAW,GAC7BC,EAAWV,EACdW,GAAG,CAAC,AAACC,GAAO,CAAD,CACV,GAAGA,CAAC,CACJC,MAAON,EAASK,EAAEC,KAAK,CAACC,MAAM,CAAC,AAACC,GAAMA,EAAEC,KAAK,CAACP,WAAW,GAAGQ,QAAQ,CAACV,IAAWK,EAAEC,KAAK,CACzF,CAAC,EACAC,MAAM,CAAC,AAACF,GAAMA,EAAEC,KAAK,CAACK,MAAM,CAAG,GAC5BC,EAAM,IAAIC,IAAInB,GAEpB,MACE,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAIoB,UAAU,6FAA6FC,QAASnB,WACnH,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CACCkB,UAAU,8GACVC,QAAS,AAACC,GAAMA,EAAEC,eAAe,aAEjC,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAIH,UAAU,sFACb,CAAA,EAAA,EAAA,GAAA,EAAC,KAAA,CAAGA,UAAU,+CAAuCxB,IACrD,CAAA,EAAA,EAAA,GAAA,EAAC,SAAA,CAAOyB,QAASnB,EAASkB,UAAU,mCAAmC,aAAW,iBAChF,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,IAAI,CAAA,CAACI,KAAK,QAAQC,KAAM,UAI7B,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAIL,UAAU,oDACb,CAAA,EAAA,EAAA,GAAA,EAAC,IAAA,CAAEA,UAAU,4CAAoCvB,IACjD,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAIuB,UAAU,qBACb,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,IAAI,CAAA,CAACI,KAAK,SAASC,KAAM,GAAIL,UAAU,oFACxC,CAAA,EAAA,EAAA,GAAA,EAAC,QAAA,CACCM,SAAS,CAAA,CAAA,EACTX,MAAOX,EACPuB,SAAU,AAACL,GAAMjB,EAAKiB,EAAEM,MAAM,CAACb,KAAK,EACpCc,YAAa/B,EACbsB,UAAU,mKAKhB,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAIA,UAAU,4CACQ,AAApBX,MAASQ,MAAM,CACd,CAAA,EAAA,EAAA,IAAA,EAAC,IAAA,CAAEG,UAAU,4DAAkD,oBAAkBhB,EAAE,QAEnF,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAIgB,UAAU,qBACZX,EAASC,GAAG,CAAC,AAACC,GACb,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,WACC,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAIS,UAAU,iHACZT,EAAEmB,KAAK,CAAC,IAAC,CAAA,EAAA,EAAA,IAAA,EAAC,OAAA,CAAKV,UAAU,qCAA2B,IAAET,EAAEC,KAAK,CAACK,MAAM,CAAC,UAExE,CAAA,EAAA,EAAA,GAAA,EAAC,MAAA,CAAIG,UAAU,kCACZT,EAAEC,KAAK,CAACF,GAAG,CAAC,AAACqB,IACZ,IAAMC,EAAKd,EAAIe,GAAG,CAACF,EAAGhB,KAAK,EAC3B,MACE,CAAA,EAAA,EAAA,IAAA,EAAC,SAAA,CAECmB,KAAK,SACLb,QAAS,IAAMpB,EAAS8B,EAAGhB,KAAK,EAChCK,UAAW,CAAC,4FAA4F,EACtGY,EAAK,2CAA6C,+EAAA,CAClD,WAEDA,GAAM,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,IAAI,CAAA,CAACR,KAAK,QAAQC,KAAM,KAChC,CAAA,EAAA,EAAA,GAAA,EAAC,OAAA,CAAKL,UAAU,gBAAQW,EAAGD,KAAK,GAChC,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,cAAc,CAAA,CAACK,MAAOJ,EAAGhB,KAAK,CAAEU,KAAM,KACtCM,EAAGK,GAAG,EAAI,CAAA,EAAA,EAAA,GAAA,EAAC,OAAA,CAAKhB,UAAU,kEAA0DW,EAAGK,GAAG,KAVtFL,EAAGhB,KAAK,CAanB,OAtBMJ,EAAEmB,KAAK,OA8BxB3B,GACC,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAIiB,UAAU,iFACb,CAAA,EAAA,EAAA,GAAA,EAAC,EAAA,IAAI,CAAA,CAACI,KAAK,YAAYC,KAAM,GAAIL,UAAU,+CAA+C,mDACzC,IACjD,CAAA,EAAA,EAAA,GAAA,EAAC,OAAA,CAAKA,UAAU,qDAA4C,gBAAkB,MAAI,IAClF,CAAA,EAAA,EAAA,GAAA,EAAC,OAAA,CAAKA,UAAU,qDAA4C,gBAAkB,6DAIlF,CAAA,EAAA,EAAA,IAAA,EAAC,MAAA,CAAIA,UAAU,sFACb,CAAA,EAAA,EAAA,IAAA,EAAC,OAAA,CAAKA,UAAU,8CAAqCpB,EAASiB,MAAM,CAAC,eACrE,CAAA,EAAA,EAAA,GAAA,EAAC,SAAA,CAAOI,QAASnB,EAASkB,UAAU,iHAAwG,gBAOtJ,4BC/FO,IAAMmB,EAAuB,CAClC,CACEC,GAAI,cACJhB,KAAM,cACNiB,KAAM,YACNC,OAAQ,YACRC,MAAO,0DACPC,YAAY,EACZC,QAAS,qCACTC,MAAO,CACL,CAAEhB,MAAO,eAAgBiB,MAAO,iBAAkB,EAClD,CAAEjB,MAAO,mBAAoBiB,MAAO,mBAAoB,EACxD,CAAEjB,MAAO,eAAgBiB,MAAO,kBAAmB,EACpD,CACDC,IAAK,CAACC,EAAMC,IAAQ,CAClB,CAAE1B,KAAM,qBAAsBT,MAAOkC,CAAK,EAC1C,CAAEzB,KAAM,oBAAqBT,MAAWmC,CAAJb,sBAAS,EAC9C,CACDc,MAAO,CACL,+DACA,gFACA,uFACD,AACH,EACA,CACEX,GAAI,WACJhB,KAAM,WACNiB,KAAM,cACNC,OAAQ,SACRC,MAAO,mDACPC,YAAY,EACZC,QAAS,gDACTC,MAAO,CAAC,CAAEhB,MAAO,QAASiB,MAAO,OAAQ,EAAE,CAC3CC,IAAK,CAACC,EAAMC,IAAQ,CAClB,CAAE1B,KAAM,kBAAmBT,MAAO,CAAA,EAAGkC,EAAK,GAAG,CAAC,AAAC,EAC/C,CAAEzB,KAAM,iBAAkBT,MArCLuB,AAqCgBY,CAAJb,EArCP,oBAqCgB,EAC3C,CACDc,MAAO,CAAC,mEAAoE,mCAAmC,AACjH,EACD,mCAEM,SAASC,AAASZ,CAAU,EACjC,OAAOD,EAAUc,IAAI,CAAC,AAACC,GAAMA,EAAEd,EAAE,GAAKA,EACxC"}
@@ -1,3 +0,0 @@
1
- module.exports=[2693,a=>{"use strict";var b=a.i(87924);let c={live:"bg-success/12 text-success",down:"bg-danger/12 text-danger",warn:"bg-warning/12 text-warning",info:"bg-info/12 text-info",neutral:"bg-surface-2 text-text-muted"};function d({tone:a="neutral",children:e,className:f}){return(0,b.jsx)("span",{className:`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${c[a]}${f?` ${f}`:""}`,children:e})}a.s(["Badge",0,d,"FormatBadge",0,function({format:a}){return(0,b.jsx)(d,{tone:"info",children:a})}])},58918,a=>{"use strict";var b=a.i(87924);a.s(["Empty",0,function({children:a}){return(0,b.jsx)("div",{className:"px-1 py-8 text-center text-[13px] text-text-muted",children:a})},"Stat",0,function({label:a,value:c,sub:d}){return(0,b.jsxs)("div",{className:"rounded-brand-lg border border-border bg-surface px-4 py-3.5 shadow-soft",children:[(0,b.jsx)("div",{className:"text-[11px] font-medium uppercase tracking-wider text-text-subtle",children:a}),(0,b.jsx)("div",{className:"mt-1 tnum text-[22px] font-semibold tracking-tight text-text",children:c}),d&&(0,b.jsx)("div",{className:"mt-0.5 text-[12px] text-text-muted",children:d})]})},"fmt",0,{int:a=>a.toLocaleString("en-US"),compact:a=>Math.abs(a)>=1e6?`${(a/1e6).toFixed(1)}M`:Math.abs(a)>=1e3?`${(a/1e3).toFixed(1)}K`:String(Math.round(a)),cost:a=>0===a?"$0":a<.01?`$${a.toFixed(4)}`:`$${a.toFixed(2)}`,time:a=>new Date(a).toLocaleString("en-US",{hour12:!1}),date(a){let b=new Date(a);return`${String(b.getDate()).padStart(2,"0")}/${String(b.getMonth()+1).padStart(2,"0")}/${b.getFullYear()}`},ago(a){let b=Math.max(0,Math.round((Date.now()-a)/1e3));return b<60?`${b}s`:b<3600?`${Math.floor(b/60)}m`:b<86400?`${Math.floor(b/3600)}h`:`${Math.floor(b/86400)}d`},duration(a){let b=Math.max(0,Math.round(a/1e3));if(b<60)return`${b}s`;if(b<3600)return`${Math.floor(b/60)}m ${b%60}s`;let c=Math.floor(b/3600),d=Math.floor(b%3600/60);if(c<24)return`${c}h ${d}m`;let e=Math.floor(c/24);return`${e}d ${c%24}h`}}])},47153,a=>{"use strict";var b=a.i(87924);a.s(["Lamp",0,function({state:a,title:c}){return(0,b.jsx)("span",{className:`lamp lamp-${a}`,title:c,"aria-label":a})}])},2799,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(93026),e=a.i(58918);a.s(["CooldownTimer",0,function({ms:a,tone:f="danger",icon:g="timer",keepZero:h=!1}){let[i]=(0,c.useState)(()=>Date.now()+a),[j,k]=(0,c.useState)(()=>Math.max(0,a));return((0,c.useEffect)(()=>{let a=()=>k(Math.max(0,i-Date.now()));a();let b=setInterval(a,1e3);return()=>clearInterval(b)},[i]),j<=0&&!h)?null:(0,b.jsxs)("span",{className:`inline-flex items-center gap-1 tnum text-[12px] ${"danger"===f?"text-danger":"text-text-muted"}`,children:[(0,b.jsx)(d.Icon,{name:g,size:13}),j<=0?"now":e.fmt.duration(j)]})}])},62293,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(38246),e=a.i(56173),f=a.i(47153),g=a.i(2693),h=a.i(2799),i=a.i(7078),j=a.i(93026),k=a.i(58918);function l({id:a,disabled:d,onDone:f}){let[g,h]=(0,c.useState)(!1);return(0,b.jsxs)("button",{type:"button",onClick:b=>{b.preventDefault(),b.stopPropagation(),g||(h(!0),e.adminApi.setProviderDisabled(a,!d).then(()=>f()).finally(()=>h(!1)))},className:`inline-flex items-center gap-1.5 text-[11px] font-medium ${d?"text-danger":"text-text-muted"}`,"aria-label":d?"Enable provider":"Disable provider",title:d?"Provider disabled — click to enable":"Provider enabled — click to disable",children:[(0,b.jsx)("span",{className:`relative h-4 w-7 rounded-full transition-colors ${d?"bg-danger":"bg-accent"} ${g?"opacity-60":""}`,children:(0,b.jsx)("span",{className:`absolute left-0.5 top-0.5 h-3 w-3 rounded-full bg-white transition-transform ${d?"translate-x-0":"translate-x-[14px]"}`})}),d?"disabled":"enabled"]})}let m=[{id:"openai",label:"OpenAI compatible",sub:"/v1/chat/completions",icon:"bolt",format:"openai",base_url:"https://api.openai.com/v1",hint:"Base URL ending in /v1 for any OpenAI-compatible API.",modelHint:"e.g. gpt-4o, glm-5.2"},{id:"anthropic",label:"Anthropic compatible",sub:"/v1/messages",icon:"smart_toy",format:"anthropic",base_url:"https://api.anthropic.com",hint:"Base URL of an Anthropic-compatible API; /messages is appended.",modelHint:"e.g. claude-sonnet-4-6"}];function n({onDone:a,onClose:d}){let[f,h]=(0,c.useState)(null),[k,l]=(0,c.useState)(""),[o,p]=(0,c.useState)(""),[q,r]=(0,c.useState)(""),[s,t]=(0,c.useState)(!1),[u,v]=(0,c.useState)(""),[w,x]=(0,c.useState)(!1),[y,z]=(0,c.useState)(!1),[A,B]=(0,c.useState)(null),[C,D]=(0,c.useState)("");if(!f)return(0,b.jsxs)("div",{className:"mb-5 rounded-brand-lg border border-border bg-surface p-5 shadow-soft",children:[(0,b.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h2",{className:"text-[14px] font-semibold text-text",children:"Add a provider"}),(0,b.jsx)("p",{className:"mt-0.5 text-[12.5px] text-text-muted",children:"Pick the API your endpoint speaks — the rest is prefilled."})]}),(0,b.jsx)("button",{type:"button",onClick:d,className:"flex-none text-text-subtle hover:text-text","aria-label":"Cancel",children:(0,b.jsx)(j.Icon,{name:"close",size:18})})]}),(0,b.jsx)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:m.map(a=>(0,b.jsxs)("button",{type:"button",onClick:()=>{h(a),p(a.base_url),B(null),D("")},className:"group flex items-start gap-3 rounded-brand-lg border border-border bg-bg p-4 text-left transition-colors hover:border-accent hover:bg-accent-soft",children:[(0,b.jsx)("span",{className:"flex h-10 w-10 flex-none items-center justify-center rounded-brand bg-surface-2 text-text-muted group-hover:text-accent",children:(0,b.jsx)(j.Icon,{name:a.icon,size:20})}),(0,b.jsxs)("span",{className:"min-w-0",children:[(0,b.jsx)("span",{className:"block text-[13.5px] font-semibold text-text",children:a.label}),(0,b.jsx)("span",{className:"block tnum text-[11.5px] text-text-subtle",children:a.sub}),(0,b.jsx)("span",{className:"mt-1 block text-[11.5px] text-text-muted",children:a.hint})]})]},a.id))})]});async function E(){if(!o||!f)return;z(!0),B(null);let a=await e.adminApi.validateProvider({format:f.format,base_url:o,api_key:q||void 0});z(!1),B(a.data??{ok:!1,reachable:!1,status:0,error:a.error})}async function F(b){if(b.preventDefault(),!f||!k||!o)return void D("name and base URL are required");x(!0),D("");let c=await e.adminApi.addProvider({id:k,format:f.format,base_url:o,api_key:q||void 0,free:!q.trim()});if(!c.ok){x(!1),D(c.error??"failed");return}u.trim()&&await e.adminApi.addModel(k,u.trim()),x(!1),a()}return(0,b.jsx)("div",{className:"mb-5 rounded-brand-lg border border-border bg-surface p-5 shadow-soft",children:(0,b.jsxs)("form",{onSubmit:F,children:[(0,b.jsxs)("div",{className:"mb-4 flex items-center gap-2.5 border-b border-border-subtle pb-4",children:[(0,b.jsx)("span",{className:"flex h-8 w-8 items-center justify-center rounded-brand bg-surface-2 text-text-muted",children:(0,b.jsx)(j.Icon,{name:f.icon,size:17})}),(0,b.jsxs)("div",{children:[(0,b.jsx)("div",{className:"text-[13.5px] font-semibold text-text",children:f.label}),(0,b.jsx)("div",{className:"tnum text-[11px] text-text-subtle",children:f.sub})]}),(0,b.jsxs)("button",{type:"button",onClick:()=>{h(null),B(null)},className:"ml-auto inline-flex items-center gap-1 text-[12px] text-text-subtle hover:text-text",children:[(0,b.jsx)(j.Icon,{name:"arrow_back",size:14})," change type"]})]}),(0,b.jsxs)("div",{className:"space-y-3",children:[(0,b.jsx)(i.Field,{label:"Name",hint:"a friendly id — also the model prefix (name/model)",children:(0,b.jsx)(i.Input,{value:k,onChange:a=>l(a.target.value),placeholder:"e.g. openai, anthropic"})}),(0,b.jsx)(i.Field,{label:"Base URL",hint:f.hint,children:(0,b.jsx)(i.Input,{value:o,onChange:a=>{p(a.target.value),B(null)},placeholder:f.base_url,className:"font-mono text-[12.5px]"})}),(0,b.jsx)(i.Field,{label:"API Key",hint:"used for Check and live requests — leave blank for a free / no-auth endpoint",children:(0,b.jsxs)("div",{className:"flex gap-2",children:[(0,b.jsxs)("div",{className:"relative flex-1",children:[(0,b.jsx)(i.Input,{type:s?"text":"password",value:q,onChange:a=>{r(a.target.value),B(null)},placeholder:"sk-…",className:"pr-9 font-mono text-[12.5px]"}),q&&(0,b.jsx)("button",{type:"button",onClick:()=>t(a=>!a),className:"absolute right-2 top-1/2 -translate-y-1/2 text-text-subtle hover:text-text","aria-label":s?"Hide key":"Show key",children:(0,b.jsx)(j.Icon,{name:s?"visibility_off":"visibility",size:15})})]}),(0,b.jsxs)(i.Button,{type:"button",variant:"ghost",disabled:y||!o,onClick:E,children:[(0,b.jsx)(j.Icon,{name:y?"progress_activity":"wifi_tethering",size:15}),y?"Checking…":"Check"]})]})}),A&&(0,b.jsxs)("div",{className:"flex items-center gap-2 text-[12px]",children:[(0,b.jsx)(g.Badge,{tone:A.ok?"live":A.reachable?"warn":"down",children:A.ok?"valid":A.reachable?`reachable (${A.status})`:"invalid"}),A.error&&(0,b.jsx)("span",{className:"text-text-subtle",children:A.error})]}),(0,b.jsx)(i.Field,{label:"Model ID",hint:"optional — seed one if the provider has no /models endpoint",children:(0,b.jsx)(i.Input,{value:u,onChange:a=>v(a.target.value),placeholder:f.modelHint,className:"font-mono text-[12.5px]"})})]}),C&&(0,b.jsx)("div",{className:"mt-2 text-[12px] text-danger",children:C}),(0,b.jsxs)("div",{className:"mt-4 flex justify-end gap-2",children:[(0,b.jsx)(i.Button,{type:"button",variant:"ghost",onClick:d,children:"Cancel"}),(0,b.jsx)(i.Button,{type:"submit",disabled:w,children:w?"Adding…":"Add provider"})]})]})})}a.s(["ProviderManager",0,function(){let[a,m]=(0,c.useState)(null),[o,p]=(0,c.useState)(""),[q,r]=(0,c.useState)(!1),s=(0,c.useCallback)(async()=>{let[a,b]=await Promise.all([fetch("/api/gw/admin/config"),e.adminApi.providers()]);a.ok&&b.ok?(p(""),m({config:await a.json(),health:b.data?.providers??[]})):p("could not reach the gateway")},[]);if((0,c.useEffect)(()=>{s()},[s]),o)return(0,b.jsx)(k.Empty,{children:o});if(!a)return(0,b.jsx)(k.Empty,{children:"Loading…"});let t=new Map(a.health.map(a=>[a.id,a]));return(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-6 flex items-center justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-[22px] font-semibold tracking-tight text-text",children:"Providers & Keys"}),(0,b.jsx)("p",{className:"mt-1 text-[13px] text-text-muted",children:"Upstream providers the gateway routes to."})]}),(0,b.jsxs)(i.Button,{onClick:()=>r(!0),children:[(0,b.jsx)(j.Icon,{name:"add",size:17}),"Add provider"]})]}),q&&(0,b.jsx)(n,{onClose:()=>r(!1),onDone:()=>{r(!1),s()}}),0===a.config.providers.length?(0,b.jsx)(k.Empty,{children:"No providers yet. Add one to start routing."}):(0,b.jsx)("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:a.config.providers.map(a=>{let c=t.get(a.id),e=!c||c.keys.some(a=>a.healthy),i=c?.keys.find(a=>!a.healthy&&a.cooldown_ms>0);return(0,b.jsxs)(d.default,{href:`/providers/${encodeURIComponent(a.id)}`,className:`group rounded-brand-lg border bg-surface p-4 shadow-soft transition-colors ${a.disabled?"border-danger/35 opacity-60 hover:opacity-100 hover:border-danger/60":"border-border hover:border-text-subtle"}`,children:[(0,b.jsxs)("div",{className:"flex items-start justify-between gap-2",children:[(0,b.jsxs)("div",{className:"flex items-center gap-2 min-w-0",children:[(0,b.jsx)(f.Lamp,{state:a.disabled?"idle":e?"live":"down"}),(0,b.jsxs)("div",{className:"min-w-0",children:[(0,b.jsx)("span",{className:"block truncate text-[14px] font-semibold text-text",children:a.name||a.id}),a.name&&(0,b.jsxs)("span",{className:"block truncate text-[11px] text-text-subtle",children:[a.id,"/"]})]})]}),(0,b.jsx)(g.FormatBadge,{format:a.format})]}),(0,b.jsx)("div",{className:"mt-2 truncate text-[12px] text-text-subtle",children:a.base_url}),(0,b.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[(0,b.jsx)(l,{id:a.id,disabled:!!a.disabled,onDone:s}),a.free&&(0,b.jsx)(g.Badge,{tone:"info",children:"free"}),a.service_account&&(0,b.jsx)(g.Badge,{tone:"info",children:"service-account"}),(0,b.jsx)(g.Badge,{tone:"neutral",children:a.free||a.service_account?`${a.api_keys?.length??0} keys`:`${a.api_keys?.length??+!!a.api_key} keys`}),(0,b.jsxs)(g.Badge,{tone:"neutral",children:[a.models.length," models"]}),i&&(0,b.jsx)(h.CooldownTimer,{ms:i.cooldown_ms})]})]},a.id)})})]})}])}];
2
-
3
- //# sourceMappingURL=src_components_0nuo5yx._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/Badge.tsx","../../../../src/components/ui.tsx","../../../../src/components/Lamp.tsx","../../../../src/components/CooldownTimer.tsx","../../../../src/components/ProviderManager.tsx"],"sourcesContent":["type Tone = \"live\" | \"down\" | \"warn\" | \"info\" | \"neutral\";\n\nconst TONES: Record<Tone, string> = {\n live: \"bg-success/12 text-success\",\n down: \"bg-danger/12 text-danger\",\n warn: \"bg-warning/12 text-warning\",\n info: \"bg-info/12 text-info\",\n neutral: \"bg-surface-2 text-text-muted\",\n};\n\nexport function Badge({\n tone = \"neutral\",\n children,\n className,\n}: {\n tone?: Tone;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${TONES[tone]}${className ? ` ${className}` : \"\"}`}\n >\n {children}\n </span>\n );\n}\n\n/** Format badge for a provider's wire format. */\nexport function FormatBadge({ format }: { format: \"openai\" | \"anthropic\" | \"gemini\" }) {\n return <Badge tone=\"info\">{format}</Badge>;\n}\n","/** Small formatting helpers shared across the console. */\nexport const fmt = {\n int(n: number): string {\n return n.toLocaleString(\"en-US\");\n },\n /** compact number: 1.2K, 3.4M */\n compact(n: number): string {\n if (Math.abs(n) >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (Math.abs(n) >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return String(Math.round(n));\n },\n cost(n: number): string {\n if (n === 0) return \"$0\";\n return n < 0.01 ? `$${n.toFixed(4)}` : `$${n.toFixed(2)}`;\n },\n time(ts: number): string {\n return new Date(ts).toLocaleString(\"en-US\", { hour12: false });\n },\n /** DD/MM/YYYY (local) */\n date(ts: number): string {\n const d = new Date(ts);\n return `${String(d.getDate()).padStart(2, \"0\")}/${String(d.getMonth() + 1).padStart(2, \"0\")}/${d.getFullYear()}`;\n },\n /** \"3m\", \"2h\", \"5d\" — coarse relative age */\n ago(ts: number): string {\n const s = Math.max(0, Math.round((Date.now() - ts) / 1000));\n if (s < 60) return `${s}s`;\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n },\n /** ms duration -> \"Xs\", \"Xm Ys\", \"Xh Ym\" for budget/cooldown countdowns */\n duration(ms: number): string {\n const s = Math.max(0, Math.round(ms / 1000));\n if (s < 60) return `${s}s`;\n if (s < 3600) return `${Math.floor(s / 60)}m ${s % 60}s`;\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n if (h < 24) return `${h}h ${m}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n },\n};\n\n/** A labelled stat block — number over a caption. */\nexport function Stat({ label, value, sub }: { label: string; value: React.ReactNode; sub?: string }) {\n return (\n <div className=\"rounded-brand-lg border border-border bg-surface px-4 py-3.5 shadow-soft\">\n <div className=\"text-[11px] font-medium uppercase tracking-wider text-text-subtle\">{label}</div>\n <div className=\"mt-1 tnum text-[22px] font-semibold tracking-tight text-text\">{value}</div>\n {sub && <div className=\"mt-0.5 text-[12px] text-text-muted\">{sub}</div>}\n </div>\n );\n}\n\n/** Empty-state hint inside a card body. */\nexport function Empty({ children }: { children: React.ReactNode }) {\n return <div className=\"px-1 py-8 text-center text-[13px] text-text-muted\">{children}</div>;\n}\n","/** Status lamp — green when serving, red pulse on cooldown, grey when idle. */\nexport function Lamp({ state, title }: { state: \"live\" | \"idle\" | \"down\"; title?: string }) {\n return <span className={`lamp lamp-${state}`} title={title} aria-label={state} />;\n}\n\nexport function lampFor(healthy: boolean): \"live\" | \"down\" {\n return healthy ? \"live\" : \"down\";\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Icon } from \"./Icon\";\nimport { fmt } from \"./ui\";\n\n/**\n * Live countdown from a gateway-snapshot remaining-ms. Counts down locally each\n * second from render. Used for both key cooldowns (danger tone) and budget window\n * resets (muted tone). Renders nothing once it hits zero unless `keepZero`.\n */\nexport function CooldownTimer({\n ms,\n tone = \"danger\",\n icon = \"timer\",\n keepZero = false,\n}: {\n ms: number;\n tone?: \"danger\" | \"muted\";\n icon?: string;\n keepZero?: boolean;\n}) {\n const [until] = useState(() => Date.now() + ms);\n const [remaining, setRemaining] = useState(() => Math.max(0, ms));\n\n useEffect(() => {\n const tick = () => setRemaining(Math.max(0, until - Date.now()));\n tick();\n const id = setInterval(tick, 1000);\n return () => clearInterval(id);\n }, [until]);\n\n if (remaining <= 0 && !keepZero) return null;\n\n const color = tone === \"danger\" ? \"text-danger\" : \"text-text-muted\";\n return (\n <span className={`inline-flex items-center gap-1 tnum text-[12px] ${color}`}>\n <Icon name={icon} size={13} />\n {remaining <= 0 ? \"now\" : fmt.duration(remaining)}\n </span>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState, useCallback } from \"react\";\nimport Link from \"next/link\";\nimport { adminApi } from \"@/lib/client\";\nimport { Lamp } from \"@/components/Lamp\";\nimport { Badge, FormatBadge } from \"@/components/Badge\";\nimport { CooldownTimer } from \"@/components/CooldownTimer\";\nimport { Button, Input, Field } from \"@/components/Button\";\nimport { Icon } from \"@/components/Icon\";\nimport { Empty } from \"@/components/ui\";\nimport type { MaskedConfig, PingResult, ProviderSnapshot, WireFormat } from \"@/lib/gateway\";\n\ninterface Loaded {\n config: MaskedConfig;\n health: ProviderSnapshot[];\n}\n\nexport function ProviderManager() {\n const [data, setData] = useState<Loaded | null>(null);\n const [error, setError] = useState(\"\");\n const [adding, setAdding] = useState(false);\n\n const reload = useCallback(async () => {\n const [cfg, prov] = await Promise.all([\n fetch(\"/api/gw/admin/config\"),\n adminApi.providers(),\n ]);\n if (!cfg.ok || !prov.ok) {\n setError(\"could not reach the gateway\");\n return;\n }\n setError(\"\");\n setData({\n config: (await cfg.json()) as MaskedConfig,\n health: prov.data?.providers ?? [],\n });\n }, []);\n\n useEffect(() => {\n void reload();\n }, [reload]);\n\n if (error) return <Empty>{error}</Empty>;\n if (!data) return <Empty>Loading…</Empty>;\n\n const healthById = new Map(data.health.map((h) => [h.id, h]));\n\n return (\n <div>\n <div className=\"mb-6 flex items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-[22px] font-semibold tracking-tight text-text\">Providers &amp; Keys</h1>\n <p className=\"mt-1 text-[13px] text-text-muted\">Upstream providers the gateway routes to.</p>\n </div>\n <Button onClick={() => setAdding(true)}>\n <Icon name=\"add\" size={17} />\n Add provider\n </Button>\n </div>\n\n {adding && (\n <AddProviderForm\n onClose={() => setAdding(false)}\n onDone={() => { setAdding(false); void reload(); }}\n />\n )}\n\n {data.config.providers.length === 0 ? (\n <Empty>No providers yet. Add one to start routing.</Empty>\n ) : (\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {data.config.providers.map((p) => {\n const health = healthById.get(p.id);\n const healthy = health ? health.keys.some((k) => k.healthy) : true;\n const cooling = health?.keys.find((k) => !k.healthy && k.cooldown_ms > 0);\n return (\n <Link\n key={p.id}\n href={`/providers/${encodeURIComponent(p.id)}`}\n className={`group rounded-brand-lg border bg-surface p-4 shadow-soft transition-colors ${\n p.disabled\n ? \"border-danger/35 opacity-60 hover:opacity-100 hover:border-danger/60\"\n : \"border-border hover:border-text-subtle\"\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-center gap-2 min-w-0\">\n <Lamp state={p.disabled ? \"idle\" : healthy ? \"live\" : \"down\"} />\n <div className=\"min-w-0\">\n <span className=\"block truncate text-[14px] font-semibold text-text\">{p.name || p.id}</span>\n {p.name && <span className=\"block truncate text-[11px] text-text-subtle\">{p.id}/</span>}\n </div>\n </div>\n <FormatBadge format={p.format} />\n </div>\n <div className=\"mt-2 truncate text-[12px] text-text-subtle\">{p.base_url}</div>\n <div className=\"mt-3 flex flex-wrap items-center gap-2\">\n <ProviderToggle id={p.id} disabled={!!p.disabled} onDone={reload} />\n {p.free && <Badge tone=\"info\">free</Badge>}\n {p.service_account && <Badge tone=\"info\">service-account</Badge>}\n <Badge tone=\"neutral\">\n {p.free || p.service_account ? `${(p.api_keys?.length ?? 0)} keys` : `${p.api_keys?.length ?? (p.api_key ? 1 : 0)} keys`}\n </Badge>\n <Badge tone=\"neutral\">{p.models.length} models</Badge>\n {cooling && <CooldownTimer ms={cooling.cooldown_ms} />}\n </div>\n </Link>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Inline enable/disable switch shown on each provider card. The card is a <Link>,\n * so the button swallows the click (preventDefault + stopPropagation) to toggle in\n * place instead of navigating into the provider. `busy` ignores double-clicks.\n */\nfunction ProviderToggle({ id, disabled, onDone }: { id: string; disabled: boolean; onDone: () => void }) {\n const [busy, setBusy] = useState(false);\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n if (busy) return;\n setBusy(true);\n void adminApi.setProviderDisabled(id, !disabled).then(() => onDone()).finally(() => setBusy(false));\n }}\n className={`inline-flex items-center gap-1.5 text-[11px] font-medium ${disabled ? \"text-danger\" : \"text-text-muted\"}`}\n aria-label={disabled ? \"Enable provider\" : \"Disable provider\"}\n title={disabled ? \"Provider disabled — click to enable\" : \"Provider enabled — click to disable\"}\n >\n <span className={`relative h-4 w-7 rounded-full transition-colors ${disabled ? \"bg-danger\" : \"bg-accent\"} ${busy ? \"opacity-60\" : \"\"}`}>\n <span className={`absolute left-0.5 top-0.5 h-3 w-3 rounded-full bg-white transition-transform ${disabled ? \"translate-x-0\" : \"translate-x-[14px]\"}`} />\n </span>\n {disabled ? \"disabled\" : \"enabled\"}\n </button>\n );\n}\n\n// Provider presets — pick a type first, which prefills Base URL + API Type, then\n// you only fill Name + Key. Matches aigetwey's per-type forms but friendlier; the\n// fields below are still aigetwey's (Name, API Type, Base URL, Key + Check, Model\n// ID), minus the separate Prefix — our Name is the id and the model prefix.\ntype Preset = { id: string; label: string; sub: string; icon: string; format: WireFormat; base_url: string; hint: string; modelHint: string };\nconst PRESETS: Preset[] = [\n {\n id: \"openai\", label: \"OpenAI compatible\", sub: \"/v1/chat/completions\", icon: \"bolt\",\n format: \"openai\", base_url: \"https://api.openai.com/v1\",\n hint: \"Base URL ending in /v1 for any OpenAI-compatible API.\", modelHint: \"e.g. gpt-4o, glm-5.2\",\n },\n {\n id: \"anthropic\", label: \"Anthropic compatible\", sub: \"/v1/messages\", icon: \"smart_toy\",\n format: \"anthropic\", base_url: \"https://api.anthropic.com\",\n hint: \"Base URL of an Anthropic-compatible API; /messages is appended.\", modelHint: \"e.g. claude-sonnet-4-6\",\n },\n];\n\nfunction AddProviderForm({ onDone, onClose }: { onDone: () => void; onClose: () => void }) {\n const [preset, setPreset] = useState<Preset | null>(null);\n const [id, setId] = useState(\"\");\n const [baseUrl, setBaseUrl] = useState(\"\");\n const [apiKey, setApiKey] = useState(\"\");\n const [showKey, setShowKey] = useState(false);\n const [modelId, setModelId] = useState(\"\");\n const [busy, setBusy] = useState(false);\n const [checking, setChecking] = useState(false);\n const [checkRes, setCheckRes] = useState<PingResult | null>(null);\n const [err, setErr] = useState(\"\");\n\n function choosePreset(p: Preset) {\n setPreset(p);\n setBaseUrl(p.base_url);\n setCheckRes(null);\n setErr(\"\");\n }\n\n // step 1: pick a type (OpenAI- or Anthropic-compatible) — this sets the wire\n // format + base URL, exactly aigetwey's \"Add OpenAI/Anthropic Compatible\".\n if (!preset) {\n return (\n <div className=\"mb-5 rounded-brand-lg border border-border bg-surface p-5 shadow-soft\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h2 className=\"text-[14px] font-semibold text-text\">Add a provider</h2>\n <p className=\"mt-0.5 text-[12.5px] text-text-muted\">Pick the API your endpoint speaks — the rest is prefilled.</p>\n </div>\n <button type=\"button\" onClick={onClose} className=\"flex-none text-text-subtle hover:text-text\" aria-label=\"Cancel\">\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n <div className=\"mt-4 grid gap-3 sm:grid-cols-2\">\n {PRESETS.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => choosePreset(p)}\n className=\"group flex items-start gap-3 rounded-brand-lg border border-border bg-bg p-4 text-left transition-colors hover:border-accent hover:bg-accent-soft\"\n >\n <span className=\"flex h-10 w-10 flex-none items-center justify-center rounded-brand bg-surface-2 text-text-muted group-hover:text-accent\">\n <Icon name={p.icon} size={20} />\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-[13.5px] font-semibold text-text\">{p.label}</span>\n <span className=\"block tnum text-[11.5px] text-text-subtle\">{p.sub}</span>\n <span className=\"mt-1 block text-[11.5px] text-text-muted\">{p.hint}</span>\n </span>\n </button>\n ))}\n </div>\n </div>\n );\n }\n\n async function check() {\n if (!baseUrl || !preset) return;\n setChecking(true);\n setCheckRes(null);\n const r = await adminApi.validateProvider({ format: preset.format, base_url: baseUrl, api_key: apiKey || undefined });\n setChecking(false);\n setCheckRes(r.data ?? { ok: false, reachable: false, status: 0, error: r.error });\n }\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n if (!preset || !id || !baseUrl) {\n setErr(\"name and base URL are required\");\n return;\n }\n setBusy(true);\n setErr(\"\");\n const res = await adminApi.addProvider({ id, format: preset.format, base_url: baseUrl, api_key: apiKey || undefined, free: !apiKey.trim() });\n if (!res.ok) {\n setBusy(false);\n setErr(res.error ?? \"failed\");\n return;\n }\n if (modelId.trim()) await adminApi.addModel(id, modelId.trim());\n setBusy(false);\n onDone();\n }\n\n // step 2: the aigetwey field set — Name, Base URL, API Key (for Check), Model ID.\n return (\n <div className=\"mb-5 rounded-brand-lg border border-border bg-surface p-5 shadow-soft\">\n <form onSubmit={submit}>\n <div className=\"mb-4 flex items-center gap-2.5 border-b border-border-subtle pb-4\">\n <span className=\"flex h-8 w-8 items-center justify-center rounded-brand bg-surface-2 text-text-muted\">\n <Icon name={preset.icon} size={17} />\n </span>\n <div>\n <div className=\"text-[13.5px] font-semibold text-text\">{preset.label}</div>\n <div className=\"tnum text-[11px] text-text-subtle\">{preset.sub}</div>\n </div>\n <button\n type=\"button\"\n onClick={() => { setPreset(null); setCheckRes(null); }}\n className=\"ml-auto inline-flex items-center gap-1 text-[12px] text-text-subtle hover:text-text\"\n >\n <Icon name=\"arrow_back\" size={14} /> change type\n </button>\n </div>\n\n <div className=\"space-y-3\">\n <Field label=\"Name\" hint=\"a friendly id — also the model prefix (name/model)\">\n <Input value={id} onChange={(e) => setId(e.target.value)} placeholder=\"e.g. openai, anthropic\" />\n </Field>\n <Field label=\"Base URL\" hint={preset.hint}>\n <Input value={baseUrl} onChange={(e) => { setBaseUrl(e.target.value); setCheckRes(null); }} placeholder={preset.base_url} className=\"font-mono text-[12.5px]\" />\n </Field>\n <Field label=\"API Key\" hint=\"used for Check and live requests — leave blank for a free / no-auth endpoint\">\n <div className=\"flex gap-2\">\n <div className=\"relative flex-1\">\n <Input\n type={showKey ? \"text\" : \"password\"}\n value={apiKey}\n onChange={(e) => { setApiKey(e.target.value); setCheckRes(null); }}\n placeholder=\"sk-…\"\n className=\"pr-9 font-mono text-[12.5px]\"\n />\n {apiKey && (\n <button type=\"button\" onClick={() => setShowKey((v) => !v)} className=\"absolute right-2 top-1/2 -translate-y-1/2 text-text-subtle hover:text-text\" aria-label={showKey ? \"Hide key\" : \"Show key\"}>\n <Icon name={showKey ? \"visibility_off\" : \"visibility\"} size={15} />\n </button>\n )}\n </div>\n <Button type=\"button\" variant=\"ghost\" disabled={checking || !baseUrl} onClick={check}>\n <Icon name={checking ? \"progress_activity\" : \"wifi_tethering\"} size={15} />\n {checking ? \"Checking…\" : \"Check\"}\n </Button>\n </div>\n </Field>\n {checkRes && (\n <div className=\"flex items-center gap-2 text-[12px]\">\n <Badge tone={checkRes.ok ? \"live\" : checkRes.reachable ? \"warn\" : \"down\"}>\n {checkRes.ok ? \"valid\" : checkRes.reachable ? `reachable (${checkRes.status})` : \"invalid\"}\n </Badge>\n {checkRes.error && <span className=\"text-text-subtle\">{checkRes.error}</span>}\n </div>\n )}\n <Field label=\"Model ID\" hint=\"optional — seed one if the provider has no /models endpoint\">\n <Input value={modelId} onChange={(e) => setModelId(e.target.value)} placeholder={preset.modelHint} className=\"font-mono text-[12.5px]\" />\n </Field>\n </div>\n\n {err && <div className=\"mt-2 text-[12px] text-danger\">{err}</div>}\n <div className=\"mt-4 flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" onClick={onClose}>Cancel</Button>\n <Button type=\"submit\" disabled={busy}>{busy ? \"Adding…\" : \"Add provider\"}</Button>\n </div>\n </form>\n </div>\n );\n}\n"],"names":["TONES","live","down","warn","info","neutral","Badge","tone","children","className","FormatBadge","format","fmt","int","n","toLocaleString","compact","Math","abs","toFixed","String","round","cost","time","ts","Date","hour12","date","d","getDate","padStart","getMonth","getFullYear","ago","s","max","now","floor","duration","ms","h","m","Stat","label","value","sub","Empty","Lamp","state","title","lampFor","healthy","CooldownTimer","icon","keepZero","until","remaining","setRemaining","tick","id","setInterval","clearInterval","color","name","size","ProviderManager","data","setData","error","setError","adding","setAdding","reload","cfg","prov","Promise","all","fetch","providers","ok","config","json","health","healthById","Map","map","onClick","AddProviderForm","onClose","onDone","length","p","get","keys","some","k","cooling","find","cooldown_ms","href","encodeURIComponent","disabled","base_url","ProviderToggle","free","service_account","api_keys","api_key","models","busy","setBusy","type","e","preventDefault","stopPropagation","setProviderDisabled","then","finally","PRESETS","hint","modelHint","preset","setPreset","setId","baseUrl","setBaseUrl","apiKey","setApiKey","showKey","setShowKey","modelId","setModelId","checking","setChecking","checkRes","setCheckRes","err","setErr","choosePreset","check","r","validateProvider","undefined","reachable","status","submit","res","addProvider","trim","addModel","onSubmit","onChange","target","placeholder","v","variant"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[47444,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(93026),e=a.i(52065);a.s(["ModelPicker",0,function({title:a="Add models",note:f="Click to add, click again to remove.",searchPlaceholder:g="Search models…",groups:h,selected:i,onToggle:j,onClose:k,showThinkingHint:l=!0}){let[m,n]=(0,c.useState)(""),o=m.trim().toLowerCase(),p=h.map(a=>({...a,items:o?a.items.filter(a=>a.value.toLowerCase().includes(o)):a.items})).filter(a=>a.items.length>0),q=new Set(i);return(0,b.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/60 p-6 sm:p-10",onClick:k,children:(0,b.jsxs)("div",{className:"flex max-h-[80vh] w-full max-w-lg flex-col rounded-brand-lg border border-border bg-surface shadow-elevated",onClick:a=>a.stopPropagation(),children:[(0,b.jsxs)("div",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-3",children:[(0,b.jsx)("h2",{className:"text-[14px] font-semibold text-text",children:a}),(0,b.jsx)("button",{onClick:k,className:"text-text-subtle hover:text-text","aria-label":"Close",children:(0,b.jsx)(d.Icon,{name:"close",size:18})})]}),(0,b.jsxs)("div",{className:"border-b border-border-subtle px-4 py-3",children:[(0,b.jsx)("p",{className:"mb-2 text-[12px] text-text-muted",children:f}),(0,b.jsxs)("div",{className:"relative",children:[(0,b.jsx)(d.Icon,{name:"search",size:15,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle"}),(0,b.jsx)("input",{autoFocus:!0,value:m,onChange:a=>n(a.target.value),placeholder:g,className:"w-full rounded-brand border border-border bg-bg py-2 pl-8 pr-3 text-[13px] text-text placeholder:text-text-subtle focus:border-accent focus:outline-none"})]})]}),(0,b.jsx)("div",{className:"flex-1 overflow-y-auto px-4 py-3",children:0===p.length?(0,b.jsxs)("p",{className:"py-6 text-center text-[12.5px] text-text-subtle",children:["No models match “",m,"”."]}):(0,b.jsx)("div",{className:"space-y-4",children:p.map(a=>(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-text-subtle",children:[a.label," ",(0,b.jsxs)("span",{className:"tnum text-text-subtle/70",children:["(",a.items.length,")"]})]}),(0,b.jsx)("div",{className:"flex flex-wrap gap-1.5",children:a.items.map(a=>{let c=q.has(a.value);return(0,b.jsxs)("button",{type:"button",onClick:()=>j(a.value),className:`inline-flex items-center gap-1 rounded-brand border px-2 py-1 text-[12px] transition-colors ${c?"border-accent bg-accent-soft text-accent":"border-border bg-bg text-text-muted hover:border-text-subtle hover:text-text"}`,children:[c&&(0,b.jsx)(d.Icon,{name:"check",size:12}),(0,b.jsx)("span",{className:"tnum",children:a.label}),(0,b.jsx)(e.CapacityBadges,{model:a.value,size:13}),a.tag&&(0,b.jsx)("span",{className:"rounded bg-surface-2 px-1 text-[10px] text-text-subtle",children:a.tag})]},a.value)})})]},a.label))})}),l&&(0,b.jsxs)("div",{className:"border-t border-border-subtle px-4 py-2 text-[11px] text-text-subtle",children:[(0,b.jsx)(d.Icon,{name:"neurology",size:12,className:"mr-1 inline align-text-bottom text-warning"}),"Reasoning models accept a thinking suffix — call"," ",(0,b.jsx)("code",{className:"rounded bg-surface-2 px-1 text-text-muted",children:"model(high)"})," or"," ",(0,b.jsx)("code",{className:"rounded bg-surface-2 px-1 text-text-muted",children:"model(none)"})," (high·low·medium·minimal·auto·none·or a token budget)."]}),(0,b.jsxs)("div",{className:"flex items-center justify-between border-t border-border-subtle px-4 py-3",children:[(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-subtle",children:[i.length," selected"]}),(0,b.jsx)("button",{onClick:k,className:"rounded-brand bg-accent px-3.5 py-1.5 text-[13px] font-semibold text-accent-ink hover:bg-accent-hover",children:"Done"})]})]})})}])},47153,a=>{"use strict";var b=a.i(87924);a.s(["Lamp",0,function({state:a,title:c}){return(0,b.jsx)("span",{className:`lamp lamp-${a}`,title:c,"aria-label":a})}])},1829,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(56173),e=a.i(47153),f=a.i(2693),g=a.i(85732),h=a.i(7078),i=a.i(47444),j=a.i(93026),k=a.i(73858),l=a.i(58918);function m({providers:a,onDone:e,initial:f,onCancel:g}){let k=!!f,[l,n]=(0,c.useState)(f?.alias??""),[o,p]=(0,c.useState)(()=>f?f.target.map((a,b)=>{let c=Array.isArray(f.model)?f.model[b]??f.model[0]:f.model??f.alias;return`${a}/${c}`}):[]),[q,r]=(0,c.useState)(!1),[s,t]=(0,c.useState)(f?.strategy??"fallback"),[u,v]=(0,c.useState)(f?.price_in?.toString()??""),[w,x]=(0,c.useState)(f?.price_out?.toString()??""),[y,z]=(0,c.useState)(!1),[A,B]=(0,c.useState)(""),[C,D]=(0,c.useState)(null),E=a.filter(a=>a.models.length>0).map(a=>({label:a.id,items:a.models.map(b=>({value:`${a.id}/${b.id}`,label:`${a.id}/${b.id}`}))}));async function F(a){if(a.preventDefault(),!l||0===o.length)return void B("a name and at least one model are required");z(!0),B("");let b=o.map(a=>a.slice(0,a.indexOf("/"))),c=o.map(a=>a.slice(a.indexOf("/")+1)),g=await d.adminApi.setRoute(l,{target:b,model:c,strategy:s,price_in:u?Number(u):void 0,price_out:w?Number(w):void 0});g.ok&&k&&f.alias!==l&&await d.adminApi.removeRoute(f.alias),z(!1),g.ok?e():B(g.error??"failed")}return(0,b.jsxs)("form",{onSubmit:F,className:"mb-5 rounded-brand-lg border border-border bg-surface p-4 shadow-soft",children:[(0,b.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2",children:[(0,b.jsx)(h.Field,{label:"Alias",hint:"the name your CLI requests as a model",children:(0,b.jsx)(h.Input,{value:l,onChange:a=>n(a.target.value),placeholder:"my-claude"})}),(0,b.jsx)(h.Field,{label:"Strategy",hint:"how the chain is tried",children:(0,b.jsxs)(h.Select,{value:s,onChange:a=>t(a.target.value),children:[(0,b.jsx)("option",{value:"fallback",children:"Fallback — try in order, next on failure"}),(0,b.jsx)("option",{value:"round-robin",children:"Round Robin — rotate to spread load"})]})}),(0,b.jsx)(h.Field,{label:"Price in",hint:"per 1M, optional",children:(0,b.jsx)(h.Input,{value:u,onChange:a=>v(a.target.value),placeholder:"3"})}),(0,b.jsx)(h.Field,{label:"Price out",hint:"per 1M, optional",children:(0,b.jsx)(h.Input,{value:w,onChange:a=>x(a.target.value),placeholder:"15"})})]}),(0,b.jsxs)("div",{className:"mt-3",children:[(0,b.jsxs)("div",{className:"flex items-center justify-between",children:[(0,b.jsx)("span",{className:"text-[11px] font-medium uppercase tracking-wider text-text-subtle",children:"Models — fallback order (drag to reorder)"}),(0,b.jsxs)(h.Button,{type:"button",variant:"ghost",onClick:()=>r(!0),children:[(0,b.jsx)(j.Icon,{name:"add",size:16})," Add models"]})]}),0===o.length?(0,b.jsxs)("div",{className:"mt-2 rounded-brand border border-dashed border-border-subtle px-3 py-4 text-center text-[12px] text-text-subtle",children:["No models yet. Click ",(0,b.jsx)("span",{className:"text-text-muted",children:"Add models"})," and pick from your providers."]}):(0,b.jsx)("ul",{className:"mt-2 space-y-1.5",children:o.map((a,c)=>(0,b.jsxs)("li",{draggable:!0,onDragStart:()=>D(c),onDragOver:a=>a.preventDefault(),onDrop:()=>{null!==C&&C!==c&&p(a=>{let b=[...a],[d]=b.splice(C,1);return b.splice(c,0,d),b}),D(null)},onDragEnd:()=>D(null),className:`flex cursor-grab items-center gap-2.5 rounded-brand border px-3 py-2 active:cursor-grabbing ${C===c?"border-accent bg-accent-soft":"border-border-subtle"}`,children:[(0,b.jsx)(j.Icon,{name:"drag_indicator",size:16,className:"text-text-subtle"}),(0,b.jsx)("span",{className:"tnum text-[11px] text-text-subtle",children:0===c?"primary":`#${c+1}`}),(0,b.jsx)("span",{className:"tnum truncate text-[13px] text-text",children:a}),(0,b.jsx)("button",{type:"button",onClick:()=>p(a=>a.filter((a,b)=>b!==c)),className:"ml-auto flex-none text-text-subtle hover:text-danger","aria-label":`Remove ${a}`,children:(0,b.jsx)(j.Icon,{name:"close",size:14})})]},a))})]}),A&&(0,b.jsx)("div",{className:"mt-2 text-[12px] text-danger",children:A}),(0,b.jsxs)("div",{className:"mt-3 flex justify-end gap-2",children:[g&&(0,b.jsx)(h.Button,{type:"button",variant:"ghost",onClick:g,children:"Cancel"}),(0,b.jsx)(h.Button,{type:"submit",disabled:y,children:y?"Saving…":k?"Update combo":"Save combo"})]}),q&&(0,b.jsx)(i.ModelPicker,{title:"Add models to the chain",note:"Click a model to add it, click again to remove. Drag to reorder after.",groups:E,selected:o,onToggle:function(a){B(""),p(b=>b.includes(a)?b.filter(b=>b!==a):[...b,a])},onClose:()=>r(!1)})]})}a.s(["RoutingView",0,function(){let[a,i]=(0,c.useState)(null),[n,o]=(0,c.useState)([]),[p,q]=(0,c.useState)(""),[r,s]=(0,c.useState)(!1),[t,u]=(0,c.useState)(""),[v,w]=(0,c.useState)({}),[x,y]=(0,c.useState)(null),[z,A]=(0,c.useState)(null),[B,C]=(0,c.useState)(null),D=(0,c.useCallback)(async()=>{let[a,b]=await Promise.all([fetch("/api/gw/admin/config"),d.adminApi.providers()]);a.ok?(q(""),i(await a.json()),o(b.data?.providers??[])):q("could not reach the gateway")},[]);if((0,c.useEffect)(()=>{D()},[D]),p)return(0,b.jsx)(l.Empty,{children:p});if(!a)return(0,b.jsx)(l.Empty,{children:"Loading…"});async function E(a){u(a);let b=await d.adminApi.removeRoute(a);u(""),b.ok?await D():q(b.error??"failed")}async function F(a){y(a.alias),w(b=>({...b,[a.alias]:{}}));for(let b=0;b<a.target.length;b++){w(c=>({...c,[a.alias]:{...c[a.alias],[b]:"testing"}}));let c=await d.adminApi.testProvider(a.target[b]),e=c.ok&&c.data?.ok;w(c=>({...c,[a.alias]:{...c[a.alias],[b]:e?"ok":"fail"}})),b<a.target.length-1&&await new Promise(a=>setTimeout(a,400))}y(null)}return(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-5 flex items-center justify-between gap-3",children:[(0,b.jsxs)("div",{children:[(0,b.jsx)("h1",{className:"text-[22px] font-semibold tracking-tight text-text",children:"Combos & Routing"}),(0,b.jsx)("p",{className:"mt-1 text-[13px] text-text-muted",children:"A combo is an alias your CLI tool calls, routed to a chain of providers. Fallback tries them in order; round-robin spreads load."})]}),(0,b.jsxs)(h.Button,{onClick:()=>s(a=>!a),children:[(0,b.jsx)(j.Icon,{name:r?"close":"add",size:17}),r?"Cancel":"Add combo"]})]}),r&&(0,b.jsx)(m,{providers:a.providers.filter(a=>!a.disabled),onDone:()=>{s(!1),D()}}),B&&!r&&(0,b.jsx)(m,{providers:a.providers.filter(a=>!a.disabled),initial:B,onDone:()=>{C(null),D()},onCancel:()=>C(null)}),0===a.models.length?(0,b.jsx)(l.Empty,{children:"No combos yet. Add one to expose a model alias to your CLI tools."}):(0,b.jsx)("div",{className:"grid gap-3 lg:grid-cols-2",children:a.models.map(a=>(0,b.jsx)(g.RichCard,{header:(0,b.jsxs)(b.Fragment,{children:[(0,b.jsx)(g.CardTitle,{title:a.alias,sub:`${a.target.length} in chain`}),(0,b.jsxs)("div",{className:"flex items-center gap-2",children:[(0,b.jsxs)("button",{onClick:()=>F(a),disabled:x===a.alias,className:"flex items-center gap-1 rounded px-2 py-1 text-[11px] text-text-subtle transition-colors hover:bg-surface-2 hover:text-text disabled:opacity-60",title:"Test each provider in this chain",children:[(0,b.jsx)(j.Icon,{name:x===a.alias?"progress_activity":"sync",size:14}),"Test"]}),(0,b.jsx)(f.Badge,{tone:"round-robin"===a.strategy?"info":"neutral",children:a.strategy}),(void 0!==a.price_in||void 0!==a.price_out)&&(0,b.jsxs)(f.Badge,{tone:"neutral",children:[l.fmt.cost(a.price_in??0),"/",l.fmt.cost(a.price_out??0)," per 1M"]}),(0,b.jsx)("button",{onClick:()=>C(a),className:"text-text-subtle hover:text-text","aria-label":"Edit combo",children:(0,b.jsx)(j.Icon,{name:"edit",size:16})}),(0,b.jsx)("button",{onClick:()=>A(a.alias),disabled:t===a.alias,className:"text-text-subtle hover:text-danger","aria-label":"Remove alias",children:(0,b.jsx)(j.Icon,{name:"delete",size:16})})]})]}),children:(0,b.jsx)("ol",{className:"space-y-1.5",children:a.target.map((c,d)=>{let f,g=v[a.alias]?.[d];return(0,b.jsxs)("li",{className:"flex items-center gap-2.5 rounded-brand border border-border-subtle px-3 py-2",children:[(0,b.jsx)("span",{className:"tnum text-[11px] text-text-subtle",children:0===d?"primary":`#${d+1}`}),(0,b.jsx)(e.Lamp,{state:("ok"===g?"live":"fail"===g?"down":"testing"===g?"idle":null)??(!(f=n.find(a=>a.id===c))||f.keys.some(a=>a.healthy)?"live":"down")}),(0,b.jsx)("span",{className:"text-[13px] text-text",children:c}),(0,b.jsx)("span",{className:"ml-auto tnum text-[12px] text-text-muted",children:Array.isArray(a.model)?a.model[d]??a.model[0]??a.alias:"string"==typeof a.model?a.model:a.alias}),"ok"===g&&(0,b.jsx)(j.Icon,{name:"check_circle",size:14,className:"text-success"}),"fail"===g&&(0,b.jsx)(j.Icon,{name:"cancel",size:14,className:"text-danger"}),"testing"===g&&(0,b.jsx)(j.Icon,{name:"progress_activity",size:14,className:"text-text-subtle"})]},c+d)})})},a.alias))}),z&&(0,b.jsx)(k.ConfirmModal,{title:"Remove combo",message:`Delete "${z}"? CLI tools using this alias will stop working.`,confirmLabel:"Remove",busy:t===z,onCancel:()=>A(null),onConfirm:()=>{E(z).then(()=>A(null))}})]})}])}];
2
-
3
- //# sourceMappingURL=src_components_12gk6sc._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/ModelPicker.tsx","../../../../src/components/Lamp.tsx","../../../../src/components/RoutingView.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Icon } from \"@/components/Icon\";\nimport { CapacityBadges } from \"@/components/CapacityBadges\";\n\nexport interface ModelGroup {\n label: string;\n items: { value: string; label: string; tag?: string }[];\n}\n\n/**\n * aigetwey-style model picker: a search box + provider-grouped chips you click to\n * toggle in/out of a selection. Used by the combo form and the CLI-tool model\n * selection so both add models the same way (click to add, click again to drop).\n */\nexport function ModelPicker({\n title = \"Add models\",\n note = \"Click to add, click again to remove.\",\n searchPlaceholder = \"Search models…\",\n groups,\n selected,\n onToggle,\n onClose,\n showThinkingHint = true,\n}: {\n title?: string;\n note?: string;\n searchPlaceholder?: string;\n groups: ModelGroup[];\n selected: string[];\n onToggle: (value: string) => void;\n onClose: () => void;\n /** The \"reasoning models accept a thinking suffix\" footer only makes sense when\n * picking MODELS. Provider/key pickers reuse this component, so they hide it. */\n showThinkingHint?: boolean;\n}) {\n const [q, setQ] = useState(\"\");\n const needle = q.trim().toLowerCase();\n const filtered = groups\n .map((g) => ({\n ...g,\n items: needle ? g.items.filter((i) => i.value.toLowerCase().includes(needle)) : g.items,\n }))\n .filter((g) => g.items.length > 0);\n const sel = new Set(selected);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/60 p-6 sm:p-10\" onClick={onClose}>\n <div\n className=\"flex max-h-[80vh] w-full max-w-lg flex-col rounded-brand-lg border border-border bg-surface shadow-elevated\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-border-subtle px-4 py-3\">\n <h2 className=\"text-[14px] font-semibold text-text\">{title}</h2>\n <button onClick={onClose} className=\"text-text-subtle hover:text-text\" aria-label=\"Close\">\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n\n <div className=\"border-b border-border-subtle px-4 py-3\">\n <p className=\"mb-2 text-[12px] text-text-muted\">{note}</p>\n <div className=\"relative\">\n <Icon name=\"search\" size={15} className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle\" />\n <input\n autoFocus\n value={q}\n onChange={(e) => setQ(e.target.value)}\n placeholder={searchPlaceholder}\n className=\"w-full rounded-brand border border-border bg-bg py-2 pl-8 pr-3 text-[13px] text-text placeholder:text-text-subtle focus:border-accent focus:outline-none\"\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-3\">\n {filtered.length === 0 ? (\n <p className=\"py-6 text-center text-[12.5px] text-text-subtle\">No models match “{q}”.</p>\n ) : (\n <div className=\"space-y-4\">\n {filtered.map((g) => (\n <div key={g.label}>\n <div className=\"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-text-subtle\">\n {g.label} <span className=\"tnum text-text-subtle/70\">({g.items.length})</span>\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {g.items.map((it) => {\n const on = sel.has(it.value);\n return (\n <button\n key={it.value}\n type=\"button\"\n onClick={() => onToggle(it.value)}\n className={`inline-flex items-center gap-1 rounded-brand border px-2 py-1 text-[12px] transition-colors ${\n on ? \"border-accent bg-accent-soft text-accent\" : \"border-border bg-bg text-text-muted hover:border-text-subtle hover:text-text\"\n }`}\n >\n {on && <Icon name=\"check\" size={12} />}\n <span className=\"tnum\">{it.label}</span>\n <CapacityBadges model={it.value} size={13} />\n {it.tag && <span className=\"rounded bg-surface-2 px-1 text-[10px] text-text-subtle\">{it.tag}</span>}\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {showThinkingHint && (\n <div className=\"border-t border-border-subtle px-4 py-2 text-[11px] text-text-subtle\">\n <Icon name=\"neurology\" size={12} className=\"mr-1 inline align-text-bottom text-warning\" />\n Reasoning models accept a thinking suffix — call{\" \"}\n <code className=\"rounded bg-surface-2 px-1 text-text-muted\">model(high)</code> or{\" \"}\n <code className=\"rounded bg-surface-2 px-1 text-text-muted\">model(none)</code> (high·low·medium·minimal·auto·none·or a token budget).\n </div>\n )}\n\n <div className=\"flex items-center justify-between border-t border-border-subtle px-4 py-3\">\n <span className=\"tnum text-[12px] text-text-subtle\">{selected.length} selected</span>\n <button onClick={onClose} className=\"rounded-brand bg-accent px-3.5 py-1.5 text-[13px] font-semibold text-accent-ink hover:bg-accent-hover\">\n Done\n </button>\n </div>\n </div>\n </div>\n );\n}\n","/** Status lamp — green when serving, red pulse on cooldown, grey when idle. */\nexport function Lamp({ state, title }: { state: \"live\" | \"idle\" | \"down\"; title?: string }) {\n return <span className={`lamp lamp-${state}`} title={title} aria-label={state} />;\n}\n\nexport function lampFor(healthy: boolean): \"live\" | \"down\" {\n return healthy ? \"live\" : \"down\";\n}\n","\"use client\";\n\nimport { useEffect, useState, useCallback } from \"react\";\nimport { adminApi } from \"@/lib/client\";\nimport { Lamp } from \"@/components/Lamp\";\nimport { Badge } from \"@/components/Badge\";\nimport { RichCard, CardTitle } from \"@/components/RichCard\";\nimport { Button, Input, Select, Field } from \"@/components/Button\";\nimport { ModelPicker, type ModelGroup } from \"@/components/ModelPicker\";\nimport { Icon } from \"@/components/Icon\";\nimport { ConfirmModal } from \"@/components/ConfirmModal\";\nimport { fmt, Empty } from \"@/components/ui\";\nimport type { MaskedConfig, MaskedRoute, ProviderSnapshot } from \"@/lib/gateway\";\n\n/** Upstream model id for the i-th target of a route (mirrors GatewayConfig). */\nfunction modelFor(route: MaskedRoute, i: number): string {\n if (Array.isArray(route.model)) return route.model[i] ?? route.model[0] ?? route.alias;\n if (typeof route.model === \"string\") return route.model;\n return route.alias;\n}\n\nexport function RoutingView() {\n const [config, setConfig] = useState<MaskedConfig | null>(null);\n const [health, setHealth] = useState<ProviderSnapshot[]>([]);\n const [error, setError] = useState(\"\");\n const [adding, setAdding] = useState(false);\n const [busy, setBusy] = useState(\"\");\n const [chainTest, setChainTest] = useState<Record<string, Record<number, \"testing\" | \"ok\" | \"fail\">>>({});\n const [chainBusy, setChainBusy] = useState<string | null>(null);\n const [pendingDelete, setPendingDelete] = useState<string | null>(null);\n const [editing, setEditing] = useState<MaskedRoute | null>(null);\n\n const reload = useCallback(async () => {\n const [cfgRes, prov] = await Promise.all([fetch(\"/api/gw/admin/config\"), adminApi.providers()]);\n if (!cfgRes.ok) {\n setError(\"could not reach the gateway\");\n return;\n }\n setError(\"\");\n setConfig((await cfgRes.json()) as MaskedConfig);\n setHealth(prov.data?.providers ?? []);\n }, []);\n\n useEffect(() => {\n void reload();\n }, [reload]);\n\n if (error) return <Empty>{error}</Empty>;\n if (!config) return <Empty>Loading…</Empty>;\n\n const healthy = (pid: string) => {\n const h = health.find((x) => x.id === pid);\n return h ? h.keys.some((k) => k.healthy) : true;\n };\n\n async function del(alias: string) {\n setBusy(alias);\n const r = await adminApi.removeRoute(alias);\n setBusy(\"\");\n if (!r.ok) setError(r.error ?? \"failed\");\n else await reload();\n }\n\n async function testChain(route: MaskedRoute) {\n setChainBusy(route.alias);\n setChainTest((prev) => ({ ...prev, [route.alias]: {} }));\n for (let i = 0; i < route.target.length; i++) {\n setChainTest((prev) => ({ ...prev, [route.alias]: { ...prev[route.alias], [i]: \"testing\" } }));\n const r = await adminApi.testProvider(route.target[i]!);\n const ok = r.ok && r.data?.ok;\n setChainTest((prev) => ({ ...prev, [route.alias]: { ...prev[route.alias], [i]: ok ? \"ok\" : \"fail\" } }));\n if (i < route.target.length - 1) await new Promise((resolve) => setTimeout(resolve, 400));\n }\n setChainBusy(null);\n }\n\n return (\n <div>\n <div className=\"mb-5 flex items-center justify-between gap-3\">\n <div>\n <h1 className=\"text-[22px] font-semibold tracking-tight text-text\">Combos &amp; Routing</h1>\n <p className=\"mt-1 text-[13px] text-text-muted\">\n A combo is an alias your CLI tool calls, routed to a chain of providers. Fallback tries them in order; round-robin spreads load.\n </p>\n </div>\n <Button onClick={() => setAdding((v) => !v)}>\n <Icon name={adding ? \"close\" : \"add\"} size={17} />\n {adding ? \"Cancel\" : \"Add combo\"}\n </Button>\n </div>\n\n {adding && (\n <RouteForm\n providers={config.providers.filter((p) => !p.disabled)}\n onDone={() => { setAdding(false); void reload(); }}\n />\n )}\n\n {editing && !adding && (\n <RouteForm\n providers={config.providers.filter((p) => !p.disabled)}\n initial={editing}\n onDone={() => { setEditing(null); void reload(); }}\n onCancel={() => setEditing(null)}\n />\n )}\n\n {config.models.length === 0 ? (\n <Empty>No combos yet. Add one to expose a model alias to your CLI tools.</Empty>\n ) : (\n <div className=\"grid gap-3 lg:grid-cols-2\">\n {config.models.map((route) => (\n <RichCard\n key={route.alias}\n header={\n <>\n <CardTitle title={route.alias} sub={`${route.target.length} in chain`} />\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => testChain(route)}\n disabled={chainBusy === route.alias}\n className=\"flex items-center gap-1 rounded px-2 py-1 text-[11px] text-text-subtle transition-colors hover:bg-surface-2 hover:text-text disabled:opacity-60\"\n title=\"Test each provider in this chain\"\n >\n <Icon name={chainBusy === route.alias ? \"progress_activity\" : \"sync\"} size={14} />\n Test\n </button>\n <Badge tone={route.strategy === \"round-robin\" ? \"info\" : \"neutral\"}>{route.strategy}</Badge>\n {(route.price_in !== undefined || route.price_out !== undefined) && (\n <Badge tone=\"neutral\">\n {fmt.cost(route.price_in ?? 0)}/{fmt.cost(route.price_out ?? 0)} per 1M\n </Badge>\n )}\n <button onClick={() => setEditing(route)} className=\"text-text-subtle hover:text-text\" aria-label=\"Edit combo\">\n <Icon name=\"edit\" size={16} />\n </button>\n <button onClick={() => setPendingDelete(route.alias)} disabled={busy === route.alias} className=\"text-text-subtle hover:text-danger\" aria-label=\"Remove alias\">\n <Icon name=\"delete\" size={16} />\n </button>\n </div>\n </>\n }\n >\n <ol className=\"space-y-1.5\">\n {route.target.map((pid, i) => {\n const ct = chainTest[route.alias]?.[i];\n const testLamp = ct === \"ok\" ? \"live\" : ct === \"fail\" ? \"down\" : ct === \"testing\" ? \"idle\" : null;\n return (\n <li key={pid + i} className=\"flex items-center gap-2.5 rounded-brand border border-border-subtle px-3 py-2\">\n <span className=\"tnum text-[11px] text-text-subtle\">{i === 0 ? \"primary\" : `#${i + 1}`}</span>\n <Lamp state={testLamp ?? (healthy(pid) ? \"live\" : \"down\")} />\n <span className=\"text-[13px] text-text\">{pid}</span>\n <span className=\"ml-auto tnum text-[12px] text-text-muted\">{modelFor(route, i)}</span>\n {ct === \"ok\" && <Icon name=\"check_circle\" size={14} className=\"text-success\" />}\n {ct === \"fail\" && <Icon name=\"cancel\" size={14} className=\"text-danger\" />}\n {ct === \"testing\" && <Icon name=\"progress_activity\" size={14} className=\"text-text-subtle\" />}\n </li>\n );\n })}\n </ol>\n </RichCard>\n ))}\n </div>\n )}\n\n {pendingDelete && (\n <ConfirmModal\n title=\"Remove combo\"\n message={`Delete \"${pendingDelete}\"? CLI tools using this alias will stop working.`}\n confirmLabel=\"Remove\"\n busy={busy === pendingDelete}\n onCancel={() => setPendingDelete(null)}\n onConfirm={() => {\n void del(pendingDelete).then(() => setPendingDelete(null));\n }}\n />\n )}\n </div>\n );\n}\n\n// Combo create form, for aigetwey's ComboFormModal: a name + ONE ordered\n// list of concrete `provider/model` entries (fallback priority), picked from the\n// providers' catalogs. On save each entry splits into target[i]/model[i].\ntype ProviderOption = { id: string; models: { id: string }[] };\n\nfunction RouteForm({ providers, onDone, initial, onCancel }: { providers: ProviderOption[]; onDone: () => void; initial?: MaskedRoute; onCancel?: () => void }) {\n const isEdit = !!initial;\n const [alias, setAlias] = useState(initial?.alias ?? \"\");\n const [entries, setEntries] = useState<string[]>(() => {\n if (!initial) return [];\n return initial.target.map((pid, i) => {\n const m = Array.isArray(initial.model) ? initial.model[i] ?? initial.model[0] : initial.model ?? initial.alias;\n return `${pid}/${m}`;\n });\n });\n const [pickerOpen, setPickerOpen] = useState(false);\n const [strategy, setStrategy] = useState<\"fallback\" | \"round-robin\">(initial?.strategy ?? \"fallback\");\n const [priceIn, setPriceIn] = useState(initial?.price_in?.toString() ?? \"\");\n const [priceOut, setPriceOut] = useState(initial?.price_out?.toString() ?? \"\");\n const [busy, setBusy] = useState(false);\n const [err, setErr] = useState(\"\");\n const [dragIdx, setDragIdx] = useState<number | null>(null);\n\n // aigetwey-style picker: provider-grouped, click a model to add/remove it.\n const groups: ModelGroup[] = providers\n .filter((p) => p.models.length > 0)\n .map((p) => ({ label: p.id, items: p.models.map((m) => ({ value: `${p.id}/${m.id}`, label: `${p.id}/${m.id}` })) }));\n\n function toggle(v: string) {\n setErr(\"\");\n setEntries((e) => (e.includes(v) ? e.filter((x) => x !== v) : [...e, v]));\n }\n\n // reorder fallback priority: dropping entry #from onto slot #to\n function move(from: number, to: number) {\n setEntries((e) => {\n const next = [...e];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n return next;\n });\n }\n\n async function submit(e: React.FormEvent) {\n e.preventDefault();\n if (!alias || entries.length === 0) {\n setErr(\"a name and at least one model are required\");\n return;\n }\n setBusy(true);\n setErr(\"\");\n const target = entries.map((x) => x.slice(0, x.indexOf(\"/\")));\n const model = entries.map((x) => x.slice(x.indexOf(\"/\") + 1));\n const r = await adminApi.setRoute(alias, {\n target,\n model,\n strategy,\n price_in: priceIn ? Number(priceIn) : undefined,\n price_out: priceOut ? Number(priceOut) : undefined,\n });\n // rename: the new alias is saved above; drop the old one so it doesn't linger.\n if (r.ok && isEdit && initial!.alias !== alias) {\n await adminApi.removeRoute(initial!.alias);\n }\n setBusy(false);\n if (r.ok) onDone();\n else setErr(r.error ?? \"failed\");\n }\n\n return (\n <form onSubmit={submit} className=\"mb-5 rounded-brand-lg border border-border bg-surface p-4 shadow-soft\">\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Alias\" hint=\"the name your CLI requests as a model\">\n <Input value={alias} onChange={(e) => setAlias(e.target.value)} placeholder=\"my-claude\" />\n </Field>\n <Field label=\"Strategy\" hint=\"how the chain is tried\">\n <Select value={strategy} onChange={(e) => setStrategy(e.target.value as \"fallback\" | \"round-robin\")}>\n <option value=\"fallback\">Fallback — try in order, next on failure</option>\n <option value=\"round-robin\">Round Robin — rotate to spread load</option>\n </Select>\n </Field>\n <Field label=\"Price in\" hint=\"per 1M, optional\"><Input value={priceIn} onChange={(e) => setPriceIn(e.target.value)} placeholder=\"3\" /></Field>\n <Field label=\"Price out\" hint=\"per 1M, optional\"><Input value={priceOut} onChange={(e) => setPriceOut(e.target.value)} placeholder=\"15\" /></Field>\n </div>\n\n <div className=\"mt-3\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-[11px] font-medium uppercase tracking-wider text-text-subtle\">\n Models — fallback order (drag to reorder)\n </span>\n <Button type=\"button\" variant=\"ghost\" onClick={() => setPickerOpen(true)}>\n <Icon name=\"add\" size={16} /> Add models\n </Button>\n </div>\n\n {entries.length === 0 ? (\n <div className=\"mt-2 rounded-brand border border-dashed border-border-subtle px-3 py-4 text-center text-[12px] text-text-subtle\">\n No models yet. Click <span className=\"text-text-muted\">Add models</span> and pick from your providers.\n </div>\n ) : (\n <ul className=\"mt-2 space-y-1.5\">\n {entries.map((entry, i) => (\n <li\n key={entry}\n draggable\n onDragStart={() => setDragIdx(i)}\n onDragOver={(e) => e.preventDefault()}\n onDrop={() => {\n if (dragIdx !== null && dragIdx !== i) move(dragIdx, i);\n setDragIdx(null);\n }}\n onDragEnd={() => setDragIdx(null)}\n className={`flex cursor-grab items-center gap-2.5 rounded-brand border px-3 py-2 active:cursor-grabbing ${\n dragIdx === i ? \"border-accent bg-accent-soft\" : \"border-border-subtle\"\n }`}\n >\n <Icon name=\"drag_indicator\" size={16} className=\"text-text-subtle\" />\n <span className=\"tnum text-[11px] text-text-subtle\">{i === 0 ? \"primary\" : `#${i + 1}`}</span>\n <span className=\"tnum truncate text-[13px] text-text\">{entry}</span>\n <button\n type=\"button\"\n onClick={() => setEntries((e) => e.filter((_, idx) => idx !== i))}\n className=\"ml-auto flex-none text-text-subtle hover:text-danger\"\n aria-label={`Remove ${entry}`}\n >\n <Icon name=\"close\" size={14} />\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n {err && <div className=\"mt-2 text-[12px] text-danger\">{err}</div>}\n <div className=\"mt-3 flex justify-end gap-2\">\n {onCancel && <Button type=\"button\" variant=\"ghost\" onClick={onCancel}>Cancel</Button>}\n <Button type=\"submit\" disabled={busy}>{busy ? \"Saving…\" : isEdit ? \"Update combo\" : \"Save combo\"}</Button>\n </div>\n\n {pickerOpen && (\n <ModelPicker\n title=\"Add models to the chain\"\n note=\"Click a model to add it, click again to remove. Drag to reorder after.\"\n groups={groups}\n selected={entries}\n onToggle={toggle}\n onClose={() => setPickerOpen(false)}\n />\n )}\n </form>\n );\n}\n"],"names":["ModelPicker","title","note","searchPlaceholder","groups","selected","onToggle","onClose","showThinkingHint","q","setQ","needle","trim","toLowerCase","filtered","map","g","items","filter","i","value","includes","length","sel","Set","className","onClick","e","stopPropagation","name","size","autoFocus","onChange","target","placeholder","label","it","on","has","type","model","tag","Lamp","state","lampFor","healthy","modelFor","route","Array","isArray","alias","RoutingView","config","setConfig","health","setHealth","error","setError","adding","setAdding","busy","setBusy","chainTest","setChainTest","chainBusy","setChainBusy","pendingDelete","setPendingDelete","editing","setEditing","reload","cfgRes","prov","Promise","all","fetch","providers","ok","json","data","pid","h","find","x","id","keys","some","k","del","r","removeRoute","testChain","prev","testProvider","resolve","setTimeout","v","RouteForm","p","disabled","onDone","initial","onCancel","models","header","sub","tone","strategy","price_in","undefined","price_out","cost","ct","testLamp","message","confirmLabel","onConfirm","then","isEdit","setAlias","entries","setEntries","m","pickerOpen","setPickerOpen","setStrategy","priceIn","setPriceIn","toString","priceOut","setPriceOut","err","setErr","dragIdx","setDragIdx","toggle","move","from","to","next","moved","splice","submit","preventDefault","slice","indexOf","setRoute","Number","onSubmit","hint","variant","entry","draggable","onDragStart","onDragOver","onDrop","onDragEnd","_","idx"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[2693,a=>{"use strict";var b=a.i(87924);let c={live:"bg-success/12 text-success",down:"bg-danger/12 text-danger",warn:"bg-warning/12 text-warning",info:"bg-info/12 text-info",neutral:"bg-surface-2 text-text-muted"};function d({tone:a="neutral",children:e,className:f}){return(0,b.jsx)("span",{className:`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${c[a]}${f?` ${f}`:""}`,children:e})}a.s(["Badge",0,d,"FormatBadge",0,function({format:a}){return(0,b.jsx)(d,{tone:"info",children:a})}])},58918,a=>{"use strict";var b=a.i(87924);a.s(["Empty",0,function({children:a}){return(0,b.jsx)("div",{className:"px-1 py-8 text-center text-[13px] text-text-muted",children:a})},"Stat",0,function({label:a,value:c,sub:d}){return(0,b.jsxs)("div",{className:"rounded-brand-lg border border-border bg-surface px-4 py-3.5 shadow-soft",children:[(0,b.jsx)("div",{className:"text-[11px] font-medium uppercase tracking-wider text-text-subtle",children:a}),(0,b.jsx)("div",{className:"mt-1 tnum text-[22px] font-semibold tracking-tight text-text",children:c}),d&&(0,b.jsx)("div",{className:"mt-0.5 text-[12px] text-text-muted",children:d})]})},"fmt",0,{int:a=>a.toLocaleString("en-US"),compact:a=>Math.abs(a)>=1e6?`${(a/1e6).toFixed(1)}M`:Math.abs(a)>=1e3?`${(a/1e3).toFixed(1)}K`:String(Math.round(a)),cost:a=>0===a?"$0":a<.01?`$${a.toFixed(4)}`:`$${a.toFixed(2)}`,time:a=>new Date(a).toLocaleString("en-US",{hour12:!1}),date(a){let b=new Date(a);return`${String(b.getDate()).padStart(2,"0")}/${String(b.getMonth()+1).padStart(2,"0")}/${b.getFullYear()}`},ago(a){let b=Math.max(0,Math.round((Date.now()-a)/1e3));return b<60?`${b}s`:b<3600?`${Math.floor(b/60)}m`:b<86400?`${Math.floor(b/3600)}h`:`${Math.floor(b/86400)}d`},duration(a){let b=Math.max(0,Math.round(a/1e3));if(b<60)return`${b}s`;if(b<3600)return`${Math.floor(b/60)}m ${b%60}s`;let c=Math.floor(b/3600),d=Math.floor(b%3600/60);if(c<24)return`${c}h ${d}m`;let e=Math.floor(c/24);return`${e}d ${c%24}h`}}])},85732,a=>{"use strict";var b=a.i(87924);a.s(["CardTitle",0,function({title:a,sub:c,icon:d}){return(0,b.jsxs)("div",{className:"flex items-center gap-2.5 min-w-0",children:[d,(0,b.jsxs)("div",{className:"min-w-0",children:[(0,b.jsx)("div",{className:"truncate text-[14px] font-semibold tracking-tight text-text",children:a}),c&&(0,b.jsx)("div",{className:"truncate text-[12px] text-text-muted",children:c})]})]})},"RichCard",0,function({header:a,footer:c,children:d,className:e}){return(0,b.jsxs)("section",{className:`overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft${e?` ${e}`:""}`,children:[a&&(0,b.jsx)("header",{className:"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3",children:a}),(0,b.jsx)("div",{className:"p-4",children:d}),c&&(0,b.jsx)("footer",{className:"flex items-center justify-between gap-3 border-t border-border-subtle bg-bg-alt px-4 py-2.5",children:c})]})}])}];
2
-
3
- //# sourceMappingURL=src_components_17nnhsa._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/Badge.tsx","../../../../src/components/ui.tsx","../../../../src/components/RichCard.tsx"],"sourcesContent":["type Tone = \"live\" | \"down\" | \"warn\" | \"info\" | \"neutral\";\n\nconst TONES: Record<Tone, string> = {\n live: \"bg-success/12 text-success\",\n down: \"bg-danger/12 text-danger\",\n warn: \"bg-warning/12 text-warning\",\n info: \"bg-info/12 text-info\",\n neutral: \"bg-surface-2 text-text-muted\",\n};\n\nexport function Badge({\n tone = \"neutral\",\n children,\n className,\n}: {\n tone?: Tone;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${TONES[tone]}${className ? ` ${className}` : \"\"}`}\n >\n {children}\n </span>\n );\n}\n\n/** Format badge for a provider's wire format. */\nexport function FormatBadge({ format }: { format: \"openai\" | \"anthropic\" | \"gemini\" }) {\n return <Badge tone=\"info\">{format}</Badge>;\n}\n","/** Small formatting helpers shared across the console. */\nexport const fmt = {\n int(n: number): string {\n return n.toLocaleString(\"en-US\");\n },\n /** compact number: 1.2K, 3.4M */\n compact(n: number): string {\n if (Math.abs(n) >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (Math.abs(n) >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return String(Math.round(n));\n },\n cost(n: number): string {\n if (n === 0) return \"$0\";\n return n < 0.01 ? `$${n.toFixed(4)}` : `$${n.toFixed(2)}`;\n },\n time(ts: number): string {\n return new Date(ts).toLocaleString(\"en-US\", { hour12: false });\n },\n /** DD/MM/YYYY (local) */\n date(ts: number): string {\n const d = new Date(ts);\n return `${String(d.getDate()).padStart(2, \"0\")}/${String(d.getMonth() + 1).padStart(2, \"0\")}/${d.getFullYear()}`;\n },\n /** \"3m\", \"2h\", \"5d\" — coarse relative age */\n ago(ts: number): string {\n const s = Math.max(0, Math.round((Date.now() - ts) / 1000));\n if (s < 60) return `${s}s`;\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n },\n /** ms duration -> \"Xs\", \"Xm Ys\", \"Xh Ym\" for budget/cooldown countdowns */\n duration(ms: number): string {\n const s = Math.max(0, Math.round(ms / 1000));\n if (s < 60) return `${s}s`;\n if (s < 3600) return `${Math.floor(s / 60)}m ${s % 60}s`;\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n if (h < 24) return `${h}h ${m}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n },\n};\n\n/** A labelled stat block — number over a caption. */\nexport function Stat({ label, value, sub }: { label: string; value: React.ReactNode; sub?: string }) {\n return (\n <div className=\"rounded-brand-lg border border-border bg-surface px-4 py-3.5 shadow-soft\">\n <div className=\"text-[11px] font-medium uppercase tracking-wider text-text-subtle\">{label}</div>\n <div className=\"mt-1 tnum text-[22px] font-semibold tracking-tight text-text\">{value}</div>\n {sub && <div className=\"mt-0.5 text-[12px] text-text-muted\">{sub}</div>}\n </div>\n );\n}\n\n/** Empty-state hint inside a card body. */\nexport function Empty({ children }: { children: React.ReactNode }) {\n return <div className=\"px-1 py-8 text-center text-[13px] text-text-muted\">{children}</div>;\n}\n","/**\n * Rich content card — header (title slot + trailing slot), body, optional footer.\n * Softly rounded, subtle border, warm surface. The Haulix-style workhorse.\n */\nexport function RichCard({\n header,\n footer,\n children,\n className,\n}: {\n header?: React.ReactNode;\n footer?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <section\n className={`overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft${className ? ` ${className}` : \"\"}`}\n >\n {header && (\n <header className=\"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3\">\n {header}\n </header>\n )}\n <div className=\"p-4\">{children}</div>\n {footer && (\n <footer className=\"flex items-center justify-between gap-3 border-t border-border-subtle bg-bg-alt px-4 py-2.5\">\n {footer}\n </footer>\n )}\n </section>\n );\n}\n\n/** Title + optional subtitle, for the header slot. */\nexport function CardTitle({ title, sub, icon }: { title: string; sub?: string; icon?: React.ReactNode }) {\n return (\n <div className=\"flex items-center gap-2.5 min-w-0\">\n {icon}\n <div className=\"min-w-0\">\n <div className=\"truncate text-[14px] font-semibold tracking-tight text-text\">{title}</div>\n {sub && <div className=\"truncate text-[12px] text-text-muted\">{sub}</div>}\n </div>\n </div>\n );\n}\n"],"names":["TONES","live","down","warn","info","neutral","Badge","tone","children","className","FormatBadge","format","fmt","int","n","toLocaleString","compact","Math","abs","toFixed","String","round","cost","time","ts","Date","hour12","date","d","getDate","padStart","getMonth","getFullYear","ago","s","max","now","floor","duration","ms","h","m","Stat","label","value","sub","Empty","RichCard","header","footer","CardTitle","title","icon"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[47444,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(93026),e=a.i(52065);a.s(["ModelPicker",0,function({title:a="Add models",note:f="Click to add, click again to remove.",searchPlaceholder:g="Search models…",groups:h,selected:i,onToggle:j,onClose:k,showThinkingHint:l=!0}){let[m,n]=(0,c.useState)(""),o=m.trim().toLowerCase(),p=h.map(a=>({...a,items:o?a.items.filter(a=>a.value.toLowerCase().includes(o)):a.items})).filter(a=>a.items.length>0),q=new Set(i);return(0,b.jsx)("div",{className:"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/60 p-6 sm:p-10",onClick:k,children:(0,b.jsxs)("div",{className:"flex max-h-[80vh] w-full max-w-lg flex-col rounded-brand-lg border border-border bg-surface shadow-elevated",onClick:a=>a.stopPropagation(),children:[(0,b.jsxs)("div",{className:"flex items-center justify-between border-b border-border-subtle px-4 py-3",children:[(0,b.jsx)("h2",{className:"text-[14px] font-semibold text-text",children:a}),(0,b.jsx)("button",{onClick:k,className:"text-text-subtle hover:text-text","aria-label":"Close",children:(0,b.jsx)(d.Icon,{name:"close",size:18})})]}),(0,b.jsxs)("div",{className:"border-b border-border-subtle px-4 py-3",children:[(0,b.jsx)("p",{className:"mb-2 text-[12px] text-text-muted",children:f}),(0,b.jsxs)("div",{className:"relative",children:[(0,b.jsx)(d.Icon,{name:"search",size:15,className:"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle"}),(0,b.jsx)("input",{autoFocus:!0,value:m,onChange:a=>n(a.target.value),placeholder:g,className:"w-full rounded-brand border border-border bg-bg py-2 pl-8 pr-3 text-[13px] text-text placeholder:text-text-subtle focus:border-accent focus:outline-none"})]})]}),(0,b.jsx)("div",{className:"flex-1 overflow-y-auto px-4 py-3",children:0===p.length?(0,b.jsxs)("p",{className:"py-6 text-center text-[12.5px] text-text-subtle",children:["No models match “",m,"”."]}):(0,b.jsx)("div",{className:"space-y-4",children:p.map(a=>(0,b.jsxs)("div",{children:[(0,b.jsxs)("div",{className:"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-text-subtle",children:[a.label," ",(0,b.jsxs)("span",{className:"tnum text-text-subtle/70",children:["(",a.items.length,")"]})]}),(0,b.jsx)("div",{className:"flex flex-wrap gap-1.5",children:a.items.map(a=>{let c=q.has(a.value);return(0,b.jsxs)("button",{type:"button",onClick:()=>j(a.value),className:`inline-flex items-center gap-1 rounded-brand border px-2 py-1 text-[12px] transition-colors ${c?"border-accent bg-accent-soft text-accent":"border-border bg-bg text-text-muted hover:border-text-subtle hover:text-text"}`,children:[c&&(0,b.jsx)(d.Icon,{name:"check",size:12}),(0,b.jsx)("span",{className:"tnum",children:a.label}),(0,b.jsx)(e.CapacityBadges,{model:a.value,size:13}),a.tag&&(0,b.jsx)("span",{className:"rounded bg-surface-2 px-1 text-[10px] text-text-subtle",children:a.tag})]},a.value)})})]},a.label))})}),l&&(0,b.jsxs)("div",{className:"border-t border-border-subtle px-4 py-2 text-[11px] text-text-subtle",children:[(0,b.jsx)(d.Icon,{name:"neurology",size:12,className:"mr-1 inline align-text-bottom text-warning"}),"Reasoning models accept a thinking suffix — call"," ",(0,b.jsx)("code",{className:"rounded bg-surface-2 px-1 text-text-muted",children:"model(high)"})," or"," ",(0,b.jsx)("code",{className:"rounded bg-surface-2 px-1 text-text-muted",children:"model(none)"})," (high·low·medium·minimal·auto·none·or a token budget)."]}),(0,b.jsxs)("div",{className:"flex items-center justify-between border-t border-border-subtle px-4 py-3",children:[(0,b.jsxs)("span",{className:"tnum text-[12px] text-text-subtle",children:[i.length," selected"]}),(0,b.jsx)("button",{onClick:k,className:"rounded-brand bg-accent px-3.5 py-1.5 text-[13px] font-semibold text-accent-ink hover:bg-accent-hover",children:"Done"})]})]})})}])},2799,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(93026),e=a.i(58918);a.s(["CooldownTimer",0,function({ms:a,tone:f="danger",icon:g="timer",keepZero:h=!1}){let[i]=(0,c.useState)(()=>Date.now()+a),[j,k]=(0,c.useState)(()=>Math.max(0,a));return((0,c.useEffect)(()=>{let a=()=>k(Math.max(0,i-Date.now()));a();let b=setInterval(a,1e3);return()=>clearInterval(b)},[i]),j<=0&&!h)?null:(0,b.jsxs)("span",{className:`inline-flex items-center gap-1 tnum text-[12px] ${"danger"===f?"text-danger":"text-text-muted"}`,children:[(0,b.jsx)(d.Icon,{name:g,size:13}),j<=0?"now":e.fmt.duration(j)]})}])}];
2
-
3
- //# sourceMappingURL=src_components_1kc5vh2._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/ModelPicker.tsx","../../../../src/components/CooldownTimer.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Icon } from \"@/components/Icon\";\nimport { CapacityBadges } from \"@/components/CapacityBadges\";\n\nexport interface ModelGroup {\n label: string;\n items: { value: string; label: string; tag?: string }[];\n}\n\n/**\n * aigetwey-style model picker: a search box + provider-grouped chips you click to\n * toggle in/out of a selection. Used by the combo form and the CLI-tool model\n * selection so both add models the same way (click to add, click again to drop).\n */\nexport function ModelPicker({\n title = \"Add models\",\n note = \"Click to add, click again to remove.\",\n searchPlaceholder = \"Search models…\",\n groups,\n selected,\n onToggle,\n onClose,\n showThinkingHint = true,\n}: {\n title?: string;\n note?: string;\n searchPlaceholder?: string;\n groups: ModelGroup[];\n selected: string[];\n onToggle: (value: string) => void;\n onClose: () => void;\n /** The \"reasoning models accept a thinking suffix\" footer only makes sense when\n * picking MODELS. Provider/key pickers reuse this component, so they hide it. */\n showThinkingHint?: boolean;\n}) {\n const [q, setQ] = useState(\"\");\n const needle = q.trim().toLowerCase();\n const filtered = groups\n .map((g) => ({\n ...g,\n items: needle ? g.items.filter((i) => i.value.toLowerCase().includes(needle)) : g.items,\n }))\n .filter((g) => g.items.length > 0);\n const sel = new Set(selected);\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/60 p-6 sm:p-10\" onClick={onClose}>\n <div\n className=\"flex max-h-[80vh] w-full max-w-lg flex-col rounded-brand-lg border border-border bg-surface shadow-elevated\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-border-subtle px-4 py-3\">\n <h2 className=\"text-[14px] font-semibold text-text\">{title}</h2>\n <button onClick={onClose} className=\"text-text-subtle hover:text-text\" aria-label=\"Close\">\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n\n <div className=\"border-b border-border-subtle px-4 py-3\">\n <p className=\"mb-2 text-[12px] text-text-muted\">{note}</p>\n <div className=\"relative\">\n <Icon name=\"search\" size={15} className=\"pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-text-subtle\" />\n <input\n autoFocus\n value={q}\n onChange={(e) => setQ(e.target.value)}\n placeholder={searchPlaceholder}\n className=\"w-full rounded-brand border border-border bg-bg py-2 pl-8 pr-3 text-[13px] text-text placeholder:text-text-subtle focus:border-accent focus:outline-none\"\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-4 py-3\">\n {filtered.length === 0 ? (\n <p className=\"py-6 text-center text-[12.5px] text-text-subtle\">No models match “{q}”.</p>\n ) : (\n <div className=\"space-y-4\">\n {filtered.map((g) => (\n <div key={g.label}>\n <div className=\"mb-1.5 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wider text-text-subtle\">\n {g.label} <span className=\"tnum text-text-subtle/70\">({g.items.length})</span>\n </div>\n <div className=\"flex flex-wrap gap-1.5\">\n {g.items.map((it) => {\n const on = sel.has(it.value);\n return (\n <button\n key={it.value}\n type=\"button\"\n onClick={() => onToggle(it.value)}\n className={`inline-flex items-center gap-1 rounded-brand border px-2 py-1 text-[12px] transition-colors ${\n on ? \"border-accent bg-accent-soft text-accent\" : \"border-border bg-bg text-text-muted hover:border-text-subtle hover:text-text\"\n }`}\n >\n {on && <Icon name=\"check\" size={12} />}\n <span className=\"tnum\">{it.label}</span>\n <CapacityBadges model={it.value} size={13} />\n {it.tag && <span className=\"rounded bg-surface-2 px-1 text-[10px] text-text-subtle\">{it.tag}</span>}\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {showThinkingHint && (\n <div className=\"border-t border-border-subtle px-4 py-2 text-[11px] text-text-subtle\">\n <Icon name=\"neurology\" size={12} className=\"mr-1 inline align-text-bottom text-warning\" />\n Reasoning models accept a thinking suffix — call{\" \"}\n <code className=\"rounded bg-surface-2 px-1 text-text-muted\">model(high)</code> or{\" \"}\n <code className=\"rounded bg-surface-2 px-1 text-text-muted\">model(none)</code> (high·low·medium·minimal·auto·none·or a token budget).\n </div>\n )}\n\n <div className=\"flex items-center justify-between border-t border-border-subtle px-4 py-3\">\n <span className=\"tnum text-[12px] text-text-subtle\">{selected.length} selected</span>\n <button onClick={onClose} className=\"rounded-brand bg-accent px-3.5 py-1.5 text-[13px] font-semibold text-accent-ink hover:bg-accent-hover\">\n Done\n </button>\n </div>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { Icon } from \"./Icon\";\nimport { fmt } from \"./ui\";\n\n/**\n * Live countdown from a gateway-snapshot remaining-ms. Counts down locally each\n * second from render. Used for both key cooldowns (danger tone) and budget window\n * resets (muted tone). Renders nothing once it hits zero unless `keepZero`.\n */\nexport function CooldownTimer({\n ms,\n tone = \"danger\",\n icon = \"timer\",\n keepZero = false,\n}: {\n ms: number;\n tone?: \"danger\" | \"muted\";\n icon?: string;\n keepZero?: boolean;\n}) {\n const [until] = useState(() => Date.now() + ms);\n const [remaining, setRemaining] = useState(() => Math.max(0, ms));\n\n useEffect(() => {\n const tick = () => setRemaining(Math.max(0, until - Date.now()));\n tick();\n const id = setInterval(tick, 1000);\n return () => clearInterval(id);\n }, [until]);\n\n if (remaining <= 0 && !keepZero) return null;\n\n const color = tone === \"danger\" ? \"text-danger\" : \"text-text-muted\";\n return (\n <span className={`inline-flex items-center gap-1 tnum text-[12px] ${color}`}>\n <Icon name={icon} size={13} />\n {remaining <= 0 ? \"now\" : fmt.duration(remaining)}\n </span>\n );\n}\n"],"names":["ModelPicker","title","note","searchPlaceholder","groups","selected","onToggle","onClose","showThinkingHint","q","setQ","needle","trim","toLowerCase","filtered","map","g","items","filter","i","value","includes","length","sel","Set","className","onClick","e","stopPropagation","name","size","autoFocus","onChange","target","placeholder","label","it","on","has","type","model","tag","CooldownTimer","ms","tone","icon","keepZero","until","Date","now","remaining","setRemaining","Math","max","tick","id","setInterval","clearInterval","color","duration"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- module.exports=[2693,a=>{"use strict";var b=a.i(87924);let c={live:"bg-success/12 text-success",down:"bg-danger/12 text-danger",warn:"bg-warning/12 text-warning",info:"bg-info/12 text-info",neutral:"bg-surface-2 text-text-muted"};function d({tone:a="neutral",children:e,className:f}){return(0,b.jsx)("span",{className:`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${c[a]}${f?` ${f}`:""}`,children:e})}a.s(["Badge",0,d,"FormatBadge",0,function({format:a}){return(0,b.jsx)(d,{tone:"info",children:a})}])},58918,a=>{"use strict";var b=a.i(87924);a.s(["Empty",0,function({children:a}){return(0,b.jsx)("div",{className:"px-1 py-8 text-center text-[13px] text-text-muted",children:a})},"Stat",0,function({label:a,value:c,sub:d}){return(0,b.jsxs)("div",{className:"rounded-brand-lg border border-border bg-surface px-4 py-3.5 shadow-soft",children:[(0,b.jsx)("div",{className:"text-[11px] font-medium uppercase tracking-wider text-text-subtle",children:a}),(0,b.jsx)("div",{className:"mt-1 tnum text-[22px] font-semibold tracking-tight text-text",children:c}),d&&(0,b.jsx)("div",{className:"mt-0.5 text-[12px] text-text-muted",children:d})]})},"fmt",0,{int:a=>a.toLocaleString("en-US"),compact:a=>Math.abs(a)>=1e6?`${(a/1e6).toFixed(1)}M`:Math.abs(a)>=1e3?`${(a/1e3).toFixed(1)}K`:String(Math.round(a)),cost:a=>0===a?"$0":a<.01?`$${a.toFixed(4)}`:`$${a.toFixed(2)}`,time:a=>new Date(a).toLocaleString("en-US",{hour12:!1}),date(a){let b=new Date(a);return`${String(b.getDate()).padStart(2,"0")}/${String(b.getMonth()+1).padStart(2,"0")}/${b.getFullYear()}`},ago(a){let b=Math.max(0,Math.round((Date.now()-a)/1e3));return b<60?`${b}s`:b<3600?`${Math.floor(b/60)}m`:b<86400?`${Math.floor(b/3600)}h`:`${Math.floor(b/86400)}d`},duration(a){let b=Math.max(0,Math.round(a/1e3));if(b<60)return`${b}s`;if(b<3600)return`${Math.floor(b/60)}m ${b%60}s`;let c=Math.floor(b/3600),d=Math.floor(b%3600/60);if(c<24)return`${c}h ${d}m`;let e=Math.floor(c/24);return`${e}d ${c%24}h`}}])},85732,a=>{"use strict";var b=a.i(87924);a.s(["CardTitle",0,function({title:a,sub:c,icon:d}){return(0,b.jsxs)("div",{className:"flex items-center gap-2.5 min-w-0",children:[d,(0,b.jsxs)("div",{className:"min-w-0",children:[(0,b.jsx)("div",{className:"truncate text-[14px] font-semibold tracking-tight text-text",children:a}),c&&(0,b.jsx)("div",{className:"truncate text-[12px] text-text-muted",children:c})]})]})},"RichCard",0,function({header:a,footer:c,children:d,className:e}){return(0,b.jsxs)("section",{className:`overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft${e?` ${e}`:""}`,children:[a&&(0,b.jsx)("header",{className:"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3",children:a}),(0,b.jsx)("div",{className:"p-4",children:d}),c&&(0,b.jsx)("footer",{className:"flex items-center justify-between gap-3 border-t border-border-subtle bg-bg-alt px-4 py-2.5",children:c})]})}])},52065,55690,a=>{"use strict";var b=a.i(87924);function c(a,b){return RegExp("^"+a.split("*").map(a=>a.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*")+"$","i").test(b)}let d={vision:!1,pdf:!1,audioInput:!1,videoInput:!1,imageOutput:!1,audioOutput:!1,search:!1,tools:!0,reasoning:!1,thinkingFormat:null,thinkingCanDisable:!0,thinkingRange:null,contextWindow:2e5,maxOutput:64e3},e={"claude-opus-4.6":{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive",contextWindow:1e6,maxOutput:128e3},"claude-opus-4.7":{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive",contextWindow:1e6,maxOutput:128e3},"claude-opus-4-6":{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive",contextWindow:1e6,maxOutput:128e3},"claude-sonnet-4.6":{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive",contextWindow:1e6,maxOutput:64e3},"claude-sonnet-4-6":{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive",contextWindow:1e6,maxOutput:64e3},"gpt-image-1":{imageOutput:!0,tools:!1},"glm-4.6v":{vision:!0,reasoning:!0,thinkingFormat:"zai",contextWindow:128e3},"vision-model":{vision:!0,reasoning:!0,thinkingFormat:"qwen",contextWindow:1e6},"coder-model":{reasoning:!0,thinkingFormat:"qwen",contextWindow:1e6}},f={"codebuddy-cn":{"glm-5.2":{reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:1e6,maxOutput:48e3},"glm-5.1":{reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:2e5,maxOutput:48e3},"glm-5.0":{reasoning:!0,thinkingFormat:"openai",contextWindow:2e5,maxOutput:48e3},"glm-5.0-turbo":{reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:2e5,maxOutput:48e3},"glm-5v-turbo":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:2e5,maxOutput:38e3},"glm-4.7":{reasoning:!0,thinkingFormat:"openai",contextWindow:2e5,maxOutput:48e3},"minimax-m3":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:512e3,maxOutput:48e3},"minimax-m2.7":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:2e5,maxOutput:48e3},"kimi-k2.7":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:256e3,maxOutput:32e3},"kimi-k2.6":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:256e3,maxOutput:32e3},"kimi-k2.5":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:164e3,maxOutput:32e3},"hy3-preview":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:192e3,maxOutput:64e3},"deepseek-v4-pro":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:1e6,maxOutput:5e4},"deepseek-v4-flash":{vision:!0,reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:1e6,maxOutput:5e4},"deepseek-v3-2-volc":{reasoning:!0,thinkingFormat:"openai",thinkingCanDisable:!1,contextWindow:96e3,maxOutput:32e3}}},g=[{pattern:"*claude*opus-4.6*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive"}},{pattern:"*claude*opus-4.7*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive"}},{pattern:"*claude*opus-4.8*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive"}},{pattern:"*claude*sonnet-4.6*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive"}},{pattern:"*claude*sonnet-4.7*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-adaptive"}},{pattern:"*claude*haiku*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-budget"}},{pattern:"*claude*opus*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-budget"}},{pattern:"*claude*sonnet*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-budget"}},{pattern:"*claude*fable*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-budget",contextWindow:1e6,maxOutput:128e3}},{pattern:"*claude*mythos*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-budget",contextWindow:1e6,maxOutput:128e3}},{pattern:"*claude-3*",caps:{vision:!0}},{pattern:"*claude*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"claude-budget"}},{pattern:"*gemini*image*",caps:{vision:!0,imageOutput:!0,contextWindow:1048576}},{pattern:"*gemini-3*pro*",caps:{vision:!0,audioInput:!0,videoInput:!0,reasoning:!0,search:!0,thinkingFormat:"gemini-level",thinkingCanDisable:!1,contextWindow:1048576,maxOutput:65535}},{pattern:"*gemini-3*",caps:{vision:!0,audioInput:!0,videoInput:!0,reasoning:!0,search:!0,thinkingFormat:"gemini-level",thinkingCanDisable:!1,contextWindow:1048576,maxOutput:65536}},{pattern:"*gemini-2.5*",caps:{vision:!0,audioInput:!0,videoInput:!0,reasoning:!0,search:!0,thinkingFormat:"gemini-budget",thinkingRange:{min:0,max:24576},contextWindow:1048576,maxOutput:65536}},{pattern:"*gemini-2*",caps:{vision:!0,audioInput:!0,videoInput:!0,search:!0,contextWindow:1048576,maxOutput:65536}},{pattern:"*gemini*",caps:{vision:!0,search:!0,contextWindow:1048576}},{pattern:"*gemma*",caps:{vision:!0,contextWindow:128e3}},{pattern:"*nanobanana*",caps:{vision:!0,imageOutput:!0}},{pattern:"*gpt-5*image*",caps:{imageOutput:!0}},{pattern:"*gpt-5*codex*",caps:{reasoning:!0,search:!0,thinkingFormat:"openai",contextWindow:4e5,maxOutput:128e3}},{pattern:"*gpt-5*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"openai",contextWindow:4e5,maxOutput:128e3}},{pattern:"*gpt-4o*",caps:{vision:!0,search:!0,contextWindow:128e3,maxOutput:16384}},{pattern:"*gpt-4.1*",caps:{vision:!0,contextWindow:1e6,maxOutput:32768}},{pattern:"*gpt-4-turbo*",caps:{vision:!0,contextWindow:128e3}},{pattern:"*gpt-4*",caps:{contextWindow:128e3}},{pattern:"*gpt-3.5*",caps:{contextWindow:16385,maxOutput:4096}},{pattern:"*gpt-oss*",caps:{reasoning:!0,thinkingFormat:"openai",contextWindow:128e3}},{pattern:"*o1-mini*",caps:{reasoning:!0,thinkingFormat:"openai",contextWindow:128e3}},{pattern:"*o1*",caps:{vision:!0,reasoning:!0,thinkingFormat:"openai",contextWindow:2e5,maxOutput:1e5}},{pattern:"*o3*",caps:{vision:!0,reasoning:!0,thinkingFormat:"openai",contextWindow:2e5,maxOutput:1e5}},{pattern:"*o4*",caps:{vision:!0,reasoning:!0,thinkingFormat:"openai",contextWindow:2e5,maxOutput:1e5}},{pattern:"*grok*image*",caps:{imageOutput:!0}},{pattern:"*grok-code*",caps:{reasoning:!0,thinkingFormat:"openai",contextWindow:256e3}},{pattern:"*grok-4*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"openai",contextWindow:256e3}},{pattern:"*grok-3*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"openai",contextWindow:131072}},{pattern:"*grok*",caps:{vision:!0,reasoning:!0,search:!0,thinkingFormat:"openai",contextWindow:256e3}},{pattern:"*qwen*vl*",caps:{vision:!0,reasoning:!0,thinkingFormat:"qwen",contextWindow:262144}},{pattern:"*qwen*max*",caps:{vision:!0,reasoning:!0,thinkingFormat:"qwen",contextWindow:1e6,maxOutput:65536}},{pattern:"*qwen*plus*",caps:{vision:!0,reasoning:!0,thinkingFormat:"qwen",contextWindow:1e6,maxOutput:65536}},{pattern:"*qwen*235b*",caps:{reasoning:!0,thinkingFormat:"qwen",contextWindow:262144}},{pattern:"*qwen*coder*",caps:{reasoning:!0,thinkingFormat:"qwen",contextWindow:1e6}},{pattern:"*qwq*",caps:{reasoning:!0,thinkingFormat:"qwen",thinkingCanDisable:!1,contextWindow:131072}},{pattern:"*qwen*",caps:{reasoning:!0,thinkingFormat:"qwen",contextWindow:262144}},{pattern:"*kimi*k2.7*code*",caps:{vision:!0,reasoning:!0,thinkingFormat:"kimi",thinkingCanDisable:!1,contextWindow:262144,maxOutput:262144}},{pattern:"*kimi*k2*",caps:{vision:!0,reasoning:!0,thinkingFormat:"kimi",contextWindow:262144,maxOutput:262144}},{pattern:"*kimi*",caps:{reasoning:!0,thinkingFormat:"kimi",contextWindow:262144}},{pattern:"*glm-5*",caps:{reasoning:!0,thinkingFormat:"zai",contextWindow:2e5,maxOutput:128e3}},{pattern:"*glm-4.7*",caps:{reasoning:!0,thinkingFormat:"zai",contextWindow:2e5,maxOutput:128e3}},{pattern:"*glm-4*",caps:{reasoning:!0,thinkingFormat:"zai",contextWindow:2e5}},{pattern:"*glm*",caps:{reasoning:!0,thinkingFormat:"zai",contextWindow:2e5}},{pattern:"*deepseek-v4*",caps:{reasoning:!0,thinkingFormat:"deepseek",contextWindow:1e6,maxOutput:384e3}},{pattern:"*reasoner*",caps:{reasoning:!0,thinkingFormat:"deepseek",thinkingCanDisable:!1,contextWindow:128e3}},{pattern:"*deepseek-r*",caps:{reasoning:!0,thinkingFormat:"deepseek",thinkingCanDisable:!1,contextWindow:128e3}},{pattern:"*deepseek-chat*",caps:{contextWindow:128e3}},{pattern:"*deepseek*",caps:{reasoning:!0,thinkingFormat:"deepseek",contextWindow:128e3}},{pattern:"*minimax*image*",caps:{imageOutput:!0}},{pattern:"*minimax-m3*",caps:{vision:!0,reasoning:!0,thinkingFormat:"minimax",contextWindow:1048576,maxOutput:512e3}},{pattern:"*minimax-m2.7*",caps:{reasoning:!0,thinkingFormat:"minimax",thinkingCanDisable:!1,contextWindow:204800,maxOutput:131072}},{pattern:"*minimax*",caps:{reasoning:!0,thinkingFormat:"minimax",thinkingCanDisable:!1,contextWindow:2e5,maxOutput:131072}},{pattern:"*mimo*v2.5*",caps:{vision:!0,contextWindow:1048576,maxOutput:131072}},{pattern:"*mimo*omni*",caps:{vision:!0,audioInput:!0,contextWindow:262144,maxOutput:131072}},{pattern:"*mimo*",caps:{vision:!0,contextWindow:262144,maxOutput:131072}},{pattern:"*llama-4*",caps:{vision:!0,contextWindow:1e6}},{pattern:"*llama*",caps:{contextWindow:128e3}},{pattern:"*codestral*",caps:{contextWindow:256e3}},{pattern:"*mistral-large*",caps:{vision:!0,contextWindow:256e3}},{pattern:"*mistral*",caps:{contextWindow:128e3}},{pattern:"*command-a-vision*",caps:{vision:!0,contextWindow:128e3}},{pattern:"*command*",caps:{contextWindow:128e3}},{pattern:"*sonar*",caps:{search:!0,contextWindow:128e3}},{pattern:"*pplx*",caps:{search:!0,contextWindow:128e3}},{pattern:"*perplexity*",caps:{search:!0,contextWindow:128e3}},{pattern:"*hunyuan*",caps:{reasoning:!0,thinkingFormat:"hunyuan",contextWindow:262144,maxOutput:262144}},{pattern:"hy3*",caps:{reasoning:!0,thinkingFormat:"hunyuan",contextWindow:262144,maxOutput:262144}},{pattern:"*step-*",caps:{reasoning:!0,thinkingFormat:"step",contextWindow:128e3}},{pattern:"*nemotron*",caps:{reasoning:!0,contextWindow:128e3}},{pattern:"*ling-*",caps:{reasoning:!0,contextWindow:128e3}}];function h(a,b){if(!b)return{...d};if(a&&f[a]?.[b])return{...d,...f[a][b]};let h=(b.includes("/")?b.split("/").pop():b)??b;if(e[h])return{...d,...e[h]};if(e[b])return{...d,...e[b]};for(let{pattern:a,caps:e}of g)if(c(a,h)||c(a,b))return{...d,...e};return{...d}}a.s(["getCapabilitiesForModel",0,h,"modalitiesForModel",0,function(a){let b=a.indexOf("/"),c=h(b>0?a.slice(0,b):null,b>0?a.slice(b+1):a),d=["text"];c.vision&&d.push("image"),c.pdf&&d.push("pdf"),c.audioInput&&d.push("audio"),c.videoInput&&d.push("video");let e=["text"];return c.imageOutput&&e.push("image"),c.audioOutput&&e.push("audio"),{input:d,output:e}}],55690);var i=a.i(93026);let j={vision:{icon:"visibility",label:"Vision",desc:"Supports image input",color:"text-info"},reasoning:{icon:"neurology",label:"Reasoning",desc:"Supports reasoning / thinking",color:"text-warning"}};a.s(["CapacityBadges",0,function({model:a,provider:c=null,size:d=15,className:e=""}){let f=h(c,a),g=Object.keys(j).filter(a=>f[a]);return 0===g.length?null:(0,b.jsx)("span",{className:`inline-flex flex-none items-center gap-0.5 ${e}`,children:g.map(a=>(0,b.jsx)("span",{title:`${j[a].label} — ${j[a].desc}`,className:"leading-none",children:(0,b.jsx)(i.Icon,{name:j[a].icon,size:d,className:j[a].color})},a))})}],52065)}];
2
-
3
- //# sourceMappingURL=src_components_1zwow63._.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/components/Badge.tsx","../../../../src/components/ui.tsx","../../../../src/components/RichCard.tsx","../../../../src/lib/capabilities.ts","../../../../src/components/CapacityBadges.tsx"],"sourcesContent":["type Tone = \"live\" | \"down\" | \"warn\" | \"info\" | \"neutral\";\n\nconst TONES: Record<Tone, string> = {\n live: \"bg-success/12 text-success\",\n down: \"bg-danger/12 text-danger\",\n warn: \"bg-warning/12 text-warning\",\n info: \"bg-info/12 text-info\",\n neutral: \"bg-surface-2 text-text-muted\",\n};\n\nexport function Badge({\n tone = \"neutral\",\n children,\n className,\n}: {\n tone?: Tone;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${TONES[tone]}${className ? ` ${className}` : \"\"}`}\n >\n {children}\n </span>\n );\n}\n\n/** Format badge for a provider's wire format. */\nexport function FormatBadge({ format }: { format: \"openai\" | \"anthropic\" | \"gemini\" }) {\n return <Badge tone=\"info\">{format}</Badge>;\n}\n","/** Small formatting helpers shared across the console. */\nexport const fmt = {\n int(n: number): string {\n return n.toLocaleString(\"en-US\");\n },\n /** compact number: 1.2K, 3.4M */\n compact(n: number): string {\n if (Math.abs(n) >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (Math.abs(n) >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n return String(Math.round(n));\n },\n cost(n: number): string {\n if (n === 0) return \"$0\";\n return n < 0.01 ? `$${n.toFixed(4)}` : `$${n.toFixed(2)}`;\n },\n time(ts: number): string {\n return new Date(ts).toLocaleString(\"en-US\", { hour12: false });\n },\n /** DD/MM/YYYY (local) */\n date(ts: number): string {\n const d = new Date(ts);\n return `${String(d.getDate()).padStart(2, \"0\")}/${String(d.getMonth() + 1).padStart(2, \"0\")}/${d.getFullYear()}`;\n },\n /** \"3m\", \"2h\", \"5d\" — coarse relative age */\n ago(ts: number): string {\n const s = Math.max(0, Math.round((Date.now() - ts) / 1000));\n if (s < 60) return `${s}s`;\n if (s < 3600) return `${Math.floor(s / 60)}m`;\n if (s < 86400) return `${Math.floor(s / 3600)}h`;\n return `${Math.floor(s / 86400)}d`;\n },\n /** ms duration -> \"Xs\", \"Xm Ys\", \"Xh Ym\" for budget/cooldown countdowns */\n duration(ms: number): string {\n const s = Math.max(0, Math.round(ms / 1000));\n if (s < 60) return `${s}s`;\n if (s < 3600) return `${Math.floor(s / 60)}m ${s % 60}s`;\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n if (h < 24) return `${h}h ${m}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n },\n};\n\n/** A labelled stat block — number over a caption. */\nexport function Stat({ label, value, sub }: { label: string; value: React.ReactNode; sub?: string }) {\n return (\n <div className=\"rounded-brand-lg border border-border bg-surface px-4 py-3.5 shadow-soft\">\n <div className=\"text-[11px] font-medium uppercase tracking-wider text-text-subtle\">{label}</div>\n <div className=\"mt-1 tnum text-[22px] font-semibold tracking-tight text-text\">{value}</div>\n {sub && <div className=\"mt-0.5 text-[12px] text-text-muted\">{sub}</div>}\n </div>\n );\n}\n\n/** Empty-state hint inside a card body. */\nexport function Empty({ children }: { children: React.ReactNode }) {\n return <div className=\"px-1 py-8 text-center text-[13px] text-text-muted\">{children}</div>;\n}\n","/**\n * Rich content card — header (title slot + trailing slot), body, optional footer.\n * Softly rounded, subtle border, warm surface. The Haulix-style workhorse.\n */\nexport function RichCard({\n header,\n footer,\n children,\n className,\n}: {\n header?: React.ReactNode;\n footer?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <section\n className={`overflow-hidden rounded-brand-lg border border-border bg-surface shadow-soft${className ? ` ${className}` : \"\"}`}\n >\n {header && (\n <header className=\"flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-3\">\n {header}\n </header>\n )}\n <div className=\"p-4\">{children}</div>\n {footer && (\n <footer className=\"flex items-center justify-between gap-3 border-t border-border-subtle bg-bg-alt px-4 py-2.5\">\n {footer}\n </footer>\n )}\n </section>\n );\n}\n\n/** Title + optional subtitle, for the header slot. */\nexport function CardTitle({ title, sub, icon }: { title: string; sub?: string; icon?: React.ReactNode }) {\n return (\n <div className=\"flex items-center gap-2.5 min-w-0\">\n {icon}\n <div className=\"min-w-0\">\n <div className=\"truncate text-[14px] font-semibold tracking-tight text-text\">{title}</div>\n {sub && <div className=\"truncate text-[12px] text-text-muted\">{sub}</div>}\n </div>\n </div>\n );\n}\n","// Model capabilities — what each model can read/do beyond plain text.\n//\n// Fallback order (first match wins), result merged over DEFAULT_CAPABILITIES:\n// 1. PROVIDER_CAPABILITIES[provider][model] — provider-specific override\n// 2. MODEL_CAPABILITIES[model] — canonical exact id (handles exceptions)\n// 3. PATTERN_CAPABILITIES — glob match, ordered specific -> generic\n// 4. DEFAULT_CAPABILITIES — safe floor (always returned)\n//\n// ── HOW TO ADD / UPDATE A MODEL ──────────────────────────────────────\n// Authoritative data source: https://models.dev/api.json (145 providers, 4000+\n// models, MIT). Each model exposes the exact fields we map below:\n// modalities.input [\"text\",\"image\",\"pdf\",\"audio\",\"video\"] -> vision / pdf / audioInput / videoInput\n// modalities.output [\"text\",\"image\",\"audio\"] -> imageOutput / audioOutput\n// reasoning -> reasoning tool_call -> tools\n// limit.context -> contextWindow limit.output -> maxOutput\n// Look up the model id, then:\n// • If a PATTERN below already covers it correctly -> nothing to do.\n// • If it is an exception (pattern would mis-match) -> add an exact entry to\n// MODEL_CAPABILITIES (only the fields that differ from DEFAULT).\n// • If a whole new family -> add an ordered PATTERN (specific before generic).\n// NOTE: models.dev has NO \"search\" flag (web search is a runtime tool, not a\n// model spec); set `search` from vendor docs (Claude 4.x+, GPT-5.x/4o, Gemini\n// 2.0+, Grok, Perplexity). Verify with: curl -s https://models.dev/api.json\n\n\n/**\n * Safe floor — every resolved result is merged over this so consumers\n * never need null-checks. Most modern LLMs meet these limits.\n */\nexport interface Caps {\n vision: boolean;\n pdf: boolean;\n audioInput: boolean;\n videoInput: boolean;\n imageOutput: boolean;\n audioOutput: boolean;\n search: boolean;\n tools: boolean;\n reasoning: boolean;\n thinkingFormat: string | null;\n thinkingCanDisable: boolean;\n thinkingRange: { min: number; max: number } | null;\n contextWindow: number;\n maxOutput: number;\n}\n\n/**\n * Glob (* = wildcard) match, anchored + case-insensitive. aigetwey's\n * pricing.matchPattern so capabilities resolve identically.\n */\nexport function matchPattern(pattern: string, model: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.split(\"*\").map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\".*\") + \"$\",\n \"i\",\n );\n return regex.test(model);\n}\n\nexport const DEFAULT_CAPABILITIES: Caps = {\n // input modalities\n vision: false, // read images\n pdf: false, // read PDF / documents\n audioInput: false, // read audio\n videoInput: false, // read video\n // output modalities\n imageOutput: false, // generate images\n audioOutput: false, // generate audio\n // features\n search: false, // built-in web search tool / grounding\n tools: true, // function / tool calling\n reasoning: false, // thinking / reasoning\n // thinking wire format (only meaningful when reasoning:true). null → derive from transport.format.\n // enum: openai|claude-adaptive|claude-budget|gemini-level|gemini-budget|zai|qwen|deepseek|kimi|minimax|hunyuan|step\n thinkingFormat: null,\n thinkingCanDisable: true, // false → model cannot turn thinking off (clamp to min instead of disable)\n thinkingRange: null, // { min, max } for budget formats; null = no clamp\n // limits (tokens)\n contextWindow: 200000,\n maxOutput: 64000,\n};\n\n// User-added model metadata can carry dashboard service kinds instead of the\n// runtime capability names used here. Map those typed model kinds into input /\n// output capabilities so custom vision models are not treated as text-only.\nconst SERVICE_KIND_CAPABILITIES: Record<string, Partial<Caps>> = {\n imageToText: { vision: true },\n image: { imageOutput: true },\n stt: { audioInput: true },\n tts: { audioOutput: true },\n embedding: { tools: false },\n};\n\nexport function capabilitiesFromServiceKind(kind: string): Partial<Caps> | null {\n return SERVICE_KIND_CAPABILITIES[kind] || null;\n}\n\n/**\n * Canonical exact-id overrides — used for exceptions that patterns would\n * otherwise mis-match. Only declare deltas vs DEFAULT.\n */\nexport const MODEL_CAPABILITIES: Record<string, Partial<Caps>> = {\n // Claude 4.6/4.7 have 1M context + adaptive thinking (override generic claude pattern)\n \"claude-opus-4.6\": { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\", contextWindow: 1000000, maxOutput: 128000 },\n \"claude-opus-4.7\": { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\", contextWindow: 1000000, maxOutput: 128000 },\n \"claude-opus-4-6\": { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\", contextWindow: 1000000, maxOutput: 128000 },\n \"claude-sonnet-4.6\": { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\", contextWindow: 1000000, maxOutput: 64000 },\n \"claude-sonnet-4-6\": { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\", contextWindow: 1000000, maxOutput: 64000 },\n\n // Gemini image-gen / OpenAI image / xai image variants\n \"gpt-image-1\": { imageOutput: true, tools: false },\n\n // GLM vision variant (text GLM has no vision)\n \"glm-4.6v\": { vision: true, reasoning: true, thinkingFormat: \"zai\", contextWindow: 128000 },\n\n // Qwen plain coder/text (no vision) — registry \"vision-model\" / \"coder-model\" aliases\n \"vision-model\": { vision: true, reasoning: true, thinkingFormat: \"qwen\", contextWindow: 1000000 },\n \"coder-model\": { reasoning: true, thinkingFormat: \"qwen\", contextWindow: 1000000 },\n};\n\n/**\n * Provider-specific capability overrides. Keyed by provider alias/id.\n */\nexport const PROVIDER_CAPABILITIES: Record<string, Record<string, Partial<Caps>>> = {\n // CodeBuddy.cn — authoritative per-model metadata from the gateway's model\n // config (contextWindow=maxInputTokens, maxOutput=maxOutputTokens, vision=\n // supportsImages). Every model reasons via OpenAI-style reasoning_effort\n // (see registry thinkingFormat). `onlyReasoning` models can't turn thinking\n // off → thinkingCanDisable:false (clamped to minimal instead of disabled).\n \"codebuddy-cn\": {\n \"glm-5.2\": { reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 1000000, maxOutput: 48000 },\n \"glm-5.1\": { reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 200000, maxOutput: 48000 },\n \"glm-5.0\": { reasoning: true, thinkingFormat: \"openai\", contextWindow: 200000, maxOutput: 48000 },\n \"glm-5.0-turbo\": { reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 200000, maxOutput: 48000 },\n \"glm-5v-turbo\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 200000, maxOutput: 38000 },\n \"glm-4.7\": { reasoning: true, thinkingFormat: \"openai\", contextWindow: 200000, maxOutput: 48000 },\n \"minimax-m3\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 512000, maxOutput: 48000 },\n \"minimax-m2.7\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 200000, maxOutput: 48000 },\n \"kimi-k2.7\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 256000, maxOutput: 32000 },\n \"kimi-k2.6\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 256000, maxOutput: 32000 },\n \"kimi-k2.5\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 164000, maxOutput: 32000 },\n \"hy3-preview\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 192000, maxOutput: 64000 },\n \"deepseek-v4-pro\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 1000000, maxOutput: 50000 },\n \"deepseek-v4-flash\": { vision: true, reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 1000000, maxOutput: 50000 },\n \"deepseek-v3-2-volc\": { reasoning: true, thinkingFormat: \"openai\", thinkingCanDisable: false, contextWindow: 96000, maxOutput: 32000 },\n },\n};\n\n/**\n * Pattern fallback — glob (* = wildcard), matched case-insensitively and\n * anchored (^...$) so a pattern must match the full model id. ORDER MATTERS:\n * vision/specific variants first, text-only/generic families last, to avoid\n * a broad family pattern swallowing an exception (e.g. glm-4.6v vs glm-5).\n */\nexport const PATTERN_CAPABILITIES: Array<{ pattern: string; caps: Partial<Caps> }> = [\n // ── Claude (4.6+ = adaptive thinking; older/haiku = budget) ──────\n { pattern: \"*claude*opus-4.6*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\" } },\n { pattern: \"*claude*opus-4.7*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\" } },\n { pattern: \"*claude*opus-4.8*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\" } },\n { pattern: \"*claude*sonnet-4.6*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\" } },\n { pattern: \"*claude*sonnet-4.7*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-adaptive\" } },\n { pattern: \"*claude*haiku*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-budget\" } },\n { pattern: \"*claude*opus*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-budget\" } },\n { pattern: \"*claude*sonnet*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-budget\" } },\n { pattern: \"*claude*fable*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-budget\", contextWindow: 1000000, maxOutput: 128000 } },\n { pattern: \"*claude*mythos*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-budget\", contextWindow: 1000000, maxOutput: 128000 } },\n { pattern: \"*claude-3*\", caps: { vision: true } },\n { pattern: \"*claude*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"claude-budget\" } },\n\n // ── Gemini (all 2.0+ multimodal + google_search grounding, 1M ctx) ─\n { pattern: \"*gemini*image*\", caps: { vision: true, imageOutput: true, contextWindow: 1048576 } },\n { pattern: \"*gemini-3*pro*\", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: \"gemini-level\", thinkingCanDisable: false, contextWindow: 1048576, maxOutput: 65535 } },\n { pattern: \"*gemini-3*\", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: \"gemini-level\", thinkingCanDisable: false, contextWindow: 1048576, maxOutput: 65536 } },\n { pattern: \"*gemini-2.5*\", caps: { vision: true, audioInput: true, videoInput: true, reasoning: true, search: true, thinkingFormat: \"gemini-budget\", thinkingRange: { min: 0, max: 24576 }, contextWindow: 1048576, maxOutput: 65536 } },\n { pattern: \"*gemini-2*\", caps: { vision: true, audioInput: true, videoInput: true, search: true, contextWindow: 1048576, maxOutput: 65536 } },\n { pattern: \"*gemini*\", caps: { vision: true, search: true, contextWindow: 1048576 } },\n { pattern: \"*gemma*\", caps: { vision: true, contextWindow: 128000 } },\n { pattern: \"*nanobanana*\", caps: { vision: true, imageOutput: true } },\n\n // ── OpenAI GPT-5.x (vision + thinking + web search) ──────────────\n { pattern: \"*gpt-5*image*\", caps: { imageOutput: true } },\n { pattern: \"*gpt-5*codex*\", caps: { reasoning: true, search: true, thinkingFormat: \"openai\", contextWindow: 400000, maxOutput: 128000 } },\n { pattern: \"*gpt-5*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"openai\", contextWindow: 400000, maxOutput: 128000 } },\n { pattern: \"*gpt-4o*\", caps: { vision: true, search: true, contextWindow: 128000, maxOutput: 16384 } },\n { pattern: \"*gpt-4.1*\", caps: { vision: true, contextWindow: 1000000, maxOutput: 32768 } },\n { pattern: \"*gpt-4-turbo*\", caps: { vision: true, contextWindow: 128000 } },\n { pattern: \"*gpt-4*\", caps: { contextWindow: 128000 } },\n { pattern: \"*gpt-3.5*\", caps: { contextWindow: 16385, maxOutput: 4096 } },\n { pattern: \"*gpt-oss*\", caps: { reasoning: true, thinkingFormat: \"openai\", contextWindow: 128000 } },\n\n // ── OpenAI o-series (reasoning, vision) ──────────────────────────\n { pattern: \"*o1-mini*\", caps: { reasoning: true, thinkingFormat: \"openai\", contextWindow: 128000 } },\n { pattern: \"*o1*\", caps: { vision: true, reasoning: true, thinkingFormat: \"openai\", contextWindow: 200000, maxOutput: 100000 } },\n { pattern: \"*o3*\", caps: { vision: true, reasoning: true, thinkingFormat: \"openai\", contextWindow: 200000, maxOutput: 100000 } },\n { pattern: \"*o4*\", caps: { vision: true, reasoning: true, thinkingFormat: \"openai\", contextWindow: 200000, maxOutput: 100000 } },\n\n // ── Grok (vision + Live Search) ──────────────────────────────────\n { pattern: \"*grok*image*\", caps: { imageOutput: true } },\n { pattern: \"*grok-code*\", caps: { reasoning: true, thinkingFormat: \"openai\", contextWindow: 256000 } },\n { pattern: \"*grok-4*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"openai\", contextWindow: 256000 } },\n { pattern: \"*grok-3*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"openai\", contextWindow: 131072 } },\n { pattern: \"*grok*\", caps: { vision: true, reasoning: true, search: true, thinkingFormat: \"openai\", contextWindow: 256000 } },\n\n // ── Qwen (enable_thinking + thinking_budget; QwQ = thinking-only) ─\n { pattern: \"*qwen*vl*\", caps: { vision: true, reasoning: true, thinkingFormat: \"qwen\", contextWindow: 262144 } },\n { pattern: \"*qwen*max*\", caps: { vision: true, reasoning: true, thinkingFormat: \"qwen\", contextWindow: 1000000, maxOutput: 65536 } },\n { pattern: \"*qwen*plus*\", caps: { vision: true, reasoning: true, thinkingFormat: \"qwen\", contextWindow: 1000000, maxOutput: 65536 } },\n { pattern: \"*qwen*235b*\", caps: { reasoning: true, thinkingFormat: \"qwen\", contextWindow: 262144 } },\n { pattern: \"*qwen*coder*\", caps: { reasoning: true, thinkingFormat: \"qwen\", contextWindow: 1000000 } },\n { pattern: \"*qwq*\", caps: { reasoning: true, thinkingFormat: \"qwen\", thinkingCanDisable: false, contextWindow: 131072 } },\n { pattern: \"*qwen*\", caps: { reasoning: true, thinkingFormat: \"qwen\", contextWindow: 262144 } },\n\n // ── Kimi (enabled→reasoning_effort; K2.7-code cannot disable) ─────\n { pattern: \"*kimi*k2.7*code*\", caps: { vision: true, reasoning: true, thinkingFormat: \"kimi\", thinkingCanDisable: false, contextWindow: 262144, maxOutput: 262144 } },\n { pattern: \"*kimi*k2*\", caps: { vision: true, reasoning: true, thinkingFormat: \"kimi\", contextWindow: 262144, maxOutput: 262144 } },\n { pattern: \"*kimi*\", caps: { reasoning: true, thinkingFormat: \"kimi\", contextWindow: 262144 } },\n\n // ── GLM / Z.ai (thinking.enabled; disable via enable_thinking:false) ─\n { pattern: \"*glm-5*\", caps: { reasoning: true, thinkingFormat: \"zai\", contextWindow: 200000, maxOutput: 128000 } },\n { pattern: \"*glm-4.7*\", caps: { reasoning: true, thinkingFormat: \"zai\", contextWindow: 200000, maxOutput: 128000 } },\n { pattern: \"*glm-4*\", caps: { reasoning: true, thinkingFormat: \"zai\", contextWindow: 200000 } },\n { pattern: \"*glm*\", caps: { reasoning: true, thinkingFormat: \"zai\", contextWindow: 200000 } },\n\n // ── DeepSeek (thinking.enabled + reasoning_effort; r1 = thinking-only) ─\n { pattern: \"*deepseek-v4*\", caps: { reasoning: true, thinkingFormat: \"deepseek\", contextWindow: 1000000, maxOutput: 384000 } },\n { pattern: \"*reasoner*\", caps: { reasoning: true, thinkingFormat: \"deepseek\", thinkingCanDisable: false, contextWindow: 128000 } },\n { pattern: \"*deepseek-r*\", caps: { reasoning: true, thinkingFormat: \"deepseek\", thinkingCanDisable: false, contextWindow: 128000 } },\n { pattern: \"*deepseek-chat*\", caps: { contextWindow: 128000 } },\n { pattern: \"*deepseek*\", caps: { reasoning: true, thinkingFormat: \"deepseek\", contextWindow: 128000 } },\n\n // ── MiniMax (M3 = adaptive; M2.x cannot disable) ─────────────────\n { pattern: \"*minimax*image*\", caps: { imageOutput: true } },\n { pattern: \"*minimax-m3*\", caps: { vision: true, reasoning: true, thinkingFormat: \"minimax\", contextWindow: 1048576, maxOutput: 512000 } },\n { pattern: \"*minimax-m2.7*\", caps: { reasoning: true, thinkingFormat: \"minimax\", thinkingCanDisable: false, contextWindow: 204800, maxOutput: 131072 } },\n { pattern: \"*minimax*\", caps: { reasoning: true, thinkingFormat: \"minimax\", thinkingCanDisable: false, contextWindow: 200000, maxOutput: 131072 } },\n\n // ── Xiaomi MiMo (vision, 1M / 262K ctx) ──────────────────────────\n { pattern: \"*mimo*v2.5*\", caps: { vision: true, contextWindow: 1048576, maxOutput: 131072 } },\n { pattern: \"*mimo*omni*\", caps: { vision: true, audioInput: true, contextWindow: 262144, maxOutput: 131072 } },\n { pattern: \"*mimo*\", caps: { vision: true, contextWindow: 262144, maxOutput: 131072 } },\n\n // ── Llama (4 = vision/1M; 3.x = text-only/128K) ──────────────────\n { pattern: \"*llama-4*\", caps: { vision: true, contextWindow: 1000000 } },\n { pattern: \"*llama*\", caps: { contextWindow: 128000 } },\n\n // ── Mistral (Large 3 = vision/256K; codestral text) ──────────────\n { pattern: \"*codestral*\", caps: { contextWindow: 256000 } },\n { pattern: \"*mistral-large*\", caps: { vision: true, contextWindow: 256000 } },\n { pattern: \"*mistral*\", caps: { contextWindow: 128000 } },\n\n // ── Cohere (Command A Vision = vision; others text) ──────────────\n { pattern: \"*command-a-vision*\", caps: { vision: true, contextWindow: 128000 } },\n { pattern: \"*command*\", caps: { contextWindow: 128000 } },\n\n // ── Perplexity (web search native) ───────────────────────────────\n { pattern: \"*sonar*\", caps: { search: true, contextWindow: 128000 } },\n { pattern: \"*pplx*\", caps: { search: true, contextWindow: 128000 } },\n { pattern: \"*perplexity*\", caps: { search: true, contextWindow: 128000 } },\n\n // ── Others ───────────────────────────────────────────────────────\n { pattern: \"*hunyuan*\", caps: { reasoning: true, thinkingFormat: \"hunyuan\", contextWindow: 262144, maxOutput: 262144 } },\n { pattern: \"hy3*\", caps: { reasoning: true, thinkingFormat: \"hunyuan\", contextWindow: 262144, maxOutput: 262144 } },\n { pattern: \"*step-*\", caps: { reasoning: true, thinkingFormat: \"step\", contextWindow: 128000 } },\n { pattern: \"*nemotron*\", caps: { reasoning: true, contextWindow: 128000 } },\n { pattern: \"*ling-*\", caps: { reasoning: true, contextWindow: 128000 } },\n];\n\n/**\n * Resolve capabilities for a model using the 4-step fallback chain,\n * merged over DEFAULT_CAPABILITIES so the result is always complete.\n *\n * @param {string} provider\n * @param {string} model\n * @returns {object} full capabilities object\n */\n/**\n * models.dev-style modalities for a model ref, derived from its capabilities.\n * Ref may be a `provider/model` (vendor prefix tolerated) or a bare combo alias.\n * Mirrors what opencode/aigetwey store per model in opencode.json.\n */\nexport function modalitiesForModel(ref: string): { input: string[]; output: string[] } {\n const slash = ref.indexOf(\"/\");\n const provider = slash > 0 ? ref.slice(0, slash) : null;\n const model = slash > 0 ? ref.slice(slash + 1) : ref;\n const c = getCapabilitiesForModel(provider, model);\n const input = [\"text\"];\n if (c.vision) input.push(\"image\");\n if (c.pdf) input.push(\"pdf\");\n if (c.audioInput) input.push(\"audio\");\n if (c.videoInput) input.push(\"video\");\n const output = [\"text\"];\n if (c.imageOutput) output.push(\"image\");\n if (c.audioOutput) output.push(\"audio\");\n return { input, output };\n}\n\nexport function getCapabilitiesForModel(provider: string | null, model: string): Caps {\n if (!model) return { ...DEFAULT_CAPABILITIES };\n\n // 1. Provider-specific override\n if (provider && PROVIDER_CAPABILITIES[provider]?.[model]) {\n return { ...DEFAULT_CAPABILITIES, ...PROVIDER_CAPABILITIES[provider][model] };\n }\n\n // 2. Canonical exact (strip vendor prefix: \"anthropic/claude-opus-4.7\" -> \"claude-opus-4.7\")\n const baseModel = (model.includes(\"/\") ? model.split(\"/\").pop() : model) ?? model;\n if (MODEL_CAPABILITIES[baseModel]) return { ...DEFAULT_CAPABILITIES, ...MODEL_CAPABILITIES[baseModel] };\n if (MODEL_CAPABILITIES[model]) return { ...DEFAULT_CAPABILITIES, ...MODEL_CAPABILITIES[model] };\n\n // 3. Pattern match (first match wins)\n for (const { pattern, caps } of PATTERN_CAPABILITIES) {\n if (matchPattern(pattern, baseModel) || matchPattern(pattern, model)) {\n return { ...DEFAULT_CAPABILITIES, ...caps };\n }\n }\n\n // 4. Floor\n return { ...DEFAULT_CAPABILITIES };\n}\n","\"use client\";\n\nimport { getCapabilitiesForModel, type Caps } from \"@/lib/capabilities\";\nimport { Icon } from \"@/components/Icon\";\n\n/**\n * Per-model capability icons, aigetwey's own CapacityBadges + CAPACITY_META.\n * Caps are DERIVED from the model id (not stored per-model) via the same resolver\n * aigetwey uses, so badges match wherever the model appears. Only set caps render.\n */\nconst CAPACITY_META: Record<string, { icon: string; label: string; desc: string; color: string }> = {\n vision: { icon: \"visibility\", label: \"Vision\", desc: \"Supports image input\", color: \"text-info\" },\n reasoning: { icon: \"neurology\", label: \"Reasoning\", desc: \"Supports reasoning / thinking\", color: \"text-warning\" },\n};\n\nexport function CapacityBadges({\n model,\n provider = null,\n size = 15,\n className = \"\",\n}: {\n model: string;\n provider?: string | null;\n size?: number;\n className?: string;\n}) {\n const caps = getCapabilitiesForModel(provider, model);\n const active = Object.keys(CAPACITY_META).filter((k) => caps[k as keyof Caps]);\n if (active.length === 0) return null;\n\n return (\n <span className={`inline-flex flex-none items-center gap-0.5 ${className}`}>\n {active.map((k) => (\n <span key={k} title={`${CAPACITY_META[k]!.label} — ${CAPACITY_META[k]!.desc}`} className=\"leading-none\">\n <Icon name={CAPACITY_META[k]!.icon} size={size} className={CAPACITY_META[k]!.color} />\n </span>\n ))}\n </span>\n );\n}\n"],"names":["TONES","live","down","warn","info","neutral","Badge","tone","children","className","FormatBadge","format","fmt","int","n","toLocaleString","compact","Math","abs","toFixed","String","round","cost","time","ts","Date","hour12","date","d","getDate","padStart","getMonth","getFullYear","ago","s","max","now","floor","duration","ms","h","m","Stat","label","value","sub","Empty","RichCard","header","footer","CardTitle","title","icon","matchPattern","pattern","model","regex","RegExp","split","map","replace","join","test","DEFAULT_CAPABILITIES","vision","pdf","audioInput","videoInput","imageOutput","audioOutput","search","tools","reasoning","thinkingFormat","thinkingCanDisable","thinkingRange","contextWindow","maxOutput","SERVICE_KIND_CAPABILITIES","imageToText","image","stt","tts","embedding","capabilitiesFromServiceKind","kind","MODEL_CAPABILITIES","PROVIDER_CAPABILITIES","PATTERN_CAPABILITIES","caps","min","modalitiesForModel","ref","slash","indexOf","provider","slice","c","getCapabilitiesForModel","input","push","output","baseModel","includes","pop"],"mappings":"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"}