@jheavenknows/bluerouter 5.3.16 → 5.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/app/.next-cli-build/BUILD_ID +1 -1
  2. package/app/.next-cli-build/app-path-routes-manifest.json +3 -3
  3. package/app/.next-cli-build/build-manifest.json +2 -2
  4. package/app/.next-cli-build/prerender-manifest.json +1 -1
  5. package/app/.next-cli-build/server/app/(dashboard)/dashboard/ai-power-index/page_client-reference-manifest.js +1 -1
  6. package/app/.next-cli-build/server/app/(dashboard)/dashboard/analytics/page.js +1 -1
  7. package/app/.next-cli-build/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
  8. package/app/.next-cli-build/server/app/(dashboard)/dashboard/api-keys/page_client-reference-manifest.js +1 -1
  9. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  10. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
  11. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  12. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/model-profiles/page_client-reference-manifest.js +1 -1
  13. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
  14. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  15. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cluster/page_client-reference-manifest.js +1 -1
  16. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  17. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  18. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
  19. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  20. package/app/.next-cli-build/server/app/(dashboard)/dashboard/local-ai-report/page_client-reference-manifest.js +1 -1
  21. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  22. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  23. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  24. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  25. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  26. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
  27. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  28. package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudprovider/page_client-reference-manifest.js +1 -1
  29. package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalcloudprovidermonitor/page_client-reference-manifest.js +1 -1
  30. package/app/.next-cli-build/server/app/(dashboard)/dashboard/personalquota/page_client-reference-manifest.js +1 -1
  31. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  32. package/app/.next-cli-build/server/app/(dashboard)/dashboard/prompt-logs/page_client-reference-manifest.js +1 -1
  33. package/app/.next-cli-build/server/app/(dashboard)/dashboard/provider-health/page_client-reference-manifest.js +1 -1
  34. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js +2 -2
  35. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  36. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  37. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  38. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  39. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  40. package/app/.next-cli-build/server/app/(dashboard)/dashboard/resource-monitor/page_client-reference-manifest.js +1 -1
  41. package/app/.next-cli-build/server/app/(dashboard)/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  42. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  43. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
  44. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  45. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  46. package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
  47. package/app/.next-cli-build/server/app/_global-error.html +1 -1
  48. package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
  49. package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
  50. package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  51. package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  52. package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
  53. package/app/.next-cli-build/server/app/_not-found.html +1 -1
  54. package/app/.next-cli-build/server/app/_not-found.rsc +6 -6
  55. package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +6 -6
  56. package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +6 -6
  57. package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  58. package/app/.next-cli-build/server/app/api/auth/ldap/test/route.js.nft.json +1 -1
  59. package/app/.next-cli-build/server/app/api/auth/ldap/users/route.js.nft.json +1 -1
  60. package/app/.next-cli-build/server/app/api/auth/login/route.js.nft.json +1 -1
  61. package/app/.next-cli-build/server/app/api/auth/logout/route.js.nft.json +1 -1
  62. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js.nft.json +1 -1
  63. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js.nft.json +1 -1
  64. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js.nft.json +1 -1
  65. package/app/.next-cli-build/server/app/api/auth/status/route.js.nft.json +1 -1
  66. package/app/.next-cli-build/server/app/api/auth/view-mode/route.js.nft.json +1 -1
  67. package/app/.next-cli-build/server/app/api/branding/[asset]/route.js.nft.json +1 -1
  68. package/app/.next-cli-build/server/app/api/branding/route.js.nft.json +1 -1
  69. package/app/.next-cli-build/server/app/api/branding/upload/route.js.nft.json +1 -1
  70. package/app/.next-cli-build/server/app/api/cli-model-profiles/cloud-models/route.js.nft.json +1 -1
  71. package/app/.next-cli-build/server/app/api/cli-model-profiles/route.js.nft.json +1 -1
  72. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
  73. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
  74. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/autostart/route.js.nft.json +1 -1
  75. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/prompt-log-db/route.js.nft.json +1 -1
  76. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/root-ca/route.js.nft.json +1 -1
  77. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
  78. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js.nft.json +1 -1
  79. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
  80. package/app/.next-cli-build/server/app/api/cluster/config/route.js.nft.json +1 -1
  81. package/app/.next-cli-build/server/app/api/cluster/heartbeat/route.js.nft.json +1 -1
  82. package/app/.next-cli-build/server/app/api/cluster/peers/[id]/command/route.js.nft.json +1 -1
  83. package/app/.next-cli-build/server/app/api/cluster/peers/[id]/route.js.nft.json +1 -1
  84. package/app/.next-cli-build/server/app/api/cluster/peers/route.js.nft.json +1 -1
  85. package/app/.next-cli-build/server/app/api/cluster/snapshot/route.js.nft.json +1 -1
  86. package/app/.next-cli-build/server/app/api/cluster/sync/route.js.nft.json +1 -1
  87. package/app/.next-cli-build/server/app/api/cluster/test/route.js.nft.json +1 -1
  88. package/app/.next-cli-build/server/app/api/combos/[id]/route.js.nft.json +1 -1
  89. package/app/.next-cli-build/server/app/api/combos/route.js.nft.json +1 -1
  90. package/app/.next-cli-build/server/app/api/dashboard/ai-power-index/route.js.nft.json +1 -1
  91. package/app/.next-cli-build/server/app/api/dashboard/analytics/ai-models/route.js.nft.json +1 -1
  92. package/app/.next-cli-build/server/app/api/dashboard/analytics/analyze/route.js.nft.json +1 -1
  93. package/app/.next-cli-build/server/app/api/dashboard/analytics/route.js +1 -1
  94. package/app/.next-cli-build/server/app/api/dashboard/analytics/route.js.nft.json +1 -1
  95. package/app/.next-cli-build/server/app/api/dashboard/combos/route.js.nft.json +1 -1
  96. package/app/.next-cli-build/server/app/api/dashboard/endpoint/route.js.nft.json +1 -1
  97. package/app/.next-cli-build/server/app/api/dashboard/local-ai-report/route.js.nft.json +1 -1
  98. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/[id]/route.js.nft.json +1 -1
  99. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/options/route.js.nft.json +1 -1
  100. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/route.js.nft.json +1 -1
  101. package/app/.next-cli-build/server/app/api/dashboard/token-saver/route.js.nft.json +1 -1
  102. package/app/.next-cli-build/server/app/api/keys/[id]/caveman-test/route.js.nft.json +1 -1
  103. package/app/.next-cli-build/server/app/api/keys/[id]/rotate/route.js.nft.json +1 -1
  104. package/app/.next-cli-build/server/app/api/keys/[id]/route.js.nft.json +1 -1
  105. package/app/.next-cli-build/server/app/api/keys/route.js.nft.json +1 -1
  106. package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js.nft.json +1 -1
  107. package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js.nft.json +1 -1
  108. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js.nft.json +1 -1
  109. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
  110. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js.nft.json +1 -1
  111. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js.nft.json +1 -1
  112. package/app/.next-cli-build/server/app/api/models/alias/route.js.nft.json +1 -1
  113. package/app/.next-cli-build/server/app/api/models/availability/route.js.nft.json +1 -1
  114. package/app/.next-cli-build/server/app/api/models/custom/route.js.nft.json +1 -1
  115. package/app/.next-cli-build/server/app/api/models/disabled/route.js.nft.json +1 -1
  116. package/app/.next-cli-build/server/app/api/models/route.js +1 -1
  117. package/app/.next-cli-build/server/app/api/models/route.js.nft.json +1 -1
  118. package/app/.next-cli-build/server/app/api/models/test/route.js +1 -1
  119. package/app/.next-cli-build/server/app/api/models/test/route.js.nft.json +1 -1
  120. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
  121. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
  122. package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
  123. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
  124. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
  125. package/app/.next-cli-build/server/app/api/oauth/grok-cli/device-code/route.js.nft.json +1 -1
  126. package/app/.next-cli-build/server/app/api/oauth/grok-cli/poll/route.js.nft.json +1 -1
  127. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
  128. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
  129. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
  130. package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/api-key-models/route.js.nft.json +1 -1
  131. package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/import-models/route.js.nft.json +1 -1
  132. package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/models/[...routeModel]/route.js.nft.json +1 -1
  133. package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/move/route.js.nft.json +1 -1
  134. package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/route.js.nft.json +1 -1
  135. package/app/.next-cli-build/server/app/api/personal-cloud-providers/[id]/usage/route.js.nft.json +1 -1
  136. package/app/.next-cli-build/server/app/api/personal-cloud-providers/client/route.js.nft.json +1 -1
  137. package/app/.next-cli-build/server/app/api/personal-cloud-providers/monitor/route.js.nft.json +1 -1
  138. package/app/.next-cli-build/server/app/api/personal-cloud-providers/permissions/route.js.nft.json +1 -1
  139. package/app/.next-cli-build/server/app/api/personal-cloud-providers/route.js.nft.json +1 -1
  140. package/app/.next-cli-build/server/app/api/personal-cloud-providers/routing/route.js.nft.json +1 -1
  141. package/app/.next-cli-build/server/app/api/personal-cloud-providers/shares/route.js.nft.json +1 -1
  142. package/app/.next-cli-build/server/app/api/personal-cloud-providers/visibility/route.js.nft.json +1 -1
  143. package/app/.next-cli-build/server/app/api/pricing/catalog/route.js.nft.json +1 -1
  144. package/app/.next-cli-build/server/app/api/pricing/recalculate/route.js.nft.json +1 -1
  145. package/app/.next-cli-build/server/app/api/pricing/route.js.nft.json +1 -1
  146. package/app/.next-cli-build/server/app/api/provider-health/route.js.nft.json +1 -1
  147. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js +1 -1
  148. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
  149. package/app/.next-cli-build/server/app/api/provider-nodes/route.js +1 -1
  150. package/app/.next-cli-build/server/app/api/provider-nodes/route.js.nft.json +1 -1
  151. package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
  152. package/app/.next-cli-build/server/app/api/providers/[id]/route.js.nft.json +1 -1
  153. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
  154. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js +1 -1
  155. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
  156. package/app/.next-cli-build/server/app/api/providers/client/route.js.nft.json +1 -1
  157. package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
  158. package/app/.next-cli-build/server/app/api/providers/route.js.nft.json +1 -1
  159. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js.nft.json +1 -1
  160. package/app/.next-cli-build/server/app/api/providers/validate/route.js.nft.json +1 -1
  161. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
  162. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
  163. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js.nft.json +1 -1
  164. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js.nft.json +1 -1
  165. package/app/.next-cli-build/server/app/api/proxy-pools/route.js.nft.json +1 -1
  166. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js.nft.json +1 -1
  167. package/app/.next-cli-build/server/app/api/resource-monitor/[id]/route.js.nft.json +1 -1
  168. package/app/.next-cli-build/server/app/api/resource-monitor/ai-models/route.js.nft.json +1 -1
  169. package/app/.next-cli-build/server/app/api/resource-monitor/analyze/route.js.nft.json +1 -1
  170. package/app/.next-cli-build/server/app/api/resource-monitor/history/route.js.nft.json +1 -1
  171. package/app/.next-cli-build/server/app/api/resource-monitor/route.js.nft.json +1 -1
  172. package/app/.next-cli-build/server/app/api/settings/database/route.js.nft.json +1 -1
  173. package/app/.next-cli-build/server/app/api/settings/require-login/route.js.nft.json +1 -1
  174. package/app/.next-cli-build/server/app/api/settings/route.js.nft.json +1 -1
  175. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
  176. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
  177. package/app/.next-cli-build/server/app/api/translator/send/route.js.nft.json +1 -1
  178. package/app/.next-cli-build/server/app/api/translator/translate/route.js.nft.json +1 -1
  179. package/app/.next-cli-build/server/app/api/tunnel/disable/route.js.nft.json +1 -1
  180. package/app/.next-cli-build/server/app/api/tunnel/enable/route.js.nft.json +1 -1
  181. package/app/.next-cli-build/server/app/api/tunnel/status/route.js.nft.json +1 -1
  182. package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route.js.nft.json +1 -1
  183. package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route.js.nft.json +1 -1
  184. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js.nft.json +1 -1
  185. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js.nft.json +1 -1
  186. package/app/.next-cli-build/server/app/api/tunnel/tailscale-login/route.js.nft.json +1 -1
  187. package/app/.next-cli-build/server/app/api/tunnel/tailscale-start-daemon/route.js.nft.json +1 -1
  188. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
  189. package/app/.next-cli-build/server/app/api/usage/chart/route.js.nft.json +1 -1
  190. package/app/.next-cli-build/server/app/api/usage/history/route.js.nft.json +1 -1
  191. package/app/.next-cli-build/server/app/api/usage/providers/route.js.nft.json +1 -1
  192. package/app/.next-cli-build/server/app/api/usage/request-details/route.js.nft.json +1 -1
  193. package/app/.next-cli-build/server/app/api/usage/request-logs/route.js.nft.json +1 -1
  194. package/app/.next-cli-build/server/app/api/usage/stats/route.js +1 -1
  195. package/app/.next-cli-build/server/app/api/usage/stats/route.js.nft.json +1 -1
  196. package/app/.next-cli-build/server/app/api/usage/stream/route.js.nft.json +1 -1
  197. package/app/.next-cli-build/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  198. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
  199. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
  200. package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  201. package/app/.next-cli-build/server/app/api/v1/embeddings/route.js.nft.json +1 -1
  202. package/app/.next-cli-build/server/app/api/v1/images/generations/route.js.nft.json +1 -1
  203. package/app/.next-cli-build/server/app/api/v1/messages/route.js.nft.json +1 -1
  204. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
  205. package/app/.next-cli-build/server/app/api/v1/models/route.js.nft.json +1 -1
  206. package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
  207. package/app/.next-cli-build/server/app/api/v1/responses/route.js.nft.json +1 -1
  208. package/app/.next-cli-build/server/app/api/v1/route.js.nft.json +1 -1
  209. package/app/.next-cli-build/server/app/api/v1/search/route.js.nft.json +1 -1
  210. package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
  211. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  212. package/app/.next-cli-build/server/app/api/v1beta/models/route.js.nft.json +1 -1
  213. package/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
  214. package/app/.next-cli-build/server/app/api/version/shutdown/route.js.nft.json +1 -1
  215. package/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
  216. package/app/.next-cli-build/server/app/api/version/update/route.js.nft.json +1 -1
  217. package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
  218. package/app/.next-cli-build/server/app/callback.html +1 -1
  219. package/app/.next-cli-build/server/app/callback.rsc +6 -6
  220. package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +6 -6
  221. package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +2 -2
  222. package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +6 -6
  223. package/app/.next-cli-build/server/app/dashboard/ai-power-index.html +1 -1
  224. package/app/.next-cli-build/server/app/dashboard/ai-power-index.rsc +7 -7
  225. package/app/.next-cli-build/server/app/dashboard/ai-power-index.segments/!KGRhc2hib2FyZCk/dashboard/ai-power-index/__PAGE__.segment.rsc +7 -7
  226. package/app/.next-cli-build/server/app/dashboard/ai-power-index.segments/_full.segment.rsc +7 -7
  227. package/app/.next-cli-build/server/app/dashboard/ai-power-index.segments/_tree.segment.rsc +2 -2
  228. package/app/.next-cli-build/server/app/dashboard/analytics.html +1 -1
  229. package/app/.next-cli-build/server/app/dashboard/analytics.rsc +21 -20
  230. package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics/__PAGE__.segment.rsc +30 -29
  231. package/app/.next-cli-build/server/app/dashboard/analytics.segments/_full.segment.rsc +21 -20
  232. package/app/.next-cli-build/server/app/dashboard/analytics.segments/_tree.segment.rsc +2 -2
  233. package/app/.next-cli-build/server/app/dashboard/api-keys.html +1 -1
  234. package/app/.next-cli-build/server/app/dashboard/api-keys.rsc +10 -10
  235. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard/api-keys/__PAGE__.segment.rsc +10 -10
  236. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_full.segment.rsc +10 -10
  237. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_tree.segment.rsc +2 -2
  238. package/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
  239. package/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +8 -8
  240. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +8 -8
  241. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +8 -8
  242. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +2 -2
  243. package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.html +1 -1
  244. package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.rsc +8 -8
  245. package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/model-profiles/__PAGE__.segment.rsc +8 -8
  246. package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.segments/_full.segment.rsc +8 -8
  247. package/app/.next-cli-build/server/app/dashboard/cli-tools/model-profiles.segments/_tree.segment.rsc +2 -2
  248. package/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
  249. package/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +8 -8
  250. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +8 -8
  251. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +8 -8
  252. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
  253. package/app/.next-cli-build/server/app/dashboard/cluster.html +1 -1
  254. package/app/.next-cli-build/server/app/dashboard/cluster.rsc +7 -7
  255. package/app/.next-cli-build/server/app/dashboard/cluster.segments/!KGRhc2hib2FyZCk/dashboard/cluster/__PAGE__.segment.rsc +7 -7
  256. package/app/.next-cli-build/server/app/dashboard/cluster.segments/_full.segment.rsc +7 -7
  257. package/app/.next-cli-build/server/app/dashboard/cluster.segments/_tree.segment.rsc +2 -2
  258. package/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
  259. package/app/.next-cli-build/server/app/dashboard/combos.rsc +8 -8
  260. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +8 -8
  261. package/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +8 -8
  262. package/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
  263. package/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
  264. package/app/.next-cli-build/server/app/dashboard/endpoint.rsc +8 -8
  265. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +8 -8
  266. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +8 -8
  267. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
  268. package/app/.next-cli-build/server/app/dashboard/local-ai-report.html +1 -1
  269. package/app/.next-cli-build/server/app/dashboard/local-ai-report.rsc +7 -7
  270. package/app/.next-cli-build/server/app/dashboard/local-ai-report.segments/!KGRhc2hib2FyZCk/dashboard/local-ai-report/__PAGE__.segment.rsc +7 -7
  271. package/app/.next-cli-build/server/app/dashboard/local-ai-report.segments/_full.segment.rsc +7 -7
  272. package/app/.next-cli-build/server/app/dashboard/local-ai-report.segments/_tree.segment.rsc +2 -2
  273. package/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
  274. package/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +8 -8
  275. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +8 -8
  276. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +8 -8
  277. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +2 -2
  278. package/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
  279. package/app/.next-cli-build/server/app/dashboard/mitm.rsc +8 -8
  280. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +8 -8
  281. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +8 -8
  282. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
  283. package/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
  284. package/app/.next-cli-build/server/app/dashboard/profile.rsc +8 -8
  285. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +8 -8
  286. package/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +8 -8
  287. package/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
  288. package/app/.next-cli-build/server/app/dashboard/prompt-logs.html +1 -1
  289. package/app/.next-cli-build/server/app/dashboard/prompt-logs.rsc +7 -7
  290. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard/prompt-logs/__PAGE__.segment.rsc +7 -7
  291. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_full.segment.rsc +7 -7
  292. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_tree.segment.rsc +2 -2
  293. package/app/.next-cli-build/server/app/dashboard/provider-health.html +1 -1
  294. package/app/.next-cli-build/server/app/dashboard/provider-health.rsc +7 -7
  295. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard/provider-health/__PAGE__.segment.rsc +7 -7
  296. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_full.segment.rsc +7 -7
  297. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_tree.segment.rsc +2 -2
  298. package/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
  299. package/app/.next-cli-build/server/app/dashboard/providers/new.rsc +8 -8
  300. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +8 -8
  301. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +8 -8
  302. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
  303. package/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
  304. package/app/.next-cli-build/server/app/dashboard/providers.rsc +8 -8
  305. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +8 -8
  306. package/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +8 -8
  307. package/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
  308. package/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
  309. package/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +8 -8
  310. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +8 -8
  311. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +8 -8
  312. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
  313. package/app/.next-cli-build/server/app/dashboard/quota.html +1 -1
  314. package/app/.next-cli-build/server/app/dashboard/quota.rsc +9 -9
  315. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +9 -9
  316. package/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +9 -9
  317. package/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
  318. package/app/.next-cli-build/server/app/dashboard/resource-monitor.html +1 -1
  319. package/app/.next-cli-build/server/app/dashboard/resource-monitor.rsc +7 -7
  320. package/app/.next-cli-build/server/app/dashboard/resource-monitor.segments/!KGRhc2hib2FyZCk/dashboard/resource-monitor/__PAGE__.segment.rsc +7 -7
  321. package/app/.next-cli-build/server/app/dashboard/resource-monitor.segments/_full.segment.rsc +7 -7
  322. package/app/.next-cli-build/server/app/dashboard/resource-monitor.segments/_tree.segment.rsc +2 -2
  323. package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
  324. package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +7 -7
  325. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/!KGRhc2hib2FyZCk/dashboard/settings/pricing/__PAGE__.segment.rsc +7 -7
  326. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +7 -7
  327. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
  328. package/app/.next-cli-build/server/app/dashboard/skills.html +1 -1
  329. package/app/.next-cli-build/server/app/dashboard/skills.rsc +8 -8
  330. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +8 -8
  331. package/app/.next-cli-build/server/app/dashboard/skills.segments/_full.segment.rsc +8 -8
  332. package/app/.next-cli-build/server/app/dashboard/skills.segments/_tree.segment.rsc +2 -2
  333. package/app/.next-cli-build/server/app/dashboard/token-saver.html +1 -1
  334. package/app/.next-cli-build/server/app/dashboard/token-saver.rsc +7 -7
  335. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +7 -7
  336. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_full.segment.rsc +7 -7
  337. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_tree.segment.rsc +2 -2
  338. package/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
  339. package/app/.next-cli-build/server/app/dashboard/translator.rsc +8 -8
  340. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +8 -8
  341. package/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +8 -8
  342. package/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
  343. package/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
  344. package/app/.next-cli-build/server/app/dashboard/usage.rsc +8 -8
  345. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +8 -8
  346. package/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +8 -8
  347. package/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
  348. package/app/.next-cli-build/server/app/dashboard.html +1 -1
  349. package/app/.next-cli-build/server/app/dashboard.rsc +8 -8
  350. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +8 -8
  351. package/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +8 -8
  352. package/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +2 -2
  353. package/app/.next-cli-build/server/app/index.html +1 -1
  354. package/app/.next-cli-build/server/app/index.rsc +6 -6
  355. package/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +6 -6
  356. package/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +6 -6
  357. package/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +2 -2
  358. package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
  359. package/app/.next-cli-build/server/app/landing.html +1 -1
  360. package/app/.next-cli-build/server/app/landing.rsc +6 -6
  361. package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +6 -6
  362. package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +2 -2
  363. package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +6 -6
  364. package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
  365. package/app/.next-cli-build/server/app/login.html +1 -1
  366. package/app/.next-cli-build/server/app/login.rsc +7 -7
  367. package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +7 -7
  368. package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +2 -2
  369. package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +7 -7
  370. package/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
  371. package/app/.next-cli-build/server/app-paths-manifest.json +3 -3
  372. package/app/.next-cli-build/server/chunks/3110.js +1 -1
  373. package/app/.next-cli-build/server/chunks/4746.js +1 -1
  374. package/app/.next-cli-build/server/chunks/6328.js +1 -1
  375. package/app/.next-cli-build/server/chunks/6811.js +1 -1
  376. package/app/.next-cli-build/server/chunks/7639.js +1 -1
  377. package/app/.next-cli-build/server/chunks/8640.js +1 -1
  378. package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
  379. package/app/.next-cli-build/server/pages/404.html +1 -1
  380. package/app/.next-cli-build/server/pages/500.html +1 -1
  381. package/app/.next-cli-build/static/chunks/{5263-d6ee4d6284abc821.js → 5263-3ec89c2144054b5f.js} +1 -1
  382. package/app/.next-cli-build/static/chunks/{5497-4faec8cfb542e7f8.js → 5497-71bd777d42ea46eb.js} +3 -3
  383. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/analytics/page-8eac9d90ebe66246.js +1 -0
  384. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/[id]/page-aaacd3d160675084.js +3 -0
  385. package/app/.next-cli-build/static/css/812a1f04de679632.css +1 -0
  386. package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-5.3.12-to-5.3.13-5.3.13-20260817-131047 → upgrade-5.3.15-to-5.3.16-5.3.16-20260817-162040}/data.sqlite +0 -0
  387. package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-5.3.11-to-5.3.12-5.3.12-20260817-125752 → upgrade-5.3.16-to-5.3.17-5.3.17-20260817-180200}/data.sqlite +0 -0
  388. package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite +0 -0
  389. package/app/package.json +1 -1
  390. package/package.json +1 -1
  391. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/analytics/page-85b4d203c77b909e.js +0 -1
  392. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/[id]/page-186e77449213e15b.js +0 -3
  393. package/app/.next-cli-build/static/css/f104d6561e81b0ac.css +0 -1
  394. /package/app/.next-cli-build/static/{ipwfbIyh2BtaRvddGx6I8 → yI2CHS4xc2s5mrkJyZgF-}/_buildManifest.js +0 -0
  395. /package/app/.next-cli-build/static/{ipwfbIyh2BtaRvddGx6I8 → yI2CHS4xc2s5mrkJyZgF-}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8978],{52355:(e,t,s)=>{Promise.resolve().then(s.bind(s,76174)),Promise.resolve().then(s.bind(s,85881))},76174:(e,t,s)=>{"use strict";s.d(t,{default:()=>eg});var n=s(95155),l=s(12115),r=s(9233),a=s(94027);function i(e){let t=Number(e);return Number.isFinite(t)?t:0}function o(e,t=0){return i(e).toLocaleString("vi-VN",{maximumFractionDigits:t})}function d(e){return new Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(i(e))}function c(e){let t=Number(e);return!Number.isFinite(t)||t<=0?"-":t>=1e3?`${(t/1e3).toLocaleString("vi-VN",{maximumFractionDigits:2})} s`:`${Math.round(t)} ms`}function x(e){let t=Number(e);return Number.isFinite(t)&&t>0?`${t.toLocaleString("vi-VN",{maximumFractionDigits:1})} tok/s`:"-"}function m(e){return`$${i(e).toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:4})}`}function u({row:e}){return(0,n.jsxs)("div",{className:"min-w-[105px] text-xs tabular-nums",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:d(e.totalTokens)}),(0,n.jsxs)("div",{className:"text-text-muted",children:["in ",d(e.promptTokens)," \xb7 out ",d(e.completionTokens)]})]})}function h({label:e,value:t,hint:s}){return(0,n.jsxs)("div",{className:"rounded-xl border border-border bg-background/55 px-3 py-2.5",children:[(0,n.jsx)("div",{className:"text-[10px] font-semibold uppercase tracking-wide text-text-muted",children:e}),(0,n.jsx)("div",{className:"mt-1 text-lg font-semibold tabular-nums text-text-main",children:t}),s?(0,n.jsx)("div",{className:"mt-0.5 text-[10px] text-text-muted",children:s}):null]})}function p({rows:e,cloud:t}){return e.length?(0,n.jsx)("div",{className:"overflow-x-auto overflow-y-auto rounded-2xl border border-border",style:{maxHeight:"520px"},children:(0,n.jsxs)("table",{className:"min-w-[1080px] w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"sticky top-0 z-10 bg-background/95 backdrop-blur",children:(0,n.jsxs)("tr",{children:[(0,n.jsx)("th",{className:"px-3 py-2.5 text-left text-xs font-semibold text-text-muted",children:"Model / Provider"}),(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"Req"}),(0,n.jsx)("th",{className:"px-3 py-2.5 text-left text-xs font-semibold text-text-muted",children:"Tokens"}),(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"Error"}),(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"P95 latency"}),(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"P95 TTFT"}),(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"Output speed"}),t?(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"Cost"}):null,(0,n.jsx)("th",{className:"px-3 py-2.5 text-right text-xs font-semibold text-text-muted",children:"Last used"})]})}),(0,n.jsx)("tbody",{className:"divide-y divide-border/70",children:e.map(e=>{let s,l,r=(s=i(e.requests),l=i(e.errors),s>0?l/s:i(e.errorRate));return(0,n.jsxs)("tr",{className:"hover:bg-background/50",children:[(0,n.jsxs)("td",{className:"px-3 py-2.5",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.model||e.label||"unknown"}),(0,n.jsx)("div",{className:"mt-0.5 text-xs text-text-muted",children:e.providerLabel||e.provider||"unknown"})]}),(0,n.jsx)("td",{className:"px-3 py-2.5 text-right tabular-nums",children:o(e.requests)}),(0,n.jsx)("td",{className:"px-3 py-2.5",children:(0,n.jsx)(u,{row:e})}),(0,n.jsx)("td",{className:"px-3 py-2.5 text-right",children:(0,n.jsxs)("span",{className:r>=.05?"text-red-500":r>0?"text-amber-500":"text-emerald-500",children:[(100*r).toLocaleString("vi-VN",{maximumFractionDigits:1}),"%"]})}),(0,n.jsx)("td",{className:"px-3 py-2.5 text-right tabular-nums",children:c(e.p95LatencyMs)}),(0,n.jsx)("td",{className:"px-3 py-2.5 text-right tabular-nums",children:c(e.p95TtftMs)}),(0,n.jsx)("td",{className:"px-3 py-2.5 text-right font-semibold tabular-nums",children:x(e.outputTokensPerSecond)}),t?(0,n.jsx)("td",{className:"px-3 py-2.5 text-right tabular-nums text-emerald-600 dark:text-emerald-300",children:m(e.cost)}):null,(0,n.jsx)("td",{className:"px-3 py-2.5 text-right text-xs text-text-muted",children:function(e){if(!e)return"-";let t=new Date(e);return Number.isNaN(t.getTime())?String(e):t.toLocaleString("vi-VN")}(e.lastSeen)})]},e.key||`${e.provider}-${e.model}`)})})]})}):(0,n.jsxs)("div",{className:"rounded-2xl border border-dashed border-border px-4 py-7 text-center text-sm text-text-muted",children:["Kh\xf4ng c\xf3 model ",t?"cloud":"local"," trong khoảng lọc hiện tại."]})}function b({type:e,rows:t,summary:s}){let l="local"===e;return(0,n.jsxs)("section",{className:"rounded-3xl border border-border bg-surface p-5 shadow-[var(--shadow-soft)]",children:[(0,n.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,n.jsxs)("div",{className:"flex items-start gap-3",children:[(0,n.jsx)("div",{className:`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ${l?"bg-primary/10 text-primary":"bg-amber-500/10 text-amber-600 dark:text-amber-300"}`,children:(0,n.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:l?"developer_board":"cloud"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:l?"Local Models":"Cloud Models"}),(0,n.jsx)("p",{className:"mt-0.5 text-xs text-text-muted",children:l?"Self-hosted inference: vLLM, SGLang, Ollama, llama.cpp hoặc compatible endpoint được đ\xe1nh dấu Local.":"External/cloud API providers, kể cả compatible endpoint được đ\xe1nh dấu Cloud."})]})]}),(0,n.jsxs)("span",{className:"rounded-full border border-border bg-background px-3 py-1 text-xs font-semibold text-text-muted",children:[o(s.models??t.length)," models"]})]}),(0,n.jsxs)("div",{className:"mb-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4",children:[(0,n.jsx)(h,{label:"Requests",value:o(s.requests)}),(0,n.jsx)(h,{label:"Total tokens",value:d(s.totalTokens),hint:`In ${d(s.promptTokens)} \xb7 Out ${d(s.completionTokens)}`}),l?(0,n.jsx)(h,{label:"Output speed",value:x(s.outputTokensPerSecond),hint:"Aggregate từ model experience"}):(0,n.jsx)(h,{label:"Estimated cost",value:m(s.cost)}),(0,n.jsx)(h,{label:l?"Estimated cost":"Output speed",value:l?m(s.cost):x(s.outputTokensPerSecond)})]}),(0,n.jsx)(p,{rows:t,cloud:!l})]})}function g({data:e}){let t=e?.groups||{},s=e?.deploymentAnalytics||{},l=t.localModels||[],r=t.cloudModels||[],a=t.unknownModels||[];return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsx)(b,{type:"local",rows:l,summary:s.local||{}}),(0,n.jsx)(b,{type:"cloud",rows:r,summary:s.cloud||{}}),a.length>0?(0,n.jsx)("div",{className:"rounded-2xl border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-sm text-amber-700 dark:text-amber-300",children:(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[20px]",children:"warning"}),(0,n.jsxs)("div",{children:[(0,n.jsxs)("div",{className:"font-semibold",children:[o(a.length)," model chưa x\xe1c định Local / Cloud"]}),(0,n.jsx)("div",{className:"mt-0.5 text-xs opacity-90",children:"Mở Custom Provider tương ứng v\xe0 chọn Deployment để số liệu kh\xf4ng bị gộp sai."})]})]})}):null]})}r.xI.setOptions({gfm:!0,breaks:!0});let j=[{value:"today",label:"H\xf4m nay"},{value:"todayWorking",label:"H\xf4m nay (Working time)"},{value:"yesterday",label:"H\xf4m qua"},{value:"yesterdayWorking",label:"H\xf4m qua (Working time)"},{value:"24h",label:"24 giờ"},{value:"thisWeek",label:"Tuần n\xe0y"},{value:"lastWeek",label:"Tuần trước"},{value:"7d",label:"7 ng\xe0y"},{value:"thisMonth",label:"Th\xe1ng n\xe0y"},{value:"lastMonth",label:"Th\xe1ng trước"},{value:"30d",label:"30 ng\xe0y"},{value:"60d",label:"60 ng\xe0y"},{value:"all",label:"Tất cả (60 ng\xe0y)"},{value:"custom",label:"T\xf9y chọn"}],y=[{value:"overview",label:"Tổng quan",icon:"dashboard"},{value:"apiKeys",label:"API keys",icon:"vpn_key"},{value:"clients",label:"Client/User",icon:"groups"},{value:"sources",label:"Source IP / Tool",icon:"hub"},{value:"providers",label:"Provider / Model",icon:"dns"},{value:"experience",label:"Trải nghiệm",icon:"speed"},{value:"errors",label:"Lỗi & bất thường",icon:"warning"},{value:"raw",label:"Raw usage",icon:"table"},{value:"aiHealth",label:"Đ\xe1nh gi\xe1 AI",icon:"neurology"}],v="blueRouterAnalyticsTab",k={normal:{className:"border-emerald-500/20 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",label:"B\xecnh thường"},warning:{className:"border-amber-500/20 bg-amber-500/10 text-amber-700 dark:text-amber-300",label:"Cảnh b\xe1o"},critical:{className:"border-red-500/20 bg-red-500/10 text-red-700 dark:text-red-300",label:"Nghi\xeam trọng"},no_traffic:{className:"border-border bg-surface-2 text-text-muted",label:"Kh\xf4ng c\xf3 lưu lượng"},unknown:{className:"border-border bg-surface-2 text-text-muted",label:"Kh\xf4ng r\xf5"}};function f({status:e}){let t=k[e]||k.unknown;return(0,n.jsxs)("span",{className:F("inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-semibold",t.className),children:[(0,n.jsx)("span",{className:"h-1.5 w-1.5 rounded-full bg-current"}),t.label]})}function N(e){let t=Number(e||0);if(!t)return"-";let s=["B","KiB","MiB","GiB","TiB"],n=Math.min(Math.floor(Math.log(t)/Math.log(1024)),s.length-1);return`${(t/1024**n).toLocaleString("vi-VN",{maximumFractionDigits:1})} ${s[n]}`}function w({nodes:e=[]}){return e.length?(0,n.jsxs)("section",{className:"border-y border-border py-4",children:[(0,n.jsxs)("div",{className:"mb-3 flex items-center gap-2",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[19px] text-primary",children:"developer_board"}),(0,n.jsx)("h4",{className:"text-sm font-semibold text-text-main",children:"Cấu h\xecnh phần cứng từng node tại l\xfac đ\xe1nh gi\xe1"})]}),(0,n.jsx)("div",{className:"divide-y divide-border",children:e.map(e=>(0,n.jsxs)("div",{className:"grid gap-2 py-3 text-xs md:grid-cols-[minmax(180px,0.8fr)_minmax(0,2.2fr)]",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.name}),(0,n.jsx)("div",{className:"mt-0.5 text-text-muted",children:e.host||e.hostname||"-"}),(0,n.jsx)("div",{className:e.reachable?"mt-1 text-emerald-600 dark:text-emerald-300":"mt-1 text-red-600 dark:text-red-300",children:e.reachable?"C\xf3 dữ liệu":e.error||"Chưa c\xf3 snapshot"})]}),e.reachable?(0,n.jsxs)("div",{className:"space-y-1 text-text-muted",children:[(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"font-medium text-text-main",children:"CPU:"})," ",e.cpu?.model||"-"," \xb7 ",e.cpu?.cores||0," cores \xb7 sử dụng ",Number(e.cpu?.usagePercent||0).toLocaleString("vi-VN",{maximumFractionDigits:1}),"%"]}),(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"font-medium text-text-main",children:"RAM:"})," ",N(e.memory?.totalBytes)," \xb7 đang d\xf9ng ",N(e.memory?.usedBytes)," (",Number(e.memory?.usagePercent||0).toLocaleString("vi-VN",{maximumFractionDigits:1}),"%)"]}),e.gpus?.length?e.gpus.map(t=>(0,n.jsxs)("p",{children:[(0,n.jsxs)("span",{className:"font-medium text-text-main",children:["GPU ",t.index,":"]})," ",t.name," \xb7 VRAM ",(Number(t.memoryTotalMb||0)/1024).toLocaleString("vi-VN",{maximumFractionDigits:1})," GiB \xb7 sử dụng ",Number(t.usagePercent||0).toLocaleString("vi-VN",{maximumFractionDigits:1}),"%"]},`${e.id}-${t.index}`)):(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"font-medium text-text-main",children:"GPU:"})," Kh\xf4ng ph\xe1t hiện NVIDIA GPU"]}),(0,n.jsxs)("p",{className:"text-text-subtle",children:["Snapshot: ",e.statusAt?new Date(e.statusAt).toLocaleString("vi-VN"):"-"]})]}):null]},e.id))})]}):null}function T(){let[e,t]=(0,l.useState)([]),[s,a]=(0,l.useState)(""),[i,o]=(0,l.useState)(null),[d,c]=(0,l.useState)(!1),[x,m]=(0,l.useState)(!1),[u,h]=(0,l.useState)(""),[p,b]=(0,l.useState)(!1),[g,j]=(0,l.useState)(""),[y,v]=(0,l.useState)(""),[k,N]=(0,l.useState)(!1),[T,S]=(0,l.useState)("");(0,l.useEffect)(()=>{(async()=>{let e="";try{let t=await fetch("/api/dashboard/analytics/analyze",{cache:"no-store"}),s=await t.json().catch(()=>({}));if(t.ok){o(s.analysis||null),c(!0===s.standby),e=s.selectedModel||"";let t=s.vllmConfig||"";j(t),v(t)}}catch{}try{let s=await fetch("/api/dashboard/analytics/ai-models",{cache:"no-store"}),n=(await s.json().catch(()=>({}))).options||[];t(n),a(t=>{let s=t||e;return s&&n.some(e=>e.value===s)?s:n[0]?.value||""})}catch{t([])}finally{b(!0)}})()},[]);let q=(0,l.useCallback)(e=>{a(e),fetch("/api/dashboard/analytics/analyze",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:e})}).catch(()=>{})},[]),P=(0,l.useCallback)(async({showMessage:e=!0}={})=>{N(!0),e&&S("");try{let t=await fetch("/api/dashboard/analytics/analyze",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({vllmConfig:g})}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng thể lưu cấu h\xecnh vLLM");let n=s.vllmConfig||"";return j(n),v(n),e&&S("Đ\xe3 lưu cấu h\xecnh vLLM"),n}finally{N(!1)}},[g]),M=(0,l.useCallback)(async()=>{h("");try{await P()}catch(e){S(""),h(e?.message||"Kh\xf4ng thể lưu cấu h\xecnh vLLM")}},[P]),I=(0,l.useCallback)(async()=>{if(!s)return;let e=s.indexOf("::"),t=s.slice(0,e),n=s.slice(e+2);m(!0),h("");try{g.trim()!==y&&await P({showMessage:!1});let e=await fetch("/api/dashboard/analytics/analyze",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({connectionId:t,model:n})}),s=await e.json().catch(()=>({}));if(!e.ok)throw Error(s.error||"Kh\xf4ng thể ph\xe2n t\xedch");o(s.analysis)}catch(e){h(e?.message||"Kh\xf4ng thể ph\xe2n t\xedch")}finally{m(!1)}},[P,y,s,g]),R=(0,l.useMemo)(()=>i?.summary?r.xI.parse(i.summary):"",[i]);return(0,n.jsxs)("section",{className:"overflow-hidden rounded-3xl border border-border bg-surface shadow-[var(--shadow-soft)]",children:[(0,n.jsx)("div",{className:"flex flex-wrap items-center justify-between gap-4 border-b border-border px-6 py-5",children:(0,n.jsxs)("div",{className:"flex items-center gap-4",children:[(0,n.jsx)("div",{className:"flex h-12 w-12 items-center justify-center rounded-2xl bg-primary/10 text-primary",children:(0,n.jsx)("span",{className:"material-symbols-outlined text-[27px]",children:"neurology"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-lg font-semibold text-text-main",children:"Đ\xe1nh gi\xe1 AI về trải nghiệm & hiệu năng"}),(0,n.jsx)("p",{className:"mt-0.5 text-xs text-text-muted",children:'Ph\xe2n t\xedch giờ l\xe0m việc h\xf4m nay, tập trung v\xe0o tab "Trải nghiệm" v\xe0 c\xe1c vLLM AI server local. Chạy nền tự động mỗi 1 giờ.'})]})]})}),(0,n.jsxs)("div",{className:"space-y-5 p-6",children:[d?(0,n.jsx)("div",{className:"rounded-xl border border-amber-500/20 bg-amber-500/10 px-4 py-3 text-sm text-amber-700 dark:text-amber-300",children:"Standby mode: kết quả ph\xe2n t\xedch được đồng bộ tự động từ Master. Node n\xe0y kh\xf4ng tự chạy ph\xe2n t\xedch AI."}):null,(0,n.jsxs)("div",{className:"space-y-2",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsx)("label",{htmlFor:"analytics-vllm-config",className:"text-xs font-medium text-text-muted",children:"Cấu h\xecnh vLLM của c\xe1c server"}),(0,n.jsxs)("span",{className:"text-xs text-text-subtle",children:[g.length.toLocaleString("vi-VN")," / 50.000 k\xfd tự"]})]}),(0,n.jsx)("textarea",{id:"analytics-vllm-config",rows:8,maxLength:5e4,value:g,onChange:e=>{j(e.target.value),S("")},disabled:d||k,placeholder:"M\xf4 tả theo từng node, v\xed dụ:\nnode-gpu-01: model=..., --tensor-parallel-size 4, --max-model-len 32768, --gpu-memory-utilization 0.9\nnode-gpu-02: model=..., replicas=2, c\xe1c tham số batching/concurrency...",className:"w-full resize-y rounded-lg border border-border bg-surface px-3 py-2.5 font-mono text-xs leading-5 text-text-main outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/15 disabled:opacity-60"}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsx)("p",{className:"text-xs text-text-muted",children:"D\xf9ng t\xean hoặc host tr\xf9ng với Linux node trong Resource Monitor để AI \xe1nh xạ ch\xednh x\xe1c."}),(0,n.jsxs)("div",{className:"flex items-center gap-3",children:[T?(0,n.jsx)("span",{className:"text-xs text-emerald-600 dark:text-emerald-300",children:T}):null,(0,n.jsxs)("button",{type:"button",onClick:M,disabled:d||k||g.trim()===y,className:"inline-flex items-center gap-2 rounded-lg border border-border bg-surface px-3 py-2 text-xs font-semibold text-text-main transition hover:border-primary/40 disabled:cursor-not-allowed disabled:opacity-50",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[17px]",children:k?"progress_activity":"save"}),k?"Đang lưu...":"Lưu cấu h\xecnh"]})]})]})]}),(0,n.jsxs)("div",{className:"flex flex-wrap items-end gap-3",children:[(0,n.jsxs)("label",{className:"flex min-w-[280px] flex-1 flex-col gap-1.5 text-sm",children:[(0,n.jsx)("span",{className:"text-xs font-medium text-text-muted",children:"AI model d\xf9ng để ph\xe2n t\xedch"}),(0,n.jsxs)("select",{className:"rounded-xl border border-border bg-surface px-3 py-2.5 text-sm text-text-main disabled:opacity-60",value:s,onChange:e=>q(e.target.value),disabled:!e.length||d,children:[e.length?null:(0,n.jsx)("option",{value:"",children:"Chưa c\xf3 kết nối AI n\xe0o đang hoạt động"}),e.map(e=>(0,n.jsx)("option",{value:e.value,children:e.label},e.value))]})]}),(0,n.jsxs)("button",{type:"button",onClick:I,disabled:!s||d||x,className:"flex items-center gap-2 rounded-xl bg-primary px-4 py-2.5 text-sm font-semibold text-white shadow-sm transition disabled:cursor-not-allowed disabled:opacity-60",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:x?"progress_activity":"auto_awesome"}),x?"Đang ph\xe2n t\xedch...":"Ph\xe2n t\xedch lại"]})]}),u?(0,n.jsx)("div",{className:"rounded-xl border border-red-500/20 bg-red-500/10 px-4 py-3 text-sm text-red-600 dark:text-red-300",children:u}):null,i?(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2 text-xs text-text-muted",children:[(0,n.jsxs)("span",{children:["Model: ",(0,n.jsx)("span",{className:"font-semibold",children:i.modelLabel})]}),(0,n.jsxs)("span",{children:["Cập nhật l\xfac ",i.generatedAt?new Date(i.generatedAt).toLocaleString("vi-VN"):"-"]})]}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("span",{className:"text-xs text-text-muted",children:"Tổng quan:"}),(0,n.jsx)(f,{status:i.status}),(0,n.jsx)("span",{className:"text-xs text-text-muted",children:"vLLM local:"}),(0,n.jsx)(f,{status:i.vllmStatus}),"number"==typeof i.vllmServerCount?(0,n.jsxs)("span",{className:"text-xs text-text-subtle",children:["(",i.vllmServerCount," node)"]}):null]}),(0,n.jsx)(w,{nodes:i.hardwareNodes||[]}),(0,n.jsx)("div",{className:"analytics-ai-body rounded-2xl border border-border bg-surface-2/40 p-5 text-sm leading-6 text-text-main",dangerouslySetInnerHTML:{__html:R}})]}):!x&&p?(0,n.jsx)("div",{className:"rounded-2xl border border-dashed border-border bg-surface-2/40 py-10 text-center text-sm text-text-muted",children:'Chưa c\xf3 ph\xe2n t\xedch n\xe0o — bấm "Ph\xe2n t\xedch lại" để bắt đầu.'}):null]})]})}function S(e,t=0){return Number(e||0).toLocaleString("vi-VN",{maximumFractionDigits:t})}function q(e){let t=Number(e||0);return Intl.NumberFormat("vi-VN",{notation:"compact",maximumFractionDigits:1}).format(t)}function P(e){let t=100*Number(e||0);return`${t.toLocaleString("vi-VN",{maximumFractionDigits:1})}%`}function M(e){let t=Number(e||0);return t?`$${t.toLocaleString("vi-VN",{minimumFractionDigits:4,maximumFractionDigits:6})}`:"$0"}function I(e){if(null==e||Number.isNaN(Number(e)))return"-";let t=Number(e);return t>=1e3?`${(t/1e3).toLocaleString("vi-VN",{maximumFractionDigits:2})}s`:`${t.toLocaleString("vi-VN",{maximumFractionDigits:0})}ms`}function R(e,t="/s"){if(null==e||Number.isNaN(Number(e)))return"-";let s=Number(e);return`${s.toLocaleString("vi-VN",{maximumFractionDigits:s>=10?1:2})}${t}`}function L(e){return null==e||Number.isNaN(Number(e))?"-":`${Number(e).toLocaleString("vi-VN",{maximumFractionDigits:0})}/100`}function C(e){if(!e)return null;let t=String(e).trim();return new Date(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(t)?`${t.replace(" ","T")}Z`:t)}function A(e){if(!e)return"-";try{let t=C(e);if(!t||Number.isNaN(t.getTime()))return String(e);return t.toLocaleString("vi-VN",{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}catch{return String(e)}}function $(e){if(!e)return"";try{let t=C(e);if(!t||Number.isNaN(t.getTime()))return String(e);return t.toLocaleString("vi-VN",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1})}catch{return String(e)}}function K(){let{isAdmin:e,isMonitorAdmin:t,isAiGatewaysMonitor:s}=(0,a.s)();return e||t||s}function F(...e){return e.filter(Boolean).join(" ")}function O(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"}catch{return"UTC"}}function E(e,t={}){let s=new URLSearchParams;return Object.entries({...e,...t}).forEach(([e,t])=>{let n=String(t??"").trim();n&&s.set(e,n)}),s.toString()}function U({children:e,className:t=""}){return(0,n.jsx)("div",{className:F("min-w-0 rounded-2xl border border-border bg-surface p-5 shadow-sm",t),children:e})}function _({icon:e,label:t,value:s,hint:l,help:r,tone:a="blue"}){return(0,n.jsx)(U,{className:"min-h-[126px]",children:(0,n.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"text-sm font-medium text-text-muted",children:t}),(0,n.jsx)("div",{className:"mt-2 text-2xl font-semibold text-text-main",children:s}),l?(0,n.jsx)("div",{className:"mt-2 text-xs text-text-muted",children:l}):null,r?(0,n.jsx)("div",{className:"mt-1 text-[11px] leading-4 text-text-muted/70",children:r}):null]}),(0,n.jsx)("div",{className:F("flex h-10 w-10 items-center justify-center rounded-xl",{blue:"bg-blue-500/10 text-blue-600 dark:text-blue-300",green:"bg-green-500/10 text-green-600 dark:text-green-300",red:"bg-red-500/10 text-red-600 dark:text-red-300",amber:"bg-amber-500/10 text-amber-600 dark:text-amber-300",purple:"bg-purple-500/10 text-purple-600 dark:text-purple-300",slate:"bg-slate-500/10 text-slate-600 dark:text-slate-300"}[a]||"bg-blue-500/10 text-blue-600 dark:text-blue-300"),children:(0,n.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:e})})]})})}function D({label:e,children:t}){return(0,n.jsxs)("label",{className:"space-y-1.5 text-xs font-medium text-text-muted",children:[(0,n.jsx)("span",{children:e}),t]})}function V({value:e,onChange:t,children:s}){return(0,n.jsx)("select",{value:e||"",onChange:e=>t(e.target.value),className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none transition focus:border-primary/60 focus:ring-2 focus:ring-primary/20",children:s})}function H({value:e,onChange:t,placeholder:s="",type:l="text"}){return(0,n.jsx)("input",{value:e||"",type:l,onChange:e=>t(e.target.value),placeholder:s,className:"h-10 w-full rounded-xl border border-border bg-background px-3 text-sm text-text-main outline-none transition placeholder:text-text-muted/60 focus:border-primary/60 focus:ring-2 focus:ring-primary/20"})}function B(){return(0,n.jsxs)("div",{className:"space-y-4",children:[(0,n.jsx)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:Array.from({length:8}).map((e,t)=>(0,n.jsx)("div",{className:"h-32 animate-pulse rounded-2xl border border-border bg-surface"},t))}),(0,n.jsx)("div",{className:"h-80 animate-pulse rounded-2xl border border-border bg-surface"})]})}function G({title:e="Kh\xf4ng c\xf3 dữ liệu",description:t="Kh\xf4ng t\xecm thấy dữ liệu theo bộ lọc hiện tại."}){return(0,n.jsxs)("div",{className:"flex min-h-[180px] flex-col items-center justify-center rounded-2xl border border-dashed border-border bg-surface/60 p-8 text-center",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-4xl text-text-muted",children:"database_off"}),(0,n.jsx)("div",{className:"mt-3 text-sm font-semibold text-text-main",children:e}),(0,n.jsx)("div",{className:"mt-1 max-w-xl text-sm text-text-muted",children:t})]})}function z({data:e=[],valueKey:t="totalTokens",secondaryKey:s="requests",height:l=220}){let r=e||[],a=Math.max(...r.map(e=>Number(e[t]||0)),1),i=Math.max(...r.map(e=>Number(e[s]||0)),1);return 0===r.length?(0,n.jsx)(G,{description:"Chưa c\xf3 time-series trong khoảng thời gian n\xe0y."}):(0,n.jsx)("div",{className:"overflow-x-auto",children:(0,n.jsxs)("div",{className:"min-w-[720px]",children:[(0,n.jsx)("div",{className:"flex items-end gap-1",style:{height:l},children:r.map((e,r)=>{let o=Math.max(2,Number(e[t]||0)/a*(l-42)),d=Math.max(2,Number(e[s]||0)/i*(l-42));return(0,n.jsx)("div",{className:"group flex flex-1 flex-col items-center justify-end gap-1",children:(0,n.jsxs)("div",{className:"relative flex h-full w-full max-w-[34px] items-end justify-center gap-0.5",children:[(0,n.jsx)("div",{className:"w-2 rounded-t bg-primary/70",style:{height:o}}),(0,n.jsx)("div",{className:"w-2 rounded-t bg-amber-500/70",style:{height:d}}),(0,n.jsxs)("div",{className:"pointer-events-none absolute bottom-full left-1/2 z-20 hidden w-56 -translate-x-1/2 rounded-xl border border-border bg-surface p-3 text-left text-xs shadow-xl group-hover:block",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:$(e.label)}),(0,n.jsxs)("div",{className:"mt-1 text-text-muted",children:["Request: ",S(e.requests)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["Input token: ",S(e.promptTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["Output token: ",S(e.completionTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["Tổng token: ",S(e.totalTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["Lỗi: ",S(e.errors)]})]})]})},`${e.label}-${r}`)})}),(0,n.jsxs)("div",{className:"mt-3 flex justify-between gap-2 text-[11px] text-text-muted",children:[(0,n.jsx)("span",{children:$(r[0]?.label)}),(0,n.jsx)("span",{children:$(r[Math.floor(r.length/2)]?.label)}),(0,n.jsx)("span",{children:$(r[r.length-1]?.label)})]})]})})}function X(){return(0,n.jsxs)("div",{className:"flex flex-wrap gap-3 text-xs text-text-muted",children:[(0,n.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,n.jsx)("span",{className:"h-2.5 w-2.5 rounded-sm bg-primary/70"}),"Token"]}),(0,n.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,n.jsx)("span",{className:"h-2.5 w-2.5 rounded-sm bg-amber-500/70"}),"Request"]})]})}function W({columns:e,rows:t,empty:s="Kh\xf4ng c\xf3 dữ liệu"}){return t&&0!==t.length?(0,n.jsx)("div",{className:"overflow-x-auto overflow-y-auto rounded-2xl border border-border",style:{maxHeight:"500px"},children:(0,n.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,n.jsx)("thead",{className:"bg-background/70",children:(0,n.jsx)("tr",{children:e.map(e=>(0,n.jsx)("th",{className:F("whitespace-nowrap px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-text-muted",e.className),children:e.label},e.key))})}),(0,n.jsx)("tbody",{className:"divide-y divide-border bg-surface",children:t.map((t,s)=>(0,n.jsx)("tr",{className:"hover:bg-background/60",children:e.map(e=>(0,n.jsx)("td",{className:F("whitespace-nowrap px-4 py-3 align-top text-text-main",e.className),children:e.render?e.render(t,s):t[e.key]??"-"},e.key))},t.key||t.id||`${t.label}-${s}`))})]})}):(0,n.jsx)(G,{title:s})}function J({items:e=[]}){return e&&0!==e.length?(0,n.jsx)("div",{className:"flex max-w-[360px] flex-wrap gap-1.5",children:e.slice(0,3).map(e=>(0,n.jsxs)("span",{className:"rounded-full bg-primary/10 px-2 py-0.5 text-xs text-primary",children:[e.label||e.key," \xb7 ",S(e.count??e.requests??e.totalTokens??0)]},e.key))}):(0,n.jsx)("span",{className:"text-text-muted",children:"-"})}function Z({row:e}){return(0,n.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,n.jsxs)("div",{className:"font-semibold text-text-main",children:[q(e.totalTokens)," token"]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["In ",q(e.promptTokens)," / Out ",q(e.completionTokens)]})]})}function Y({leaderboard:e={}}){let t=K(),s=e.rows||[],l=e.status||"warming",r="ready"===l?`${e.periodLabel||"H\xf4m nay"} \xb7 cập nhật ${A(e.generatedAt)} \xb7 refresh nền mỗi ${Math.round((e.refreshEveryMs||9e5)/6e4)} ph\xfat`:"error"===l?"Leaderboard đang chờ job nền tổng hợp lại dữ liệu.":"Leaderboard đang được job nền khởi tạo.";return(0,n.jsxs)(U,{className:"border-amber-500/20 bg-amber-500/[0.03]",children:[(0,n.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-2xl text-amber-500",children:"crown"}),(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top 5 vinh danh token"})]}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Xếp hạng theo API key owner d\xf9ng nhiều input + output token nhất."})]}),(0,n.jsx)("span",{className:"rounded-full bg-amber-500/10 px-3 py-1 text-xs font-semibold text-amber-700 dark:text-amber-300",children:r})]}),(0,n.jsx)(W,{rows:s,empty:"Chưa c\xf3 snapshot leaderboard từ job nền.",columns:[{key:"rank",label:"Hạng",render:e=>(0,n.jsxs)("div",{className:"flex min-w-[170px] items-center gap-3",children:[(0,n.jsx)("div",{className:F("flex h-10 w-10 shrink-0 items-center justify-center rounded-xl",1===e.rank?"bg-amber-500/15 text-amber-600":"bg-primary/10 text-primary"),children:(0,n.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:"crown"})}),(0,n.jsxs)("div",{children:[(0,n.jsxs)("div",{className:"font-semibold text-text-main",children:["#",e.rank," \xb7 ",e.title]}),(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:[P(e.tokenShare||0)," tổng token"]})]})]})},{key:"owner",label:"Owner",render:e=>(0,n.jsxs)("div",{className:"min-w-[210px]",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.ownerUser||e.label}),(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:[e.apiKeyName||"API key",t&&e.apiKeyFingerprint?` \xb7 ${e.apiKeyFingerprint}`:""]})]})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"scope",label:"Phạm vi",render:e=>(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:[(0,n.jsxs)("div",{children:["API key ",S(e.apiKeyCount)," \xb7 IP ",S(e.sourceIpCount)]}),(0,n.jsxs)("div",{children:["Model ",S(e.modelCount)," \xb7 Provider ",S(e.providerCount)]})]})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]})}function Q({value:e}){let t=Number(e||0);return(0,n.jsx)("span",{className:F("rounded-full px-2 py-1 text-xs font-semibold",t>=.2?"bg-red-500/10 text-red-600 dark:text-red-300":t>=.05?"bg-amber-500/10 text-amber-600 dark:text-amber-300":"bg-green-500/10 text-green-600 dark:text-green-300"),children:P(t)})}function ee({level:e,label:t}){let s=String(e||"none");return(0,n.jsx)("span",{className:F("rounded-full px-2 py-1 text-xs font-semibold",{fast:"bg-green-500/10 text-green-700 dark:text-green-300",ok:"bg-blue-500/10 text-blue-700 dark:text-blue-300",slow:"bg-amber-500/10 text-amber-700 dark:text-amber-300",very_slow:"bg-red-500/10 text-red-700 dark:text-red-300",low_sample:"bg-amber-500/10 text-amber-700 dark:text-amber-300",none:"bg-slate-500/10 text-slate-700 dark:text-slate-300"}[s]||"bg-slate-500/10 text-slate-700 dark:text-slate-300"),children:t||"-"})}function et({level:e,label:t}){let s=String(e||"normal");return(0,n.jsx)("span",{className:F("rounded-full px-2 py-1 text-xs font-semibold",{critical:"bg-red-500/10 text-red-700 dark:text-red-300",high:"bg-amber-500/10 text-amber-700 dark:text-amber-300",medium:"bg-blue-500/10 text-blue-700 dark:text-blue-300",normal:"bg-green-500/10 text-green-700 dark:text-green-300",none:"bg-slate-500/10 text-slate-700 dark:text-slate-300"}[s]||"bg-slate-500/10 text-slate-700 dark:text-slate-300"),children:t||"-"})}function es({value:e}){let t=String(e||"unknown"),s={gateway:{label:"Gateway",cls:"bg-purple-500/10 text-purple-700 dark:text-purple-300"},upstream:{label:"Upstream",cls:"bg-red-500/10 text-red-700 dark:text-red-300"},client:{label:"Client",cls:"bg-slate-500/10 text-slate-700 dark:text-slate-300"},rate_limit:{label:"Rate limit",cls:"bg-amber-500/10 text-amber-700 dark:text-amber-300"},unknown:{label:"Unknown",cls:"bg-zinc-500/10 text-zinc-700 dark:text-zinc-300"}}[t]||{label:t,cls:"bg-zinc-500/10 text-zinc-700 dark:text-zinc-300"};return(0,n.jsx)("span",{className:F("rounded-full px-2 py-1 text-xs font-semibold",s.cls),children:s.label})}function en({row:e}){let t=e.sampleMessage||e.errorMessageShort||"";return t?(0,n.jsx)("span",{className:"block max-w-[360px] truncate text-xs text-text-muted",title:t,children:t}):(0,n.jsx)("span",{className:"text-text-muted",children:"-"})}function el({icon:e,label:t,value:s,hint:l,tone:r="slate"}){return(0,n.jsx)("div",{className:F("rounded-2xl border p-4 shadow-sm",{red:"border-red-500/20 bg-red-500/10 text-red-700 dark:text-red-300",amber:"border-amber-500/20 bg-amber-500/10 text-amber-700 dark:text-amber-300",purple:"border-purple-500/20 bg-purple-500/10 text-purple-700 dark:text-purple-300",slate:"border-border bg-surface text-text-main",green:"border-green-500/20 bg-green-500/10 text-green-700 dark:text-green-300"}[r]||"border-border bg-surface text-text-main"),children:(0,n.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide opacity-75",children:t}),(0,n.jsx)("div",{className:"mt-2 text-2xl font-bold",children:S(s)}),l?(0,n.jsx)("div",{className:"mt-1 text-xs opacity-80",children:l}):null]}),(0,n.jsx)("span",{className:"material-symbols-outlined text-[24px] opacity-80",children:e})]})})}function er({anomaly:e}){let t="danger"===e.level?"border-red-500/30 bg-red-500/10 text-red-700 dark:text-red-300":"border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300",s="danger"===e.level?"error":"warning";return(0,n.jsx)("div",{className:F("rounded-2xl border p-4",t),children:(0,n.jsxs)("div",{className:"flex gap-3",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:s}),(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.title}),(0,n.jsx)("div",{className:"mt-1 text-sm opacity-90",children:e.detail})]})]})})}function ea({notes:e=[]}){return e.length?(0,n.jsx)("div",{className:"space-y-2 rounded-2xl border border-blue-500/20 bg-blue-500/10 p-4 text-sm text-blue-700 dark:text-blue-300",children:e.map((e,t)=>(0,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"info"}),(0,n.jsx)("span",{children:e})]},t))}):null}function ei(e){let t=e=>String(e).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}T${t(e.getHours())}:${t(e.getMinutes())}`}function eo({filters:e,setFilters:t,options:s,onRefresh:l,onExportCsv:r,loading:a,showProviderFilters:i=!0}){let o=(e,s)=>{let n=null;t(t=>{if("period"===e&&"custom"===s){let e,l;return n={...t,period:s,...((l=new Date(e=new Date)).setHours(8,0,0,0),{dateFrom:ei(l),dateTo:ei(e)})}}return{...t,[e]:s}}),n&&l?.(n)};return(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"grid gap-3 md:grid-cols-2 xl:grid-cols-6",children:[(0,n.jsx)(D,{label:"Khoảng thời gian",children:(0,n.jsx)(V,{value:e.period,onChange:e=>o("period",e),children:j.map(e=>(0,n.jsx)("option",{value:e.value,children:e.label},e.value))})}),(0,n.jsx)(D,{label:"Từ ng\xe0y",children:(0,n.jsx)(H,{type:"datetime-local",value:e.dateFrom,onChange:e=>o("dateFrom",e)})}),(0,n.jsx)(D,{label:"Đến ng\xe0y",children:(0,n.jsx)(H,{type:"datetime-local",value:e.dateTo,onChange:e=>o("dateTo",e)})}),i?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(D,{label:"Provider",children:(0,n.jsxs)(V,{value:e.provider,onChange:e=>o("provider",e),children:[(0,n.jsx)("option",{value:"",children:"Tất cả provider"}),(s.providers||[]).map(e=>{let t="string"==typeof e?e:e.value,s="string"==typeof e?e:e.label||e.value;return(0,n.jsx)("option",{value:t,children:s},t)})]})}),(0,n.jsx)(D,{label:"Model",children:(0,n.jsxs)(V,{value:e.model,onChange:e=>o("model",e),children:[(0,n.jsx)("option",{value:"",children:"Tất cả model"}),(s.models||[]).map(e=>(0,n.jsx)("option",{value:e,children:e},e))]})}),(0,n.jsx)(D,{label:"Provider account",children:(0,n.jsxs)(V,{value:e.connectionId,onChange:e=>o("connectionId",e),children:[(0,n.jsx)("option",{value:"",children:"Tất cả account"}),(s.connections||[]).map(e=>(0,n.jsx)("option",{value:e.value,children:e.label},e.value))]})})]}):null,(0,n.jsx)(D,{label:"API key",children:(0,n.jsxs)(V,{value:e.apiKey,onChange:e=>o("apiKey",e),children:[(0,n.jsx)("option",{value:"",children:"Tất cả API key"}),(s.apiKeys||[]).map(e=>(0,n.jsx)("option",{value:e.value,children:e.label},e.value))]})}),(0,n.jsx)(D,{label:"Source IP",children:(0,n.jsx)(H,{value:e.clientIp,onChange:e=>o("clientIp",e),placeholder:"172.16.253.1"})}),(0,n.jsx)(D,{label:"Source tool",children:(0,n.jsx)(H,{value:e.sourceTool,onChange:e=>o("sourceTool",e),placeholder:"copilot, antigravity..."})}),(0,n.jsx)(D,{label:"Endpoint",children:(0,n.jsxs)(V,{value:e.endpoint,onChange:e=>o("endpoint",e),children:[(0,n.jsx)("option",{value:"",children:"Tất cả endpoint"}),(s.endpoints||[]).map(e=>(0,n.jsx)("option",{value:e,children:e},e))]})}),(0,n.jsx)(D,{label:"Status",children:(0,n.jsxs)(V,{value:e.status,onChange:e=>o("status",e),children:[(0,n.jsx)("option",{value:"",children:"Tất cả status"}),(s.statuses||[]).map(e=>(0,n.jsx)("option",{value:e,children:e},e))]})}),(0,n.jsx)(D,{label:"Session / keyword",children:(0,n.jsx)(H,{value:e.sessionId||e.keyword,onChange:e=>o("keyword",e),placeholder:"session, prompt, error..."})})]}),(0,n.jsxs)("div",{className:"mt-4 flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsx)("div",{className:"text-xs text-text-muted",children:"Token/cost lấy từ UsageHistory. Source IP/tool/session lấy từ Prompt Logs."}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("button",{onClick:()=>t({period:"today",dateFrom:"",dateTo:"",provider:"",model:"",connectionId:"",status:"",endpoint:"",apiKey:"",clientIp:"",sourceTool:"",sessionId:"",keyword:""}),className:"rounded-xl border border-border px-3 py-2 text-sm font-medium text-text-main hover:bg-background",children:"Reset"}),(0,n.jsxs)("button",{onClick:r,className:"rounded-xl border border-border px-3 py-2 text-sm font-medium text-text-main hover:bg-background",children:[(0,n.jsx)("span",{className:"material-symbols-outlined mr-1 align-[-4px] text-[18px]",children:"download"}),"Export CSV"]}),(0,n.jsxs)("button",{onClick:()=>l?.(),disabled:a,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white shadow-sm disabled:opacity-60",children:[(0,n.jsx)("span",{className:"material-symbols-outlined mr-1 align-[-4px] text-[18px]",children:"refresh"}),a?"Đang tải...":"Refresh"]})]})]})]})}function ed({data:e}){let t=K(),s=e.overview||{},l=e.latency||{},r=e.experience||{};return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsx)(Y,{leaderboard:e.tokenLeaderboard}),(0,n.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,n.jsx)(_,{icon:"call_made",label:"Tổng request",value:S(s.requests),hint:`${S(s.requestsPerMinute,2)} request/ph\xfat`,help:"Số request khớp bộ lọc hiện tại."}),(0,n.jsx)(_,{icon:"check_circle",label:"Th\xe0nh c\xf4ng",value:S(s.success),hint:`Tỷ lệ lỗi ${P(s.errorRate)}`,help:"Request trả về th\xe0nh c\xf4ng v\xe0 c\xf3 trạng th\xe1i OK.",tone:"green"}),(0,n.jsx)(_,{icon:"dns",label:"Lỗi server/provider",value:S(s.serverErrorEvents),hint:`Server-impacting ${P(s.serverErrorRate)} \xb7 client ${S(s.clientErrorEvents)}`,help:"Lỗi từ gateway, provider hoặc model server; t\xe1ch ri\xeang lỗi client.",tone:s.serverErrorEvents?"red":"green"}),(0,n.jsx)(_,{icon:"speed",label:"Trải nghiệm",value:L(r.score),hint:`${r.label||"-"} \xb7 ${S(r.samples)} mẫu`,help:"Điểm 0-100. Trừ tối đa 45 cho tốc độ (latency/TTFT/slow-rate t\xednh gộp, kh\xf4ng cộng dồn) v\xe0 40 cho lỗi server. Rate limit v\xe0 lỗi client chỉ trừ nhẹ v\xec kh\xf4ng phản \xe1nh chất lượng dịch vụ.",tone:r.tone||"purple"}),(0,n.jsx)(_,{icon:"timer",label:"Latency P95",value:I(r.p95LatencyMs||l.p95Ms),hint:`AVG ${I(r.avgLatencyMs||l.avgMs)} \xb7 P50 ${I(r.p50LatencyMs||l.p50Ms)}`,help:"95% request ho\xe0n tất nhanh hơn gi\xe1 trị n\xe0y.",tone:"purple"}),(0,n.jsx)(_,{icon:"bolt",label:"TTFT P95",value:I(r.p95TtftMs),hint:"Thời gian chờ token đầu ti\xean",help:"95% request nhận token đầu ti\xean nhanh hơn gi\xe1 trị n\xe0y.",tone:r.slowTtftRate>=.2?"amber":"blue"}),(0,n.jsx)(_,{icon:"input",label:"Input P95",value:q(r.p95PromptTokens||0),hint:`Avg ${q(r.avgPromptTokens||s.avgPromptTokens)} \xb7 >=30k ${P(r.longInputRate)}`,help:"95% request c\xf3 k\xedch thước input nhỏ hơn gi\xe1 trị n\xe0y."}),(0,n.jsx)(_,{icon:"psychology_alt",label:"Auto-off thinking",value:P(e.thinkingAnalytics?.autoOffRate),hint:`${S(e.thinkingAnalytics?.autoOffRequests||0)} request bị tắt theo policy`,help:"Tỷ lệ request bị tắt thinking do vượt ngưỡng hoặc policy.",tone:(e.thinkingAnalytics?.autoOffRate||0)>=.3?"amber":"slate"}),(0,n.jsx)(_,{icon:"data_object",label:"Large context >=50k",value:P(e.largeContextAnalytics?.gte50kRate),hint:`>=100k ${P(e.largeContextAnalytics?.gte100kRate)}`,help:"Tỷ lệ request c\xf3 context rất lớn, dễ l\xe0m tăng TTFT/latency.",tone:(e.largeContextAnalytics?.gte50kRate||0)>=.3?"amber":"slate"}),(0,n.jsx)(_,{icon:"person_alert",label:"Top user nặng",value:s.topHeavyUser||"-",hint:`Chiếm ${P(s.topHeavyUserTokenShare)} tổng token`,help:"User/API key ti\xeau thụ nhiều token nhất trong bộ lọc.",tone:s.topHeavyUserTokenShare>=.35?"amber":"slate"}),(0,n.jsx)(_,{icon:"running_with_errors",label:"Request chậm",value:P(r.slowRequestRate),hint:`>= ${I(r.thresholds?.slowLatencyMs||45e3)} \xb7 max ${I(r.maxLatencyMs)}`,help:"Tỷ lệ request vượt ngưỡng chậm đ\xe3 cấu h\xecnh.",tone:r.slowRequestRate>=.2?"amber":"green"}),(0,n.jsx)(_,{icon:"output",label:"Output tokens",value:q(s.completionTokens),hint:`Avg ${S(s.avgCompletionTokens,1)} / request`,help:"Tổng token model sinh ra."}),(0,n.jsx)(_,{icon:"token",label:"Tổng tokens",value:q(s.totalTokens),hint:`${q(s.tokensPerMinute)} token/ph\xfat`,help:"Tổng input + output token.",tone:"amber"}),(0,n.jsx)(_,{icon:"speed",label:"Output speed",value:R(r.decodeTokensPerSecond," tok/s"),hint:`Latency/10k input ${I(r.latencyMsPer10kInputTokens)}`,help:"Tốc độ sinh token trung b\xecnh sau khi model bắt đầu trả lời.",tone:"slate"}),(0,n.jsx)(_,{icon:"payments",label:"Cost ước t\xednh",value:M(s.cost),hint:"Dựa tr\xean pricing đ\xe3 cấu h\xecnh",help:"Chi ph\xed suy ra từ token usage v\xe0 bảng gi\xe1 hiện tại.",tone:"green"})]}),(0,n.jsxs)("div",{className:"grid min-w-0 gap-5 xl:grid-cols-[2fr_1fr]",children:[(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Tần suất request & token theo thời gian"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Cột xanh l\xe0 token, cột v\xe0ng l\xe0 số request trong từng bucket thời gian."})]}),(0,n.jsx)(X,{})]}),(0,n.jsx)(z,{data:e.timeSeries||[]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"T\xf3m tắt active"}),(0,n.jsx)("div",{className:"mt-4 space-y-3",children:[["API key đang d\xf9ng",s.activeApiKeys],["Provider active",s.activeProviders],["Model active",s.activeModels],["Endpoint active",s.activeEndpoints],["Cached tokens",s.cachedTokens],["Reasoning tokens",s.reasoningTokens],["Latency AVG",I(r.avgLatencyMs||l.avgMs)],["Latency P50",I(r.p50LatencyMs||l.p50Ms)],["Latency P99",I(r.p99LatencyMs||l.p99Ms)],["TTFT P95",I(r.p95TtftMs)],["Input P95",q(r.p95PromptTokens||0)],["Long input >=30k",P(r.longInputRate)]].map(([e,t])=>(0,n.jsxs)("div",{className:"flex items-center justify-between rounded-xl bg-background px-3 py-2",children:[(0,n.jsx)("span",{className:"text-sm text-text-muted",children:e}),(0,n.jsx)("span",{className:"font-semibold text-text-main",children:"number"==typeof t?S(t):t})]},e))})]})]}),(0,n.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top API key d\xf9ng nhiều token"}),(0,n.jsx)(W,{rows:(e.clientRequests?.topApiKeysByTokens||e.groups?.apiKeys||[]).slice(0,8),columns:[{key:"name",label:"API key",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.name||e.label}),(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:[t?e.fingerprint||e.apiKeyFingerprint:"",e.ownerUser||e.apiKeyOwner?`${t&&(e.fingerprint||e.apiKeyFingerprint)?" \xb7 ":""}${e.ownerUser||e.apiKeyOwner}`:""]})]})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"input",label:"P95/Max input",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:q(e.p95PromptTokens||0)}),(0,n.jsxs)("div",{className:"text-text-muted",children:["max ",q(e.maxPromptTokens||0)]})]})}]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top Source IP d\xf9ng nhiều token"}),(0,n.jsx)(W,{rows:(e.clientRequests?.topSourceIpsByTokens||[]).slice(0,8),columns:[{key:"label",label:"Source IP",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"heavy",label:"Nặng",render:e=>(0,n.jsxs)("span",{className:"text-xs text-text-muted",children:[S(e.heavyRequests||0)," req"]})}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]})]})]})}function ec({data:e}){let t=K(),s=e.clientRequests||{},l=s.summary||{},r=s.topHeavyUsers||[],a=s.topProblemClients||[],i=s.topApiKeysByTokens||[],o=s.topSourceIpsByTokens||[];s.topSourceIpsByHeavyRequests;let d=s.inputBuckets||[],c=e=>(0,n.jsxs)("div",{className:"min-w-[220px]",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.label}),(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.ownerUser?`Owner ${e.ownerUser}`:e.apiKeyName||"Kh\xf4ng c\xf3 owner"}),(0,n.jsx)("div",{className:"font-mono text-[11px] text-text-muted",children:t?e.apiKeyFingerprint||e.primaryClientIp||e.key:e.primaryClientIp||""})]}),x=e=>(0,n.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,n.jsxs)("div",{children:["Nặng ",S(e.heavyRequests)," \xb7 ",P(e.heavyRequestRate)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["P95 input ",q(e.p95PromptTokens)," \xb7 Max ",q(e.maxPromptTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:[">=70k ",S(e.extremeInputRequests)," \xb7 ",P(e.extremeInputRate)]})]});return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,n.jsx)(_,{icon:"person_alert",label:"Top user nặng nhất",value:l.topUserLabel||"-",hint:`${q(l.topUserTokens)} token \xb7 ${P(l.topUserTokenShare)} tổng token`,tone:l.topUserTokenShare>=.35?"amber":"slate"}),(0,n.jsx)(_,{icon:"vpn_key",label:"Top API key nhiều token",value:l.topApiKeyLabel||"-",hint:`${q(l.topApiKeyTokens)} token \xb7 ${P(l.topApiKeyTokenShare)} tổng token`,tone:l.topApiKeyTokenShare>=.35?"amber":"blue"}),(0,n.jsx)(_,{icon:"lan",label:"Top IP nhiều token",value:l.topSourceIpLabel||"-",hint:`${q(l.topSourceIpTokens)} token \xb7 ${P(l.topSourceIpTokenShare)} tổng token`,tone:l.topSourceIpTokenShare>=.35?"amber":"purple"}),(0,n.jsx)(_,{icon:"input",label:"Input d\xe0i >=30k",value:P(l.longInputBucketShare||0),hint:`>=70k ${P(l.extremeInputShare||0)}`,tone:(l.extremeInputShare||0)>=.1?"amber":"green"}),(0,n.jsx)(_,{icon:"groups",label:"User/API key được theo d\xf5i",value:S(l.trackedUsers||0),hint:"Theo owner/API key fingerprint/source IP",tone:"blue"}),(0,n.jsx)(_,{icon:"network_check",label:"Top IP request nặng",value:l.topSourceIpHeavyLabel||"-",hint:`${S(l.topSourceIpHeavyRequests||0)} request >=30k input/total`,tone:l.topSourceIpHeavyRequests?"amber":"slate"}),(0,n.jsx)(_,{icon:"report",label:"Client lỗi nhiều",value:S(l.problemClients||0),hint:"Nh\xf3m user/API key c\xf3 error rows",tone:l.problemClients?"amber":"green"})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top user/API key gửi request nặng nhất"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Xếp theo tổng input/output token của request th\xe0nh c\xf4ng c\xf3 token. D\xf9ng để ph\xe1t hiện user VS Code/agent đang tạo tải long-context lớn."})]}),(0,n.jsx)("span",{className:"rounded-full bg-primary/10 px-3 py-1 text-xs font-semibold text-primary",children:"Kh\xf4ng hiển thị full bearer token"})]}),(0,n.jsx)(W,{rows:r,columns:[{key:"user",label:"User/API key",render:c},{key:"quality",label:"\xc1p lực",render:e=>(0,n.jsx)(et,{level:e.level,label:e.pressureLabel})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"input",label:"Input pressure",render:e=>(0,n.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,n.jsxs)("div",{children:["Avg ",q(e.avgPromptTokens)," \xb7 P95 ",q(e.p95PromptTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["Max ",q(e.maxPromptTokens)," \xb7 >=30k ",P(e.longInputRate)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:[">=50k ",P(e.hugeInputRate)," \xb7 >=70k ",P(e.extremeInputRate)]})]})},{key:"latency",label:"Latency / TTFT",render:e=>(0,n.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,n.jsxs)("div",{children:["P95 ",I(e.p95LatencyMs)," \xb7 Max ",I(e.maxLatencyMs)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["TTFT P95 ",I(e.p95TtftMs)," \xb7 Slow ",P(e.slowRequestRate)]})]})},{key:"topModels",label:"Top model",render:e=>(0,n.jsx)(J,{items:e.topModels})},{key:"topIps",label:"IP / Tool",render:e=>(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsx)(J,{items:e.topIps}),(0,n.jsx)(J,{items:e.topTools})]})},{key:"meta",label:"Meta",render:e=>(0,n.jsxs)("div",{className:"space-y-1 text-xs text-text-muted",children:[(0,n.jsxs)("div",{children:["Key ",S(e.apiKeyCount)," \xb7 IP ",S(e.sourceIpCount)," \xb7 Tool ",S(e.sourceToolCount)]}),(0,n.jsxs)("div",{children:["Session ",S(e.sessionCount)," \xb7 Last ",A(e.lastSeen)]})]})}],empty:"Kh\xf4ng c\xf3 request th\xe0nh c\xf4ng c\xf3 token trong khoảng lọc."})]}),(0,n.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top API key d\xf9ng nhiều token nhất"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Xếp theo tổng input + output token từ UsageHistory, kh\xf4ng lộ full bearer token."})]}),(0,n.jsx)(W,{rows:i,columns:[{key:"apiKey",label:"API key",render:e=>(0,n.jsxs)("div",{className:"min-w-[220px]",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e.label}),(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.apiKeyOwner?`Owner ${e.apiKeyOwner}`:e.apiKeyName||e.primarySourceTool||"-"}),(0,n.jsx)("div",{className:"font-mono text-[11px] text-text-muted",children:t?e.apiKeyFingerprint||e.primaryClientIp||e.key:e.primaryClientIp||""})]})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"input",label:"Input nặng",render:x},{key:"meta",label:"Nguồn",render:e=>(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:[(0,n.jsxs)("div",{children:["IP ",S(e.sourceIpCount)," \xb7 Tool ",S(e.sourceToolCount)]}),(0,n.jsxs)("div",{children:["Model ",S(e.modelCount)," \xb7 Provider ",S(e.providerCount)]})]})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 API key c\xf3 token trong khoảng lọc."})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top Source IP d\xf9ng nhiều token nhất"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Dựa tr\xean UsageHistory n\xean c\xf3 input/output token, kh\xe1c với bảng Source IP từ Prompt Logs chỉ đếm log."})]}),(0,n.jsx)(W,{rows:o,columns:[{key:"ip",label:"Source IP",render:e=>(0,n.jsxs)("div",{className:"min-w-[180px]",children:[(0,n.jsx)("div",{className:"font-mono text-sm font-semibold text-text-main",children:e.label}),(0,n.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:["Tool ",S(e.sourceToolCount)," \xb7 API key ",S(e.apiKeyCount)]}),(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:["Model ",S(e.modelCount)," \xb7 Provider ",S(e.providerCount)]})]})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"input",label:"Input nặng",render:x},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]})]}),(0,n.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Ph\xe2n bố request theo k\xedch thước input"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Gi\xfap admin biết workload đang l\xe0 chat ngắn hay long-context VS Code/agent."})]}),(0,n.jsx)(W,{rows:d,columns:[{key:"label",label:"Input bucket",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"share",label:"Tỷ trọng",render:e=>P(e.share)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"latency",label:"Latency P95/MAX",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsxs)("div",{children:[I(e.p95LatencyMs)," / ",I(e.maxLatencyMs)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["TTFT P95 ",I(e.p95TtftMs)]})]})}],empty:"Kh\xf4ng c\xf3 dữ liệu bucket input."})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Client/API key lỗi nhiều"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"D\xf9ng để ph\xe1t hiện sai endpoint/model/auth/policy hoặc client tool cấu h\xecnh sai."})]}),(0,n.jsx)(W,{rows:a,columns:[{key:"user",label:"Client",render:c},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"errors",label:"Lỗi",render:e=>S(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"source",label:"IP/Tool",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{className:"font-mono",children:e.primaryClientIp||"-"}),(0,n.jsx)("div",{className:"text-text-muted",children:e.primarySourceTool||"-"})]})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 client lỗi theo bộ lọc hiện tại."})]})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"G\xf3c nh\xecn monitor client n\xean d\xf9ng"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"C\xe1c chỉ số n\xe0y bổ sung cho latency/model để admin ph\xe2n biệt server chậm hay client gửi request qu\xe1 nặng."})]}),(0,n.jsx)("div",{className:"grid gap-3 text-sm md:grid-cols-2 xl:grid-cols-3",children:[["Token/user","X\xe1c định user/API key tạo tải lớn nhất, hữu \xedch cho quota v\xe0 hướng dẫn workflow VS Code."],["Input bucket","Nếu phần lớn request nằm ở 30k-70k+, P95/P99 cao chủ yếu do prompt eval/context d\xe0i."],["TTFT theo user","TTFT cao cho một user thường l\xe0 input d\xe0i hoặc chờ slot, kh\xf4ng nhất thiết provider lỗi."],["Error theo client","T\xe1ch lỗi sai endpoint/model/API key khỏi lỗi server/provider để kh\xf4ng cảnh b\xe1o nhầm."],["Source IP/tool","Ph\xe1t hiện m\xe1y/tool gửi request nhiều hoặc cấu h\xecnh sai."],["Top request nặng","D\xf9ng Raw usage để drill-down request cụ thể khi một user k\xe9o tải hệ thống."]].map(([e,t])=>(0,n.jsxs)("div",{className:"rounded-xl border border-border bg-background p-3",children:[(0,n.jsx)("div",{className:"font-semibold text-text-main",children:e}),(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:t})]},e))})]})]})}function ex({data:e}){let t=K();return(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Thống k\xea theo API key"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Kh\xf4ng hiển thị full bearer token. Dashboard chỉ d\xf9ng fingerprint/masked key."})]}),(0,n.jsx)(W,{rows:e.groups?.apiKeys||[],columns:[{key:"name",label:"API key",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.name}),(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:[t?e.fingerprint:"",e.ownerUser?`${t&&e.fingerprint?" \xb7 ":""}Owner: ${e.ownerUser}`:""]})]})},{key:"requests",label:"Requests",render:e=>S(e.requests)},{key:"success",label:"OK/Lỗi",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsxs)("div",{className:"text-green-600",children:["OK ",S(e.success)]}),(0,n.jsxs)("div",{className:"text-red-600",children:["Lỗi ",S(e.errors)]})]})},{key:"tokens",label:"In/Out token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"cost",label:"Cost",render:e=>M(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})},{key:"topModels",label:"Top model",render:e=>(0,n.jsx)(J,{items:e.topModels})},{key:"topProviders",label:"Top provider",render:e=>(0,n.jsx)(J,{items:e.topProviders})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]})}function em({data:e}){let t=e.clientRequests?.topSourceIpsByTokens||[],s=e.clientRequests?.topSourceIpsByHeavyRequests||[],l=e=>(0,n.jsxs)("div",{className:"min-w-[180px]",children:[(0,n.jsx)("div",{className:"font-mono text-sm font-semibold text-text-main",children:e.label}),(0,n.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:["API key ",S(e.apiKeyCount)," \xb7 Tool ",S(e.sourceToolCount)]}),(0,n.jsxs)("div",{className:"text-xs text-text-muted",children:["Model ",S(e.modelCount)," \xb7 Provider ",S(e.providerCount)]})]});return(0,n.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top IP d\xf9ng nhiều token nhất"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Aggregate từ UsageHistory, xếp theo tổng input + output token."})]}),(0,n.jsx)(W,{rows:t,columns:[{key:"ip",label:"Source IP",render:l},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top IP gửi request nặng nhất"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Xếp theo số request input/total token từ 30k trở l\xean, sau đ\xf3 theo max/P95 input."})]}),(0,n.jsx)(W,{rows:s,columns:[{key:"ip",label:"Source IP",render:l},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"heavy",label:"Request nặng",render:e=>(0,n.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,n.jsxs)("div",{children:["Nặng ",S(e.heavyRequests)," \xb7 ",P(e.heavyRequestRate)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["P95 input ",q(e.p95PromptTokens)," \xb7 Max ",q(e.maxPromptTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:[">=70k ",S(e.extremeInputRequests)," \xb7 ",P(e.extremeInputRate)]})]})},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP gửi request nặng trong khoảng lọc."})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Source IP từ Prompt Logs"}),(0,n.jsx)(W,{rows:e.promptLogs?.topClientIps||[],columns:[{key:"label",label:"IP",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Logs",render:e=>S(e.requests)},{key:"errors",label:"Lỗi",render:e=>S(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})},{key:"topTools",label:"Tools",render:e=>(0,n.jsx)(J,{items:e.topTools})},{key:"topModels",label:"Models",render:e=>(0,n.jsx)(J,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Source tool"}),(0,n.jsx)(W,{rows:e.promptLogs?.topSourceTools||[],columns:[{key:"label",label:"Tool",render:e=>(0,n.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Logs",render:e=>S(e.requests)},{key:"errors",label:"Lỗi",render:e=>S(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})},{key:"topIps",label:"Top IP",render:e=>(0,n.jsx)(J,{items:e.topIps})},{key:"topModels",label:"Top model",render:e=>(0,n.jsx)(J,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]}),(0,n.jsxs)(U,{className:"xl:col-span-2",children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Session nhiều hoạt động"}),(0,n.jsx)(W,{rows:e.promptLogs?.topSessions||[],columns:[{key:"label",label:"Session",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Logs",render:e=>S(e.requests)},{key:"errors",label:"Lỗi",render:e=>S(e.errors)},{key:"topIps",label:"IP",render:e=>(0,n.jsx)(J,{items:e.topIps})},{key:"topTools",label:"Tool",render:e=>(0,n.jsx)(J,{items:e.topTools})},{key:"topModels",label:"Model",render:e=>(0,n.jsx)(J,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]})]})}function eu({data:e}){return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Provider"}),(0,n.jsx)(W,{rows:e.groups?.providers||[],columns:[{key:"label",label:"Provider",render:e=>(0,n.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Requests",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"cost",label:"Cost",render:e=>M(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})},{key:"topModels",label:"Top model",render:e=>(0,n.jsx)(J,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]}),(0,n.jsx)(g,{data:e}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Provider account / connection"}),(0,n.jsx)(W,{rows:e.groups?.providerAccounts||[],columns:[{key:"label",label:"Account",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.label}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider||e.connectionId})]})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"errorRate",label:"Lỗi",render:e=>(0,n.jsx)(Q,{value:e.errorRate})}]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Endpoint"}),(0,n.jsx)(W,{rows:e.groups?.endpoints||[],columns:[{key:"label",label:"Endpoint",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Requests",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"cost",label:"Cost",render:e=>M(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]})]})}function eh({data:e}){let t=K(),s=e.experience||{},l=s.thresholds||{},r=e.thinkingAnalytics||{},a=e.largeContextAnalytics||{},i=s.byModel||[],o=s.slowestRequests||[];return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,n.jsx)(_,{icon:"verified",label:"Đ\xe1nh gi\xe1 tổng",value:L(s.score),hint:`${s.label||"-"} \xb7 ${S(s.samples)} mẫu success c\xf3 token`,help:"Điểm 0-100 từ request th\xe0nh c\xf4ng c\xf3 token. Tốc độ trừ tối đa 45 (chuẩn ho\xe1 theo k\xedch thước input khi prompt lớn), lỗi server trừ tối đa 40. Rate limit trừ nhẹ v\xec đ\xf3 l\xe0 hệ thống tự bảo vệ.",tone:s.tone||"slate"}),(0,n.jsx)(_,{icon:"timer",label:"Latency AVG / P95",value:`${I(s.avgLatencyMs)} / ${I(s.p95LatencyMs)}`,hint:`P50 ${I(s.p50LatencyMs)} \xb7 P99 ${I(s.p99LatencyMs)}`,help:"AVG l\xe0 trung b\xecnh; P95 thể hiện nh\xf3m 5% request chậm nhất.",tone:"purple"}),(0,n.jsx)(_,{icon:"bolt",label:"TTFT AVG / P95",value:`${I(s.avgTtftMs)} / ${I(s.p95TtftMs)}`,hint:"TTFT cao thường l\xe0 queue/prompt eval/input d\xe0i",help:"Thời gian từ l\xfac gửi request đến token đầu ti\xean.",tone:s.slowTtftRate>=.2?"amber":"blue"}),(0,n.jsx)(_,{icon:"keyboard_double_arrow_up",label:"Input AVG / P95",value:`${q(s.avgPromptTokens)} / ${q(s.p95PromptTokens)}`,hint:`>=30k ${P(s.longInputRate)} \xb7 >=50k ${P(s.hugeInputRate)}`,help:"Input c\xe0ng lớn th\xec prompt eval v\xe0 TTFT thường c\xe0ng cao."}),(0,n.jsx)(_,{icon:"running_with_errors",label:"Slow request",value:P(s.slowRequestRate),hint:`Latency >= ${I(l.slowLatencyMs||45e3)} \xb7 rất chậm ${P(s.verySlowRequestRate)}`,help:"Tỷ lệ request ho\xe0n tất chậm hơn ngưỡng vận h\xe0nh.",tone:s.slowRequestRate>=.2?"amber":"green"}),(0,n.jsx)(_,{icon:"pending_actions",label:"Slow TTFT",value:P(s.slowTtftRate),hint:`TTFT >= ${I(l.slowTtftMs||2e4)}`,help:"Tỷ lệ request chờ token đầu ti\xean qu\xe1 l\xe2u.",tone:s.slowTtftRate>=.2?"amber":"green"}),(0,n.jsx)(_,{icon:"speed",label:"Output tốc độ",value:R(s.decodeTokensPerSecond," tok/s"),hint:`Output/latency ${R(s.outputTokensPerSecond," tok/s")}`,tone:"slate"}),(0,n.jsx)(_,{icon:"data_usage",label:"Latency / 10k input",value:I(s.latencyMsPer10kInputTokens),hint:"Hữu \xedch khi VS Code gửi 30k–70k token",help:"Chuẩn h\xf3a latency theo k\xedch thước input để so s\xe1nh c\xf4ng bằng hơn.",tone:"slate"}),(0,n.jsx)(_,{icon:"psychology_alt",label:"Thinking auto-off",value:P(r.autoOffRate),hint:`${S(r.autoOffRequests||0)} / ${S(r.totalRequests||0)} request`,help:"Request bị tắt thinking tự động do vượt ngưỡng prompt chars.",tone:(r.autoOffRate||0)>=.3?"amber":"green"}),(0,n.jsx)(_,{icon:"toggle_off",label:"Thinking OFF",value:P(r.thinkingOffRate),hint:`ON ${P(r.thinkingOnRate)} \xb7 unknown ${P(r.unknownRate)}`,help:"Tỷ lệ request cuối c\xf9ng chạy ở chế độ kh\xf4ng thinking.",tone:(r.thinkingOffRate||0)>=.5?"blue":"slate"}),(0,n.jsx)(_,{icon:"data_object",label:"Large context",value:P(a.gte50kRate),hint:`>=30k ${P(a.gte30kRate)} \xb7 >=100k ${P(a.gte100kRate)}`,help:"Tỷ lệ request c\xf3 context lớn; thường l\xe0 nguy\xean nh\xe2n l\xe0m P95/P99 tăng.",tone:(a.gte50kRate||0)>=.3?"amber":"slate"})]}),(0,n.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Thinking Analytics"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Theo d\xf5i request bật/tắt thinking v\xe0 tỷ lệ auto-off do vượt ngưỡng prompt chars."})]}),(0,n.jsx)("div",{className:"grid gap-3 md:grid-cols-2",children:[["Thinking ON",S(r.thinkingOnRequests||0),P(r.thinkingOnRate)],["Thinking OFF",S(r.thinkingOffRequests||0),P(r.thinkingOffRate)],["Auto-off hit",S(r.autoOffRequests||0),P(r.autoOffRate)],["C\xf3 ngưỡng auto-off",S(r.thresholdConfiguredRequests||0),`hit ${P(r.autoOffEligibleHitRate)}`]].map(([e,t,s])=>(0,n.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,n.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:e}),(0,n.jsx)("div",{className:"mt-2 text-xl font-semibold text-text-main",children:t}),(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:s})]},e))}),(0,n.jsx)("div",{className:"mt-4",children:(0,n.jsx)(W,{rows:r.byModel||[],empty:"Chưa c\xf3 dữ liệu thinking trong khoảng lọc.",columns:[{key:"model",label:"Model",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.model}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:e.provider})]})},{key:"requests",label:"Req",render:e=>S(e.requests)},{key:"autoOff",label:"Auto-off",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:S(e.autoOffRequests)}),(0,n.jsx)("div",{className:"text-text-muted",children:P(e.autoOffRate)})]})},{key:"thinking",label:"ON/OFF",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsxs)("div",{children:["ON ",S(e.thinkingOnRequests)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["OFF ",S(e.thinkingOffRequests)]})]})},{key:"chars",label:"Chars avg/max",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:q(e.avgPromptChars)}),(0,n.jsxs)("div",{className:"text-text-muted",children:["max ",q(e.maxPromptChars)]})]})}]})})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Large Context Analytics"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Bucket theo request size, ưu ti\xean prompt chars; nếu chưa c\xf3 chars th\xec fallback prompt tokens."})]}),(0,n.jsx)("div",{className:"grid gap-3 md:grid-cols-3",children:[[">=30k",a.gte30kRequests,a.gte30kRate],[">=50k",a.gte50kRequests,a.gte50kRate],[">=100k",a.gte100kRequests,a.gte100kRate]].map(([e,t,s])=>(0,n.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,n.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:e}),(0,n.jsx)("div",{className:"mt-2 text-xl font-semibold text-text-main",children:S(t||0)}),(0,n.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:P(s)})]},e))}),(0,n.jsx)("div",{className:"mt-4",children:(0,n.jsx)(W,{rows:a.buckets||[],empty:"Chưa c\xf3 large context buckets trong khoảng lọc.",columns:[{key:"label",label:"Bucket",render:e=>(0,n.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Req",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:S(e.requests)}),(0,n.jsx)("div",{className:"text-text-muted",children:P(e.share)})]})},{key:"chars",label:"Size avg/max",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:q(e.avgRequestSize)}),(0,n.jsxs)("div",{className:"text-text-muted",children:["max ",q(e.maxRequestSize)]})]})},{key:"latency",label:"Latency/TTFT",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:I(e.avgLatencyMs)}),(0,n.jsxs)("div",{className:"text-text-muted",children:["TTFT ",I(e.avgTtftMs)]})]})},{key:"autoOff",label:"Auto-off",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:S(e.autoOffRequests)}),(0,n.jsx)("div",{className:"text-text-muted",children:P(e.autoOffRate)})]})}]})})]})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"C\xe1ch đọc trải nghiệm user"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Nh\xf3m n\xe0y chỉ t\xednh request th\xe0nh c\xf4ng c\xf3 token v\xe0 latency > 0. Error/pending/success 0-token kh\xf4ng trộn v\xe0o tốc độ model. TTFT l\xe0 thời gian tới token đầu ti\xean; với VS Code input 30k–70k, TTFT cao thường phản \xe1nh chờ slot hoặc prompt eval d\xe0i."})]}),(0,n.jsxs)("div",{className:"grid gap-3 md:grid-cols-3",children:[(0,n.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,n.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"Nhanh/chậm thực tế"}),(0,n.jsx)("div",{className:"mt-2 text-sm text-text-main",children:"Latency AVG/P50/P95/MAX cho biết user phải chờ bao l\xe2u để request ho\xe0n tất."})]}),(0,n.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,n.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"Queue hoặc prompt eval"}),(0,n.jsx)("div",{className:"mt-2 text-sm text-text-main",children:"TTFT cao + input P95 cao l\xe0 t\xedn hiệu request d\xe0i, hết slot hoặc upstream đang queue."})]}),(0,n.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,n.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"VS Code / agent"}),(0,n.jsx)("div",{className:"mt-2 text-sm text-text-main",children:"Theo d\xf5i tỷ lệ input >=30k/50k/70k để biết P95/P99 cao c\xf3 phải do context cực d\xe0i hay kh\xf4ng."})]})]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Chất lượng phản hồi theo provider/model"}),(0,n.jsx)(W,{rows:i,empty:"Chưa c\xf3 mẫu latency cho model trong khoảng lọc.",columns:[{key:"model",label:"Model",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.model}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"quality",label:"Đ\xe1nh gi\xe1",render:e=>(0,n.jsxs)("div",{className:"space-y-1",children:[(0,n.jsx)(ee,{level:e.level,label:e.labelQuality}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:L(e.score)})]})},{key:"samples",label:"Mẫu",render:e=>S(e.samples)},{key:"latency",label:"Latency P50/P95/MAX",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsxs)("div",{children:[I(e.p50LatencyMs)," / ",I(e.p95LatencyMs)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:["max ",I(e.maxLatencyMs)]})]})},{key:"ttft",label:"TTFT P95",render:e=>I(e.p95TtftMs)},{key:"input",label:"Input avg/P95",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsxs)("div",{children:[q(e.avgPromptTokens)," / ",q(e.p95PromptTokens)]}),(0,n.jsxs)("div",{className:"text-text-muted",children:[">=30k ",P(e.longInputRate)]})]})},{key:"slow",label:"Chậm",render:e=>(0,n.jsx)(Q,{value:e.slowRequestRate})},{key:"speed",label:"Output tok/s",render:e=>R(e.outputTokensPerSecond," tok/s")}]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Request chậm nhất"}),(0,n.jsx)(W,{rows:o,empty:"Kh\xf4ng c\xf3 request chậm trong khoảng lọc.",columns:[{key:"timestamp",label:"Time",render:e=>A(e.timestamp)},{key:"model",label:"Model",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.model}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"latency",label:"Latency / TTFT",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{className:"font-semibold",children:I(e.latencyMs)}),(0,n.jsxs)("div",{className:"text-text-muted",children:["TTFT ",I(e.ttftMs)]})]})},{key:"tokens",label:"In / Out",render:e=>(0,n.jsx)(Z,{row:e})},{key:"apiKeyName",label:"API key",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{children:e.apiKeyName}),t?(0,n.jsx)("div",{className:"font-mono text-xs text-text-muted",children:e.apiKeyFingerprint}):null]})},{key:"sourceTool",label:"Tool/IP",render:e=>(0,n.jsxs)("div",{className:"text-xs",children:[(0,n.jsx)("div",{children:e.sourceTool||"-"}),(0,n.jsx)("div",{className:"font-mono text-text-muted",children:e.clientIp||"-"})]})},{key:"endpoint",label:"Endpoint",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.endpoint||"-"})}]})]})]})}function ep({data:e}){let t=K(),s=e.requestErrors||{},l=s.summary||{},r=e.overview||{},a=Number(r.serverErrorRate||0),i=Number(r.clientErrorRate||0),o=Number(r.rateLimitErrorRate||0),d=[{key:"faultOwner",label:"Loại",render:e=>(0,n.jsx)(es,{value:e.faultOwner})},{key:"status",label:"Status",render:e=>(0,n.jsx)("span",{className:"rounded-full bg-red-500/10 px-2 py-1 text-xs font-semibold text-red-600 dark:text-red-300",children:e.status})},{key:"provider",label:"Provider",render:e=>e.providerLabel||e.provider},{key:"model",label:"Model"},{key:"endpoint",label:"Endpoint",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"requests",label:"Lỗi",render:e=>S(e.errors||e.requests)},{key:"errorType",label:"Type",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.errorType||e.errorCode||"-"})},{key:"sampleMessage",label:"Sample",render:e=>(0,n.jsx)(en,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}];return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-5",children:[(0,n.jsx)(el,{icon:"dns",label:"Server/provider",value:l.serverImpacting||0,hint:`${P(a)} tr\xean tổng request`,tone:l.serverImpacting?"red":"green"}),(0,n.jsx)(el,{icon:"cloud_off",label:"Upstream",value:l.upstream||0,hint:"Provider/model server, timeout, network, 5xx",tone:l.upstream?"red":"green"}),(0,n.jsx)(el,{icon:"router",label:"Gateway",value:l.gateway||0,hint:"Lỗi nội bộ BlueRouter/gateway",tone:l.gateway?"purple":"green"}),(0,n.jsx)(el,{icon:"integration_instructions",label:"Client/request",value:l.client||0,hint:`${P(i)} do endpoint/model/body/auth`,tone:l.client?"slate":"green"}),(0,n.jsx)(el,{icon:"speed",label:"Rate/quota",value:l.rateLimit||0,hint:`${P(o)} rate-limit/quota`,tone:l.rateLimit?"amber":"green"})]}),(0,n.jsx)("div",{className:"rounded-2xl border border-blue-500/20 bg-blue-500/10 p-4 text-sm text-blue-700 dark:text-blue-300",children:(0,n.jsxs)("div",{className:"flex gap-3",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:"rule_settings"}),(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:"Ph\xe2n loại lỗi đ\xe3 t\xe1ch client khỏi server/provider"}),(0,n.jsxs)("div",{className:"mt-1 opacity-90",children:["Cảnh b\xe1o vận h\xe0nh n\xean ưu ti\xean nh\xf3m ",(0,n.jsx)("b",{children:"Server/provider"})," gồm gateway, upstream, timeout, network v\xe0 5xx. Nh\xf3m ",(0,n.jsx)("b",{children:"Client/request"})," vẫn được log đầy đủ nhưng thường l\xe0 sai endpoint, model, auth, JSON/body hoặc context."]})]})]})}),e.anomalies?.length?(0,n.jsx)("div",{className:"grid gap-4 xl:grid-cols-2",children:e.anomalies.map((e,t)=>(0,n.jsx)(er,{anomaly:e},t))}):(0,n.jsxs)("div",{className:"rounded-2xl border border-green-500/20 bg-green-500/10 p-4 text-sm text-green-700 dark:text-green-300",children:[(0,n.jsx)("span",{className:"material-symbols-outlined mr-2 align-[-5px]",children:"check_circle"}),"Chưa ph\xe1t hiện bất thường server/provider r\xf5 r\xe0ng theo bộ lọc hiện tại."]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Lỗi server/provider cần xử l\xfd"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Chỉ gồm gateway/upstream/server-impacting errors. Đ\xe2y l\xe0 bảng quan trọng nhất cho vận h\xe0nh."})]}),(0,n.jsxs)("span",{className:"rounded-full bg-red-500/10 px-3 py-1 text-xs font-semibold text-red-600 dark:text-red-300",children:[S(l.serverImpacting||0)," lỗi"]})]}),(0,n.jsx)(W,{rows:s.topServerErrors||[],columns:d,empty:"Kh\xf4ng c\xf3 lỗi server/provider trong khoảng lọc."})]}),(0,n.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Lỗi client/request sai"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Sai endpoint, model, auth, JSON/body, context length. D\xf9ng để hướng dẫn client sửa request."})]}),(0,n.jsx)(W,{rows:s.topClientErrors||[],columns:d.filter(e=>!["sampleMessage"].includes(e.key)),empty:"Kh\xf4ng c\xf3 lỗi client/request trong khoảng lọc."})]}),(0,n.jsxs)(U,{children:[(0,n.jsxs)("div",{className:"mb-4",children:[(0,n.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Ph\xe2n bố loại lỗi"}),(0,n.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"T\xe1ch nguồn chịu tr\xe1ch nhiệm để kh\xf4ng nhầm lỗi client th\xe0nh lỗi server."})]}),(0,n.jsx)(W,{rows:s.byFaultOwner||[],columns:[{key:"faultOwner",label:"Loại",render:e=>(0,n.jsx)(es,{value:e.faultOwner||e.key})},{key:"requests",label:"Số lỗi",render:e=>S(e.requests)},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 lỗi để ph\xe2n loại."})]})]}),s.topRateLimitErrors?.length?(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Rate limit / quota"}),(0,n.jsx)(W,{rows:s.topRateLimitErrors||[],columns:d})]}):null,(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Tất cả lỗi raw theo status/provider/model/endpoint"}),(0,n.jsx)(W,{rows:[...e.groups?.errors||[]].sort((e,t)=>new Date(C(t.lastSeen)||0)-new Date(C(e.lastSeen)||0)||Number(t.errors||t.requests||0)-Number(e.errors||e.requests||0)),columns:[{key:"faultOwner",label:"Loại",render:e=>(0,n.jsx)(es,{value:e.faultOwner})},{key:"status",label:"Status",render:e=>(0,n.jsx)("span",{className:"rounded-full bg-red-500/10 px-2 py-1 text-xs font-semibold text-red-600 dark:text-red-300",children:e.status})},{key:"provider",label:"Provider",render:e=>e.providerLabel||e.provider},{key:"model",label:"Model"},{key:"endpoint",label:"Endpoint",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"requests",label:"Lỗi",render:e=>S(e.errors||e.requests)},{key:"apiKey",label:"API key",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:t?e.apiKey:e.apiKeyName||"•••"})},{key:"lastSeen",label:"Last seen",render:e=>A(e.lastSeen)}]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Status distribution"}),(0,n.jsx)(W,{rows:e.groups?.statuses||[],columns:[{key:"label",label:"Status"},{key:"requests",label:"Requests",render:e=>S(e.requests)},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"errorRate",label:"Error %",render:e=>(0,n.jsx)(Q,{value:e.errorRate})}]})]})]})}function eb({data:e}){let t=K();return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top request nặng token"}),(0,n.jsx)(W,{rows:e.heavyRequests||[],columns:[{key:"timestamp",label:"Time",render:e=>A(e.timestamp)},{key:"model",label:"Model",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-semibold",children:e.model}),(0,n.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"apiKeyName",label:"API key",render:e=>(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{children:e.apiKeyName}),t?(0,n.jsx)("div",{className:"font-mono text-xs text-text-muted",children:e.apiKeyFingerprint}):null]})},{key:"accountName",label:"Account"},{key:"endpoint",label:"Endpoint",render:e=>(0,n.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"status",label:"Status"}]})]}),(0,n.jsxs)(U,{children:[(0,n.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Recent usage"}),(0,n.jsx)(W,{rows:e.recentUsage||[],columns:[{key:"timestamp",label:"Time",render:e=>A(e.timestamp)},{key:"provider",label:"Provider",render:e=>e.providerLabel||e.provider},{key:"model",label:"Model"},{key:"apiKeyName",label:"API key"},{key:"tokens",label:"Token",render:e=>(0,n.jsx)(Z,{row:e})},{key:"cost",label:"Cost",render:e=>M(e.cost)},{key:"status",label:"Status"}]})]})]})}function eg(){let{isAdmin:e,isMonitorAdmin:t,isAiGatewaysMonitor:s}=(0,a.s)(),r=e||t||s,i=(0,l.useMemo)(()=>e?y:y.filter(e=>"aiHealth"!==e.value),[e]),[o,d]=(0,l.useState)({period:"today",dateFrom:"",dateTo:"",provider:"",model:"",connectionId:"",status:"",endpoint:"",apiKey:"",clientIp:"",sourceTool:"",sessionId:"",keyword:""}),[c,x]=(0,l.useState)(null),[m,u]=(0,l.useState)(!0),[h,p]=(0,l.useState)(""),[b,g]=(0,l.useState)("overview"),[j,k]=(0,l.useState)(null),f=function(e,t=450){let[s,n]=(0,l.useState)(e);return(0,l.useEffect)(()=>{let s=setTimeout(()=>n(e),t);return()=>clearTimeout(s)},[e,t]),s}(o,450),N=(0,l.useRef)(0),w=(0,l.useCallback)(async({clear:e=!1,filtersOverride:t=null}={})=>{let s=N.current+1;N.current=s,e&&x(null),u(!0),p("");let n=Date.now();try{let e=t||f,l=E(e,{timeZone:O()}),r=await fetch(`/api/dashboard/analytics?${l}`,{cache:"no-store"}),a=await r.json().catch(()=>({}));if(s!==N.current)return;if(!r.ok)throw Error(a.error||"Kh\xf4ng tải được dữ liệu analytics");x(a),k({loadedMs:Date.now()-n,cacheState:a.cacheState||"",cacheAgeMs:a.cacheAgeMs||0})}catch(e){if(s!==N.current)return;p(e.message||"Kh\xf4ng tải được dữ liệu analytics")}finally{s===N.current&&u(!1)}},[f]);(0,l.useEffect)(()=>{w({clear:!0})},[w]),(0,l.useEffect)(()=>{let e=localStorage.getItem(v);e&&i.some(t=>t.value===e)&&g(e)},[i]),(0,l.useEffect)(()=>{i.some(e=>e.value===b)||g("overview")},[i,b]),(0,l.useEffect)(()=>{localStorage.setItem(v,b)},[b]);let S=c?.options||{},q=(0,l.useMemo)(()=>c?.generatedAt?A(c.generatedAt):"-",[c]);return(0,n.jsxs)("div",{className:"space-y-5 p-4 md:p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 text-primary",children:[(0,n.jsx)("span",{className:"material-symbols-outlined",children:"monitoring"}),(0,n.jsx)("span",{className:"text-sm font-semibold uppercase tracking-wide",children:"BlueRouter Analytics"})]}),(0,n.jsx)("h1",{className:"mt-2 text-2xl font-bold text-text-main",children:"Thống k\xea sử dụng Gateway"}),(0,n.jsx)("p",{className:"mt-1 max-w-3xl text-sm text-text-muted",children:"Theo d\xf5i tần suất request, input/output token, API key, provider, model, endpoint, Source IP, source tool v\xe0 lỗi vận h\xe0nh."})]}),(0,n.jsxs)("div",{className:"flex items-center gap-3 rounded-2xl border border-border bg-surface px-4 py-3 text-sm text-text-muted",children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[20px]",children:"schedule"}),(0,n.jsxs)("div",{children:[(0,n.jsxs)("div",{children:["Generated: ",q]}),j?(0,n.jsxs)("div",{className:"mt-0.5 text-xs",children:["Loaded in ",j.loadedMs>=1e3?`${(j.loadedMs/1e3).toLocaleString("vi-VN",{maximumFractionDigits:1})}s`:`${j.loadedMs}ms`,"hit"===j.cacheState?(0,n.jsxs)("span",{className:"ml-1.5 rounded bg-emerald-500/10 px-1.5 py-0.5 font-medium text-emerald-500",children:["cache hit",j.cacheAgeMs?` \xb7 ${Math.round(j.cacheAgeMs/1e3)}s`:""]}):"joined"===j.cacheState?(0,n.jsx)("span",{className:"ml-1.5 rounded bg-sky-500/10 px-1.5 py-0.5 font-medium text-sky-500",children:"shared compute"}):"fresh"===j.cacheState?(0,n.jsx)("span",{className:"ml-1.5 rounded bg-amber-500/10 px-1.5 py-0.5 font-medium text-amber-500",children:"fresh compute"}):null]}):null]})]})]}),(0,n.jsx)(eo,{filters:o,setFilters:d,options:S,onRefresh:e=>w({filtersOverride:e||o}),onExportCsv:()=>{let e=E(o,{format:"csv",timeZone:O()});window.open(`/api/dashboard/analytics?${e}`,"_blank","noopener,noreferrer")},loading:m,showProviderFilters:r}),h?(0,n.jsxs)("div",{className:"rounded-2xl border border-red-500/30 bg-red-500/10 p-4 text-sm text-red-700 dark:text-red-300",children:[(0,n.jsx)("span",{className:"material-symbols-outlined mr-2 align-[-5px]",children:"error"}),h]}):null,c?.qualityNotes?.length?(0,n.jsx)(ea,{notes:c.qualityNotes}):null,(0,n.jsx)("div",{className:"flex flex-wrap gap-2 rounded-2xl border border-border bg-surface p-2",children:i.map(e=>(0,n.jsxs)("button",{onClick:()=>g(e.value),className:F("flex items-center gap-2 rounded-xl px-3 py-2 text-sm font-medium transition",b===e.value?"bg-primary text-white shadow-sm":"text-text-muted hover:bg-background hover:text-text-main"),children:[(0,n.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:e.icon}),e.label]},e.value))}),m&&!c?(0,n.jsx)(B,{}):null,!m&&c&&c.overview?.requests===0&&0===(c.promptLogs?.total||0)?(0,n.jsx)(G,{title:"Chưa c\xf3 dữ liệu analytics",description:"Kh\xf4ng c\xf3 UsageHistory hoặc Prompt Logs theo bộ lọc hiện tại."}):null,c?(0,n.jsxs)(n.Fragment,{children:["overview"===b?(0,n.jsx)(ed,{data:c}):null,"apiKeys"===b?(0,n.jsx)(ex,{data:c}):null,"clients"===b?(0,n.jsx)(ec,{data:c}):null,"sources"===b?(0,n.jsx)(em,{data:c}):null,"providers"===b?(0,n.jsx)(eu,{data:c}):null,"experience"===b?(0,n.jsx)(eh,{data:c}):null,"errors"===b?(0,n.jsx)(ep,{data:c}):null,"raw"===b?(0,n.jsx)(eb,{data:c}):null]}):null,"aiHealth"===b&&e?(0,n.jsx)(T,{}):null]})}},85881:(e,t,s)=>{"use strict";s.d(t,{default:()=>i});var n=s(12115);let l=new Set(["lastMonth","60d","all"]);function r(e){let t=e=>String(e).padStart(2,"0");return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}T${t(e.getHours())}:${t(e.getMinutes())}`}function a(e){return Array.from(document.querySelectorAll("label")).find(t=>{let s=t.querySelector(":scope > span");return s?.textContent?.trim()===e})||null}function i(){return(0,n.useEffect)(()=>{let e=!1,t=()=>{e||(e=!0,requestAnimationFrame(()=>{e=!1,function(){let e=a("Khoảng thời gian"),t=e?.querySelector("select");if(t){let e=t.value;for(let e of Array.from(t.options)){if(l.has(e.value)){e.remove();continue}"thisMonth"===e.value&&"Th\xe1ng n\xe0y (tối đa 30 ng\xe0y)"!==e.textContent&&(e.textContent="Th\xe1ng n\xe0y (tối đa 30 ng\xe0y)"),"custom"===e.value&&"T\xf9y chọn (tối đa 30 ng\xe0y)"!==e.textContent&&(e.textContent="T\xf9y chọn (tối đa 30 ng\xe0y)")}l.has(e)&&(t.value="30d",t.dispatchEvent(new Event("change",{bubbles:!0})))}let s=new Date,n=r(new Date(s.getTime()-2592e6)),i=r(s);for(let e of["Từ ng\xe0y","Đến ng\xe0y"]){let t=a(e)?.querySelector('input[type="datetime-local"]');t&&(t.min!==n&&(t.min=n),t.max!==i&&(t.max=i),t.title="Analytics chỉ truy vấn tối đa 30 ng\xe0y gần nhất")}}()}))};t();let s=new MutationObserver(t);s.observe(document.body,{childList:!0,subtree:!0});let n=window.setInterval(t,3e5);return()=>{s.disconnect(),window.clearInterval(n)}},[]),null}},94027:(e,t,s)=>{"use strict";s.d(t,{Y:()=>o,s:()=>d});var n=s(95155),l=s(12115),r=s(14051),a=s.n(r);let i=(0,l.createContext)(null);function o({children:e}){let[t,s]=(0,l.useState)(null),[r,a]=(0,l.useState)(!0),[d,c]=(0,l.useState)(""),x=(0,l.useCallback)(async()=>{a(!0),c("");try{let e=await fetch("/api/auth/status",{cache:"no-store"}),t=await e.json().catch(()=>({}));if(!e.ok)throw Error(t?.error||"Kh\xf4ng tải được trạng th\xe1i đăng nhập");return s(t||{}),t||{}}catch(e){return c(e?.message||"Kh\xf4ng tải được trạng th\xe1i đăng nhập"),s({}),{}}finally{a(!1)}},[]);(0,l.useEffect)(()=>{let e=!1;return(async()=>{a(!0),c("");try{let t=await fetch("/api/auth/status",{cache:"no-store"}),n=await t.json().catch(()=>({}));if(e)return;if(!t.ok)throw Error(n?.error||"Kh\xf4ng tải được trạng th\xe1i đăng nhập");s(n||{})}catch(t){e||(c(t?.message||"Kh\xf4ng tải được trạng th\xe1i đăng nhập"),s({}))}finally{e||a(!1)}})(),()=>{e=!0}},[]);let m=(0,l.useMemo)(()=>{let e,s,n,l,r,a,i;return s=(e=t&&"object"==typeof t?t:{}).displayName||e.oidcName||e.oidcEmail||e.userId||"",l=(n=!0===e.actualIsAdmin||!0===e.isAdmin&&!0!==e.showAsUser)&&!0===e.showAsUser,r=!0===e.isAdmin&&!l,a=!0===e.isMonitorAdmin,i=!0===e.isAiGatewaysMonitor,{status:e,displayName:s,userId:e.userId||"",loginMethod:e.loginMethod||"",role:e.role||"guest",actualRole:e.actualRole||e.role||"guest",isAdmin:r,actualIsAdmin:n,showAsUser:l,canToggleUserMode:!0===e.canToggleUserMode||n,isMonitorAdmin:a,isAiGatewaysMonitor:i,canManageApiKeys:!0===e.canManageApiKeys||r||a,canUseMonitorAdminTabs:!0===e.canUseMonitorAdminTabs||r||a,canViewAllAnalytics:!0===e.canViewAllAnalytics||r||a||i}},[t]),u=(0,l.useMemo)(()=>({...m,loading:r,error:d,reload:x}),[m,r,d,x]);return(0,n.jsx)(i.Provider,{value:u,children:e})}function d(){let e=(0,l.useContext)(i);return e||{status:{},displayName:"",userId:"",loginMethod:"",role:"admin",actualRole:"admin",isAdmin:!0,actualIsAdmin:!0,showAsUser:!1,canToggleUserMode:!0,isMonitorAdmin:!1,isAiGatewaysMonitor:!1,canManageApiKeys:!0,canUseMonitorAdminTabs:!0,canViewAllAnalytics:!0,loading:!1,error:"",reload:async()=>({})}}o.propTypes={children:a().node}}},e=>{e.O(0,[9959,8441,3794,7358],()=>e(e.s=52355)),_N_E=e.O()}]);
@@ -0,0 +1,3 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[2134],{18205:(e,t,a)=>{Promise.resolve().then(a.bind(a,57662))},57662:(e,t,a)=>{"use strict";a.r(t),a.d(t,{default:()=>Y});var s=a(95155),i=a(12115),l=a(73321),r=a(98500),n=a.n(r),o=a(5772),d=a(35497),c=a(52679),m=a(28777),p=a(11059);let u=new Map;async function x(e){if(!e?.url||!e?.type)return[];let t=u.get(e.url);if(t&&Date.now()<t.expiresAt)return t.data;try{let t=new URLSearchParams({url:e.url,type:e.type}),a=await fetch(`/api/providers/suggested-models?${t}`);if(!a.ok)return[];let s=(await a.json()).data??[];return u.set(e.url,{data:s,expiresAt:Date.now()+6e5}),s}catch{return[]}}var h=a(14051),g=a.n(h);function b({model:e,fullModel:t,alias:a,copied:i,onCopy:l,testStatus:r,isCustom:n,isFree:o,onDeleteAlias:d,onTest:c,isTesting:m,onDisable:p}){let u="ok"===r?"#22c55e":"error"===r?"#ef4444":void 0;return(0,s.jsx)("div",{className:`group min-w-0 max-w-full rounded-lg border px-3 py-2 ${"ok"===r?"border-green-500/40":"error"===r?"border-red-500/40":"border-border"} hover:bg-sidebar/50`,children:(0,s.jsxs)("div",{className:"flex min-w-0 items-start gap-2 sm:items-center",children:[(0,s.jsx)("span",{className:"material-symbols-outlined shrink-0 text-base",style:u?{color:u}:void 0,children:"ok"===r?"check_circle":"error"===r?"cancel":"smart_toy"}),(0,s.jsxs)("div",{className:"flex min-w-0 flex-1 flex-col gap-1",children:[(0,s.jsx)("code",{className:"max-w-[72vw] truncate rounded bg-sidebar px-1.5 py-0.5 font-mono text-xs text-text-muted sm:max-w-[360px]",children:t}),e.name&&(0,s.jsx)("span",{className:"truncate pl-1 text-[9px] italic text-text-muted/70",children:e.name})]}),c&&(0,s.jsxs)("div",{className:"relative shrink-0 group/btn",children:[(0,s.jsx)("button",{onClick:c,disabled:m,className:`rounded p-0.5 text-text-muted transition-opacity hover:bg-sidebar hover:text-primary ${m?"opacity-100":"opacity-100 sm:opacity-0 sm:group-hover:opacity-100"}`,children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",style:m?{animation:"spin 1s linear infinite"}:void 0,children:m?"progress_activity":"science"})}),(0,s.jsx)("span",{className:"pointer-events-none absolute mt-1 top-5 left-1/2 -translate-x-1/2 text-[10px] text-text-muted whitespace-nowrap opacity-0 group-hover/btn:opacity-100 transition-opacity",children:m?"Testing...":"Test"})]}),(0,s.jsxs)("div",{className:"relative shrink-0 group/btn",children:[(0,s.jsx)("button",{onClick:()=>l(t,`model-${e.id}`),className:"rounded p-0.5 text-text-muted hover:bg-sidebar hover:text-primary",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:i===`model-${e.id}`?"check":"content_copy"})}),(0,s.jsx)("span",{className:"pointer-events-none absolute mt-1 top-5 left-1/2 -translate-x-1/2 text-[10px] text-text-muted whitespace-nowrap opacity-0 group-hover/btn:opacity-100 transition-opacity",children:i===`model-${e.id}`?"Copied!":"Copy"})]}),n?(0,s.jsx)("button",{onClick:d,className:"ml-auto rounded p-0.5 text-text-muted opacity-100 transition-opacity hover:bg-red-500/10 hover:text-red-500 sm:opacity-0 sm:group-hover:opacity-100",title:"Remove custom model",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"close"})}):p?(0,s.jsx)("button",{onClick:p,className:"ml-auto rounded p-0.5 text-text-muted opacity-100 transition-opacity hover:bg-red-500/10 hover:text-red-500 sm:opacity-0 sm:group-hover:opacity-100",title:"Disable this model",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"close"})}):null]})})}function f({modelId:e,fullModel:t,copied:a,onCopy:i,onDeleteAlias:l,onTest:r,testStatus:n,isTesting:o}){let d=`model_support:${e}`,c="ok"===n?"#22c55e":"error"===n?"#ef4444":void 0;return(0,s.jsxs)("div",{className:`flex items-center gap-3 p-3 rounded-lg border ${"ok"===n?"border-green-500/40":"error"===n?"border-red-500/40":"border-border"} hover:bg-sidebar/50`,children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-base text-text-muted",style:c?{color:c}:void 0,children:"ok"===n?"check_circle":"error"===n?"cancel":"smart_toy"}),(0,s.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,s.jsx)("p",{className:"text-sm font-medium truncate",children:e}),(0,s.jsxs)("div",{className:"flex items-center gap-1 mt-1",children:[(0,s.jsx)("code",{className:"text-xs text-text-muted font-mono bg-sidebar px-1.5 py-0.5 rounded",children:t}),(0,s.jsxs)("div",{className:"relative group/btn",children:[(0,s.jsx)("button",{onClick:()=>i(t,`model-${e}`),className:"p-0.5 hover:bg-sidebar rounded text-text-muted hover:text-primary",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:a===`model-${e}`?"check":"content_copy"})}),(0,s.jsx)("span",{className:"pointer-events-none absolute top-5 left-1/2 -translate-x-1/2 text-[10px] text-text-muted whitespace-nowrap opacity-0 group-hover/btn:opacity-100 transition-opacity",children:a===`model-${e}`?"Copied!":"Copy"})]}),r&&(0,s.jsxs)("div",{className:"relative group/btn",children:[(0,s.jsx)("button",{onClick:r,disabled:o,className:"p-0.5 hover:bg-sidebar rounded text-text-muted hover:text-primary transition-colors",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",style:o?{animation:"spin 1s linear infinite"}:void 0,children:o?"progress_activity":"science"})}),(0,s.jsx)("span",{className:"pointer-events-none absolute top-5 left-1/2 -translate-x-1/2 text-[10px] text-text-muted whitespace-nowrap opacity-0 group-hover/btn:opacity-100 transition-opacity",children:o?"Testing...":"Test"})]})]}),(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-1.5",children:[(0,s.jsx)("span",{className:"text-[10px] text-text-muted",children:"LAN tag:"}),(0,s.jsx)("code",{className:"rounded bg-primary/10 px-1.5 py-0.5 font-mono text-[10px] text-primary",children:d}),(0,s.jsx)("button",{type:"button",onClick:()=>i(d,`tag-${e}`),className:"rounded px-1 py-0.5 text-[10px] text-text-muted hover:bg-sidebar hover:text-primary",title:"Copy model_support tag",children:a===`tag-${e}`?"Copied":"Copy tag"})]})]}),(0,s.jsx)("button",{onClick:l,className:"p-1 hover:bg-red-50 rounded text-red-500",title:"Remove model",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"delete"})})]})}function y({providerStorageAlias:e,providerDisplayAlias:t,modelAliases:a,copied:l,onCopy:r,onSetAlias:n,onDeleteAlias:o,connections:c,isAnthropic:m}){let[p,u]=(0,i.useState)(""),[x,h]=(0,i.useState)(!1),[g,b]=(0,i.useState)(!1),[v,j]=(0,i.useState)(null),[k,N]=(0,i.useState)({}),w=async t=>{if(!v){j(t);try{let a,s=await fetch("/api/models/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:`${e}/${t}`,connectionId:(a=c.find(e=>!1!==e.isActive),a?.id||c[0]?.id||null)})}),i=await s.json();N(e=>({...e,[t]:i.ok?"ok":"error"}))}catch{N(e=>({...e,[t]:"error"}))}finally{j(null)}}},C=Object.entries(a).filter(([,t])=>t.startsWith(`${e}/`)).map(([t,a])=>({modelId:a.replace(`${e}/`,""),fullModel:a,alias:t})),S=s=>{let i,l=`${e}/${s}`;if(Object.values(a).includes(l))return null;let r=(i=s.split("/"))[i.length-1];if(!a[r])return r;let n=`${t}-${r}`;return a[n]?null:n},A=async()=>{if(!p.trim()||x)return;let t=p.trim(),a=S(t);if(!a)return void alert("All suggested aliases already exist. Please choose a different model or remove conflicting aliases.");h(!0);try{await n(t,a,e),u("")}catch(e){console.log("Error adding model:",e)}finally{h(!1)}},T=async()=>{if(g)return;let t=c.find(e=>!1!==e.isActive);if(t){b(!0);try{let a=await fetch(`/api/providers/${t.id}/models`),s=await a.json();if(!a.ok)return void alert(s.error||"Failed to import models");let i=s.models||[];if(0===i.length)return void alert("No models returned from /models.");let l=0;for(let t of i){let a=t.id||t.name||t.model;if(!a)continue;let s=S(a);s&&(await n(a,s,e),l+=1)}0===l&&alert("No new models were added.")}catch(e){console.log("Error importing models:",e)}finally{b(!1)}}},$=c.some(e=>!1!==e.isActive);return(0,s.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,s.jsxs)("p",{className:"text-sm text-text-muted",children:["Add ",m?"Anthropic":"OpenAI","-compatible models manually or import them from the /models endpoint. Each model also shows a ",(0,s.jsx)("code",{className:"rounded bg-sidebar px-1 py-0.5 font-mono text-xs",children:"model_support:*"})," tag you can paste into an Ollama endpoint label for Combo tag routing."]}),(0,s.jsxs)("div",{className:"flex items-end gap-2 flex-wrap",children:[(0,s.jsxs)("div",{className:"flex-1 min-w-[240px]",children:[(0,s.jsx)("label",{htmlFor:"new-compatible-model-input",className:"text-xs text-text-muted mb-1 block",children:"Model ID"}),(0,s.jsx)("input",{id:"new-compatible-model-input",type:"text",value:p,onChange:e=>u(e.target.value),onKeyDown:e=>"Enter"===e.key&&A(),placeholder:m?"claude-3-opus-20240229":"gpt-4o",className:"w-full px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"})]}),(0,s.jsx)(d.$n,{size:"sm",icon:"add",onClick:A,disabled:!p.trim()||x,children:x?"Adding...":"Add"}),(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"download",onClick:T,disabled:!$||g,children:g?"Importing...":"Import from /models"})]}),!$&&(0,s.jsx)("p",{className:"text-xs text-text-muted",children:"Add a connection to enable importing models."}),C.length>0&&(0,s.jsx)("div",{className:"flex flex-col gap-3",children:C.map(({modelId:e,fullModel:a,alias:i})=>(0,s.jsx)(f,{modelId:e,fullModel:`${t}/${e}`,copied:l,onCopy:r,onDeleteAlias:()=>o(i),onTest:c.length>0?()=>w(e):void 0,testStatus:k[e],isTesting:v===e},a))})]})}function v({until:e}){let[t,a]=(0,i.useState)("");return((0,i.useEffect)(()=>{let t=()=>{let t=new Date(e).getTime()-Date.now();if(t<=0)return void a("");let s=Math.floor(t/1e3);if(s<60)a(`${s}s`);else if(s<3600)a(`${Math.floor(s/60)}m ${s%60}s`);else{let e=Math.floor(s/3600),t=Math.floor(s%3600/60);a(`${e}h ${t}m`)}};t();let s=setInterval(t,1e3);return()=>clearInterval(s)},[e]),t)?(0,s.jsxs)("span",{className:"text-xs text-orange-500 font-mono",children:["⏱ ",t]}):null}function j(e){if(!e)return"never";try{return new Date(e).toLocaleString()}catch{return e}}function k(e={}){let t=e&&"object"==typeof e?e:{};return{enabled:!0===t.enabled,intervalSec:Math.max(10,Number.parseInt(t.intervalSec||60,10)||60),failureThreshold:Math.max(1,Number.parseInt(t.failureThreshold||3,10)||3),timeoutMs:Math.max(1e3,Number.parseInt(t.timeoutMs||15e3,10)||15e3),prompt:t.prompt||"Say hi",disableThinking:!1!==t.disableThinking}}function N({connection:e,proxyPools:t,isOAuth:a,isFirst:l,isLast:r,onMoveUp:n,onMoveDown:o,onToggleActive:c,onUpdateProxy:m,onEdit:p,onDelete:u,oneByOneStatus:x=null,providerHealthConfig:h=null,healthCheckRunning:g=!1,onRunHealthCheck:b=null}){let[f,y]=(0,i.useState)(!1),[w,C]=(0,i.useState)(!1),S=(0,i.useRef)(null),A=new Map((t||[]).map(e=>[e.id,e])),T=e.providerSpecificData?.proxyPoolId||null,$=T?A.get(T):null,I=e.providerSpecificData?.connectionProxyEnabled===!0&&!!e.providerSpecificData?.connectionProxyUrl,R=!!T||I,O=$?`Pool: ${$.name}`:T?`Pool: ${T} (inactive/missing)`:I?`Legacy: ${e.providerSpecificData?.connectionProxyUrl}`:"",P="";if($?.proxyUrl||e.providerSpecificData?.connectionProxyUrl){let t=$?.proxyUrl||e.providerSpecificData?.connectionProxyUrl;try{let e=new URL(t);P=`${e.protocol}//${e.hostname}${e.port?`:${e.port}`:""}`}catch{P=t}}let E=$?.noProxy||e.providerSpecificData?.connectionNoProxy||"",D=function(e={}){let t=e.tags||e.labels||e.providerSpecificData?.routingTags||e.providerSpecificData?.tags||e.providerSpecificData?.labels||[];return Array.isArray(t)?t.map(e=>String(e||"").trim()).filter(Boolean):"string"==typeof t?t.split(/[\n,;\s]+/).map(e=>e.trim()).filter(Boolean):t&&"object"==typeof t?Object.entries(t).filter(([,e])=>!1!==e&&null!=e).map(([e,t])=>!0===t?e:`${e}:${t}`):[]}(e),M=e.providerSpecificData?.maxInFlight||e.maxInFlight||null,U="default";$?.isActive===!0?U="success":(T||I)&&(U="error"),(0,i.useEffect)(()=>{if(!f)return;let e=e=>{S.current&&!S.current.contains(e.target)&&y(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[f]);let _=async e=>{C(!0);try{await m("__none__"===e?null:e)}finally{C(!1),y(!1)}},F=e.authType||(a?"oauth":"apikey"),L="oauth"===F,z="cookie"===F,q=e=>"string"==typeof e&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e),K=L?q(e.email)?e.email:q(e.name)?e.name:e.name||e.email||e.displayName||"OAuth Account":e.name||e.email||e.displayName||"API Key",[H,J]=(0,i.useState)(!1),W=Object.entries(e).filter(([e])=>e.startsWith("modelLock_")).map(([,e])=>e).filter(e=>!!e).sort()[0]||null;(0,i.useEffect)(()=>{let t=()=>{J(!!Object.entries(e).filter(([e])=>e.startsWith("modelLock_")).map(([,e])=>e).filter(e=>e&&new Date(e).getTime()>Date.now()).sort()[0])};t();let a=W?setInterval(t,1e3):null;return()=>{a&&clearInterval(a)}},[W]);let B="unavailable"!==e.testStatus||H?e.testStatus:"active",G=()=>x?"queued"===x.state?"queued":"testing"===x.state?"testing":"success"===x.state?"success":"failed"===x.state?x.error?`failed: ${x.error}`:"failed":null:null,V=function(e={},t=null){let a=t&&"object"==typeof t?t:{};return!0===a.overrideConnections?{healthCheck:k(a.healthCheck||a),source:"provider",override:!0}:{healthCheck:k(e.healthCheck||{}),source:"account",override:!1}}(e,h),Q=V.healthCheck,Z=!0===Q.enabled,X=e.healthStatus||"unknown",Y=Number(e.healthConsecutiveFailures||0),ee=Number(Q.failureThreshold||3),et=Z?"degraded"===X?`Health: Degraded ${Y}/${ee}`:"dead"===X?"Health: Dead":"alive"===X?"Health: Alive":"Health: Unknown":"Health: off";return(0,s.jsxs)("div",{className:`group flex min-w-0 flex-col gap-3 rounded-lg p-2 transition-colors hover:bg-black/[0.02] dark:hover:bg-white/[0.02] sm:flex-row sm:items-center sm:justify-between ${!1===e.isActive?"opacity-60":""}`,children:[(0,s.jsxs)("div",{className:"flex min-w-0 flex-1 items-start gap-2 sm:items-center sm:gap-3",children:[(0,s.jsxs)("div",{className:"flex shrink-0 flex-col",children:[(0,s.jsx)("button",{onClick:n,disabled:l,className:`p-0.5 rounded ${l?"text-text-muted/30 cursor-not-allowed":"hover:bg-sidebar text-text-muted hover:text-primary"}`,children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"keyboard_arrow_up"})}),(0,s.jsx)("button",{onClick:o,disabled:r,className:`p-0.5 rounded ${r?"text-text-muted/30 cursor-not-allowed":"hover:bg-sidebar text-text-muted hover:text-primary"}`,children:(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"keyboard_arrow_down"})})]}),(0,s.jsx)("span",{className:"material-symbols-outlined shrink-0 text-base text-text-muted",children:z?"cookie":L?"lock":"key"}),(0,s.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,s.jsx)("p",{className:"text-sm font-medium truncate",children:K}),(0,s.jsxs)("div",{className:"mt-1 flex min-w-0 flex-wrap items-center gap-1.5 sm:gap-2",children:[(0,s.jsx)(d.Ex,{variant:!1===e.isActive?"default":"active"===B||"success"===B?"success":"error"===B||"expired"===B||"unavailable"===B?"error":"default",size:"sm",dot:!0,children:!1===e.isActive?"disabled":B||"Unknown"}),(0,s.jsx)(d.Ex,{variant:"default",size:"sm",children:L?"OAuth":z?"Cookie":"API Key"}),R&&(0,s.jsx)(d.Ex,{variant:U,size:"sm",children:"Proxy"}),M&&(0,s.jsxs)(d.Ex,{variant:"default",size:"sm",children:["max ",M," in-flight"]}),D.slice(0,3).map(e=>(0,s.jsx)(d.Ex,{variant:"primary",size:"sm",children:e},e)),D.length>3&&(0,s.jsxs)(d.Ex,{variant:"default",size:"sm",children:["+",D.length-3," tags"]}),H&&!1!==e.isActive&&(0,s.jsx)(v,{until:W}),e.lastError&&!1!==e.isActive&&(0,s.jsx)("span",{className:"max-w-full truncate text-xs text-red-500 sm:max-w-[300px]",title:e.lastError,children:e.lastError}),(0,s.jsxs)("span",{className:"text-xs text-text-muted",children:["#",e.priority]}),e.globalPriority&&(0,s.jsxs)("span",{className:"text-xs text-text-muted",children:["Auto: ",e.globalPriority]}),G()&&(0,s.jsx)(d.Ex,{variant:x?"success"===x.state?"success":"failed"===x.state?"error":"testing"===x.state?"primary":"default":"default",size:"sm",children:G()})]}),(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-2 text-xs text-text-muted",children:[" ",(0,s.jsx)(d.Ex,{variant:"alive"===X?"success":"dead"===X?"error":"default",children:et})," ",(0,s.jsx)("span",{children:V.override?"provider policy":"account policy"})," ",(0,s.jsxs)("span",{children:["last check: ",j(e.healthLastCheckedAt)]})," ",null!=e.healthLastLatencyMs&&(0,s.jsxs)("span",{children:[e.healthLastLatencyMs,"ms"]})," ",e.healthLastRecoveredAt&&(0,s.jsxs)("span",{children:["recovered: ",j(e.healthLastRecoveredAt)]})," ",e.healthLastError&&(0,s.jsx)("span",{className:"text-red-500",children:e.healthLastError})," ",(0,s.jsx)("button",{type:"button",onClick:b||void 0,disabled:!b||g,className:"rounded border border-border px-2 py-1 text-xs text-text-main transition-colors hover:border-primary hover:text-primary disabled:cursor-not-allowed disabled:opacity-50",children:g?"Checking...":"Run health check now"})," "]})," ",D.length>0&&(0,s.jsxs)("div",{className:"mt-1 flex items-center gap-1.5 flex-wrap",children:[(0,s.jsx)("span",{className:"text-[11px] text-text-muted",children:"routing tags:"}),D.map(e=>(0,s.jsx)("code",{className:"rounded bg-primary/10 px-1 py-0.5 font-mono text-[10px] text-primary",children:e},e))]}),R&&(0,s.jsxs)("div",{className:"mt-1 flex items-center gap-2 flex-wrap",children:[(0,s.jsx)("span",{className:"max-w-full truncate text-[11px] text-text-muted sm:max-w-[420px]",title:O,children:O}),P&&(0,s.jsx)("code",{className:"max-w-full truncate rounded bg-black/5 px-1 py-0.5 font-mono text-[10px] text-text-muted dark:bg-white/5 sm:max-w-[260px]",children:P}),E&&(0,s.jsxs)("span",{className:"max-w-full truncate text-[11px] text-text-muted sm:max-w-[320px]",title:E,children:["no_proxy: ",E]})]})]})]}),(0,s.jsxs)("div",{className:"flex w-full items-center justify-between gap-2 sm:w-auto sm:justify-end",children:[(0,s.jsxs)("div",{className:"grid flex-1 grid-cols-3 gap-1 sm:flex sm:flex-none",children:[(t||[]).length>0&&(0,s.jsxs)("div",{className:"relative",ref:S,children:[(0,s.jsxs)("button",{onClick:()=>y(e=>!e),className:`flex w-full flex-col items-center rounded px-2 py-1 transition-colors hover:bg-black/5 dark:hover:bg-white/5 ${R?"text-primary":"text-text-muted hover:text-primary"}`,disabled:w,children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:w?"progress_activity":"lan"}),(0,s.jsx)("span",{className:"text-[10px] leading-tight",children:"Proxy"})]}),f&&(0,s.jsxs)("div",{className:"absolute right-0 top-full z-50 mt-1 max-w-[78vw] min-w-[160px] rounded-lg border border-border bg-bg py-1 shadow-lg",children:[(0,s.jsx)("button",{onClick:()=>_("__none__"),className:`w-full text-left px-3 py-1.5 text-sm hover:bg-black/5 dark:hover:bg-white/5 ${!T?"text-primary font-medium":"text-text-main"}`,children:"None"}),(t||[]).map(e=>(0,s.jsx)("button",{onClick:()=>_(e.id),className:`w-full text-left px-3 py-1.5 text-sm hover:bg-black/5 dark:hover:bg-white/5 ${T===e.id?"text-primary font-medium":"text-text-main"}`,children:e.name},e.id))]})]}),(0,s.jsxs)("button",{onClick:p,className:"flex flex-col items-center rounded px-2 py-1 text-text-muted hover:bg-black/5 hover:text-primary dark:hover:bg-white/5",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"edit"}),(0,s.jsx)("span",{className:"text-[10px] leading-tight",children:"Edit"})]}),(0,s.jsxs)("button",{onClick:u,className:"flex flex-col items-center rounded px-2 py-1 text-red-500 hover:bg-red-500/10",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"delete"}),(0,s.jsx)("span",{className:"text-[10px] leading-tight",children:"Delete"})]})]}),(0,s.jsx)(d.lM,{size:"sm",checked:e.isActive??!0,onChange:c,title:e.isActive??!0?"Disable connection":"Enable connection"})]})]})}b.propTypes={model:g().shape({id:g().string.isRequired}).isRequired,fullModel:g().string.isRequired,alias:g().string,copied:g().string,onCopy:g().func.isRequired,testStatus:g().oneOf(["ok","error"]),isCustom:g().bool,isFree:g().bool,onDeleteAlias:g().func,onTest:g().func,isTesting:g().bool,onDisable:g().func},g().string.isRequired,g().string.isRequired,g().string,g().func.isRequired,g().func.isRequired,g().func,g().oneOf(["ok","error"]),g().bool,g().string.isRequired,g().object.isRequired,g().string,g().func.isRequired,g().func.isRequired,g().func.isRequired,y.propTypes={providerStorageAlias:g().string.isRequired,providerDisplayAlias:g().string.isRequired,modelAliases:g().object.isRequired,copied:g().string,onCopy:g().func.isRequired,onSetAlias:g().func.isRequired,onDeleteAlias:g().func.isRequired,connections:g().arrayOf(g().shape({id:g().string,isActive:g().bool})).isRequired,isAnthropic:g().bool},v.propTypes={until:g().string.isRequired},N.propTypes={connection:g().shape({id:g().string,name:g().string,email:g().string,displayName:g().string,modelLockUntil:g().string,testStatus:g().string,isActive:g().bool,lastError:g().string,priority:g().number,globalPriority:g().number,providerSpecificData:g().object,tags:g().oneOfType([g().string,g().array]),labels:g().oneOfType([g().string,g().array]),maxInFlight:g().oneOfType([g().string,g().number]),healthCheck:g().object,healthStatus:g().string,healthConsecutiveFailures:g().number,healthLastCheckedAt:g().string,healthLastOkAt:g().string,healthLastRecoveredAt:g().string,healthLastLatencyMs:g().number,healthLastError:g().string}).isRequired,proxyPools:g().arrayOf(g().shape({id:g().string,name:g().string,proxyUrl:g().string,noProxy:g().string,isActive:g().bool})),isOAuth:g().bool.isRequired,isFirst:g().bool.isRequired,isLast:g().bool.isRequired,onMoveUp:g().func.isRequired,onMoveDown:g().func.isRequired,onToggleActive:g().func.isRequired,onUpdateProxy:g().func,onEdit:g().func.isRequired,onDelete:g().func.isRequired,oneByOneStatus:g().shape({state:g().string,error:g().string}),providerHealthConfig:g().object,healthCheckRunning:g().bool,onRunHealthCheck:g().func};var w=a(90620),C=a(12494);let S=[{value:1,label:"Mon"},{value:2,label:"Tue"},{value:3,label:"Wed"},{value:4,label:"Thu"},{value:5,label:"Fri"},{value:6,label:"Sat"},{value:0,label:"Sun"}],A=[0,1,2,3,4,5,6],T={enabled:!0,weekdays:A,fromTime:"00:00",toTime:"23:59"},$={enabled:!1,intervalSec:60,failureThreshold:3,timeoutMs:15e3,prompt:"Say hi",disableThinking:!0,model:""};function I(e,t){let a=String(e||"").trim();return/^([01]\d|2[0-3]):([0-5]\d)$/.test(a)?a:t}function R(e={}){let t=e&&"object"==typeof e?e:{},a=Array.isArray(t.weekdays)?t.weekdays.map(Number).filter(e=>e>=0&&e<=6):A;return{enabled:!1!==t.enabled,weekdays:[...new Set(a)].sort((e,t)=>e-t),fromTime:I(t.fromTime||t.from,"00:00"),toTime:I(t.toTime||t.to,"23:59")}}function O(e={}){return{overrideConnections:!0===e.overrideConnections,schedule:R(e.schedule||T)}}function P(e={}){var t;let a=e&&"object"==typeof e?e:{};return{enabled:!0===a.enabled,intervalSec:Math.max(10,Number.parseInt(a.intervalSec||$.intervalSec,10)||$.intervalSec),failureThreshold:Math.max(1,Number.parseInt(a.failureThreshold||$.failureThreshold,10)||$.failureThreshold),timeoutMs:Math.max(1e3,Number.parseInt(a.timeoutMs||$.timeoutMs,10)||$.timeoutMs),prompt:"string"==typeof a.prompt&&a.prompt.trim()?a.prompt.trim():$.prompt,disableThinking:!1!==a.disableThinking,model:"string"==typeof(t=a.model||a.healthModel||a.testModel)?t.trim():""}}function E(e={}){return{overrideConnections:!0===e.overrideConnections,healthCheck:P(e.healthCheck||e||$)}}function D(){return"text-xs font-medium text-text-muted"}function M(){return"mt-1 w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-text-main outline-none focus:border-primary disabled:cursor-not-allowed disabled:opacity-50"}function U({providerId:e,onSaved:t}){let[a,l]=(0,i.useState)(O()),[r,n]=(0,i.useState)(E()),[o,d]=(0,i.useState)([]),[m,p]=(0,i.useState)(!1),[u,x]=(0,i.useState)(""),[h,g]=(0,i.useState)(!0),[b,f]=(0,i.useState)(!1),[y,v]=(0,i.useState)(!1),j=function(e=""){if((0,c.gb)(e))return"anthropic";if((0,c.mq)(e)||"cloudflare-ai"===e)return"openai";if("gemini"===e)return"gemini";if("github"===e)return"openai";let t=w.X3?.[e]||"";return t.includes("/messages")?"anthropic":t.includes("/chat/completions")||t.includes("/responses")?"openai":null}(e),k=!!j,N="anthropic"===j,T=(0,C.wB)(o,r.healthCheck.model);(0,i.useEffect)(()=>{let t=!1;return async function(){try{let a=await fetch("/api/settings",{cache:"no-store"}),s=a.ok?await a.json():{};t||(l(O((s.providerSchedules||{})[e]||{})),n(E((s.providerHealthChecks||{})[e]||{})))}finally{t||g(!1)}}(),()=>{t=!0}},[e]),(0,i.useEffect)(()=>{let t=!1;return async function(){p(!0),x("");try{let a=await fetch(`/api/providers?provider=${encodeURIComponent(e)}&summary=1`,{cache:"no-store"}),s=((a.ok?await a.json():{}).connections||[]).filter(t=>t.provider===e),i=await (0,C.ns)({providerId:e,connections:s,currentModel:r.healthCheck.model});t||(d(i.models),x(i.warning||""))}catch(e){t||(d([]),x(e.message||"Failed to load local Available Models list"))}finally{t||p(!1)}}(),()=>{t=!0}},[e,r.healthCheck.model]);let $=e=>{l(t=>({...t,schedule:R({...t.schedule,...e})})),v(!1)},I=e=>{n(t=>({...t,healthCheck:P({...t.healthCheck,...e})})),v(!1)},_=async()=>{f(!0),v(!1);try{let s=await fetch("/api/settings",{cache:"no-store"}),i=s.ok?await s.json():{},l={...i.providerSchedules||{},[e]:O(a)},n={...i.providerHealthChecks||{},[e]:E(r)};(await fetch("/api/settings",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerSchedules:l,providerHealthChecks:n})})).ok&&(v(!0),"function"==typeof t&&await t())}finally{f(!1)}};return h?null:(0,s.jsxs)("div",{className:"rounded-2xl border border-border bg-card p-4",children:[(0,s.jsxs)("div",{className:"mb-5",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-text-main",children:"Provider Scheduler Override"}),(0,s.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"When enabled, every account in this provider uses this provider-level schedule and account schedulers are locked."})]}),(0,s.jsxs)("label",{className:"mb-4 flex items-center gap-2 text-sm text-text-main",children:[(0,s.jsx)("input",{type:"checkbox",checked:a.overrideConnections,onChange:e=>{l(t=>({...t,overrideConnections:e.target.checked})),v(!1)}}),"Override all accounts"]}),(0,s.jsxs)("div",{className:"mb-5 space-y-3",children:[(0,s.jsx)("p",{className:D(),children:"Weekdays"}),(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:S.map(e=>(0,s.jsxs)("label",{className:"flex items-center gap-1.5 rounded-lg border border-border px-2.5 py-1.5 text-xs text-text-main",children:[(0,s.jsx)("input",{type:"checkbox",checked:a.schedule.weekdays.includes(e.value),onChange:()=>{var t;return t=e.value,void(l(e=>{let a=new Set(Array.isArray(e.schedule.weekdays)?e.schedule.weekdays:A);return a.has(t)?a.delete(t):a.add(t),{...e,schedule:{...e.schedule,weekdays:[...a].sort((e,t)=>e-t)}}}),v(!1))}}),e.label]},e.value))}),!1!==a.schedule.enabled&&0===a.schedule.weekdays.length&&(0,s.jsx)("p",{className:"text-xs text-yellow-500",children:"No weekdays selected. This provider schedule will make accounts unavailable until at least one weekday is selected."})]}),(0,s.jsxs)("div",{className:"mb-6 grid gap-3 sm:grid-cols-2",children:[(0,s.jsxs)("label",{className:D(),children:["From time",(0,s.jsx)("input",{type:"time",value:a.schedule.fromTime,onChange:e=>$({fromTime:e.target.value}),className:M()})]}),(0,s.jsxs)("label",{className:D(),children:["To time",(0,s.jsx)("input",{type:"time",value:a.schedule.toTime,onChange:e=>$({toTime:e.target.value}),className:M()})]})]}),(0,s.jsxs)("div",{className:"mb-5 border-t border-border pt-5",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-text-main",children:"Provider Health Check Override"}),(0,s.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"When enabled, every account in this provider uses the same periodic ping policy and account health settings are locked."})]}),(0,s.jsxs)("div",{className:"mb-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-5",children:[(0,s.jsxs)("label",{className:"flex items-center gap-2 text-sm text-text-main",children:[(0,s.jsx)("input",{type:"checkbox",checked:r.overrideConnections,onChange:e=>{n(t=>({...t,overrideConnections:e.target.checked})),v(!1)}}),"Override all accounts"]}),(0,s.jsxs)("label",{className:"flex items-center gap-2 text-sm text-text-main",children:[(0,s.jsx)("input",{type:"checkbox",checked:r.healthCheck.enabled,onChange:e=>I({enabled:e.target.checked})}),"Enable periodic ping healthcheck"]})]}),r.healthCheck.enabled&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("label",{className:D(),children:["Healthcheck model",(0,s.jsxs)("select",{value:r.healthCheck.model||"",onChange:e=>I({model:e.target.value}),className:M(),disabled:m,children:[(0,s.jsx)("option",{value:"",children:"Connection/base URL only — no chat ping"}),T.map(e=>(0,s.jsx)("option",{value:e.id,children:e.name||e.id},e.id))]})]}),(0,s.jsxs)("label",{className:`${D()} mt-3 block`,children:["Manual healthcheck model",(0,s.jsx)("input",{value:r.healthCheck.model||"",onChange:e=>I({model:e.target.value}),placeholder:N?"claude/model name from this endpoint":"gemini"===j?"gemini model, e.g. gemini-2.5-flash":"model name from Available Models",className:M(),disabled:m})]}),m&&(0,s.jsx)("p",{className:"mt-2 text-xs text-text-muted",children:"Loading local Available Models..."}),u&&(0,s.jsxs)("p",{className:"mt-2 text-xs text-yellow-500",children:["Model list note: ",u]}),!m&&!u&&(0,s.jsx)("p",{className:"mt-2 text-xs text-text-muted",children:"Model list is loaded from local Available Models / DB, not from the provider /models API."}),N&&(0,s.jsxs)("p",{className:"mt-2 text-xs text-text-muted",children:["Anthropic-compatible healthcheck sends ",(0,s.jsx)("code",{children:"Say hi"})," to ",(0,s.jsx)("code",{children:"/v1/messages"})," only when a model is selected."]}),"gemini"===j&&(0,s.jsxs)("p",{className:"mt-2 text-xs text-text-muted",children:["Gemini healthcheck sends ",(0,s.jsx)("code",{children:"Say hi"})," with the native ",(0,s.jsx)("code",{children:"generateContent"})," API only when a model is selected."]}),"cloudflare-ai"===e&&(0,s.jsxs)("p",{className:"mt-2 text-xs text-text-muted",children:["Cloudflare healthcheck sends ",(0,s.jsx)("code",{children:"Say hi"})," to the Workers AI OpenAI-style chat endpoint only when a model is selected."]}),!k&&(0,s.jsx)("p",{className:"mt-2 text-xs text-text-muted",children:"This provider can still show local Available Models. Auto healthcheck will keep using the original connection/token/account probe until a direct chat endpoint is available."})]}),r.healthCheck.enabled&&(!k||!r.healthCheck.model)&&(0,s.jsx)("p",{className:"mt-4 rounded-lg border border-border bg-sidebar/40 px-3 py-2 text-xs text-text-muted",children:"No direct chat healthcheck model/endpoint is active. Auto healthcheck will test connection/base URL/key/token/account and will not send the Say hi chat ping."}),(0,s.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-3",children:[(0,s.jsxs)("label",{className:D(),children:["Interval seconds",(0,s.jsx)("input",{type:"number",min:"10",value:r.healthCheck.intervalSec,onChange:e=>I({intervalSec:Math.max(10,Number.parseInt(e.target.value,10)||60)}),className:M()})]}),(0,s.jsxs)("label",{className:D(),children:["Fail threshold",(0,s.jsx)("input",{type:"number",min:"1",value:r.healthCheck.failureThreshold,onChange:e=>I({failureThreshold:Math.max(1,Number.parseInt(e.target.value,10)||3)}),className:M()})]}),(0,s.jsxs)("label",{className:D(),children:["Timeout ms",(0,s.jsx)("input",{type:"number",min:"1000",value:r.healthCheck.timeoutMs,onChange:e=>I({timeoutMs:Math.max(1e3,Number.parseInt(e.target.value,10)||15e3)}),className:M()})]})]}),(0,s.jsxs)("label",{className:`${D()} mt-3 block`,children:["Prompt",(0,s.jsx)("input",{value:r.healthCheck.prompt,onChange:e=>I({prompt:e.target.value}),className:M()})]}),(0,s.jsxs)("label",{className:"mt-3 flex items-center gap-2 text-sm text-text-main",children:[(0,s.jsx)("input",{type:"checkbox",checked:r.healthCheck.disableThinking,onChange:e=>I({disableThinking:e.target.checked})}),"Force lightweight test payload / disable thinking when provider supports it"]}),(0,s.jsxs)("div",{className:"mt-5 flex items-center gap-3",children:[(0,s.jsx)("button",{type:"button",onClick:_,disabled:b,className:"rounded-lg bg-primary px-4 py-2 text-sm font-medium text-white transition-colors hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60",children:b?"Saving...":"Save Provider Policy"}),y&&(0,s.jsx)("span",{className:"text-xs font-medium text-green-500",children:"Saved"})]})]})}let _=`name1|sk-key1
2
+ name2|sk-key2
3
+ sk-key-only-auto-named`;function F({isOpen:e,provider:t,providerName:a,isCompatible:l,isAnthropic:r,authType:n,authHint:o,website:m,proxyPools:p,error:u,onSave:x,onBulkDone:h,onClose:g}){let b="__none__",f="ollama-local"===t,y="cookie"===n,v="xai"===t&&!y,j=y?"Cookie Value":"API Key",k="azure"===t,N="cloudflare-ai"===t,w=c.Q2?.[t]?.regions||null,C=c.Q2?.[t]?.defaultRegion||w?.[0]?.id||"",[S,A]=(0,i.useState)({name:"",apiKey:"",defaultModel:"",priority:1,proxyPoolId:b,ollamaHostUrl:""}),[T,$]=(0,i.useState)({azureEndpoint:"",apiVersion:"2024-10-01-preview",deployment:"",organization:""}),[I,R]=(0,i.useState)({accountId:""}),[O,P]=(0,i.useState)(C),[E,D]=(0,i.useState)(!1),[M,U]=(0,i.useState)(null),[L,z]=(0,i.useState)(!1),[q,K]=(0,i.useState)("single"),[H,J]=(0,i.useState)(""),[W,B]=(0,i.useState)(null),G=()=>f&&S.ollamaHostUrl.trim()?{baseUrl:S.ollamaHostUrl.trim()}:k?{azureEndpoint:T.azureEndpoint,apiVersion:T.apiVersion,deployment:T.deployment,organization:T.organization}:N?{accountId:I.accountId}:w&&O?{region:O}:void 0,V=async()=>{D(!0);try{let e=await fetch("/api/providers/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:t,apiKey:S.apiKey,providerSpecificData:G()})}),a=await e.json();U(a.valid?"success":"failed")}catch{U("failed")}finally{D(!1)}},Q=async()=>{if(t&&(f||S.apiKey)&&(f||S.name)&&(!l||S.defaultModel.trim())){z(!0);try{let e=!1;try{D(!0),U(null);let a=await fetch("/api/providers/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:t,apiKey:S.apiKey,providerSpecificData:G()})});e=!!(await a.json()).valid,U(e?"success":"failed")}catch{U("failed")}finally{D(!1)}await x({name:S.name||(f?"Ollama Local":""),apiKey:S.apiKey,defaultModel:l?S.defaultModel.trim():void 0,priority:S.priority,proxyPoolId:S.proxyPoolId===b?null:S.proxyPoolId,testStatus:e?"active":"unknown",providerSpecificData:G()})}finally{z(!1)}}},Z=async()=>{let e=H.split("\n").map(e=>e.trim()).filter(Boolean);if(!e.length)return;z(!0),B(null);let a=0,s=0,i=new Set;try{let e=await fetch(`/api/providers?provider=${encodeURIComponent(t)}&summary=1`,{cache:"no-store"});if(!e.ok)throw Error(`Unable to load existing keys (${e.status})`);for(let t of(await e.json()).connections||[])t?.name&&i.add(String(t.name).trim().toLowerCase())}catch{z(!1),B({success:0,failed:e.length});return}for(let l=0;l<e.length;l++){let r=e[l].split("|"),n=r.length>=2?r.slice(1).join("|").trim():r[0].trim(),o=function(e,t){let a=String(e||"Key").trim()||"Key",s=RegExp(`^${String(a).replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\s+(\\d+)$`,"i"),i=new Set;for(let e of t){let t=String(e||"").trim().match(s);t&&i.add(Number(t[1]))}let l=1;for(;i.has(l);)l+=1;let r=`${a} ${l}`;return t.add(r.toLowerCase()),r}(r.length>=2?r[0].trim():"Key",i);try{(await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:t,apiKey:n,name:o,priority:1,testStatus:"unknown"})})).ok?a++:s++}catch{s++}}z(!1),B({success:a,failed:s}),a>0&&h&&h()};return t?(0,s.jsx)(d.aF,{isOpen:e,title:`Add ${a||t} ${j}`,onClose:g,children:(0,s.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.$n,{size:"sm",variant:"single"===q?"primary":"ghost",onClick:()=>{K("single"),B(null)},children:"Single"}),(0,s.jsx)(d.$n,{size:"sm",variant:"bulk"===q?"primary":"ghost",onClick:()=>{K("bulk"),B(null)},children:"Bulk Add"})]}),"bulk"===q&&(0,s.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,s.jsxs)("p",{className:"text-xs text-text-muted",children:["One key per line. Format: ",(0,s.jsx)("code",{children:"name|apiKey"})," or just ",(0,s.jsx)("code",{children:"apiKey"})," (auto-named by index)."]}),(0,s.jsx)("textarea",{className:"w-full rounded border border-accent/30 bg-sidebar p-2 text-sm font-mono resize-y min-h-[140px] focus:outline-none focus:ring-1 focus:ring-primary",placeholder:_,value:H,onChange:e=>J(e.target.value)}),W&&(0,s.jsxs)("div",{className:`text-sm font-medium ${W.failed>0?"text-yellow-400":"text-green-400"}`,children:["✓ ",W.success," added",W.failed>0?`, ✗ ${W.failed} failed`:""]}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.$n,{onClick:Z,fullWidth:!0,disabled:L||!H.trim(),children:L?"Adding...":"Add All Keys"}),(0,s.jsx)(d.$n,{onClick:g,variant:"ghost",fullWidth:!0,children:"Cancel"})]})]}),"single"===q&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(d.pd,{label:"Name",value:S.name,onChange:e=>A({...S,name:e.target.value}),placeholder:f?"Ollama Local":"Production Key"}),f&&(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.pd,{label:"Ollama Host URL",value:S.ollamaHostUrl,onChange:e=>A({...S,ollamaHostUrl:e.target.value}),placeholder:"http://localhost:11434",className:"flex-1"}),(0,s.jsx)("div",{className:"pt-6",children:(0,s.jsx)(d.$n,{onClick:V,disabled:E||L,variant:"secondary",children:E?"Checking...":"Check"})})]}),!f&&(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.pd,{label:j,type:y?"text":"password",value:S.apiKey,onChange:e=>A({...S,apiKey:e.target.value}),placeholder:y?"grok-web"===t?"sso=xxxxx... or just the raw value":"eyJhbGciOi...":v?"xai-...":"",className:"flex-1"}),(0,s.jsx)("div",{className:"pt-6",children:(0,s.jsx)(d.$n,{onClick:V,disabled:!S.apiKey||E||L,variant:"secondary",children:E?"Checking...":"Check"})})]}),v&&(0,s.jsx)("p",{className:"text-xs text-text-muted",children:"Use a direct xAI API key from console.x.ai. This is separate from Grok Build OAuth."}),y&&o&&(0,s.jsxs)("p",{className:"text-xs text-text-muted",children:[o,m&&(0,s.jsxs)(s.Fragment,{children:[" ",(0,s.jsxs)("a",{href:m,target:"_blank",rel:"noopener noreferrer",className:"text-primary underline",children:["Open ",m.replace(/^https?:\/\//,"")]})]})]}),w&&(0,s.jsx)(d.l6,{label:"Region",value:O,onChange:e=>P(e.target.value),options:w.map(e=>({value:e.id,label:e.label}))}),l&&(0,s.jsx)(d.pd,{label:"Default Model",value:S.defaultModel,onChange:e=>A({...S,defaultModel:e.target.value}),placeholder:r?"claude-3-5-sonnet-latest":"gpt-4o-mini"}),f&&(0,s.jsxs)("p",{className:"text-xs text-text-muted",children:["Leave blank to use ",(0,s.jsx)("code",{children:"http://localhost:11434"}),". For remote Ollama, enter the full host URL (e.g. ",(0,s.jsx)("code",{children:"http://192.168.1.10:11434"}),")."]}),M&&(0,s.jsx)(d.Ex,{variant:"success"===M?"success":"error",children:"success"===M?"Valid":"Invalid"}),u&&(0,s.jsx)("p",{className:"text-xs text-red-500 break-words",children:u}),l&&(0,s.jsx)("p",{className:"text-xs text-text-muted",children:"Enter the model ID exactly as your compatible endpoint expects it. This model will be saved as the connection default."}),N&&(0,s.jsxs)("div",{className:"bg-sidebar/50 p-4 rounded-lg border border-accent/20",children:[(0,s.jsx)("h3",{className:"font-semibold mb-3 text-sm",children:"Cloudflare Workers AI"}),(0,s.jsx)(d.pd,{label:"Account ID",value:I.accountId,onChange:e=>R({...I,accountId:e.target.value}),placeholder:"abc123def456..."}),(0,s.jsxs)("p",{className:"text-xs text-text-muted mt-2",children:["Find your Account ID in the right sidebar of ",(0,s.jsx)("a",{href:"https://dash.cloudflare.com",target:"_blank",rel:"noopener noreferrer",className:"text-primary underline",children:"dash.cloudflare.com"})]})]}),k&&(0,s.jsxs)("div",{className:"bg-sidebar/50 p-4 rounded-lg border border-accent/20",children:[(0,s.jsx)("h3",{className:"font-semibold mb-3 text-sm",children:"Azure OpenAI Configuration"}),(0,s.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,s.jsx)(d.pd,{label:"Azure Endpoint",value:T.azureEndpoint,onChange:e=>$({...T,azureEndpoint:e.target.value}),placeholder:"https://your-resource.openai.azure.com"}),(0,s.jsx)(d.pd,{label:"Deployment Name",value:T.deployment,onChange:e=>$({...T,deployment:e.target.value}),placeholder:"gpt-4"}),(0,s.jsx)(d.pd,{label:"API Version",value:T.apiVersion,onChange:e=>$({...T,apiVersion:e.target.value}),placeholder:"2024-10-01-preview"}),(0,s.jsx)(d.pd,{label:"Organization",value:T.organization,onChange:e=>$({...T,organization:e.target.value}),placeholder:"Organization ID"})]})]}),(0,s.jsx)(d.pd,{label:"Priority",type:"number",value:S.priority,onChange:e=>A({...S,priority:Number.parseInt(e.target.value)||1})}),(0,s.jsx)(d.l6,{label:"Proxy Pool",value:S.proxyPoolId,onChange:e=>A({...S,proxyPoolId:e.target.value}),options:[{value:b,label:"None"},...(p||[]).map(e=>({value:e.id,label:e.name}))],placeholder:"None"}),0===(p||[]).length&&(0,s.jsx)("p",{className:"text-xs text-text-muted",children:"No active proxy pools available. Create one in Proxy Pools page first."}),(0,s.jsx)("p",{className:"text-xs text-text-muted",children:"Legacy manual proxy fields are still accepted by API for backward compatibility."}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.$n,{onClick:Q,fullWidth:!0,disabled:L||!f&&(!S.name||!S.apiKey)||l&&!S.defaultModel.trim()||k&&(!T.azureEndpoint||!T.deployment||!T.organization)||N&&!I.accountId,children:L?"Saving...":"Save"}),(0,s.jsx)(d.$n,{onClick:g,variant:"ghost",fullWidth:!0,children:"Cancel"})]})]})]})}):null}F.propTypes={isOpen:g().bool.isRequired,provider:g().string,providerName:g().string,isCompatible:g().bool,isAnthropic:g().bool,authType:g().string,authHint:g().string,website:g().string,proxyPools:g().arrayOf(g().shape({id:g().string,name:g().string})),error:g().string,onSave:g().func.isRequired,onBulkDone:g().func,onClose:g().func.isRequired};let L="local",z="cloud",q="unknown",K=[{value:L,label:"Local / Self-hosted",description:"Model is hosted on infrastructure you operate (vLLM, SGLang, Ollama, llama.cpp, private GPU server)."},{value:z,label:"Cloud / External",description:"Model is served by an external/cloud API provider."}];function H(e){return String(e??"").trim()}function J({isOpen:e,node:t,onSave:a,onClose:l,isAnthropic:r}){let[n,o]=(0,i.useState)({name:"",prefix:"",apiType:"chat",baseUrl:"https://api.openai.com/v1",deploymentType:"cloud",openAICompatibleRuntime:c.hb,routingTags:"",maxInFlight:""}),[m,p]=(0,i.useState)(!1),[u,x]=(0,i.useState)(""),[h,g]=(0,i.useState)(""),[b,f]=(0,i.useState)(!1),[y,v]=(0,i.useState)(null);(0,i.useEffect)(()=>{if(t){let e=t.baseUrl||(r?"https://api.anthropic.com/v1":"https://api.openai.com/v1");o({name:t.name||"",prefix:t.prefix||"",apiType:t.apiType||"chat",baseUrl:e,deploymentType:function(e,t=q){let a=H(e).toLowerCase();return a===L?L:a===z?z:a===q?q:t}(t.deploymentType,"")||function(e,t=q){let a,s=H(e);if(!s)return t;try{a=new URL(s.includes("://")?s:`http://${s}`)}catch{return t}let i=H(a.hostname).replace(/^\[|\]$/g,"").toLowerCase();return i?"localhost"===i||"::1"===i||"0.0.0.0"===i||i.endsWith(".localhost")||i.endsWith(".local")||function(e){let t=e.split(".").map(e=>Number(e));if(4!==t.length||t.some(e=>!Number.isInteger(e)||e<0||e>255))return!1;let[a,s]=t;return 10===a||127===a||169===a&&254===s||172===a&&!!(s>=16)&&!!(s<=31)||192===a&&168===s}(i)?L:z:t}(e),openAICompatibleRuntime:t.openAICompatibleRuntime||t.providerSpecificData?.openAICompatibleRuntime||c.hb,routingTags:Array.isArray(t.providerSpecificData?.routingTags||t.providerSpecificData?.tags||t.tags)?(t.providerSpecificData?.routingTags||t.providerSpecificData?.tags||t.tags).join(", "):t.providerSpecificData?.routingTags||t.providerSpecificData?.tags||t.tags||"",maxInFlight:t.providerSpecificData?.maxInFlight||t.maxInFlight||""})}},[t,r]);let j=K.map(({value:e,label:t})=>({value:e,label:t})),k=async()=>{if(n.name.trim()&&n.prefix.trim()&&n.baseUrl.trim()){p(!0);try{let e=String(n.routingTags||"").split(/[\n,;]+/).map(e=>e.trim()).filter(Boolean),s=Number(n.maxInFlight),i={...t.providerSpecificData||{},routingTags:e,tags:e};Number.isFinite(s)&&s>0?i.maxInFlight=s:delete i.maxInFlight;let l={name:n.name,prefix:n.prefix,baseUrl:n.baseUrl,deploymentType:n.deploymentType,routingTags:e,tags:e,providerSpecificData:i};r||(l.apiType=n.apiType,l.openAICompatibleRuntime=n.openAICompatibleRuntime),await a(l)}finally{p(!1)}}},N=async()=>{f(!0);try{let e=await fetch("/api/provider-nodes/validate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({baseUrl:n.baseUrl,apiKey:u,type:r?"anthropic-compatible":"openai-compatible",modelId:h.trim()||void 0})}),t=await e.json();v(t.valid?"success":"failed")}catch{v("failed")}finally{f(!1)}};return t?(0,s.jsx)(d.aF,{isOpen:e,title:`Edit ${r?"Anthropic":"OpenAI"} Compatible`,onClose:l,children:(0,s.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,s.jsx)(d.pd,{label:"Name",value:n.name,onChange:e=>o({...n,name:e.target.value}),placeholder:`${r?"Anthropic":"OpenAI"} Compatible (Prod)`,hint:"Required. A friendly label for this node."}),(0,s.jsx)(d.pd,{label:"Prefix",value:n.prefix,onChange:e=>o({...n,prefix:e.target.value}),placeholder:r?"ac-prod":"oc-prod",hint:"Required. Used as the provider prefix for model IDs."}),!r&&(0,s.jsx)(d.l6,{label:"API Type",options:[{value:"chat",label:"Chat Completions"},{value:"responses",label:"Responses API"}],value:n.apiType,onChange:e=>o({...n,apiType:e.target.value})}),!r&&(0,s.jsx)(d.l6,{label:"Server Type",options:c._8,value:n.openAICompatibleRuntime,onChange:e=>o({...n,openAICompatibleRuntime:e.target.value}),hint:c._8.find(e=>e.value===n.openAICompatibleRuntime)?.description||"Controls how BlueRouter maps thinking/reasoning params for this endpoint."}),(0,s.jsx)(d.pd,{label:"Base URL",value:n.baseUrl,onChange:e=>o({...n,baseUrl:e.target.value}),placeholder:r?"https://api.anthropic.com/v1":"https://api.openai.com/v1",hint:`Use the base URL (ending in /v1) for your ${r?"Anthropic":"OpenAI"}-compatible API.`}),(0,s.jsx)(d.l6,{label:"Deployment",options:j,value:n.deploymentType,onChange:e=>o({...n,deploymentType:e.target.value}),hint:"Controls Local vs Cloud usage/analytics classification. Compatible describes the API protocol, not where the model runs."}),(0,s.jsx)(d.pd,{label:"Routing Tags / Labels",value:n.routingTags,onChange:e=>o({...n,routingTags:e.target.value}),placeholder:"gpu, vram:8gb, model_support:qwen3:8b",hint:"Comma or newline separated. Used by Combo least-latency/P2C tag rules for LAN Ollama."}),(0,s.jsx)(d.pd,{label:"Max In-flight Requests",type:"number",value:n.maxInFlight,onChange:e=>o({...n,maxInFlight:e.target.value}),placeholder:"2",hint:"Optional per-endpoint concurrency cap used by P2C and circuit-aware routing."}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.pd,{label:"API Key (for Check)",type:"password",value:u,onChange:e=>x(e.target.value),className:"flex-1"}),(0,s.jsx)("div",{className:"pt-6",children:(0,s.jsx)(d.$n,{onClick:N,disabled:!u||b||!n.baseUrl.trim(),variant:"secondary",children:b?"Checking...":"Check"})})]}),(0,s.jsx)(d.pd,{label:"Model ID (optional)",value:h,onChange:e=>g(e.target.value),placeholder:"e.g. my-model-id",hint:"If provider lacks /models endpoint, enter a model ID to validate via chat/completions instead."}),y&&(0,s.jsx)(d.Ex,{variant:"success"===y?"success":"error",children:"success"===y?"Valid":"Invalid"}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)(d.$n,{onClick:k,fullWidth:!0,disabled:!n.name.trim()||!n.prefix.trim()||!n.baseUrl.trim()||m,children:m?"Saving...":"Save"}),(0,s.jsx)(d.$n,{onClick:l,variant:"ghost",fullWidth:!0,children:"Cancel"})]})]})}):null}function W({isOpen:e,providerAlias:t,providerDisplayAlias:a,connectionId:l,onSave:r,onClose:n}){let[o,c]=(0,i.useState)(""),[m,p]=(0,i.useState)(null),[u,x]=(0,i.useState)(""),[h,g]=(0,i.useState)(!1);(0,i.useEffect)(()=>{e&&(c(""),p(null),x(""))},[e]);let b=e=>{let a=`${t}/`;return e.startsWith(a)?e.slice(a.length):e},f=async()=>{let e=b(o.trim());if(e){p("testing"),x("");try{let a=await fetch("/api/models/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:`${t}/${e}`,connectionId:l})}),s=await a.json();p(s.ok?"ok":"error"),x(s.error||"")}catch(e){p("error"),x(e.message)}}},y=async()=>{let e=b(o.trim());if(e&&!h){g(!0);try{await r(e)}finally{g(!1)}}};return(0,s.jsx)(d.aF,{isOpen:e,onClose:n,title:"Add Custom Model",children:(0,s.jsxs)("div",{className:"flex flex-col gap-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{className:"text-sm font-medium mb-1.5 block",children:"Model ID"}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("input",{type:"text",value:o,onChange:e=>{c(e.target.value),p(null),x("")},onKeyDown:e=>{"Enter"===e.key&&f()},placeholder:"e.g. claude-opus-4-5",className:"flex-1 px-3 py-2 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary",autoFocus:!0}),(0,s.jsx)(d.$n,{variant:"secondary",icon:"science",loading:"testing"===m,onClick:f,disabled:!o.trim()||"testing"===m,children:"testing"===m?"Testing...":"Test"})]}),(0,s.jsxs)("p",{className:"text-xs text-text-muted mt-1",children:["Sent to provider as: ",(0,s.jsx)("code",{className:"font-mono bg-sidebar px-1 rounded",children:b(o.trim())||"model-id"})]})]}),"ok"===m&&(0,s.jsxs)("div",{className:"flex items-center gap-2 text-sm text-green-600",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-base",children:"check_circle"}),"Model is reachable"]}),"error"===m&&(0,s.jsxs)("div",{className:"flex items-start gap-2 text-sm text-red-500",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-base shrink-0",children:"cancel"}),(0,s.jsx)("span",{children:u||"Model not reachable"})]}),(0,s.jsxs)("div",{className:"flex gap-2 pt-1",children:[(0,s.jsx)(d.$n,{onClick:n,variant:"ghost",fullWidth:!0,size:"sm",children:"Cancel"}),(0,s.jsx)(d.$n,{onClick:y,fullWidth:!0,size:"sm",disabled:!o.trim()||h,children:h?"Adding...":"Add Model"})]})]})})}J.propTypes={isOpen:g().bool.isRequired,node:g().shape({id:g().string,name:g().string,prefix:g().string,apiType:g().string,openAICompatibleRuntime:g().string,baseUrl:g().string,deploymentType:g().string,providerSpecificData:g().object,tags:g().oneOfType([g().string,g().array]),maxInFlight:g().oneOfType([g().string,g().number])}),onSave:g().func.isRequired,onClose:g().func.isRequired,isAnthropic:g().bool},W.propTypes={isOpen:g().bool.isRequired,providerAlias:g().string.isRequired,providerDisplayAlias:g().string.isRequired,connectionId:g().string,onSave:g().func.isRequired,onClose:g().func.isRequired};var B=a(65921);let G=[{key:"cached",label:"Cached input",hint:"Per 1M tokens"},{key:"reasoning",label:"Reasoning",hint:"Per 1M tokens"},{key:"cache_creation",label:"Cache creation",hint:"Per 1M tokens"}];function V(e){if(null==e||""===e)return"";let t=Number(e);return Number.isFinite(t)?String(t):""}function Q(e,t,a){let s=t||a||{};return{modelId:e,isOverride:!!t,defaults:a||null,input:V(s.input),output:V(s.output),cached:V(s.cached),reasoning:V(s.reasoning),cache_creation:V(s.cache_creation)}}function Z({providerStorageAlias:e,providerDisplayAlias:t,modelAliases:a}){let l=(0,B.i)(),[r,n]=(0,i.useState)({}),[o,c]=(0,i.useState)(!0),[m,p]=(0,i.useState)(null),[u,x]=(0,i.useState)({}),[h,g]=(0,i.useState)({}),[b,f]=(0,i.useState)(()=>new Set),[y,v]=(0,i.useState)({}),[j,k]=(0,i.useState)(null),[N,w]=(0,i.useState)(!1),C=(0,i.useMemo)(()=>{let t=`${e}/`,s=[];for(let e of Object.values(a||{})){if(!e.startsWith(t))continue;let a=e.slice(t.length);a&&!s.includes(a)&&s.push(a)}return s.sort((e,t)=>e.localeCompare(t))},[a,e]),S=async()=>{try{let t=await fetch("/api/pricing",{cache:"no-store"});if(!t.ok)return;let a=await t.json(),s=a?.[e]||{};n(s)}catch(e){console.log("Error fetching pricing:",e)}finally{c(!1)}};(0,i.useEffect)(()=>{c(!0),S()},[e]),(0,i.useEffect)(()=>{g(e=>{let t={};for(let a of C){if(b.has(a)&&e[a]){t[a]=e[a];continue}t[a]=Q(a,r[a],null)}return t})},[C.join("|"),JSON.stringify(r)]);let A=(e,t,a)=>{g(s=>({...s,[e]:{...s[e],[t]:a}})),f(t=>{if(t.has(e))return t;let a=new Set(t);return a.add(e),a}),y[e]&&v(t=>{let a={...t};return delete a[e],a})},T=async t=>{let a,s=h[t];if(s){try{a=function(e){let t={};for(let a of["input","output","cached","reasoning","cache_creation"]){if(""===e[a]||null===e[a]||void 0===e[a])continue;let s=Number(e[a]);if(!Number.isFinite(s)||s<0)throw Error(`Invalid ${a}: must be ≥ 0`);t[a]=s}if(void 0===t.input&&void 0===t.output)throw Error("Set at least input and output");return t}(s)}catch(e){v(a=>({...a,[t]:e.message}));return}p(t);try{let s=await fetch("/api/pricing",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({[e]:{[t]:a}})}),i=await s.json();if(!s.ok)return void v(e=>({...e,[t]:i?.error||"Failed to save"}));n(i?.[e]||{}),f(e=>{if(!e.has(t))return e;let a=new Set(e);return a.delete(t),a}),v(e=>{let a={...e};return delete a[t],a}),l?.success?.(`Pricing saved for ${t}`)}catch(e){v(a=>({...a,[t]:e?.message||"Network error"}))}finally{p(null)}}},$=async t=>{p(t);try{let a=`/api/pricing?provider=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}`,s=await fetch(a,{method:"DELETE"}),i=await s.json();if(!s.ok)return void v(e=>({...e,[t]:i?.error||"Failed to reset"}));n(i?.[e]||{}),f(e=>{if(!e.has(t))return e;let a=new Set(e);return a.delete(t),a}),l?.info?.(`Pricing reset for ${t}`)}catch(e){v(a=>({...a,[t]:e?.message||"Network error"}))}finally{p(null)}},I=async()=>{if(j){w(!0);try{let e=await fetch("/api/pricing/recalculate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(j.payload||{})}),t=await e.json();if(!e.ok)return void l?.error?.(t?.error||"Recalculate failed");let a=t.skippedNoPricing?` \xb7 skipped ${t.skippedNoPricing} (no pricing)`:"";l?.success?.(`Recalculated ${t.rowsUpdated} row${1===t.rowsUpdated?"":"s"} across ${t.groupsUpdated} model${1===t.groupsUpdated?"":"s"}${a}`)}catch(e){l?.error?.(e?.message||"Network error")}finally{w(!1),k(null)}}};return(0,s.jsxs)(d.Zp,{children:[(0,s.jsxs)("div",{className:"mb-4 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[20px] text-text-muted",children:"payments"}),(0,s.jsx)("h2",{className:"text-lg font-semibold",children:"Model Pricing"}),(0,s.jsx)(d.Ex,{variant:"secondary",size:"sm",children:"Per 1M tokens"})]}),(0,s.jsxs)("p",{className:"mt-1 text-xs leading-relaxed text-text-muted",children:["Set custom input/output rates used by the Usage dashboard to estimate cost for"," ",(0,s.jsx)("code",{className:"rounded bg-sidebar px-1.5 py-0.5 font-mono text-[11px]",children:t}),". Overrides apply only to this custom endpoint; falls back to built-in pricing tables when unset. New rates take effect on the next request — use"," ",(0,s.jsx)("span",{className:"font-medium text-text-main",children:"Recalc cost"})," to rewrite past rows."]})]}),C.length>0&&(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"restart_alt",onClick:()=>{k({scope:"provider",label:`all models on ${t}`,payload:{provider:e}})},disabled:N,className:"shrink-0",children:"Recalc all"})]}),o?(0,s.jsx)("p",{className:"text-sm text-text-muted",children:"Loading pricing..."}):0===C.length?(0,s.jsx)("div",{className:"rounded-lg border border-dashed border-border px-4 py-6 text-center text-sm text-text-muted",children:"Add models in the section below first — pricing can then be set per model here."}):(0,s.jsx)("div",{className:"flex flex-col gap-3",children:C.map(a=>{let i=h[a]||Q(a,r[a],null),l=!!r[a],n=!!u[a],o=(e=>{let t=h[e];if(!t)return!1;let a=r[e];if(!a)return!!(t.input||t.output||t.cached||t.reasoning||t.cache_creation);for(let e of["input","output","cached","reasoning","cache_creation"])if(((""===t[e]?null:Number(t[e]))??null)!==((void 0===a[e]?null:Number(a[e]))??null))return!0;return!1})(a),c=y[a],p=m===a;return(0,s.jsxs)("div",{className:"rounded-xl border border-border bg-surface-2/40 p-3 sm:p-4",children:[(0,s.jsxs)("div",{className:"mb-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[(0,s.jsxs)("div",{className:"flex min-w-0 items-center gap-2",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px] text-text-muted",children:"smart_toy"}),(0,s.jsx)("code",{className:"truncate font-mono text-sm font-semibold text-text-main",children:a}),l?(0,s.jsx)(d.Ex,{variant:"success",size:"sm",children:"Override"}):(0,s.jsx)(d.Ex,{variant:"default",size:"sm",children:"Default"})]}),(0,s.jsx)("div",{className:"flex shrink-0 items-center gap-2",children:(0,s.jsxs)("button",{type:"button",onClick:()=>{x(e=>({...e,[a]:!e[a]}))},className:"inline-flex items-center gap-1 text-xs text-text-muted hover:text-primary",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:n?"expand_less":"tune"}),n?"Hide advanced":"Advanced"]})})]}),(0,s.jsxs)("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:[(0,s.jsx)(X,{label:"Input",hint:"$ per 1M input tokens",value:i.input,onChange:e=>A(a,"input",e),disabled:p}),(0,s.jsx)(X,{label:"Output",hint:"$ per 1M output tokens",value:i.output,onChange:e=>A(a,"output",e),disabled:p})]}),n&&(0,s.jsx)("div",{className:"mt-3 grid grid-cols-1 gap-3 sm:grid-cols-3",children:G.map(e=>(0,s.jsx)(X,{label:e.label,hint:e.hint,value:i[e.key],onChange:t=>A(a,e.key,t),disabled:p},e.key))}),c&&(0,s.jsxs)("p",{className:"mt-2 flex items-center gap-1 text-xs text-red-500",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"error"}),c]}),(0,s.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-end",children:[(0,s.jsx)(d.$n,{size:"sm",variant:"ghost",icon:"calculate",onClick:()=>{k({scope:"model",label:`${t}/${a}`,payload:{provider:e,model:a}})},disabled:p||N,title:"Rewrite past usage rows for this model with current pricing",children:"Recalc cost"}),l&&(0,s.jsx)(d.$n,{size:"sm",variant:"ghost",icon:"restart_alt",onClick:()=>$(a),disabled:p,children:"Reset to default"}),(0,s.jsx)(d.$n,{size:"sm",icon:"save",onClick:()=>T(a),disabled:p||!o,children:p?"Saving...":o?"Save":"Saved"})]})]},a)})}),(0,s.jsx)(d.uo,{isOpen:!!j,onClose:()=>!N&&k(null),onConfirm:I,title:"Recalculate cost",message:j?`Rewrite the cost column on past usage rows for ${j.label} using the current pricing? This overwrites whatever cost was stored at request time.`:"",confirmText:N?"Recalculating...":"Recalculate",cancelText:"Cancel"})]})}function X({label:e,hint:t,value:a,onChange:i,disabled:l}){return(0,s.jsxs)("label",{className:"flex flex-col gap-1.5",children:[(0,s.jsx)("span",{className:"text-[11px] font-semibold uppercase tracking-wide text-text-muted",children:e}),(0,s.jsxs)("div",{className:"relative",children:[(0,s.jsx)("span",{className:"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-sm text-text-muted",children:"$"}),(0,s.jsx)("input",{type:"number",step:"0.0001",min:0,value:a,onChange:e=>i(e.target.value),disabled:l,placeholder:"0.00",className:"w-full rounded-[10px] border border-transparent bg-surface-2 py-2.5 pl-7 pr-3 text-[16px] text-text-main placeholder-text-muted/70 transition-all duration-150 ease-out focus:border-brand-500/40 focus:outline-none focus:ring-2 focus:ring-brand-500/30 disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm"})]}),t&&(0,s.jsx)("span",{className:"text-[11px] text-text-muted",children:t})]})}function Y(){let e,t=(0,l.useParams)(),a=(0,l.useRouter)(),r=t.id,[u,h]=(0,i.useState)([]),[g,f]=(0,i.useState)(!0),[v,j]=(0,i.useState)(null),[k,w]=(0,i.useState)([]),[C,S]=(0,i.useState)(!1),[A,T]=(0,i.useState)(!1),[$,I]=(0,i.useState)(!1),[R,O]=(0,i.useState)(""),[P,E]=(0,i.useState)(!1),[D,M]=(0,i.useState)(!1),[_,L]=(0,i.useState)(!1),[z,q]=(0,i.useState)(null),[K,H]=(0,i.useState)({}),[B,G]=(0,i.useState)(!1),[V,Q]=(0,i.useState)({}),[X,Y]=(0,i.useState)(""),[ee,et]=(0,i.useState)(null),[ea,es]=(0,i.useState)(!1),[ei,el]=(0,i.useState)([]),[er,en]=(0,i.useState)("__none__"),[eo,ed]=(0,i.useState)(!1),[ec,em]=(0,i.useState)(null),[ep,eu]=(0,i.useState)({}),[ex,eh]=(0,i.useState)(null),[eg,eb]=(0,i.useState)(""),[ef,ey]=(0,i.useState)("global"),[ev,ej]=(0,i.useState)("120"),[ek,eN]=(0,i.useState)(!0),[ew,eC]=(0,i.useState)(!0),[eS,eA]=(0,i.useState)("3"),[eT,e$]=(0,i.useState)("auto"),[eI,eR]=(0,i.useState)([]),[eO,eP]=(0,i.useState)([]),[eE,eD]=(0,i.useState)([]),[eM,eU]=(0,i.useState)(null),[e_,eF]=(0,i.useState)(!1),[eL,ez]=(0,i.useState)(!1),[eq,eK]=(0,i.useState)(!1),[eH,eJ]=(0,i.useState)(null),[eW,eB]=(0,i.useState)({}),[eG,eV]=(0,i.useState)(null),eQ=(0,i.useRef)(!1),{copied:eZ,copy:eX}=(0,p.C)(),eY="ag_risk_confirmed",e0=()=>{S(!0)},e1=()=>{"antigravity"===r&&"true"!==window.localStorage.getItem(eY)?eF(!0):e6?e0():(O(""),I(!0))},e2=()=>{O(""),I(!0)},e5=()=>{e6?e1():e2()},e3=v?{id:v.id,name:v.name||("anthropic-compatible"===v.type?"Anthropic Compatible":"OpenAI Compatible"),color:"anthropic-compatible"===v.type?"#D97757":"#10A37F",textIcon:"anthropic-compatible"===v.type?"AC":"OC",apiType:v.apiType,baseUrl:v.baseUrl,type:v.type}:c.zN[r]||c.fg[r]||c.IS[r]||c.nJ[r]||c.br[r],e4=e3?.authModes||[],e6=!!c.zN[r]||!!c.IS[r]||e4.includes("oauth"),e7=!!c.fg[r]||e4.includes("apikey"),e9=!!c.IS[r]?.noAuth,e8=(0,m.KC)(r),te=(0,c.wG)(r),tt=(0,c.mq)(r),ta=(0,c.gb)(r),ts=tt||ta,ti=!ts&&e6&&e7,tl="xai"===r?"Grok Build OAuth":"OAuth",tr="xai"===r?"xAI API Key":"API Key";c.Q2[r]?.thinkingConfig||c.s9.extended;let tn=ts?r:te,to=ts?v?.prefix||r:te,td=(0,i.useCallback)(async()=>{try{let e=await fetch(`/api/models/disabled?providerAlias=${encodeURIComponent(tn)}`,{cache:"no-store"}),t=await e.json();e.ok&&eD(t.ids||[])}catch(e){console.log("Error fetching disabled models:",e)}},[tn]),tc=async e=>{try{(await fetch("/api/models/disabled",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerAlias:tn,ids:[e]})})).ok&&await td()}catch(e){console.log("Error disabling model:",e)}},tm=async e=>{try{(await fetch(`/api/models/disabled?providerAlias=${encodeURIComponent(tn)}&id=${encodeURIComponent(e)}`,{method:"DELETE"})).ok&&await td()}catch(e){console.log("Error enabling model:",e)}},tp=async e=>{e.length&&eU({title:"Disable All Models",message:`Disable all ${e.length} model(s)?`,onConfirm:async()=>{eU(null);try{(await fetch("/api/models/disabled",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerAlias:tn,ids:e})})).ok&&await td()}catch(e){console.log("Error disabling all models:",e)}}})},tu=async()=>{try{(await fetch(`/api/models/disabled?providerAlias=${encodeURIComponent(tn)}`,{method:"DELETE"})).ok&&await td()}catch(e){console.log("Error enabling all models:",e)}},tx=(0,i.useCallback)(async()=>{try{let e=await fetch("/api/models/alias"),t=await e.json();e.ok&&H(t.aliases||{})}catch(e){console.log("Error fetching aliases:",e)}},[]);(0,i.useEffect)(()=>{"kilocode"===r&&fetch("/api/providers/kilo/free-models").then(e=>e.json()).then(e=>{e.models?.length&&eP(e.models)}).catch(()=>{})},[r]);let th=(0,i.useCallback)(async()=>{try{let[e,t,a,s]=await Promise.all([fetch("/api/providers",{cache:"no-store"}),fetch("/api/provider-nodes",{cache:"no-store"}),fetch("/api/proxy-pools?isActive=true",{cache:"no-store"}),fetch("/api/settings",{cache:"no-store"})]),i=await e.json(),l=await t.json(),n=await a.json(),o=s.ok?await s.json():{};if(e.ok){let e=(i.connections||[]).filter(e=>e.provider===r);h(e)}a.ok&&w(n.proxyPools||[]),em((o.providerHealthChecks||{})[r]||null);let d=(o.providerStrategies||{})[r]||{};eh(d.fallbackStrategy||null),eb(null!=d.stickyRoundRobinLimit?String(d.stickyRoundRobinLimit):"1"),ey(d.stickyScope||"global"),ej(null!=d.stickyTtlMinutes?String(d.stickyTtlMinutes):"120"),eN(!1!==d.stickyFallbackToClientIp),eC(!1!==d.stickyRebindOnFailure),eA(null!=d.stickyRebindFailureThreshold?String(d.stickyRebindFailureThreshold):"3");let c=(o.providerThinking||{})[r]||{};if(e$(c.mode||"auto"),t.ok){let e=(l.nodes||[]).find(e=>e.id===r)||null;if(!e&&ts)for(let t=0;t<3;t+=1){await new Promise(e=>setTimeout(e,150));let t=await fetch("/api/provider-nodes",{cache:"no-store"});if(t.ok&&(e=((await t.json()).nodes||[]).find(e=>e.id===r)||null))break}j(e)}}catch(e){console.log("Error fetching connections:",e)}finally{f(!1)}},[r,ts]),tg=async e=>{try{let t=await fetch(`/api/provider-nodes/${r}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}),a=await t.json();t.ok&&(j(a.node),await th(),M(!1))}catch(e){console.log("Error updating provider node:",e)}},tb=async(e,t,a={})=>{try{let s=await fetch("/api/settings",{cache:"no-store"}),i=(s.ok?await s.json():{}).providerStrategies||{},l={...i[r]||{}};delete l.fallbackStrategy,delete l.stickyRoundRobinLimit,delete l.stickyScope,delete l.stickyTtlMinutes,delete l.stickyFallbackToClientIp,delete l.stickyRebindOnFailure,delete l.stickyRebindFailureThreshold,e&&(l.fallbackStrategy=e),"round-robin"===e&&(l.stickyRoundRobinLimit=Number(t||eg||1)||1,l.stickyScope=a.stickyScope??ef??"global",l.stickyTtlMinutes=Number(a.stickyTtlMinutes??ev??120)||120,l.stickyFallbackToClientIp=void 0!==a.stickyFallbackToClientIp?!!a.stickyFallbackToClientIp:!1!==ek,l.stickyRebindOnFailure=void 0!==a.stickyRebindOnFailure?!!a.stickyRebindOnFailure:!1!==ew,l.stickyRebindFailureThreshold=Number(a.stickyRebindFailureThreshold??eS??3)||3);let n={...i};0===Object.keys(l).length?delete n[r]:n[r]=l,await fetch("/api/settings",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({providerStrategies:n})})}catch(e){console.log("Error saving provider strategy:",e)}};(0,i.useEffect)(()=>{th(),tx(),td()},[th,tx,td]),(0,i.useEffect)(()=>{let e=(c.zN[r]||c.fg[r]||c.IS[r]||c.nJ[r])?.modelsFetcher;e&&x(e).then(eR)},[r]);let tf=async(e,t,a=te)=>{let s=`${a}/${e}`;try{let e=await fetch("/api/models/alias",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:s,alias:t})});if(e.ok)await tx();else{let t=await e.json();alert(t.error||"Failed to set alias")}}catch(e){console.log("Error setting alias:",e)}},ty=async e=>{try{(await fetch(`/api/models/alias?alias=${encodeURIComponent(e)}`,{method:"DELETE"})).ok&&await tx()}catch(e){console.log("Error deleting alias:",e)}},tv=async()=>{if(eL||0===u.length)return;let e=Object.fromEntries(u.map(e=>[e.id,{state:"queued",error:null}]));eQ.current=!1,ez(!0),eK(!1),eJ(null),eB(e),eV({total:u.length,completed:0,passed:0,failed:0,stopped:!1});let t=0,a=0;try{for(let e=0;e<u.length;e+=1){if(eQ.current){eV({total:u.length,completed:e,passed:t,failed:a,stopped:!0});break}let s=u[e];eJ(s.id),eB(e=>({...e,[s.id]:{state:"testing",error:null}}));try{let e=await fetch(`/api/providers/${s.id}/test`,{method:"POST"}),i=await e.json(),l=!!i.valid;l?t+=1:a+=1,eB(e=>({...e,[s.id]:{state:l?"success":"failed",error:l?null:i.error||null}}))}catch(e){a+=1,eB(t=>({...t,[s.id]:{state:"failed",error:e.message||"Test failed"}}))}eV({total:u.length,completed:e+1,passed:t,failed:a,stopped:!1}),e<u.length-1&&await new Promise(e=>setTimeout(e,1e3))}}finally{eJ(null),ez(!1),eK(!1),eQ.current=!1}},tj=async e=>{eu(t=>({...t,[e]:!0}));try{let t=await fetch("/api/provider-health",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({connectionId:e})}),a=await t.json().catch(()=>({}));t.ok||alert(a.error||"Health check failed"),await th()}catch(e){console.log("Error running health check:",e),alert(e.message||"Health check failed")}finally{eu(t=>({...t,[e]:!1}))}},tk=async e=>{eU({title:"Delete Connection",message:"Delete this connection?",onConfirm:async()=>{eU(null);try{(await fetch(`/api/providers/${e}`,{method:"DELETE"})).ok&&h(u.filter(t=>t.id!==e))}catch(e){console.log("Error deleting connection:",e)}}})},tN=()=>{th(),S(!1)},tw=async e=>{O("");try{let t=await fetch("/api/providers",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({provider:r,...e})}),a=null;try{a=await t.json()}catch{a=null}if(t.ok){await th(),I(!1);return}O(a?.error||"Failed to save connection")}catch(e){console.log("Error saving connection:",e),O("Failed to save connection")}},tC=async e=>{try{(await fetch(`/api/providers/${z.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).ok&&(await th(),E(!1))}catch(e){console.log("Error updating connection:",e)}},tS=async(e,t)=>{try{(await fetch(`/api/providers/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:t})})).ok&&h(a=>a.map(a=>a.id===e?{...a,isActive:t}:a))}catch(e){console.log("Error updating connection status:",e)}},tA=async(e,t)=>{let a=[...u];[a[e],a[t]]=[a[t],a[e]],h(a);try{await Promise.all([fetch(`/api/providers/${a[e].id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({priority:e})}),fetch(`/api/providers/${a[t].id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({priority:t})})])}catch(e){console.log("Error swapping priority:",e),await th()}},tT=u.filter(e=>ei.includes(e.id));u.length>0&&(ei.length,u.length),(0,i.useEffect)(()=>{el(e=>e.filter(e=>u.some(t=>t.id===e)))},[u]),(()=>{if(0===tT.length)return;let e=new Set(tT.map(e=>e.providerSpecificData?.proxyPoolId||"__none__"));if(1===e.size){let t=[...e][0];if("__none__"===t)return;let a=k.find(e=>e.id===t);return a?.name}})();let t$=()=>{eo||L(!1)},tI=async e=>{ed(!0);try{let t=0;for(let{connectionId:a,proxyPoolId:s}of e)try{(await fetch(`/api/providers/${a}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({proxyPoolId:s})})).ok||(t+=1)}catch(e){console.log("Error applying proxy for",a,e),t+=1}t>0&&alert(`Updated with ${t} failed request(s).`),await th(),L(!1)}finally{ed(!1)}},tR=e=>tI(u.map(t=>({connectionId:t.id,proxyPoolId:e}))),tO=(0,s.jsx)("div",{className:"flex min-w-0 flex-col divide-y divide-black/[0.03] dark:divide-white/[0.03]",children:u.map((e,t)=>(0,s.jsx)("div",{className:"flex min-w-0 items-stretch",children:(0,s.jsx)("div",{className:"flex-1 min-w-0",children:(0,s.jsx)(N,{connection:e,proxyPools:k,isOAuth:e6,isFirst:0===t,isLast:t===u.length-1,onMoveUp:()=>tA(t,t-1),onMoveDown:()=>tA(t,t+1),onToggleActive:t=>tS(e.id,t),onUpdateProxy:async t=>{try{(await fetch(`/api/providers/${e.id}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({proxyPoolId:t||null})})).ok&&h(a=>a.map(a=>a.id===e.id?{...a,providerSpecificData:{...a.providerSpecificData,proxyPoolId:t||null}}:a))}catch(e){console.log("Error updating proxy:",e)}},onEdit:()=>{q(e),E(!0)},onDelete:()=>tk(e.id),oneByOneStatus:eW[e.id]||null,providerHealthConfig:ec,healthCheckRunning:!!ep[e.id],onRunHealthCheck:()=>tj(e.id)})})},e.id))}),tP=k.filter(e=>!0===e.isActive),tE=(0,s.jsx)(d.aF,{isOpen:_,onClose:t$,title:`Apply Proxy (${u.length} connections)`,children:(0,s.jsxs)("div",{className:"flex flex-col gap-3",children:[(0,s.jsxs)("div",{className:"flex flex-col",children:[(0,s.jsxs)("button",{onClick:()=>{let e=k.filter(e=>!0===e.isActive);return 0===e.length?void alert("No active proxy pools available."):tI(u.map((t,a)=>({connectionId:t.id,proxyPoolId:e[a%e.length].id})))},disabled:eo||0===tP.length,className:"flex items-center gap-2 rounded-lg px-3 py-2 text-left transition-colors hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:cursor-not-allowed disabled:opacity-50",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted text-[18px]",children:"sync_alt"}),(0,s.jsx)("span",{className:"text-sm text-text-main",children:"One-to-one (rotate)"})]}),(0,s.jsxs)("button",{onClick:()=>tR(null),disabled:eo,className:"flex items-center gap-2 rounded-lg px-3 py-2 text-left transition-colors hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:cursor-not-allowed disabled:opacity-50",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted text-[18px]",children:"link_off"}),(0,s.jsx)("span",{className:"text-sm text-text-main",children:"None (unbind all)"})]}),k.map(e=>(0,s.jsxs)("button",{onClick:()=>tR(e.id),disabled:eo||!0!==e.isActive,className:"flex items-center gap-2 rounded-lg px-3 py-2 text-left transition-colors hover:bg-black/[0.04] dark:hover:bg-white/[0.04] disabled:cursor-not-allowed disabled:opacity-50",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-text-muted text-[18px]",children:"lan"}),(0,s.jsx)("span",{className:"truncate text-sm text-text-main",children:e.name}),!0!==e.isActive&&(0,s.jsx)("span",{className:"text-[10px] text-text-muted",children:"(inactive)"})]},e.id))]}),eo&&(0,s.jsx)("p",{className:"text-xs text-text-muted",children:"Applying..."}),(0,s.jsx)(d.$n,{onClick:t$,variant:"ghost",fullWidth:!0,disabled:eo,children:"Cancel"})]})}),tD=()=>{let e=u.find(e=>!1!==e.isActive);return e?.id||u[0]?.id||null},tM=async e=>{if(!ee){et(e);try{let t=await fetch("/api/models/test",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:`${tn}/${e}`,connectionId:tD()})}),a=await t.json();Q(t=>({...t,[e]:a.ok?"ok":"error"})),Y(a.ok?"":a.error||"Model not reachable")}catch{Q(t=>({...t,[e]:"error"})),Y("Network error")}finally{et(null)}}};return g?(0,s.jsxs)("div",{className:"flex flex-col gap-8",children:[(0,s.jsx)(d.Qv,{}),(0,s.jsx)(d.Qv,{})]}):e3?(0,s.jsxs)("div",{className:"flex min-w-0 flex-col gap-6 px-1 sm:gap-8 sm:px-0",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)(n(),{href:"/dashboard/providers",className:"inline-flex items-center gap-1 text-sm text-text-muted hover:text-primary transition-colors mb-4",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-lg",children:"arrow_back"}),"Back to Providers"]}),(0,s.jsxs)("div",{className:"flex min-w-0 items-center gap-3 sm:gap-4",children:[(0,s.jsx)("div",{className:"flex size-12 shrink-0 items-center justify-center rounded-lg",style:{backgroundColor:`${e3.color}15`},children:B?(0,s.jsx)("span",{className:"text-sm font-bold",style:{color:e3.color},children:e3.textIcon||e3.id.slice(0,2).toUpperCase()}):(0,s.jsx)(o.default,{src:tt&&e3.apiType?"responses"===e3.apiType?"/providers/oai-r.png":"/providers/oai-cc.png":ta?"/providers/anthropic-m.png":`/providers/${e3.id}.png`,alt:e3.name,width:48,height:48,className:"max-h-12 max-w-12 rounded-lg object-contain",sizes:"48px",onError:()=>G(!0)})}),(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3 flex-wrap",children:[(0,s.jsx)("h1",{className:"truncate text-2xl font-semibold tracking-tight sm:text-3xl",children:e3.name}),(e3.notice?.apiKeyUrl||e3.notice?.signupUrl||e3.website)&&(0,s.jsxs)("a",{href:e3.notice?.apiKeyUrl||e3.notice?.signupUrl||e3.website,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-primary hover:underline inline-flex items-center gap-1",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"open_in_new"}),e3.notice?.apiKeyUrl?"Get API Key":"Sign up / Learn more"]})]}),(0,s.jsxs)("p",{className:"text-text-muted",children:[u.length," connection",1===u.length?"":"s"]})]})]})]}),e3.deprecated&&(0,s.jsxs)("div",{className:"flex items-center gap-2 px-3 py-2 rounded-lg bg-yellow-500/10 border border-yellow-500/30",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px] text-yellow-500 mt-0.5 shrink-0",children:"warning"}),(0,s.jsx)("p",{className:"text-xs text-red-600 dark:text-yellow-400 leading-relaxed",children:e3.deprecationNotice})]}),e3.notice?.text&&!e3.deprecated&&(0,s.jsxs)("div",{className:"flex flex-col gap-2 rounded-lg border border-blue-500/30 bg-blue-500/10 px-3 py-2 sm:flex-row sm:items-center",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[16px] text-blue-500 shrink-0",children:"info"}),(0,s.jsx)("p",{className:"min-w-0 flex-1 text-xs leading-relaxed text-blue-600 dark:text-blue-400",children:e3.notice.text}),e3.notice.apiKeyUrl&&(0,s.jsx)("a",{href:e3.notice.apiKeyUrl,target:"_blank",rel:"noopener noreferrer",className:"inline-flex justify-center rounded bg-blue-500 px-2 py-1 text-xs font-medium text-white transition-colors hover:bg-blue-600 sm:py-0.5",children:"Get API Key →"})]}),ts&&v&&(0,s.jsx)(d.Zp,{children:(0,s.jsxs)("div",{className:"mb-4 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold",children:ta?"Anthropic Compatible Details":"OpenAI Compatible Details"}),(0,s.jsxs)("p",{className:"break-all text-sm text-text-muted",children:[ta?"Messages API":"responses"===v.apiType?"Responses API":"Chat Completions"," \xb7 ",(v.baseUrl||"").replace(/\/$/,""),"/",ta?"messages":"responses"===v.apiType?"responses":"chat/completions"]})]}),(0,s.jsxs)("div",{className:"grid grid-cols-1 gap-2 sm:flex sm:items-center",children:[(0,s.jsx)(d.$n,{size:"sm",icon:"add",onClick:()=>{O(""),I(!0)},className:"w-full sm:w-auto",children:"Add API Key"}),(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"edit",onClick:()=>M(!0),className:"w-full sm:w-auto",children:"Edit"}),(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"delete",onClick:async()=>{eU({title:"Delete Compatible Node",message:`Delete this ${ta?"Anthropic":"OpenAI"} Compatible node?`,onConfirm:async()=>{eU(null);try{(await fetch(`/api/provider-nodes/${r}`,{method:"DELETE"})).ok&&a.push("/dashboard/providers")}catch(e){console.log("Error deleting provider node:",e)}}})},className:"w-full sm:w-auto",children:"Delete"})]})]})}),ts&&v&&(0,s.jsx)(Z,{providerStorageAlias:tn,providerDisplayAlias:to,modelAliases:K}),e9?(0,s.jsx)(d.gw,{providerId:r}):(0,s.jsxs)(d.Zp,{children:[(0,s.jsxs)("div",{className:"mb-5 flex flex-col gap-4",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold",children:"Connections"}),"round-robin"===ex&&(0,s.jsx)("p",{className:"mt-1 text-xs text-text-muted",children:"Round Robin distributes requests across active accounts for this provider."})]}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 lg:justify-end",children:[u.length>0&&k.length>0&&(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"lan",onClick:()=>L(!0),children:"Apply Proxy"}),u.length>0&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"sync",onClick:tv,disabled:eL,children:eL?"Testing Connection One-by-One...":"Test Connection One-by-One"}),eL&&(0,s.jsx)(d.$n,{size:"sm",variant:"ghost",icon:"stop",onClick:()=>{eL&&(eQ.current=!0,eK(!0))},disabled:eq,children:eq?"Stopping...":"Stop"})]}),(0,s.jsxs)("div",{className:"flex items-center gap-2 rounded-xl border border-border bg-surface/60 px-3 py-2 shadow-sm",children:[(0,s.jsx)("span",{className:"text-xs font-medium text-text-muted",children:"Round Robin"}),(0,s.jsx)(d.lM,{checked:"round-robin"===ex,onChange:e=>{let t=e?"round-robin":null,a=e?eg||"1":eg;e&&!eg&&eb("1"),eh(t),tb(t,a)}}),"round-robin"===ex&&(0,s.jsxs)("label",{className:"flex items-center gap-1.5 border-l border-border pl-2",children:[(0,s.jsx)("span",{className:"text-xs text-text-muted",children:"Sticky:"}),(0,s.jsx)("input",{type:"number",min:1,value:eg,onChange:e=>{var t;eb(t=e.target.value),tb("round-robin",t)},placeholder:"1",className:"w-14 rounded-md border border-border bg-background px-2 py-1 text-xs focus:border-primary focus:outline-none",title:"How many selections/sessions use the same account before global round-robin advances."})]})]})]})]}),"round-robin"===ex&&(0,s.jsxs)("div",{className:"rounded-2xl border border-border bg-surface/70 p-4 shadow-sm",children:[(0,s.jsxs)("div",{className:"mb-4 flex flex-col gap-2 lg:flex-row lg:items-start lg:justify-between",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px] text-primary",children:"sticky_note_2"}),(0,s.jsx)("h3",{className:"text-sm font-semibold text-text-main",children:"Provider Round Robin Sticky"})]}),(0,s.jsx)("p",{className:"mt-1 max-w-3xl text-xs leading-relaxed text-text-muted",children:"Choose how this provider keeps the same account/API key/OAuth connection for a client. Leave it on Global to keep the current behavior."})]}),(0,s.jsx)(d.Ex,{variant:"secondary",className:"w-fit shrink-0",children:"Per provider"})]}),(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-3",children:[(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"mb-1 block text-[11px] font-semibold uppercase tracking-wide text-text-muted",children:"Sticky mode"}),(0,s.jsxs)("select",{value:ef,onChange:e=>{var t;ey(t=e.target.value),tb("round-robin",eg||"1",{stickyScope:t})},className:"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-text-main outline-none focus:border-primary",children:[(0,s.jsx)("option",{value:"global",children:"Global / current behavior"}),(0,s.jsx)("option",{value:"client_ip",children:"Client IP"}),(0,s.jsx)("option",{value:"client_session",children:"Client IP + chat session"})]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] leading-relaxed text-text-muted",children:"Global rotates like before. Client/session modes keep account identity more stable."})]}),(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"mb-1 block text-[11px] font-semibold uppercase tracking-wide text-text-muted",children:"Sticky TTL minutes"}),(0,s.jsx)("input",{type:"number",min:1,max:10080,value:ev,onChange:e=>{var t;ej(t=e.target.value),tb("round-robin",eg||"1",{stickyTtlMinutes:Number(t)||120})},className:"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-text-main outline-none focus:border-primary"}),(0,s.jsx)("p",{className:"mt-1 text-[11px] leading-relaxed text-text-muted",children:"Sticky assignments stay in memory and expire after this time."})]}),(0,s.jsxs)("label",{className:"block",children:[(0,s.jsx)("span",{className:"mb-1 block text-[11px] font-semibold uppercase tracking-wide text-text-muted",children:"Rebind after fallback count"}),(0,s.jsx)("input",{type:"number",min:1,max:50,value:eS,onChange:e=>{var t;eA(t=e.target.value),tb("round-robin",eg||"1",{stickyRebindFailureThreshold:Number(t)||3})},disabled:!ew,className:"w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-text-main outline-none focus:border-primary disabled:cursor-not-allowed disabled:opacity-50"}),(0,s.jsx)("p",{className:"mt-1 text-[11px] leading-relaxed text-text-muted",children:"After this many temporary fallbacks, the session is rebound to the fallback account."})]})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-3 lg:grid-cols-2",children:[(0,s.jsxs)("label",{className:"flex items-start gap-3 rounded-xl border border-border bg-background/70 p-3",children:[(0,s.jsx)("input",{type:"checkbox",checked:ek,onChange:e=>{var t;eN(t=e.target.checked),tb("round-robin",eg||"1",{stickyFallbackToClientIp:t})},className:"mt-0.5"}),(0,s.jsxs)("span",{children:[(0,s.jsx)("span",{className:"block text-xs font-medium text-text-main",children:"Fallback to Client IP when session id is missing"}),(0,s.jsx)("span",{className:"mt-1 block text-[11px] leading-relaxed text-text-muted",children:"Useful when the app does not send a stable chat session id."})]})]}),(0,s.jsxs)("label",{className:"flex items-start gap-3 rounded-xl border border-border bg-background/70 p-3",children:[(0,s.jsx)("input",{type:"checkbox",checked:ew,onChange:e=>{var t;eC(t=e.target.checked),tb("round-robin",eg||"1",{stickyRebindOnFailure:t})},className:"mt-0.5"}),(0,s.jsxs)("span",{children:[(0,s.jsx)("span",{className:"block text-xs font-medium text-text-main",children:"Rebind session after repeated unavailable/rate-limited hits"}),(0,s.jsx)("span",{className:"mt-1 block text-[11px] leading-relaxed text-text-muted",children:"First fallbacks are temporary; repeated failures switch that sticky session to a healthier account."})]})]})]}),(0,s.jsxs)("div",{className:"mt-4 rounded-xl border border-primary/20 bg-primary/5 px-3 py-2 text-[11px] leading-relaxed text-text-muted",children:["Recommended for Codex/Copilot-style OAuth providers:",(0,s.jsx)("span",{className:"font-medium text-text-main",children:" Client IP + chat session"}),", TTL 120 minutes, Client IP fallback enabled, rebind enabled after 3 fallbacks."]})]})]}),(0,s.jsx)(U,{providerId:r,onSaved:th})," ",0===u.length?(0,s.jsxs)("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"inline-flex items-center justify-center w-9 h-9 rounded-full bg-primary/10 text-primary shrink-0",children:(0,s.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:e6?"lock":"key"})}),(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsx)("p",{className:"text-sm text-text-muted",children:"No connections yet"}),ti&&(0,s.jsxs)("p",{className:"text-xs text-text-muted",children:["Choose ",tl," or ",tr,"."]})]})]}),(0,s.jsx)("div",{className:"flex gap-2",children:ti?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(d.$n,{size:"sm",icon:"lock",variant:"secondary",onClick:e1,children:tl}),(0,s.jsx)(d.$n,{size:"sm",icon:"key",onClick:e2,children:tr})]}):(0,s.jsxs)(s.Fragment,{children:[!ts&&"iflow"===r&&(0,s.jsx)(d.$n,{size:"sm",icon:"cookie",variant:"secondary",onClick:()=>T(!0),children:"Cookie"}),(0,s.jsx)(d.$n,{size:"sm",icon:"add",onClick:e5,children:ts?"Add API Key":"iflow"===r?"OAuth":"Add Connection"})]})})]}):(0,s.jsxs)(s.Fragment,{children:[eG&&(0,s.jsx)("div",{className:"mb-4 rounded-lg border border-black/10 bg-black/[0.02] px-3 py-2 text-xs text-text-muted dark:border-white/10 dark:bg-white/[0.03]",children:(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,s.jsxs)("span",{children:["Total: ",eG.total]}),(0,s.jsxs)("span",{children:["Completed: ",eG.completed]}),(0,s.jsxs)("span",{children:["Passed: ",eG.passed]}),(0,s.jsxs)("span",{children:["Failed: ",eG.failed]}),eG.stopped&&(0,s.jsx)("span",{className:"text-amber-600 dark:text-amber-400",children:"Stopped"}),eL&&eH&&(0,s.jsxs)("span",{children:["Running: ",u.find(e=>e.id===eH)?.name||eH]})]})}),tO,!ts&&(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-1 gap-2 sm:flex",children:["iflow"===r&&(0,s.jsx)(d.$n,{size:"sm",icon:"cookie",variant:"secondary",onClick:()=>T(!0),title:"Add connection using browser cookie",className:"w-full sm:w-auto",children:"Cookie"}),ti?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(d.$n,{size:"sm",icon:"lock",variant:"secondary",onClick:e1,className:"w-full sm:w-auto",children:tl}),(0,s.jsx)(d.$n,{size:"sm",icon:"key",onClick:e2,className:"w-full sm:w-auto",children:tr})]}):(0,s.jsx)(d.$n,{size:"sm",icon:"add",onClick:e5,className:"w-full sm:w-auto",children:"Add"})]})]})]}),(0,s.jsxs)(d.Zp,{children:[(0,s.jsxs)("div",{className:"mb-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold",children:"Available Models"}),!ts&&(e=[...e8,...eO.filter(e=>!e8.some(t=>t.id===e.id))].filter(e=>!e.type||"llm"===e.type).map(e=>e.id).filter(e=>!eE.includes(e)),(0,s.jsxs)("div",{className:"flex gap-2",children:[eE.length>0&&(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"restart_alt",onClick:tu,children:"Active All"}),e.length>0&&(0,s.jsx)(d.$n,{size:"sm",variant:"secondary",icon:"block",onClick:()=>tp(e),children:"Disable All"})]}))]}),!!X&&(0,s.jsx)("p",{className:"text-xs text-red-500 mb-3 break-words",children:X}),(()=>{let e,t,a;if(ts)return(0,s.jsx)(y,{providerStorageAlias:tn,providerDisplayAlias:to,modelAliases:K,copied:eZ,onCopy:eX,onSetAlias:tf,onDeleteAlias:ty,connections:u,isAnthropic:ta});let i=[...e8,...eO.filter(e=>!e8.some(t=>t.id===e.id))].filter(e=>!e.type||"llm"===e.type),l=new Set(eE),n=i.filter(e=>!l.has(e.id)),o=i.filter(e=>l.has(e.id)),d=Object.entries(K).filter(([e,t])=>{let a=`${tn}/`;if(!t.startsWith(a))return!1;let s=t.slice(a.length);return e3.passthroughModels?!e8.some(e=>e.id===s):!e8.some(e=>e.id===s)&&e===s}).map(([e,t])=>({id:t.slice(`${tn}/`.length),alias:e,fullModel:t}));return(0,s.jsxs)("div",{className:"flex flex-wrap gap-3",children:[d.map(e=>(0,s.jsx)(b,{model:{id:e.id},fullModel:`${to}/${e.id}`,alias:e.alias,copied:eZ,onCopy:eX,onSetAlias:()=>{},onDeleteAlias:()=>ty(e.alias),testStatus:V[e.id],onTest:u.length>0||e9?()=>tM(e.id):void 0,isTesting:ee===e.id,isCustom:!0,isFree:!1},e.id)),n.map(e=>{let t=`${tn}/${e.id}`,a=`${r}/${e.id}`,i=Object.entries(K).find(([,e])=>e===t||e===a)?.[0];return(0,s.jsx)(b,{model:e,fullModel:`${to}/${e.id}`,alias:i,copied:eZ,onCopy:eX,onSetAlias:t=>tf(e.id,t,tn),onDeleteAlias:()=>ty(i),testStatus:V[e.id],onTest:u.length>0||e9?()=>tM(e.id):void 0,isTesting:ee===e.id,isFree:e.isFree,onDisable:()=>tc(e.id)},e.id)}),(0,s.jsxs)("button",{onClick:()=>es(!0),className:"flex w-full items-center justify-center gap-1.5 rounded-lg border border-dashed border-primary/40 px-3 py-2 text-xs text-primary transition-colors hover:border-primary hover:bg-primary/5 sm:w-auto",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-sm",children:"add"}),"Add Model"]}),eI.length>0&&(e=new Set(Object.values(K)),t=new Set(e8.map(e=>e.id)),0===(a=eI.filter(a=>!e.has(`${tn}/${a.id}`)&&!t.has(a.id))).length?null:(0,s.jsxs)("div",{className:"w-full mt-2",children:[(0,s.jsx)("p",{className:"text-xs text-text-muted mb-2",children:"Suggested free models (≥200k context):"}),(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:a.map(e=>(0,s.jsxs)("button",{onClick:async()=>{let t=e.id.split("/").pop();await tf(e.id,t,tn)},className:"flex items-center gap-1 px-2.5 py-1.5 rounded-lg border border-black/10 dark:border-white/10 text-xs text-text-muted hover:text-primary hover:border-primary/40 hover:bg-primary/5 transition-colors",title:`${e.name} \xb7 ${(e.contextLength/1e3).toFixed(0)}k ctx`,children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"add"}),e.id.split("/").pop()]},e.id))})]})),o.length>0&&(0,s.jsxs)("div",{className:"w-full mt-2",children:[(0,s.jsxs)("p",{className:"text-xs text-text-muted mb-2",children:["Disabled models (",o.length,"):"]}),(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:o.map(e=>(0,s.jsxs)("button",{onClick:()=>tm(e.id),className:"flex items-center gap-1 px-2.5 py-1.5 rounded-lg border border-dashed border-black/10 dark:border-white/10 text-xs text-text-muted hover:text-primary hover:border-primary/40 hover:bg-primary/5 transition-colors",title:"Restore model",children:[(0,s.jsx)("span",{className:"material-symbols-outlined text-[13px]",children:"add"}),e.id]},e.id))})]})]})})()]}),tE,"kiro"===r?(0,s.jsx)(d.Mh,{isOpen:C,providerInfo:e3,onSuccess:tN,onClose:()=>S(!1)}):"cursor"===r?(0,s.jsx)(d.G9,{isOpen:C,onSuccess:tN,onClose:()=>S(!1)}):"gitlab"===r?(0,s.jsx)(d.vj,{isOpen:C,providerInfo:e3,onSuccess:tN,onClose:()=>S(!1)}):(0,s.jsx)(d.LF,{isOpen:C,provider:r,providerInfo:e3,onSuccess:tN,onClose:()=>S(!1)}),"iflow"===r&&(0,s.jsx)(d.vE,{isOpen:A,onSuccess:()=>{th(),T(!1)},onClose:()=>T(!1)}),(0,s.jsx)(F,{isOpen:$,provider:r,providerName:e3.name,isCompatible:ts,isAnthropic:ta,authType:e3?.authType,authHint:e3?.authHint,website:e3?.website,proxyPools:k,error:R,onSave:tw,onBulkDone:th,onClose:()=>{O(""),I(!1)}}),(0,s.jsx)(d.wI,{isOpen:P,connection:z,proxyPools:k,onSave:tC,onClose:()=>E(!1)}),ts&&(0,s.jsx)(J,{isOpen:D,node:v,onSave:tg,onClose:()=>M(!1),isAnthropic:ta}),!ts&&(0,s.jsx)(W,{isOpen:ea,providerAlias:tn,providerDisplayAlias:to,connectionId:tD(),onSave:async e=>{let t=e3?.passthroughModels?e.split("/").pop():e;await tf(e,t,tn),es(!1)},onClose:()=>es(!1)}),(0,s.jsx)(d.uo,{isOpen:e_,onClose:()=>eF(!1),onConfirm:()=>{(window.localStorage.setItem(eY,"true"),eF(!1),e6)?e0():e2()},title:"Risk Notice",message:e3?.deprecationNotice,confirmText:"I Understand, Continue",cancelText:"Cancel",variant:"danger"}),(0,s.jsx)(d.uo,{isOpen:!!eM,onClose:()=>eU(null),onConfirm:eM?.onConfirm,title:eM?.title||"Confirm",message:eM?.message,variant:"danger"})]}):(0,s.jsxs)("div",{className:"text-center py-20",children:[(0,s.jsx)("p",{className:"text-text-muted",children:"Provider not found"}),(0,s.jsx)(n(),{href:"/dashboard/providers",className:"text-primary mt-4 inline-block",children:"Back to Providers"})]})}X.propTypes={label:g().string.isRequired,hint:g().string,value:g().string.isRequired,onChange:g().func.isRequired,disabled:g().bool},Z.propTypes={providerStorageAlias:g().string.isRequired,providerDisplayAlias:g().string.isRequired,modelAliases:g().object.isRequired}}},e=>{e.O(0,[8991,3862,9893,9959,1997,5772,5564,5263,7033,5497,8441,3794,7358],()=>e(e.s=18205)),_N_E=e.O()}]);