@jheavenknows/bluerouter 2.0.87 → 2.0.89

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 (583) 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/server/app/(dashboard)/dashboard/analytics/page.js +1 -1
  5. package/app/.next-cli-build/server/app/(dashboard)/dashboard/analytics/page.js.nft.json +1 -1
  6. package/app/.next-cli-build/server/app/(dashboard)/dashboard/analytics/page_client-reference-manifest.js +1 -1
  7. package/app/.next-cli-build/server/app/(dashboard)/dashboard/api-keys/page.js +1 -1
  8. package/app/.next-cli-build/server/app/(dashboard)/dashboard/api-keys/page.js.nft.json +1 -1
  9. package/app/.next-cli-build/server/app/(dashboard)/dashboard/api-keys/page_client-reference-manifest.js +1 -1
  10. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page.js +1 -1
  11. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
  12. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  13. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js +1 -1
  14. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
  15. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  16. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js +1 -1
  17. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
  18. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  19. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page.js +1 -1
  20. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
  21. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  22. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page.js +1 -1
  23. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
  24. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  25. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js +1 -1
  26. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
  27. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  28. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +1 -1
  29. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js.nft.json +1 -1
  30. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  31. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js +1 -1
  32. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js.nft.json +1 -1
  33. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  34. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js +1 -1
  35. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js.nft.json +1 -1
  36. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  37. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page.js +1 -1
  38. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page.js.nft.json +1 -1
  39. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  40. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page.js +1 -1
  41. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
  42. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  43. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js +1 -1
  44. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
  45. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  46. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page.js +1 -1
  47. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
  48. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  49. package/app/.next-cli-build/server/app/(dashboard)/dashboard/prompt-logs/page.js +1 -1
  50. package/app/.next-cli-build/server/app/(dashboard)/dashboard/prompt-logs/page.js.nft.json +1 -1
  51. package/app/.next-cli-build/server/app/(dashboard)/dashboard/prompt-logs/page_client-reference-manifest.js +1 -1
  52. package/app/.next-cli-build/server/app/(dashboard)/dashboard/provider-health/page.js +1 -1
  53. package/app/.next-cli-build/server/app/(dashboard)/dashboard/provider-health/page.js.nft.json +1 -1
  54. package/app/.next-cli-build/server/app/(dashboard)/dashboard/provider-health/page_client-reference-manifest.js +1 -1
  55. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js +1 -1
  56. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
  57. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  58. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page.js +1 -1
  59. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
  60. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  61. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page.js +1 -1
  62. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
  63. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  64. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page.js +1 -1
  65. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
  66. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  67. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page.js +1 -1
  68. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
  69. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  70. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page.js +1 -1
  71. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page.js.nft.json +1 -1
  72. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  73. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page.js +1 -1
  74. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
  75. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  76. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page.js +1 -1
  77. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
  78. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  79. package/app/.next-cli-build/server/app/_global-error/page.js.nft.json +1 -1
  80. package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
  81. package/app/.next-cli-build/server/app/_global-error.html +1 -1
  82. package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
  83. package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
  84. package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  85. package/app/.next-cli-build/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  86. package/app/.next-cli-build/server/app/_global-error.segments/_head.segment.rsc +1 -1
  87. package/app/.next-cli-build/server/app/_global-error.segments/_index.segment.rsc +1 -1
  88. package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  89. package/app/.next-cli-build/server/app/_not-found/page.js +1 -1
  90. package/app/.next-cli-build/server/app/_not-found/page.js.nft.json +1 -1
  91. package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
  92. package/app/.next-cli-build/server/app/_not-found.html +1 -1
  93. package/app/.next-cli-build/server/app/_not-found.rsc +3 -3
  94. package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +3 -3
  95. package/app/.next-cli-build/server/app/_not-found.segments/_head.segment.rsc +1 -1
  96. package/app/.next-cli-build/server/app/_not-found.segments/_index.segment.rsc +3 -3
  97. package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  98. package/app/.next-cli-build/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  99. package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  100. package/app/.next-cli-build/server/app/api/auth/ldap/test/route.js +1 -1
  101. package/app/.next-cli-build/server/app/api/auth/ldap/test/route.js.nft.json +1 -1
  102. package/app/.next-cli-build/server/app/api/auth/ldap/users/route.js +1 -1
  103. package/app/.next-cli-build/server/app/api/auth/ldap/users/route.js.nft.json +1 -1
  104. package/app/.next-cli-build/server/app/api/auth/login/route.js +1 -1
  105. package/app/.next-cli-build/server/app/api/auth/login/route.js.nft.json +1 -1
  106. package/app/.next-cli-build/server/app/api/auth/logout/route.js.nft.json +1 -1
  107. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js +1 -1
  108. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js.nft.json +1 -1
  109. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js +1 -1
  110. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js.nft.json +1 -1
  111. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js +1 -1
  112. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js.nft.json +1 -1
  113. package/app/.next-cli-build/server/app/api/auth/status/route.js +1 -1
  114. package/app/.next-cli-build/server/app/api/auth/status/route.js.nft.json +1 -1
  115. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
  116. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
  117. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/autostart/route.js.nft.json +1 -1
  118. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/prompt-log-db/route.js +1 -1
  119. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/prompt-log-db/route.js.nft.json +1 -1
  120. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/root-ca/route.js.nft.json +1 -1
  121. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
  122. package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route.js.nft.json +1 -1
  123. package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route.js.nft.json +1 -1
  124. package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js.nft.json +1 -1
  125. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js.nft.json +1 -1
  126. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route.js.nft.json +1 -1
  127. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route.js.nft.json +1 -1
  128. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
  129. package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route.js.nft.json +1 -1
  130. package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route.js.nft.json +1 -1
  131. package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route.js.nft.json +1 -1
  132. package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route.js.nft.json +1 -1
  133. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js.nft.json +1 -1
  134. package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route.js.nft.json +1 -1
  135. package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route.js.nft.json +1 -1
  136. package/app/.next-cli-build/server/app/api/combos/[id]/route.js +1 -1
  137. package/app/.next-cli-build/server/app/api/combos/[id]/route.js.nft.json +1 -1
  138. package/app/.next-cli-build/server/app/api/combos/route.js +1 -1
  139. package/app/.next-cli-build/server/app/api/combos/route.js.nft.json +1 -1
  140. package/app/.next-cli-build/server/app/api/dashboard/analytics/route.js +110 -96
  141. package/app/.next-cli-build/server/app/api/dashboard/analytics/route.js.nft.json +1 -1
  142. package/app/.next-cli-build/server/app/api/dashboard/combos/route.js +1 -1
  143. package/app/.next-cli-build/server/app/api/dashboard/combos/route.js.nft.json +1 -1
  144. package/app/.next-cli-build/server/app/api/dashboard/endpoint/route.js +1 -1
  145. package/app/.next-cli-build/server/app/api/dashboard/endpoint/route.js.nft.json +1 -1
  146. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/[id]/route.js +32 -1
  147. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/[id]/route.js.nft.json +1 -1
  148. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/options/route.js +32 -1
  149. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/options/route.js.nft.json +1 -1
  150. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/route.js +32 -1
  151. package/app/.next-cli-build/server/app/api/dashboard/prompt-logs/route.js.nft.json +1 -1
  152. package/app/.next-cli-build/server/app/api/health/route.js.nft.json +1 -1
  153. package/app/.next-cli-build/server/app/api/init/route.js.nft.json +1 -1
  154. package/app/.next-cli-build/server/app/api/keys/[id]/rotate/route.js +1 -1
  155. package/app/.next-cli-build/server/app/api/keys/[id]/rotate/route.js.nft.json +1 -1
  156. package/app/.next-cli-build/server/app/api/keys/[id]/route.js +1 -1
  157. package/app/.next-cli-build/server/app/api/keys/[id]/route.js.nft.json +1 -1
  158. package/app/.next-cli-build/server/app/api/keys/route.js +1 -1
  159. package/app/.next-cli-build/server/app/api/keys/route.js.nft.json +1 -1
  160. package/app/.next-cli-build/server/app/api/locale/route.js.nft.json +1 -1
  161. package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js.nft.json +1 -1
  162. package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js.nft.json +1 -1
  163. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js +1 -1
  164. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js.nft.json +1 -1
  165. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js +1 -1
  166. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
  167. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js +1 -1
  168. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js.nft.json +1 -1
  169. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js +1 -1
  170. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js.nft.json +1 -1
  171. package/app/.next-cli-build/server/app/api/media-providers/tts/voices/route.js.nft.json +1 -1
  172. package/app/.next-cli-build/server/app/api/models/alias/route.js +1 -1
  173. package/app/.next-cli-build/server/app/api/models/alias/route.js.nft.json +1 -1
  174. package/app/.next-cli-build/server/app/api/models/availability/route.js +1 -1
  175. package/app/.next-cli-build/server/app/api/models/availability/route.js.nft.json +1 -1
  176. package/app/.next-cli-build/server/app/api/models/custom/route.js +1 -1
  177. package/app/.next-cli-build/server/app/api/models/custom/route.js.nft.json +1 -1
  178. package/app/.next-cli-build/server/app/api/models/disabled/route.js +1 -1
  179. package/app/.next-cli-build/server/app/api/models/disabled/route.js.nft.json +1 -1
  180. package/app/.next-cli-build/server/app/api/models/route.js +1 -1
  181. package/app/.next-cli-build/server/app/api/models/route.js.nft.json +1 -1
  182. package/app/.next-cli-build/server/app/api/models/test/route.js +1 -1
  183. package/app/.next-cli-build/server/app/api/models/test/route.js.nft.json +1 -1
  184. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
  185. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
  186. package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
  187. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js +1 -1
  188. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
  189. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js +1 -1
  190. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
  191. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js +1 -1
  192. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
  193. package/app/.next-cli-build/server/app/api/oauth/kiro/auto-import/route.js.nft.json +1 -1
  194. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js +1 -1
  195. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
  196. package/app/.next-cli-build/server/app/api/oauth/kiro/social-authorize/route.js.nft.json +1 -1
  197. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js +1 -1
  198. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
  199. package/app/.next-cli-build/server/app/api/pricing/route.js +1 -1
  200. package/app/.next-cli-build/server/app/api/pricing/route.js.nft.json +1 -1
  201. package/app/.next-cli-build/server/app/api/provider-health/route.js +1 -1
  202. package/app/.next-cli-build/server/app/api/provider-health/route.js.nft.json +1 -1
  203. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js +1 -1
  204. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
  205. package/app/.next-cli-build/server/app/api/provider-nodes/route.js +1 -1
  206. package/app/.next-cli-build/server/app/api/provider-nodes/route.js.nft.json +1 -1
  207. package/app/.next-cli-build/server/app/api/provider-nodes/validate/route.js.nft.json +1 -1
  208. package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
  209. package/app/.next-cli-build/server/app/api/providers/[id]/route.js +1 -1
  210. package/app/.next-cli-build/server/app/api/providers/[id]/route.js.nft.json +1 -1
  211. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js +1 -1
  212. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
  213. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js +1 -1
  214. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
  215. package/app/.next-cli-build/server/app/api/providers/client/route.js.nft.json +1 -1
  216. package/app/.next-cli-build/server/app/api/providers/kilo/free-models/route.js.nft.json +1 -1
  217. package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
  218. package/app/.next-cli-build/server/app/api/providers/route.js.nft.json +1 -1
  219. package/app/.next-cli-build/server/app/api/providers/suggested-models/route.js.nft.json +1 -1
  220. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js +1 -1
  221. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js.nft.json +1 -1
  222. package/app/.next-cli-build/server/app/api/providers/validate/route.js +1 -1
  223. package/app/.next-cli-build/server/app/api/providers/validate/route.js.nft.json +1 -1
  224. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js +1 -1
  225. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
  226. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js +1 -1
  227. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
  228. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js +1 -1
  229. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js.nft.json +1 -1
  230. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js +1 -1
  231. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js.nft.json +1 -1
  232. package/app/.next-cli-build/server/app/api/proxy-pools/route.js +1 -1
  233. package/app/.next-cli-build/server/app/api/proxy-pools/route.js.nft.json +1 -1
  234. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js +1 -1
  235. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js.nft.json +1 -1
  236. package/app/.next-cli-build/server/app/api/settings/database/route.js +1 -1
  237. package/app/.next-cli-build/server/app/api/settings/database/route.js.nft.json +1 -1
  238. package/app/.next-cli-build/server/app/api/settings/proxy-test/route.js.nft.json +1 -1
  239. package/app/.next-cli-build/server/app/api/settings/require-login/route.js +1 -1
  240. package/app/.next-cli-build/server/app/api/settings/require-login/route.js.nft.json +1 -1
  241. package/app/.next-cli-build/server/app/api/settings/route.js +1 -1
  242. package/app/.next-cli-build/server/app/api/settings/route.js.nft.json +1 -1
  243. package/app/.next-cli-build/server/app/api/shutdown/route.js.nft.json +1 -1
  244. package/app/.next-cli-build/server/app/api/tags/route.js.nft.json +1 -1
  245. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
  246. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js.nft.json +1 -1
  247. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
  248. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js.nft.json +1 -1
  249. package/app/.next-cli-build/server/app/api/translator/load/route.js.nft.json +1 -1
  250. package/app/.next-cli-build/server/app/api/translator/save/route.js.nft.json +1 -1
  251. package/app/.next-cli-build/server/app/api/translator/send/route.js.nft.json +1 -1
  252. package/app/.next-cli-build/server/app/api/translator/translate/route.js.nft.json +1 -1
  253. package/app/.next-cli-build/server/app/api/tunnel/disable/route.js.nft.json +1 -1
  254. package/app/.next-cli-build/server/app/api/tunnel/enable/route.js.nft.json +1 -1
  255. package/app/.next-cli-build/server/app/api/tunnel/status/route.js.nft.json +1 -1
  256. package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route.js.nft.json +1 -1
  257. package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route.js.nft.json +1 -1
  258. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js.nft.json +1 -1
  259. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js.nft.json +1 -1
  260. package/app/.next-cli-build/server/app/api/tunnel/tailscale-login/route.js.nft.json +1 -1
  261. package/app/.next-cli-build/server/app/api/tunnel/tailscale-start-daemon/route.js.nft.json +1 -1
  262. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
  263. package/app/.next-cli-build/server/app/api/usage/chart/route.js +1 -1
  264. package/app/.next-cli-build/server/app/api/usage/chart/route.js.nft.json +1 -1
  265. package/app/.next-cli-build/server/app/api/usage/history/route.js +1 -1
  266. package/app/.next-cli-build/server/app/api/usage/history/route.js.nft.json +1 -1
  267. package/app/.next-cli-build/server/app/api/usage/providers/route.js +1 -1
  268. package/app/.next-cli-build/server/app/api/usage/providers/route.js.nft.json +1 -1
  269. package/app/.next-cli-build/server/app/api/usage/request-details/route.js +1 -1
  270. package/app/.next-cli-build/server/app/api/usage/request-details/route.js.nft.json +1 -1
  271. package/app/.next-cli-build/server/app/api/usage/request-logs/route.js +1 -1
  272. package/app/.next-cli-build/server/app/api/usage/request-logs/route.js.nft.json +1 -1
  273. package/app/.next-cli-build/server/app/api/usage/stats/route.js +1 -1
  274. package/app/.next-cli-build/server/app/api/usage/stats/route.js.nft.json +1 -1
  275. package/app/.next-cli-build/server/app/api/usage/stream/route.js +1 -1
  276. package/app/.next-cli-build/server/app/api/usage/stream/route.js.nft.json +1 -1
  277. package/app/.next-cli-build/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  278. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js +1 -1
  279. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
  280. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js +1 -1
  281. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
  282. package/app/.next-cli-build/server/app/api/v1/audio/voices/route.js.nft.json +1 -1
  283. package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  284. package/app/.next-cli-build/server/app/api/v1/embeddings/route.js.nft.json +1 -1
  285. package/app/.next-cli-build/server/app/api/v1/images/generations/route.js.nft.json +1 -1
  286. package/app/.next-cli-build/server/app/api/v1/messages/count_tokens/route.js.nft.json +1 -1
  287. package/app/.next-cli-build/server/app/api/v1/messages/route.js.nft.json +1 -1
  288. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
  289. package/app/.next-cli-build/server/app/api/v1/models/info/route.js.nft.json +1 -1
  290. package/app/.next-cli-build/server/app/api/v1/models/route.js.nft.json +1 -1
  291. package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
  292. package/app/.next-cli-build/server/app/api/v1/responses/route.js.nft.json +1 -1
  293. package/app/.next-cli-build/server/app/api/v1/route.js.nft.json +1 -1
  294. package/app/.next-cli-build/server/app/api/v1/search/route.js.nft.json +1 -1
  295. package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
  296. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  297. package/app/.next-cli-build/server/app/api/v1beta/models/route.js +1 -1
  298. package/app/.next-cli-build/server/app/api/v1beta/models/route.js.nft.json +1 -1
  299. package/app/.next-cli-build/server/app/api/version/restart/route.js.nft.json +1 -1
  300. package/app/.next-cli-build/server/app/api/version/route.js +1 -1
  301. package/app/.next-cli-build/server/app/api/version/route.js.nft.json +1 -1
  302. package/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
  303. package/app/.next-cli-build/server/app/api/version/shutdown/route.js.nft.json +1 -1
  304. package/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
  305. package/app/.next-cli-build/server/app/api/version/update/route.js.nft.json +1 -1
  306. package/app/.next-cli-build/server/app/callback/page.js +1 -1
  307. package/app/.next-cli-build/server/app/callback/page.js.nft.json +1 -1
  308. package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
  309. package/app/.next-cli-build/server/app/callback.html +1 -1
  310. package/app/.next-cli-build/server/app/callback.rsc +3 -3
  311. package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +3 -3
  312. package/app/.next-cli-build/server/app/callback.segments/_head.segment.rsc +1 -1
  313. package/app/.next-cli-build/server/app/callback.segments/_index.segment.rsc +3 -3
  314. package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +1 -1
  315. package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  316. package/app/.next-cli-build/server/app/callback.segments/callback.segment.rsc +1 -1
  317. package/app/.next-cli-build/server/app/dashboard/analytics.html +1 -1
  318. package/app/.next-cli-build/server/app/dashboard/analytics.rsc +5 -5
  319. package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics/__PAGE__.segment.rsc +2 -2
  320. package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard/analytics.segment.rsc +1 -1
  321. package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  322. package/app/.next-cli-build/server/app/dashboard/analytics.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  323. package/app/.next-cli-build/server/app/dashboard/analytics.segments/_full.segment.rsc +5 -5
  324. package/app/.next-cli-build/server/app/dashboard/analytics.segments/_head.segment.rsc +1 -1
  325. package/app/.next-cli-build/server/app/dashboard/analytics.segments/_index.segment.rsc +3 -3
  326. package/app/.next-cli-build/server/app/dashboard/analytics.segments/_tree.segment.rsc +1 -1
  327. package/app/.next-cli-build/server/app/dashboard/api-keys.html +1 -1
  328. package/app/.next-cli-build/server/app/dashboard/api-keys.rsc +5 -5
  329. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard/api-keys/__PAGE__.segment.rsc +2 -2
  330. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard/api-keys.segment.rsc +1 -1
  331. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  332. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  333. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_full.segment.rsc +5 -5
  334. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_head.segment.rsc +1 -1
  335. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_index.segment.rsc +3 -3
  336. package/app/.next-cli-build/server/app/dashboard/api-keys.segments/_tree.segment.rsc +1 -1
  337. package/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
  338. package/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +5 -5
  339. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
  340. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
  341. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  342. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  343. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +5 -5
  344. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
  345. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_index.segment.rsc +3 -3
  346. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
  347. package/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
  348. package/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +5 -5
  349. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  350. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  351. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  352. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  353. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +5 -5
  354. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  355. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
  356. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
  357. package/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
  358. package/app/.next-cli-build/server/app/dashboard/combos.rsc +5 -5
  359. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  360. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  361. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  362. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  363. package/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
  364. package/app/.next-cli-build/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  365. package/app/.next-cli-build/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
  366. package/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
  367. package/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
  368. package/app/.next-cli-build/server/app/dashboard/endpoint.rsc +5 -5
  369. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  370. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  371. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  372. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  373. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +5 -5
  374. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  375. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
  376. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
  377. package/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
  378. package/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +5 -5
  379. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
  380. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
  381. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
  382. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  383. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  384. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +5 -5
  385. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
  386. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +3 -3
  387. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
  388. package/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
  389. package/app/.next-cli-build/server/app/dashboard/mitm.rsc +5 -5
  390. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  391. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  392. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  393. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  394. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
  395. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  396. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
  397. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
  398. package/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
  399. package/app/.next-cli-build/server/app/dashboard/profile.rsc +4 -4
  400. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +1 -1
  401. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  402. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  403. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  404. package/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +4 -4
  405. package/app/.next-cli-build/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  406. package/app/.next-cli-build/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
  407. package/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
  408. package/app/.next-cli-build/server/app/dashboard/prompt-logs.html +1 -1
  409. package/app/.next-cli-build/server/app/dashboard/prompt-logs.rsc +5 -5
  410. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard/prompt-logs/__PAGE__.segment.rsc +2 -2
  411. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard/prompt-logs.segment.rsc +1 -1
  412. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  413. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  414. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_full.segment.rsc +5 -5
  415. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_head.segment.rsc +1 -1
  416. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_index.segment.rsc +3 -3
  417. package/app/.next-cli-build/server/app/dashboard/prompt-logs.segments/_tree.segment.rsc +1 -1
  418. package/app/.next-cli-build/server/app/dashboard/provider-health.html +1 -1
  419. package/app/.next-cli-build/server/app/dashboard/provider-health.rsc +4 -4
  420. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard/provider-health/__PAGE__.segment.rsc +1 -1
  421. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard/provider-health.segment.rsc +1 -1
  422. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  423. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  424. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_full.segment.rsc +4 -4
  425. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_head.segment.rsc +1 -1
  426. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_index.segment.rsc +3 -3
  427. package/app/.next-cli-build/server/app/dashboard/provider-health.segments/_tree.segment.rsc +1 -1
  428. package/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
  429. package/app/.next-cli-build/server/app/dashboard/providers/new.rsc +5 -5
  430. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  431. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  432. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  433. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  434. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  435. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
  436. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  437. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
  438. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
  439. package/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
  440. package/app/.next-cli-build/server/app/dashboard/providers.rsc +5 -5
  441. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  442. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  443. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  444. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  445. package/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
  446. package/app/.next-cli-build/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  447. package/app/.next-cli-build/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
  448. package/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
  449. package/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
  450. package/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +5 -5
  451. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  452. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  453. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  454. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  455. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
  456. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  457. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
  458. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
  459. package/app/.next-cli-build/server/app/dashboard/quota.html +1 -1
  460. package/app/.next-cli-build/server/app/dashboard/quota.rsc +6 -6
  461. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
  462. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  463. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  464. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  465. package/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +6 -6
  466. package/app/.next-cli-build/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  467. package/app/.next-cli-build/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
  468. package/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
  469. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page.js +1 -1
  470. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page.js.nft.json +1 -1
  471. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  472. package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
  473. package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +3 -3
  474. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
  475. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  476. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
  477. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
  478. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  479. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  480. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  481. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  482. package/app/.next-cli-build/server/app/dashboard/skills.html +1 -1
  483. package/app/.next-cli-build/server/app/dashboard/skills.rsc +5 -5
  484. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +2 -2
  485. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills.segment.rsc +1 -1
  486. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  487. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  488. package/app/.next-cli-build/server/app/dashboard/skills.segments/_full.segment.rsc +5 -5
  489. package/app/.next-cli-build/server/app/dashboard/skills.segments/_head.segment.rsc +1 -1
  490. package/app/.next-cli-build/server/app/dashboard/skills.segments/_index.segment.rsc +3 -3
  491. package/app/.next-cli-build/server/app/dashboard/skills.segments/_tree.segment.rsc +1 -1
  492. package/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
  493. package/app/.next-cli-build/server/app/dashboard/translator.rsc +5 -5
  494. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  495. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  496. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  497. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  498. package/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
  499. package/app/.next-cli-build/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  500. package/app/.next-cli-build/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
  501. package/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
  502. package/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
  503. package/app/.next-cli-build/server/app/dashboard/usage.rsc +5 -5
  504. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  505. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  506. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  507. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  508. package/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
  509. package/app/.next-cli-build/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  510. package/app/.next-cli-build/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
  511. package/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
  512. package/app/.next-cli-build/server/app/dashboard.html +1 -1
  513. package/app/.next-cli-build/server/app/dashboard.rsc +5 -5
  514. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  515. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  516. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  517. package/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +5 -5
  518. package/app/.next-cli-build/server/app/dashboard.segments/_head.segment.rsc +1 -1
  519. package/app/.next-cli-build/server/app/dashboard.segments/_index.segment.rsc +3 -3
  520. package/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +1 -1
  521. package/app/.next-cli-build/server/app/favicon.ico/route.js.nft.json +1 -1
  522. package/app/.next-cli-build/server/app/index.html +1 -1
  523. package/app/.next-cli-build/server/app/index.rsc +3 -3
  524. package/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  525. package/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +3 -3
  526. package/app/.next-cli-build/server/app/index.segments/_head.segment.rsc +1 -1
  527. package/app/.next-cli-build/server/app/index.segments/_index.segment.rsc +3 -3
  528. package/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +1 -1
  529. package/app/.next-cli-build/server/app/landing/page.js +1 -1
  530. package/app/.next-cli-build/server/app/landing/page.js.nft.json +1 -1
  531. package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
  532. package/app/.next-cli-build/server/app/landing.html +1 -1
  533. package/app/.next-cli-build/server/app/landing.rsc +3 -3
  534. package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +3 -3
  535. package/app/.next-cli-build/server/app/landing.segments/_head.segment.rsc +1 -1
  536. package/app/.next-cli-build/server/app/landing.segments/_index.segment.rsc +3 -3
  537. package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +1 -1
  538. package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  539. package/app/.next-cli-build/server/app/landing.segments/landing.segment.rsc +1 -1
  540. package/app/.next-cli-build/server/app/login/page.js +1 -1
  541. package/app/.next-cli-build/server/app/login/page.js.nft.json +1 -1
  542. package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
  543. package/app/.next-cli-build/server/app/login.html +1 -1
  544. package/app/.next-cli-build/server/app/login.rsc +3 -3
  545. package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +3 -3
  546. package/app/.next-cli-build/server/app/login.segments/_head.segment.rsc +1 -1
  547. package/app/.next-cli-build/server/app/login.segments/_index.segment.rsc +3 -3
  548. package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +1 -1
  549. package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  550. package/app/.next-cli-build/server/app/login.segments/login.segment.rsc +1 -1
  551. package/app/.next-cli-build/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  552. package/app/.next-cli-build/server/app/page.js +1 -1
  553. package/app/.next-cli-build/server/app/page.js.nft.json +1 -1
  554. package/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
  555. package/app/.next-cli-build/server/app-paths-manifest.json +3 -3
  556. package/app/.next-cli-build/server/chunks/2338.js +4 -4
  557. package/app/.next-cli-build/server/chunks/3110.js +1 -1
  558. package/app/.next-cli-build/server/chunks/402.js +14 -58
  559. package/app/.next-cli-build/server/chunks/4746.js +1 -1
  560. package/app/.next-cli-build/server/chunks/5901.js +23 -67
  561. package/app/.next-cli-build/server/chunks/7130.js +1 -1
  562. package/app/.next-cli-build/server/chunks/7153.js +1 -1
  563. package/app/.next-cli-build/server/instrumentation.js +1 -1
  564. package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
  565. package/app/.next-cli-build/server/middleware.js +4 -4
  566. package/app/.next-cli-build/server/pages/404.html +1 -1
  567. package/app/.next-cli-build/server/pages/500.html +1 -1
  568. package/app/.next-cli-build/static/chunks/{1321-8c45bbbccb18c6e5.js → 1321-edcba502a5f7c6c0.js} +1 -1
  569. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/analytics/page-b68a56ad8276dece.js +1 -0
  570. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/mitm/page-99f8c146d571e6e7.js +1 -0
  571. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/prompt-logs/page-f5228970334d7b36.js +1 -0
  572. package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite-shm +0 -0
  573. package/app/cli/.build-home/AppData/Roaming/bluerouter/db/data.sqlite-wal +0 -0
  574. package/app/package.json +1 -1
  575. package/package.json +1 -1
  576. package/app/.next-cli-build/server/chunks/6050.js +0 -81
  577. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/analytics/page-d75d359efb7b7b2f.js +0 -1
  578. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/mitm/page-045950c3d0610b2c.js +0 -1
  579. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/prompt-logs/page-a0151da8f40c4ea4.js +0 -1
  580. /package/app/.next-cli-build/static/{iOcCnF-oha4dR4oAXJ9EM → fjRDrRq569K5V63gqrUkp}/_buildManifest.js +0 -0
  581. /package/app/.next-cli-build/static/{iOcCnF-oha4dR4oAXJ9EM → fjRDrRq569K5V63gqrUkp}/_ssgManifest.js +0 -0
  582. /package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-2.0.83-to-2.0.84-2.0.84-20260616-111525 → upgrade-2.0.87-to-2.0.88-2.0.88-20260616-165249}/data.sqlite +0 -0
  583. /package/app/cli/.build-home/AppData/Roaming/bluerouter/db/backups/{upgrade-2.0.84-to-2.0.83-2.0.83-20260616-110903 → upgrade-2.0.88-to-2.0.89-2.0.89-20260617-073907}/data.sqlite +0 -0
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8978],{39944:(e,t,s)=>{Promise.resolve().then(s.bind(s,70959))},70959:(e,t,s)=>{"use strict";s.d(t,{default:()=>z});var l=s(95155),r=s(12115);let n=[{value:"today",label:"H\xf4m nay"},{value:"yesterday",label:"H\xf4m qua"},{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ả"},{value:"custom",label:"T\xf9y chọn"}],a=[{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"}];function o(e,t=0){return Number(e||0).toLocaleString("vi-VN",{maximumFractionDigits:t})}function i(e){let t=Number(e||0);return Intl.NumberFormat("vi-VN",{notation:"compact",maximumFractionDigits:1}).format(t)}function d(e){let t=100*Number(e||0);return`${t.toLocaleString("vi-VN",{maximumFractionDigits:1})}%`}function c(e){let t=Number(e||0);return t?`$${t.toLocaleString("vi-VN",{minimumFractionDigits:4,maximumFractionDigits:6})}`:"$0"}function x(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 m(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 u(e){return null==e||Number.isNaN(Number(e))?"-":`${Number(e).toLocaleString("vi-VN",{maximumFractionDigits:0})}/100`}function h(e){if(!e)return"-";try{let t=new Date(e);if(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 p(e){if(!e)return"";try{let t=new Date(e);if(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 b(...e){return e.filter(Boolean).join(" ")}function g(e,t={}){let s=new URLSearchParams;return Object.entries({...e,...t}).forEach(([e,t])=>{let l=String(t??"").trim();l&&s.set(e,l)}),s.toString()}function j({children:e,className:t=""}){return(0,l.jsx)("div",{className:b("min-w-0 rounded-2xl border border-border bg-surface p-5 shadow-sm",t),children:e})}function v({icon:e,label:t,value:s,hint:r,tone:n="blue"}){return(0,l.jsx)(j,{className:"min-h-[126px]",children:(0,l.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"text-sm font-medium text-text-muted",children:t}),(0,l.jsx)("div",{className:"mt-2 text-2xl font-semibold text-text-main",children:s}),r?(0,l.jsx)("div",{className:"mt-2 text-xs text-text-muted",children:r}):null]}),(0,l.jsx)("div",{className:b("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"}[n]||"bg-blue-500/10 text-blue-600 dark:text-blue-300"),children:(0,l.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:e})})]})})}function y({label:e,children:t}){return(0,l.jsxs)("label",{className:"space-y-1.5 text-xs font-medium text-text-muted",children:[(0,l.jsx)("span",{children:e}),t]})}function k({value:e,onChange:t,children:s}){return(0,l.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 N({value:e,onChange:t,placeholder:s="",type:r="text"}){return(0,l.jsx)("input",{value:e||"",type:r,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 f(){return(0,l.jsxs)("div",{className:"space-y-4",children:[(0,l.jsx)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:Array.from({length:8}).map((e,t)=>(0,l.jsx)("div",{className:"h-32 animate-pulse rounded-2xl border border-border bg-surface"},t))}),(0,l.jsx)("div",{className:"h-80 animate-pulse rounded-2xl border border-border bg-surface"})]})}function T({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,l.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,l.jsx)("span",{className:"material-symbols-outlined text-4xl text-text-muted",children:"database_off"}),(0,l.jsx)("div",{className:"mt-3 text-sm font-semibold text-text-main",children:e}),(0,l.jsx)("div",{className:"mt-1 max-w-xl text-sm text-text-muted",children:t})]})}function w({data:e=[],valueKey:t="totalTokens",secondaryKey:s="requests",height:r=220}){let n=e||[],a=Math.max(...n.map(e=>Number(e[t]||0)),1),i=Math.max(...n.map(e=>Number(e[s]||0)),1);return 0===n.length?(0,l.jsx)(T,{description:"Chưa c\xf3 time-series trong khoảng thời gian n\xe0y."}):(0,l.jsx)("div",{className:"overflow-x-auto",children:(0,l.jsxs)("div",{className:"min-w-[720px]",children:[(0,l.jsx)("div",{className:"flex items-end gap-1",style:{height:r},children:n.map((e,n)=>{let d=Math.max(2,Number(e[t]||0)/a*(r-42)),c=Math.max(2,Number(e[s]||0)/i*(r-42));return(0,l.jsx)("div",{className:"group flex flex-1 flex-col items-center justify-end gap-1",children:(0,l.jsxs)("div",{className:"relative flex h-full w-full max-w-[34px] items-end justify-center gap-0.5",children:[(0,l.jsx)("div",{className:"w-2 rounded-t bg-primary/70",style:{height:d}}),(0,l.jsx)("div",{className:"w-2 rounded-t bg-amber-500/70",style:{height:c}}),(0,l.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,l.jsx)("div",{className:"font-semibold text-text-main",children:p(e.label)}),(0,l.jsxs)("div",{className:"mt-1 text-text-muted",children:["Request: ",o(e.requests)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Input token: ",o(e.promptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Output token: ",o(e.completionTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Tổng token: ",o(e.totalTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Lỗi: ",o(e.errors)]})]})]})},`${e.label}-${n}`)})}),(0,l.jsxs)("div",{className:"mt-3 flex justify-between gap-2 text-[11px] text-text-muted",children:[(0,l.jsx)("span",{children:p(n[0]?.label)}),(0,l.jsx)("span",{children:p(n[Math.floor(n.length/2)]?.label)}),(0,l.jsx)("span",{children:p(n[n.length-1]?.label)})]})]})})}function P(){return(0,l.jsxs)("div",{className:"flex flex-wrap gap-3 text-xs text-text-muted",children:[(0,l.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,l.jsx)("span",{className:"h-2.5 w-2.5 rounded-sm bg-primary/70"}),"Token"]}),(0,l.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,l.jsx)("span",{className:"h-2.5 w-2.5 rounded-sm bg-amber-500/70"}),"Request"]})]})}function q({columns:e,rows:t,empty:s="Kh\xf4ng c\xf3 dữ liệu"}){return t&&0!==t.length?(0,l.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,l.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,l.jsx)("thead",{className:"bg-background/70",children:(0,l.jsx)("tr",{children:e.map(e=>(0,l.jsx)("th",{className:b("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,l.jsx)("tbody",{className:"divide-y divide-border bg-surface",children:t.map((t,s)=>(0,l.jsx)("tr",{className:"hover:bg-background/60",children:e.map(e=>(0,l.jsx)("td",{className:b("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,l.jsx)(T,{title:s})}function S({items:e=[]}){return e&&0!==e.length?(0,l.jsx)("div",{className:"flex max-w-[360px] flex-wrap gap-1.5",children:e.slice(0,3).map(e=>(0,l.jsxs)("span",{className:"rounded-full bg-primary/10 px-2 py-0.5 text-xs text-primary",children:[e.label||e.key," \xb7 ",o(e.count??e.requests??e.totalTokens??0)]},e.key))}):(0,l.jsx)("span",{className:"text-text-muted",children:"-"})}function I({row:e}){return(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{className:"font-semibold text-text-main",children:[i(e.totalTokens)," token"]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["In ",i(e.promptTokens)," / Out ",i(e.completionTokens)]})]})}function R({value:e}){let t=Number(e||0);return(0,l.jsx)("span",{className:b("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:d(t)})}function L({level:e,label:t}){let s=String(e||"none");return(0,l.jsx)("span",{className:b("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 M({level:e,label:t}){let s=String(e||"normal");return(0,l.jsx)("span",{className:b("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 C({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,l.jsx)("span",{className:b("rounded-full px-2 py-1 text-xs font-semibold",s.cls),children:s.label})}function K({row:e}){let t=e.sampleMessage||e.errorMessageShort||"";return t?(0,l.jsx)("span",{className:"block max-w-[360px] truncate text-xs text-text-muted",title:t,children:t}):(0,l.jsx)("span",{className:"text-text-muted",children:"-"})}function $({icon:e,label:t,value:s,hint:r,tone:n="slate"}){return(0,l.jsx)("div",{className:b("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"}[n]||"border-border bg-surface text-text-main"),children:(0,l.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide opacity-75",children:t}),(0,l.jsx)("div",{className:"mt-2 text-2xl font-bold",children:o(s)}),r?(0,l.jsx)("div",{className:"mt-1 text-xs opacity-80",children:r}):null]}),(0,l.jsx)("span",{className:"material-symbols-outlined text-[24px] opacity-80",children:e})]})})}function A({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,l.jsx)("div",{className:b("rounded-2xl border p-4",t),children:(0,l.jsxs)("div",{className:"flex gap-3",children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:s}),(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.title}),(0,l.jsx)("div",{className:"mt-1 text-sm opacity-90",children:e.detail})]})]})})}function E({notes:e=[]}){return e.length?(0,l.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,l.jsxs)("div",{className:"flex gap-2",children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"info"}),(0,l.jsx)("span",{children:e})]},t))}):null}function F({filters:e,setFilters:t,options:s,onRefresh:r,onExportCsv:a,loading:o}){let i=(e,s)=>t(t=>({...t,[e]:s}));return(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"grid gap-3 md:grid-cols-2 xl:grid-cols-6",children:[(0,l.jsx)(y,{label:"Khoảng thời gian",children:(0,l.jsx)(k,{value:e.period,onChange:e=>i("period",e),children:n.map(e=>(0,l.jsx)("option",{value:e.value,children:e.label},e.value))})}),(0,l.jsx)(y,{label:"Từ ng\xe0y",children:(0,l.jsx)(N,{type:"datetime-local",value:e.dateFrom,onChange:e=>i("dateFrom",e)})}),(0,l.jsx)(y,{label:"Đến ng\xe0y",children:(0,l.jsx)(N,{type:"datetime-local",value:e.dateTo,onChange:e=>i("dateTo",e)})}),(0,l.jsx)(y,{label:"Provider",children:(0,l.jsxs)(k,{value:e.provider,onChange:e=>i("provider",e),children:[(0,l.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,l.jsx)("option",{value:t,children:s},t)})]})}),(0,l.jsx)(y,{label:"Model",children:(0,l.jsxs)(k,{value:e.model,onChange:e=>i("model",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả model"}),(s.models||[]).map(e=>(0,l.jsx)("option",{value:e,children:e},e))]})}),(0,l.jsx)(y,{label:"Provider account",children:(0,l.jsxs)(k,{value:e.connectionId,onChange:e=>i("connectionId",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả account"}),(s.connections||[]).map(e=>(0,l.jsx)("option",{value:e.value,children:e.label},e.value))]})}),(0,l.jsx)(y,{label:"API key",children:(0,l.jsxs)(k,{value:e.apiKey,onChange:e=>i("apiKey",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả API key"}),(s.apiKeys||[]).map(e=>(0,l.jsx)("option",{value:e.value,children:e.label},e.value))]})}),(0,l.jsx)(y,{label:"Source IP",children:(0,l.jsx)(N,{value:e.clientIp,onChange:e=>i("clientIp",e),placeholder:"172.16.253.1"})}),(0,l.jsx)(y,{label:"Source tool",children:(0,l.jsx)(N,{value:e.sourceTool,onChange:e=>i("sourceTool",e),placeholder:"copilot, antigravity..."})}),(0,l.jsx)(y,{label:"Endpoint",children:(0,l.jsxs)(k,{value:e.endpoint,onChange:e=>i("endpoint",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả endpoint"}),(s.endpoints||[]).map(e=>(0,l.jsx)("option",{value:e,children:e},e))]})}),(0,l.jsx)(y,{label:"Status",children:(0,l.jsxs)(k,{value:e.status,onChange:e=>i("status",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả status"}),(s.statuses||[]).map(e=>(0,l.jsx)("option",{value:e,children:e},e))]})}),(0,l.jsx)(y,{label:"Session / keyword",children:(0,l.jsx)(N,{value:e.sessionId||e.keyword,onChange:e=>i("keyword",e),placeholder:"session, prompt, error..."})})]}),(0,l.jsxs)("div",{className:"mt-4 flex flex-wrap items-center justify-between gap-3",children:[(0,l.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,l.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,l.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,l.jsxs)("button",{onClick:a,className:"rounded-xl border border-border px-3 py-2 text-sm font-medium text-text-main hover:bg-background",children:[(0,l.jsx)("span",{className:"material-symbols-outlined mr-1 align-[-4px] text-[18px]",children:"download"}),"Export CSV"]}),(0,l.jsxs)("button",{onClick:r,disabled:o,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white shadow-sm disabled:opacity-60",children:[(0,l.jsx)("span",{className:"material-symbols-outlined mr-1 align-[-4px] text-[18px]",children:"refresh"}),o?"Đang tải...":"Refresh"]})]})]})]})}function _({data:e}){let t=e.overview||{},s=e.latency||{},r=e.experience||{};return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,l.jsx)(v,{icon:"call_made",label:"Tổng request",value:o(t.requests),hint:`${o(t.requestsPerMinute,2)} request/ph\xfat`}),(0,l.jsx)(v,{icon:"check_circle",label:"Th\xe0nh c\xf4ng",value:o(t.success),hint:`Tỷ lệ lỗi ${d(t.errorRate)}`,tone:"green"}),(0,l.jsx)(v,{icon:"dns",label:"Lỗi server/provider",value:o(t.serverErrorEvents),hint:`Server-impacting ${d(t.serverErrorRate)} \xb7 client ${o(t.clientErrorEvents)}`,tone:t.serverErrorEvents?"red":"green"}),(0,l.jsx)(v,{icon:"speed",label:"Trải nghiệm",value:u(r.score),hint:`${r.label||"-"} \xb7 ${o(r.samples)} mẫu`,tone:r.tone||"purple"}),(0,l.jsx)(v,{icon:"timer",label:"Latency P95",value:x(r.p95LatencyMs||s.p95Ms),hint:`AVG ${x(r.avgLatencyMs||s.avgMs)} \xb7 P50 ${x(r.p50LatencyMs||s.p50Ms)}`,tone:"purple"}),(0,l.jsx)(v,{icon:"bolt",label:"TTFT P95",value:x(r.p95TtftMs),hint:"Thời gian chờ token đầu ti\xean",tone:r.slowTtftRate>=.2?"amber":"blue"}),(0,l.jsx)(v,{icon:"input",label:"Input P95",value:i(r.p95PromptTokens||0),hint:`Avg ${i(r.avgPromptTokens||t.avgPromptTokens)} \xb7 >=30k ${d(r.longInputRate)}`}),(0,l.jsx)(v,{icon:"person_alert",label:"Top user nặng",value:t.topHeavyUser||"-",hint:`Chiếm ${d(t.topHeavyUserTokenShare)} tổng token`,tone:t.topHeavyUserTokenShare>=.35?"amber":"slate"}),(0,l.jsx)(v,{icon:"running_with_errors",label:"Request chậm",value:d(r.slowRequestRate),hint:`>= ${x(r.thresholds?.slowLatencyMs||45e3)} \xb7 max ${x(r.maxLatencyMs)}`,tone:r.slowRequestRate>=.2?"amber":"green"}),(0,l.jsx)(v,{icon:"output",label:"Output tokens",value:i(t.completionTokens),hint:`Avg ${o(t.avgCompletionTokens,1)} / request`}),(0,l.jsx)(v,{icon:"token",label:"Tổng tokens",value:i(t.totalTokens),hint:`${i(t.tokensPerMinute)} token/ph\xfat`,tone:"amber"}),(0,l.jsx)(v,{icon:"speed",label:"Output speed",value:m(r.decodeTokensPerSecond," tok/s"),hint:`Latency/10k input ${x(r.latencyMsPer10kInputTokens)}`,tone:"slate"}),(0,l.jsx)(v,{icon:"payments",label:"Cost ước t\xednh",value:c(t.cost),hint:"Dựa tr\xean pricing đ\xe3 cấu h\xecnh",tone:"green"})]}),(0,l.jsxs)("div",{className:"grid min-w-0 gap-5 xl:grid-cols-[2fr_1fr]",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Tần suất request & token theo thời gian"}),(0,l.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,l.jsx)(P,{})]}),(0,l.jsx)(w,{data:e.timeSeries||[]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"T\xf3m tắt active"}),(0,l.jsx)("div",{className:"mt-4 space-y-3",children:[["API key đang d\xf9ng",t.activeApiKeys],["Provider active",t.activeProviders],["Model active",t.activeModels],["Endpoint active",t.activeEndpoints],["Cached tokens",t.cachedTokens],["Reasoning tokens",t.reasoningTokens],["Latency AVG",x(r.avgLatencyMs||s.avgMs)],["Latency P50",x(r.p50LatencyMs||s.p50Ms)],["Latency P99",x(r.p99LatencyMs||s.p99Ms)],["TTFT P95",x(r.p95TtftMs)],["Input P95",i(r.p95PromptTokens||0)],["Long input >=30k",d(r.longInputRate)]].map(([e,t])=>(0,l.jsxs)("div",{className:"flex items-center justify-between rounded-xl bg-background px-3 py-2",children:[(0,l.jsx)("span",{className:"text-sm text-text-muted",children:e}),(0,l.jsx)("span",{className:"font-semibold text-text-main",children:"number"==typeof t?o(t):t})]},e))})]})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top API key d\xf9ng nhiều token"}),(0,l.jsx)(q,{rows:(e.clientRequests?.topApiKeysByTokens||e.groups?.apiKeys||[]).slice(0,8),columns:[{key:"name",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.name||e.label}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:[e.fingerprint||e.apiKeyFingerprint,e.ownerUser||e.apiKeyOwner?` \xb7 ${e.ownerUser||e.apiKeyOwner}`:""]})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"P95/Max input",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{children:i(e.p95PromptTokens||0)}),(0,l.jsxs)("div",{className:"text-text-muted",children:["max ",i(e.maxPromptTokens||0)]})]})}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top Source IP d\xf9ng nhiều token"}),(0,l.jsx)(q,{rows:(e.clientRequests?.topSourceIpsByTokens||[]).slice(0,8),columns:[{key:"label",label:"Source IP",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"heavy",label:"Nặng",render:e=>(0,l.jsxs)("span",{className:"text-xs text-text-muted",children:[o(e.heavyRequests||0)," req"]})}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]})]})]})}function O({data:e}){let t=e.clientRequests||{},s=t.summary||{},r=t.topHeavyUsers||[],n=t.topProblemClients||[],a=t.topApiKeysByTokens||[],c=t.topSourceIpsByTokens||[];t.topSourceIpsByHeavyRequests;let m=t.inputBuckets||[],u=e=>(0,l.jsxs)("div",{className:"min-w-[220px]",children:[(0,l.jsx)("div",{className:"font-semibold text-text-main",children:e.label}),(0,l.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.ownerUser?`Owner ${e.ownerUser}`:e.apiKeyName||"Kh\xf4ng c\xf3 owner"}),(0,l.jsx)("div",{className:"font-mono text-[11px] text-text-muted",children:e.apiKeyFingerprint||e.primaryClientIp||e.key})]}),p=e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["Nặng ",o(e.heavyRequests)," \xb7 ",d(e.heavyRequestRate)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["P95 input ",i(e.p95PromptTokens)," \xb7 Max ",i(e.maxPromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=70k ",o(e.extremeInputRequests)," \xb7 ",d(e.extremeInputRate)]})]});return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,l.jsx)(v,{icon:"person_alert",label:"Top user nặng nhất",value:s.topUserLabel||"-",hint:`${i(s.topUserTokens)} token \xb7 ${d(s.topUserTokenShare)} tổng token`,tone:s.topUserTokenShare>=.35?"amber":"slate"}),(0,l.jsx)(v,{icon:"vpn_key",label:"Top API key nhiều token",value:s.topApiKeyLabel||"-",hint:`${i(s.topApiKeyTokens)} token \xb7 ${d(s.topApiKeyTokenShare)} tổng token`,tone:s.topApiKeyTokenShare>=.35?"amber":"blue"}),(0,l.jsx)(v,{icon:"lan",label:"Top IP nhiều token",value:s.topSourceIpLabel||"-",hint:`${i(s.topSourceIpTokens)} token \xb7 ${d(s.topSourceIpTokenShare)} tổng token`,tone:s.topSourceIpTokenShare>=.35?"amber":"purple"}),(0,l.jsx)(v,{icon:"input",label:"Input d\xe0i >=30k",value:d(s.longInputBucketShare||0),hint:`>=70k ${d(s.extremeInputShare||0)}`,tone:(s.extremeInputShare||0)>=.1?"amber":"green"}),(0,l.jsx)(v,{icon:"groups",label:"User/API key được theo d\xf5i",value:o(s.trackedUsers||0),hint:"Theo owner/API key fingerprint/source IP",tone:"blue"}),(0,l.jsx)(v,{icon:"network_check",label:"Top IP request nặng",value:s.topSourceIpHeavyLabel||"-",hint:`${o(s.topSourceIpHeavyRequests||0)} request >=30k input/total`,tone:s.topSourceIpHeavyRequests?"amber":"slate"}),(0,l.jsx)(v,{icon:"report",label:"Client lỗi nhiều",value:o(s.problemClients||0),hint:"Nh\xf3m user/API key c\xf3 error rows",tone:s.problemClients?"amber":"green"})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top user/API key gửi request nặng nhất"}),(0,l.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,l.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,l.jsx)(q,{rows:r,columns:[{key:"user",label:"User/API key",render:u},{key:"quality",label:"\xc1p lực",render:e=>(0,l.jsx)(M,{level:e.level,label:e.pressureLabel})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"Input pressure",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["Avg ",i(e.avgPromptTokens)," \xb7 P95 ",i(e.p95PromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Max ",i(e.maxPromptTokens)," \xb7 >=30k ",d(e.longInputRate)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=50k ",d(e.hugeInputRate)," \xb7 >=70k ",d(e.extremeInputRate)]})]})},{key:"latency",label:"Latency / TTFT",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["P95 ",x(e.p95LatencyMs)," \xb7 Max ",x(e.maxLatencyMs)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["TTFT P95 ",x(e.p95TtftMs)," \xb7 Slow ",d(e.slowRequestRate)]})]})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"topIps",label:"IP / Tool",render:e=>(0,l.jsxs)("div",{className:"space-y-1",children:[(0,l.jsx)(S,{items:e.topIps}),(0,l.jsx)(S,{items:e.topTools})]})},{key:"meta",label:"Meta",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs text-text-muted",children:[(0,l.jsxs)("div",{children:["Key ",o(e.apiKeyCount)," \xb7 IP ",o(e.sourceIpCount)," \xb7 Tool ",o(e.sourceToolCount)]}),(0,l.jsxs)("div",{children:["Session ",o(e.sessionCount)," \xb7 Last ",h(e.lastSeen)]})]})}],empty:"Kh\xf4ng c\xf3 request th\xe0nh c\xf4ng c\xf3 token trong khoảng lọc."})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top API key d\xf9ng nhiều token nhất"}),(0,l.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,l.jsx)(q,{rows:a,columns:[{key:"apiKey",label:"API key",render:e=>(0,l.jsxs)("div",{className:"min-w-[220px]",children:[(0,l.jsx)("div",{className:"font-semibold text-text-main",children:e.label}),(0,l.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.apiKeyOwner?`Owner ${e.apiKeyOwner}`:e.apiKeyName||e.primarySourceTool||"-"}),(0,l.jsx)("div",{className:"font-mono text-[11px] text-text-muted",children:e.apiKeyFingerprint||e.primaryClientIp||e.key})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"Input nặng",render:p},{key:"meta",label:"Nguồn",render:e=>(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:[(0,l.jsxs)("div",{children:["IP ",o(e.sourceIpCount)," \xb7 Tool ",o(e.sourceToolCount)]}),(0,l.jsxs)("div",{children:["Model ",o(e.modelCount)," \xb7 Provider ",o(e.providerCount)]})]})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 API key c\xf3 token trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top Source IP d\xf9ng nhiều token nhất"}),(0,l.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,l.jsx)(q,{rows:c,columns:[{key:"ip",label:"Source IP",render:e=>(0,l.jsxs)("div",{className:"min-w-[180px]",children:[(0,l.jsx)("div",{className:"font-mono text-sm font-semibold text-text-main",children:e.label}),(0,l.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:["Tool ",o(e.sourceToolCount)," \xb7 API key ",o(e.apiKeyCount)]}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:["Model ",o(e.modelCount)," \xb7 Provider ",o(e.providerCount)]})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"Input nặng",render:p},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Ph\xe2n bố request theo k\xedch thước input"}),(0,l.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,l.jsx)(q,{rows:m,columns:[{key:"label",label:"Input bucket",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"share",label:"Tỷ trọng",render:e=>d(e.share)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"latency",label:"Latency P95/MAX",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{children:[x(e.p95LatencyMs)," / ",x(e.maxLatencyMs)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["TTFT P95 ",x(e.p95TtftMs)]})]})}],empty:"Kh\xf4ng c\xf3 dữ liệu bucket input."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Client/API key lỗi nhiều"}),(0,l.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,l.jsx)(q,{rows:n,columns:[{key:"user",label:"Client",render:u},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"source",label:"IP/Tool",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{className:"font-mono",children:e.primaryClientIp||"-"}),(0,l.jsx)("div",{className:"text-text-muted",children:e.primarySourceTool||"-"})]})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 client lỗi theo bộ lọc hiện tại."})]})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"G\xf3c nh\xecn monitor client n\xean d\xf9ng"}),(0,l.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,l.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,l.jsxs)("div",{className:"rounded-xl border border-border bg-background p-3",children:[(0,l.jsx)("div",{className:"font-semibold text-text-main",children:e}),(0,l.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:t})]},e))})]})]})}function U({data:e}){return(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Thống k\xea theo API key"}),(0,l.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,l.jsx)(q,{rows:e.groups?.apiKeys||[],columns:[{key:"name",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.name}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:[e.fingerprint,e.ownerUser?` \xb7 Owner: ${e.ownerUser}`:""]})]})},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"success",label:"OK/Lỗi",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{className:"text-green-600",children:["OK ",o(e.success)]}),(0,l.jsxs)("div",{className:"text-red-600",children:["Lỗi ",o(e.errors)]})]})},{key:"tokens",label:"In/Out token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"topProviders",label:"Top provider",render:e=>(0,l.jsx)(S,{items:e.topProviders})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]})}function V({data:e}){let t=e.clientRequests?.topSourceIpsByTokens||[],s=e.clientRequests?.topSourceIpsByHeavyRequests||[],r=e=>(0,l.jsxs)("div",{className:"min-w-[180px]",children:[(0,l.jsx)("div",{className:"font-mono text-sm font-semibold text-text-main",children:e.label}),(0,l.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:["API key ",o(e.apiKeyCount)," \xb7 Tool ",o(e.sourceToolCount)]}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:["Model ",o(e.modelCount)," \xb7 Provider ",o(e.providerCount)]})]});return(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top IP d\xf9ng nhiều token nhất"}),(0,l.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Aggregate từ UsageHistory, xếp theo tổng input + output token."})]}),(0,l.jsx)(q,{rows:t,columns:[{key:"ip",label:"Source IP",render:r},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top IP gửi request nặng nhất"}),(0,l.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,l.jsx)(q,{rows:s,columns:[{key:"ip",label:"Source IP",render:r},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"heavy",label:"Request nặng",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["Nặng ",o(e.heavyRequests)," \xb7 ",d(e.heavyRequestRate)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["P95 input ",i(e.p95PromptTokens)," \xb7 Max ",i(e.maxPromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=70k ",o(e.extremeInputRequests)," \xb7 ",d(e.extremeInputRate)]})]})},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP gửi request nặng trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Source IP từ Prompt Logs"}),(0,l.jsx)(q,{rows:e.promptLogs?.topClientIps||[],columns:[{key:"label",label:"IP",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Logs",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topTools",label:"Tools",render:e=>(0,l.jsx)(S,{items:e.topTools})},{key:"topModels",label:"Models",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Source tool"}),(0,l.jsx)(q,{rows:e.promptLogs?.topSourceTools||[],columns:[{key:"label",label:"Tool",render:e=>(0,l.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Logs",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topIps",label:"Top IP",render:e=>(0,l.jsx)(S,{items:e.topIps})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)(j,{className:"xl:col-span-2",children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Session nhiều hoạt động"}),(0,l.jsx)(q,{rows:e.promptLogs?.topSessions||[],columns:[{key:"label",label:"Session",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Logs",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"topIps",label:"IP",render:e=>(0,l.jsx)(S,{items:e.topIps})},{key:"topTools",label:"Tool",render:e=>(0,l.jsx)(S,{items:e.topTools})},{key:"topModels",label:"Model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]})]})}function D({data:e}){return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Provider"}),(0,l.jsx)(q,{rows:e.groups?.providers||[],columns:[{key:"label",label:"Provider",render:e=>(0,l.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Model"}),(0,l.jsx)(q,{rows:e.groups?.models||[],columns:[{key:"label",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"errorRate",label:"Lỗi",render:e=>(0,l.jsx)(R,{value:e.errorRate})}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Provider account / connection"}),(0,l.jsx)(q,{rows:e.groups?.providerAccounts||[],columns:[{key:"label",label:"Account",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.label}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.provider||e.connectionId})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"errorRate",label:"Lỗi",render:e=>(0,l.jsx)(R,{value:e.errorRate})}]})]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Endpoint"}),(0,l.jsx)(q,{rows:e.groups?.endpoints||[],columns:[{key:"label",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]})]})}function H({data:e}){let t=e.experience||{},s=t.thresholds||{},r=t.byModel||[],n=t.slowestRequests||[];return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,l.jsx)(v,{icon:"verified",label:"Đ\xe1nh gi\xe1 tổng",value:u(t.score),hint:`${t.label||"-"} \xb7 ${o(t.samples)} mẫu success c\xf3 token`,tone:t.tone||"slate"}),(0,l.jsx)(v,{icon:"timer",label:"Latency AVG / P95",value:`${x(t.avgLatencyMs)} / ${x(t.p95LatencyMs)}`,hint:`P50 ${x(t.p50LatencyMs)} \xb7 P99 ${x(t.p99LatencyMs)}`,tone:"purple"}),(0,l.jsx)(v,{icon:"bolt",label:"TTFT AVG / P95",value:`${x(t.avgTtftMs)} / ${x(t.p95TtftMs)}`,hint:"TTFT cao thường l\xe0 queue/prompt eval/input d\xe0i",tone:t.slowTtftRate>=.2?"amber":"blue"}),(0,l.jsx)(v,{icon:"keyboard_double_arrow_up",label:"Input AVG / P95",value:`${i(t.avgPromptTokens)} / ${i(t.p95PromptTokens)}`,hint:`>=30k ${d(t.longInputRate)} \xb7 >=50k ${d(t.hugeInputRate)}`}),(0,l.jsx)(v,{icon:"running_with_errors",label:"Slow request",value:d(t.slowRequestRate),hint:`Latency >= ${x(s.slowLatencyMs||45e3)} \xb7 rất chậm ${d(t.verySlowRequestRate)}`,tone:t.slowRequestRate>=.2?"amber":"green"}),(0,l.jsx)(v,{icon:"pending_actions",label:"Slow TTFT",value:d(t.slowTtftRate),hint:`TTFT >= ${x(s.slowTtftMs||2e4)}`,tone:t.slowTtftRate>=.2?"amber":"green"}),(0,l.jsx)(v,{icon:"speed",label:"Output tốc độ",value:m(t.decodeTokensPerSecond," tok/s"),hint:`Output/latency ${m(t.outputTokensPerSecond," tok/s")}`,tone:"slate"}),(0,l.jsx)(v,{icon:"data_usage",label:"Latency / 10k input",value:x(t.latencyMsPer10kInputTokens),hint:"Hữu \xedch khi VS Code gửi 30k–70k token",tone:"slate"})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"C\xe1ch đọc trải nghiệm user"}),(0,l.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,l.jsxs)("div",{className:"grid gap-3 md:grid-cols-3",children:[(0,l.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"Nhanh/chậm thực tế"}),(0,l.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,l.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"Queue hoặc prompt eval"}),(0,l.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,l.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"VS Code / agent"}),(0,l.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,l.jsxs)(j,{children:[(0,l.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,l.jsx)(q,{rows:r,empty:"Chưa c\xf3 mẫu latency cho model trong khoảng lọc.",columns:[{key:"model",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"quality",label:"Đ\xe1nh gi\xe1",render:e=>(0,l.jsxs)("div",{className:"space-y-1",children:[(0,l.jsx)(L,{level:e.level,label:e.labelQuality}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:u(e.score)})]})},{key:"samples",label:"Mẫu",render:e=>o(e.samples)},{key:"latency",label:"Latency P50/P95/MAX",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{children:[x(e.p50LatencyMs)," / ",x(e.p95LatencyMs)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["max ",x(e.maxLatencyMs)]})]})},{key:"ttft",label:"TTFT P95",render:e=>x(e.p95TtftMs)},{key:"input",label:"Input avg/P95",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{children:[i(e.avgPromptTokens)," / ",i(e.p95PromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=30k ",d(e.longInputRate)]})]})},{key:"slow",label:"Chậm",render:e=>(0,l.jsx)(R,{value:e.slowRequestRate})},{key:"speed",label:"Output tok/s",render:e=>m(e.outputTokensPerSecond," tok/s")}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Request chậm nhất"}),(0,l.jsx)(q,{rows:n,empty:"Kh\xf4ng c\xf3 request chậm trong khoảng lọc.",columns:[{key:"timestamp",label:"Time",render:e=>h(e.timestamp)},{key:"model",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.provider})]})},{key:"latency",label:"Latency / TTFT",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{className:"font-semibold",children:x(e.latencyMs)}),(0,l.jsxs)("div",{className:"text-text-muted",children:["TTFT ",x(e.ttftMs)]})]})},{key:"tokens",label:"In / Out",render:e=>(0,l.jsx)(I,{row:e})},{key:"apiKeyName",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:e.apiKeyName}),(0,l.jsx)("div",{className:"font-mono text-xs text-text-muted",children:e.apiKeyFingerprint})]})},{key:"sourceTool",label:"Tool/IP",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{children:e.sourceTool||"-"}),(0,l.jsx)("div",{className:"font-mono text-text-muted",children:e.clientIp||"-"})]})},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint||"-"})}]})]})]})}function B({data:e}){let t=e.requestErrors||{},s=t.summary||{},r=e.overview||{},n=Number(r.serverErrorRate||0),a=Number(r.clientErrorRate||0),i=Number(r.rateLimitErrorRate||0),c=[{key:"faultOwner",label:"Loại",render:e=>(0,l.jsx)(C,{value:e.faultOwner})},{key:"status",label:"Status",render:e=>(0,l.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"},{key:"model",label:"Model"},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"requests",label:"Lỗi",render:e=>o(e.errors||e.requests)},{key:"errorType",label:"Type",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.errorType||e.errorCode||"-"})},{key:"sampleMessage",label:"Sample",render:e=>(0,l.jsx)(K,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}];return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-5",children:[(0,l.jsx)($,{icon:"dns",label:"Server/provider",value:s.serverImpacting||0,hint:`${d(n)} tr\xean tổng request`,tone:s.serverImpacting?"red":"green"}),(0,l.jsx)($,{icon:"cloud_off",label:"Upstream",value:s.upstream||0,hint:"Provider/model server, timeout, network, 5xx",tone:s.upstream?"red":"green"}),(0,l.jsx)($,{icon:"router",label:"Gateway",value:s.gateway||0,hint:"Lỗi nội bộ BlueRouter/gateway",tone:s.gateway?"purple":"green"}),(0,l.jsx)($,{icon:"integration_instructions",label:"Client/request",value:s.client||0,hint:`${d(a)} do endpoint/model/body/auth`,tone:s.client?"slate":"green"}),(0,l.jsx)($,{icon:"speed",label:"Rate/quota",value:s.rateLimit||0,hint:`${d(i)} rate-limit/quota`,tone:s.rateLimit?"amber":"green"})]}),(0,l.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,l.jsxs)("div",{className:"flex gap-3",children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:"rule_settings"}),(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:"Ph\xe2n loại lỗi đ\xe3 t\xe1ch client khỏi server/provider"}),(0,l.jsxs)("div",{className:"mt-1 opacity-90",children:["Cảnh b\xe1o vận h\xe0nh n\xean ưu ti\xean nh\xf3m ",(0,l.jsx)("b",{children:"Server/provider"})," gồm gateway, upstream, timeout, network v\xe0 5xx. Nh\xf3m ",(0,l.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,l.jsx)("div",{className:"grid gap-4 xl:grid-cols-2",children:e.anomalies.map((e,t)=>(0,l.jsx)(A,{anomaly:e},t))}):(0,l.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,l.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,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Lỗi server/provider cần xử l\xfd"}),(0,l.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,l.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:[o(s.serverImpacting||0)," lỗi"]})]}),(0,l.jsx)(q,{rows:t.topServerErrors||[],columns:c,empty:"Kh\xf4ng c\xf3 lỗi server/provider trong khoảng lọc."})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Lỗi client/request sai"}),(0,l.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,l.jsx)(q,{rows:t.topClientErrors||[],columns:c.filter(e=>!["sampleMessage"].includes(e.key)),empty:"Kh\xf4ng c\xf3 lỗi client/request trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Ph\xe2n bố loại lỗi"}),(0,l.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,l.jsx)(q,{rows:t.byFaultOwner||[],columns:[{key:"faultOwner",label:"Loại",render:e=>(0,l.jsx)(C,{value:e.faultOwner||e.key})},{key:"requests",label:"Số lỗi",render:e=>o(e.requests)},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 lỗi để ph\xe2n loại."})]})]}),t.topRateLimitErrors?.length?(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Rate limit / quota"}),(0,l.jsx)(q,{rows:t.topRateLimitErrors||[],columns:c})]}):null,(0,l.jsxs)(j,{children:[(0,l.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,l.jsx)(q,{rows:e.groups?.errors||[],columns:[{key:"faultOwner",label:"Loại",render:e=>(0,l.jsx)(C,{value:e.faultOwner})},{key:"status",label:"Status",render:e=>(0,l.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"},{key:"model",label:"Model"},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"requests",label:"Lỗi",render:e=>o(e.errors||e.requests)},{key:"apiKey",label:"API key",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.apiKey})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Status distribution"}),(0,l.jsx)(q,{rows:e.groups?.statuses||[],columns:[{key:"label",label:"Status"},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})}]})]})]})}function G({data:e}){return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top request nặng token"}),(0,l.jsx)(q,{rows:e.heavyRequests||[],columns:[{key:"timestamp",label:"Time",render:e=>h(e.timestamp)},{key:"model",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.provider})]})},{key:"apiKeyName",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:e.apiKeyName}),(0,l.jsx)("div",{className:"font-mono text-xs text-text-muted",children:e.apiKeyFingerprint})]})},{key:"accountName",label:"Account"},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"status",label:"Status"}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Recent usage"}),(0,l.jsx)(q,{rows:e.recentUsage||[],columns:[{key:"timestamp",label:"Time",render:e=>h(e.timestamp)},{key:"provider",label:"Provider"},{key:"model",label:"Model"},{key:"apiKeyName",label:"API key"},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"status",label:"Status"}]})]})]})}function z(){let[e,t]=(0,r.useState)({period:"today",dateFrom:"",dateTo:"",provider:"",model:"",connectionId:"",status:"",endpoint:"",apiKey:"",clientIp:"",sourceTool:"",sessionId:"",keyword:""}),[s,n]=(0,r.useState)(null),[o,i]=(0,r.useState)(!0),[d,c]=(0,r.useState)(""),[x,m]=(0,r.useState)("overview"),[u,p]=(0,r.useState)(!1),j=function(e,t=450){let[s,l]=(0,r.useState)(e);return(0,r.useEffect)(()=>{let s=setTimeout(()=>l(e),t);return()=>clearTimeout(s)},[e,t]),s}(e,450),v=(0,r.useCallback)(async()=>{i(!0),c("");try{let e=g(j),t=await fetch(`/api/dashboard/analytics?${e}`,{cache:"no-store"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng tải được dữ liệu analytics");n(s)}catch(e){c(e.message||"Kh\xf4ng tải được dữ liệu analytics")}finally{i(!1)}},[j]);(0,r.useEffect)(()=>{v()},[v]),(0,r.useEffect)(()=>{if(!u)return;let e=setInterval(()=>v(),1e4);return()=>clearInterval(e)},[u,v]);let y=s?.options||{},k=(0,r.useMemo)(()=>s?.generatedAt?h(s.generatedAt):"-",[s]);return(0,l.jsxs)("div",{className:"space-y-5 p-4 md:p-6",children:[(0,l.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center gap-2 text-primary",children:[(0,l.jsx)("span",{className:"material-symbols-outlined",children:"monitoring"}),(0,l.jsx)("span",{className:"text-sm font-semibold uppercase tracking-wide",children:"BlueRouter Analytics"})]}),(0,l.jsx)("h1",{className:"mt-2 text-2xl font-bold text-text-main",children:"Thống k\xea sử dụng Gateway"}),(0,l.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,l.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,l.jsx)("span",{className:"material-symbols-outlined text-[20px]",children:"schedule"}),(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{children:["Generated: ",k]}),(0,l.jsxs)("label",{className:"mt-1 flex cursor-pointer items-center gap-2 text-xs",children:[(0,l.jsx)("input",{type:"checkbox",checked:u,onChange:e=>p(e.target.checked)}),"Auto refresh 10s"]})]})]})]}),(0,l.jsx)(F,{filters:e,setFilters:t,options:y,onRefresh:v,onExportCsv:()=>{let e=g(j,{format:"csv"});window.open(`/api/dashboard/analytics?${e}`,"_blank","noopener,noreferrer")},loading:o}),d?(0,l.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,l.jsx)("span",{className:"material-symbols-outlined mr-2 align-[-5px]",children:"error"}),d]}):null,s?.qualityNotes?.length?(0,l.jsx)(E,{notes:s.qualityNotes}):null,(0,l.jsx)("div",{className:"flex flex-wrap gap-2 rounded-2xl border border-border bg-surface p-2",children:a.map(e=>(0,l.jsxs)("button",{onClick:()=>m(e.value),className:b("flex items-center gap-2 rounded-xl px-3 py-2 text-sm font-medium transition",x===e.value?"bg-primary text-white shadow-sm":"text-text-muted hover:bg-background hover:text-text-main"),children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:e.icon}),e.label]},e.value))}),o&&!s?(0,l.jsx)(f,{}):null,!o&&s&&s.overview?.requests===0&&0===(s.promptLogs?.total||0)?(0,l.jsx)(T,{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,s?(0,l.jsxs)(l.Fragment,{children:["overview"===x?(0,l.jsx)(_,{data:s}):null,"apiKeys"===x?(0,l.jsx)(U,{data:s}):null,"clients"===x?(0,l.jsx)(O,{data:s}):null,"sources"===x?(0,l.jsx)(V,{data:s}):null,"providers"===x?(0,l.jsx)(D,{data:s}):null,"experience"===x?(0,l.jsx)(H,{data:s}):null,"errors"===x?(0,l.jsx)(B,{data:s}):null,"raw"===x?(0,l.jsx)(G,{data:s}):null]}):null]})}}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=39944)),_N_E=e.O()}]);
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6607],{2276:(e,s,a)=>{Promise.resolve().then(a.bind(a,55987))},55987:(e,s,a)=>{"use strict";a.d(s,{default:()=>x});var t=a(95155),l=a(12115),r=a(3534),o=a(28777),n=a(52679),i=a(38719),d=a(35497);let c={enabled:!1,type:"mysql",host:"",port:"",database:"",username:"",password:"",ssl:!1,createDatabase:!1,logClientRequest:!0,logSourceRequest:!0,logTargetRequest:!0,logProviderResponse:!1,logErrors:!0,retentionDays:30};function g({label:e,value:s,onChange:a,type:l="text",placeholder:r="",disabled:o=!1}){return(0,t.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,t.jsx)("span",{className:"text-text-muted",children:e}),(0,t.jsx)("input",{type:l,value:s||"",placeholder:r,disabled:o,onChange:e=>a(e.target.value),className:"w-full rounded border border-border bg-surface px-2 py-1.5 text-xs text-text-main focus:outline-none focus:ring-1 focus:ring-primary/50 disabled:opacity-50"})]})}function u({label:e,checked:s,onChange:a,disabled:l=!1}){return(0,t.jsxs)("label",{className:"flex items-center gap-2 text-xs text-text-main",children:[(0,t.jsx)("input",{type:"checkbox",checked:!!s,disabled:l,onChange:e=>a(e.target.checked)}),e]})}function p(){let[e,s]=(0,l.useState)(c),[a,r]=(0,l.useState)(!1),[o,n]=(0,l.useState)(null),[i,p]=(0,l.useState)(null),x=e=>s(s=>({...s,...e})),b=async()=>{r(!0),p(null);try{let e=await fetch("/api/cli-tools/antigravity-mitm/prompt-log-db"),a=await e.json();if(!e.ok)throw Error(a.error||"Failed to load config");s({...c,...a.config||{}})}catch(e){p(e.message||"Failed to load config")}finally{r(!1)}};(0,l.useEffect)(()=>{b()},[]);let h=async()=>{r(!0),p(null),n(null);try{let a=await fetch("/api/cli-tools/antigravity-mitm/prompt-log-db",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({config:e})}),t=await a.json();if(!a.ok)throw Error(t.error||"Failed to save config");s({...c,...t.config||{}}),n("Saved")}catch(e){p(e.message||"Failed to save config")}finally{r(!1)}},m=async s=>{r(!0),p(null),n(null);try{let a=await fetch("/api/cli-tools/antigravity-mitm/prompt-log-db",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:s,config:e})}),t=await a.json();if(!a.ok)throw Error(t.error||"Action failed");n(t.message||t.init?.message||"OK")}catch(e){p(e.message||"Action failed")}finally{r(!1)}},y="postgres"===e.type||"mysql"===e.type;return(0,t.jsx)(d.Zp,{title:"Prompt Log Database",subtitle:"Store MITM/Copilot prompt logs in a queryable database",icon:"database",children:(0,t.jsxs)("div",{className:"space-y-4",children:[(0,t.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,t.jsx)(d.Ex,{variant:e.enabled?"success":"default",children:e.enabled?"Enabled":"Disabled"}),(0,t.jsx)("span",{className:"text-xs text-text-muted",children:"File logs still remain available under DATA_DIR/logs/requests."})]}),(0,t.jsx)("div",{className:"rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-3 text-xs text-yellow-700 dark:text-yellow-300",children:"Prompt logs may contain source code, selected code, internal URLs, and user prompts. Protect the database and set retention according to your policy."}),(0,t.jsxs)("div",{className:"grid gap-3 md:grid-cols-2",children:[(0,t.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,t.jsx)("span",{className:"text-text-muted",children:"Database type"}),(0,t.jsxs)("select",{value:e.type,disabled:a,onChange:s=>{let a=s.target.value;x({type:a,port:"postgres"===a?e.port||"5432":"mysql"===a?e.port||"3306":e.port})},className:"w-full rounded border border-border bg-surface px-2 py-1.5 text-xs text-text-main focus:outline-none focus:ring-1 focus:ring-primary/50",children:[(0,t.jsx)("option",{value:"mysql",children:"MySQL / MariaDB"}),(0,t.jsx)("option",{value:"postgres",children:"PostgreSQL"})]})]}),(0,t.jsx)(g,{label:"Retention days",type:"number",value:String(e.retentionDays||30),onChange:e=>x({retentionDays:Number(e)||30}),disabled:a})]}),y&&(0,t.jsxs)("div",{className:"grid gap-3 md:grid-cols-2",children:[(0,t.jsx)(g,{label:"Host",value:e.host,placeholder:"127.0.0.1",onChange:e=>x({host:e}),disabled:a}),(0,t.jsx)(g,{label:"Port",value:e.port,placeholder:"postgres"===e.type?"5432":"3306",onChange:e=>x({port:e}),disabled:a}),(0,t.jsx)(g,{label:"Database",value:e.database,placeholder:"bluerouter_logs",onChange:e=>x({database:e}),disabled:a}),(0,t.jsx)(g,{label:"Username",value:e.username,placeholder:"bluerouter",onChange:e=>x({username:e}),disabled:a}),(0,t.jsx)(g,{label:"Password",type:"password",value:e.password,placeholder:"Leave as ******** to keep existing password",onChange:e=>x({password:e}),disabled:a}),(0,t.jsxs)("div",{className:"flex flex-col justify-end gap-2",children:[(0,t.jsx)(u,{label:"Use SSL",checked:e.ssl,onChange:e=>x({ssl:e}),disabled:a}),(0,t.jsx)(u,{label:"Create database if missing",checked:e.createDatabase,onChange:e=>x({createDatabase:e}),disabled:a})]})]}),(0,t.jsxs)("div",{className:"grid gap-2 rounded-lg border border-border bg-surface/40 p-3 md:grid-cols-2",children:[(0,t.jsx)(u,{label:"Enable database prompt logging",checked:e.enabled,onChange:e=>x({enabled:e}),disabled:a}),(0,t.jsx)(u,{label:"Log client request",checked:e.logClientRequest,onChange:e=>x({logClientRequest:e}),disabled:a}),(0,t.jsx)(u,{label:"Log normalized/source request",checked:e.logSourceRequest,onChange:e=>x({logSourceRequest:e}),disabled:a}),(0,t.jsx)(u,{label:"Log target/provider request",checked:e.logTargetRequest,onChange:e=>x({logTargetRequest:e}),disabled:a}),(0,t.jsx)(u,{label:"Log provider response",checked:e.logProviderResponse,onChange:e=>x({logProviderResponse:e}),disabled:a}),(0,t.jsx)(u,{label:"Log errors",checked:e.logErrors,onChange:e=>x({logErrors:e}),disabled:a})]}),y&&(0,t.jsxs)("div",{className:"rounded-lg border border-blue-500/30 bg-blue-500/10 p-3 text-xs text-blue-700 dark:text-blue-300",children:["Prompt logs now support MySQL/MariaDB and PostgreSQL only. MySQL/MariaDB requires ",(0,t.jsx)("code",{children:"mysql2"}),"; PostgreSQL requires ",(0,t.jsx)("code",{children:"pg"}),"."]}),o&&(0,t.jsx)("div",{className:"rounded-lg border border-green-500/30 bg-green-500/10 p-2 text-xs text-green-600",children:o}),i&&(0,t.jsx)("div",{className:"rounded-lg border border-red-500/30 bg-red-500/10 p-2 text-xs text-red-500",children:i}),(0,t.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,t.jsx)(d.$n,{size:"sm",variant:"secondary",onClick:b,loading:a,children:"Reload"}),(0,t.jsx)(d.$n,{size:"sm",variant:"secondary",onClick:()=>m("test"),loading:a,children:"Test connection"}),(0,t.jsx)(d.$n,{size:"sm",variant:"secondary",onClick:()=>m("init"),loading:a,children:"Initialize schema"}),(0,t.jsx)(d.$n,{size:"sm",onClick:h,loading:a,children:"Save"}),(0,t.jsx)(d.$n,{size:"sm",variant:"success",onClick:()=>m("save-and-init"),loading:a,children:"Save & initialize"})]})]})})}function x(){let[e,s]=(0,l.useState)([]),[a,d]=(0,l.useState)([]),[c,g]=(0,l.useState)({}),[u,x]=(0,l.useState)(!1),[b,h]=(0,l.useState)(null),[m,y]=(0,l.useState)({running:!1,certExists:!1,dnsStatus:{},hasCachedPassword:!1});(0,l.useEffect)(()=>{f(),j(),v(),w()},[]);let f=async()=>{try{let e=await fetch("/api/providers");if(e.ok){let a=await e.json();s(a.connections||[])}}catch{}},j=async()=>{try{let e=await fetch("/api/keys");if(e.ok){let s=await e.json();d(s.keys||[])}}catch{}},v=async()=>{try{let e=await fetch("/api/models/alias");if(e.ok){let s=await e.json();g(s.aliases||{})}}catch{}},w=async()=>{try{let e=await fetch("/api/settings");if(e.ok){let s=await e.json();x(s.cloudEnabled||!1)}}catch{}},C=()=>e.filter(e=>!1!==e.isActive),S=Object.entries(r.wn);return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)("div",{className:"rounded-lg border border-yellow-500/30 bg-yellow-500/10 p-4 text-sm text-yellow-700 dark:text-yellow-300",children:[(0,t.jsx)("span",{className:"material-symbols-rounded align-middle text-base",children:"warning"})," ","⚠️ MITM intercepts HTTPS traffic of IDE tools (Antigravity, GitHub Copilot, Kiro) via local CA to redirect requests to your providers. May violate ToS → account ban. Use at your own risk."]}),(0,t.jsx)(i.tA,{apiKeys:a,cloudEnabled:u,onStatusChange:y}),(0,t.jsx)(i.k0,{serverRunning:m.running,onChanged:e=>y(s=>({...s,certExists:e?.certExists??s.certExists}))}),(0,t.jsx)(p,{}),S.map(([e,s])=>(0,t.jsx)(i.kn,{tool:{...s,id:e},isExpanded:b===e,onToggle:()=>h(b===e?null:e),serverRunning:m.running,dnsActive:m.dnsStatus?.[e]||!1,hasCachedPassword:m.hasCachedPassword||!1,needsSudoPassword:!1!==m.needsSudoPassword,isWin:!0===m.isWin,apiKeys:a,activeProviders:C(),hasActiveProviders:C().some(e=>(0,o.KC)(e.provider).length>0||(0,n.mq)(e.provider)||(0,n.gb)(e.provider)),modelAliases:c,cloudEnabled:u,onDnsChange:e=>y(s=>({...s,dnsStatus:e.dnsStatus??s.dnsStatus}))},e))]})}}},e=>{e.O(0,[2574,3862,2649,5772,1321,5497,4404,8441,3794,7358],()=>e(e.s=2276)),_N_E=e.O()}]);
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7692],{55478:(e,t,r)=>{"use strict";r.d(t,{default:()=>g});var s=r(95155),a=r(12115);let l={client:"Client request",source:"Source request",openai:"OpenAI normalized",target:"Provider request",provider_response:"Provider response",error:"Error"},o={client:"bg-blue-500/10 text-blue-600 border-blue-500/20",source:"bg-cyan-500/10 text-cyan-600 border-cyan-500/20",openai:"bg-purple-500/10 text-purple-600 border-purple-500/20",target:"bg-orange-500/10 text-orange-600 border-orange-500/20",provider_response:"bg-green-500/10 text-green-600 border-green-500/20",error:"bg-red-500/10 text-red-600 border-red-500/20"};function d(e){if(!e)return"-";try{let t=function(e){if(!e)return"";if(e instanceof Date)return e.toISOString();let t=String(e).trim();if(!t)return"";let r=t.replace(" ","T");return/(?:Z|[+-]\d{2}:?\d{2})$/i.test(r)?r:`${r}Z`}(e),r=new Date(t);if(Number.isNaN(r.getTime()))return String(e);return r.toLocaleString("vi-VN",{timeZone:"Asia/Ho_Chi_Minh",day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}catch{return e}}function n(e,t=240){let r=String(e||"").replace(/\s+/g," ").trim();return r.length>t?`${r.slice(0,t)}...`:r}function i(e){let t=String(e||"").trim();if(!t)return"";try{return new URL(t).hostname||""}catch{return t.replace(/^https?:\/\//,"").replace(/\/.*$/,"").replace(/:\d+$/,"")}}function x(e){return e?.provider_name||e?.provider_label||e?.provider_id||e?.provider||i(e?.provider_url)||i(e?.endpoint)||""}function c(e){if(e?.display_model)return e.display_model;let t=e?.model||"-",r=x(e);return!r||"-"===t||String(t).startsWith(`${r}/`)?t:`${r}/${t}`}function m({value:e}){let t=function(e){if(!e)return null;if("object"==typeof e)return e;try{return JSON.parse(e)}catch{return null}}(e),r=t?JSON.stringify(t,null,2):String(e||"");return(0,s.jsx)("pre",{className:"max-h-[42vh] max-w-full overflow-auto whitespace-pre-wrap break-words rounded-2xl bg-zinc-950 p-4 text-xs leading-relaxed text-zinc-100 shadow-inner [overflow-wrap:anywhere]",children:r||"No JSON"})}function p({value:e,empty:t="No content"}){return(0,s.jsx)("pre",{className:"max-h-[42vh] max-w-full overflow-auto whitespace-pre-wrap break-words rounded-2xl border border-zinc-200 bg-white p-4 font-mono text-xs leading-relaxed text-zinc-950 shadow-sm [overflow-wrap:anywhere] dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100",children:e||t})}function u({label:e,value:t}){return(0,s.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-4 shadow-sm",children:[(0,s.jsx)("div",{className:"text-xs uppercase tracking-wide text-text-muted",children:e}),(0,s.jsx)("div",{className:"mt-1 text-2xl font-semibold text-text-main",children:t})]})}function b({stage:e}){let t=o[e]||"bg-surface text-text-main border-border";return(0,s.jsx)("span",{className:`inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-medium ${t}`,children:l[e]||e||"-"})}function h({label:e,value:t}){return(0,s.jsxs)("div",{className:"rounded-2xl border border-zinc-200 bg-white p-3 shadow-sm dark:border-zinc-700 dark:bg-zinc-950",children:[(0,s.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wide text-text-muted",children:e}),(0,s.jsx)("pre",{className:"mt-2 whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-text-main",children:t||"-"})]})}function g(){let[e,t]=(0,a.useState)({keyword:"",model:"",stage:"",sourceTool:"",clientIp:"",sessionId:"",dateFrom:"",dateTo:"",limit:"50",offset:"0"}),[r,o]=(0,a.useState)([]),[i,g]=(0,a.useState)([]),[f,j]=(0,a.useState)([]),[N,v]=(0,a.useState)(0),[w,y]=(0,a.useState)(null),[k,_]=(0,a.useState)(""),[z,S]=(0,a.useState)(""),[C,I]=(0,a.useState)(!1),[T,P]=(0,a.useState)(null),[E,M]=(0,a.useState)("prompt"),$=(0,a.useMemo)(()=>{let t=Number(e.limit||50);return Math.floor(Number(e.offset||0)/t)+1},[e.limit,e.offset]),D=(0,a.useCallback)(async()=>{I(!0),S(""),_("");try{let t=new URLSearchParams;Object.entries(e).forEach(([e,r])=>{String(r||"").trim()&&t.set(e,String(r).trim())});let r=await fetch(`/api/dashboard/prompt-logs?${t}`),s=await r.json();if(!r.ok)throw Error(s.error||"Failed to load prompt logs");o(s.rows||[]),g(s.models||[]),j(s.stages||[]),v(s.total||0),y(s.dbInfo||null),s.disabled&&_("Database prompt logging is disabled. Enable it in Dashboard -> MITM -> Prompt Log Database."),s.missing&&_("Prompt log database/table has no data yet, or the configured database is not initialized.")}catch(e){S(e.message||"Failed to load prompt logs")}finally{I(!1)}},[e]);(0,a.useEffect)(()=>{D()},[D]);let F=e=>{t(t=>({...t,...e,offset:void 0!==e.offset?e.offset:"0"}))},O=async e=>{S("");try{let t=await fetch(`/api/dashboard/prompt-logs/${encodeURIComponent(e)}`),r=await t.json();if(!t.ok)throw Error(r.error||"Failed to load detail");P(r.row),M("prompt")}catch(e){S(e.message||"Failed to load detail")}},q=async e=>{await navigator.clipboard.writeText(String(e||""))},L=async()=>{T?.id&&confirm("Delete this prompt log row?")&&(await fetch(`/api/dashboard/prompt-logs/${encodeURIComponent(T.id)}`,{method:"DELETE"})).ok&&(P(null),D())};return(0,s.jsxs)("div",{className:"flex w-full max-w-none flex-col gap-5 p-3 md:p-4 lg:p-6",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-2 md:flex-row md:items-end md:justify-between",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h1",{className:"text-2xl font-semibold text-text-main",children:"Prompt Logs"}),(0,s.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Search Copilot/MITM prompts across the currently configured prompt log database."})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("a",{href:"/dashboard/mitm",className:"rounded-xl border border-border px-3 py-2 text-sm hover:bg-surface",children:"MITM Settings"}),(0,s.jsx)("button",{onClick:D,disabled:C,className:"rounded-xl bg-primary px-3 py-2 text-sm font-medium text-white disabled:opacity-50",children:C?"Loading...":"Refresh"})]})]}),k&&(0,s.jsx)("div",{className:"rounded-2xl border border-yellow-500/30 bg-yellow-500/10 p-4 text-sm text-yellow-700 dark:text-yellow-300",children:k}),z&&(0,s.jsx)("div",{className:"rounded-2xl border border-red-500/30 bg-red-500/10 p-4 text-sm text-red-500",children:z}),(0,s.jsxs)("div",{className:"grid gap-4 md:grid-cols-4",children:[(0,s.jsx)(u,{label:"Matching rows",value:N}),(0,s.jsx)(u,{label:"Loaded rows",value:r.length}),(0,s.jsx)(u,{label:"Page",value:$}),(0,s.jsx)(u,{label:"Database",value:w?.type||"-"})]}),w&&(0,s.jsxs)("div",{className:"rounded-2xl border border-border bg-surface p-3 text-xs text-text-muted",children:["DB: ",(0,s.jsx)("code",{children:w.type}),w.host?(0,s.jsxs)(s.Fragment,{children:[" ","\xb7 Host: ",(0,s.jsx)("code",{children:w.host})]}):null,w.database?(0,s.jsxs)(s.Fragment,{children:[" ","\xb7 Database: ",(0,s.jsx)("code",{children:w.database})]}):null]}),(0,s.jsx)("div",{className:"rounded-2xl border border-border bg-surface p-4 shadow-sm",children:(0,s.jsxs)("div",{className:"grid gap-3 md:grid-cols-4 xl:grid-cols-6",children:[(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Keyword"}),(0,s.jsx)("input",{value:e.keyword,onChange:e=>F({keyword:e.target.value}),placeholder:"prompt, code, model, error...",className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Model"}),(0,s.jsxs)("select",{value:e.model,onChange:e=>F({model:e.target.value}),className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30",children:[(0,s.jsx)("option",{value:"",children:"All models"}),i.map(e=>(0,s.jsx)("option",{value:e,children:e},e))]})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Stage"}),(0,s.jsxs)("select",{value:e.stage,onChange:e=>F({stage:e.target.value}),className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30",children:[(0,s.jsx)("option",{value:"",children:"All stages"}),f.map(e=>(0,s.jsx)("option",{value:e,children:l[e]||e},e))]})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Tool"}),(0,s.jsx)("input",{value:e.sourceTool,onChange:e=>F({sourceTool:e.target.value}),placeholder:"copilot, antigravity...",className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Client IP"}),(0,s.jsx)("input",{value:e.clientIp,onChange:e=>F({clientIp:e.target.value}),placeholder:"172.16.253.1",className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Session ID"}),(0,s.jsx)("input",{value:e.sessionId,onChange:e=>F({sessionId:e.target.value}),placeholder:"session id",className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"From"}),(0,s.jsx)("input",{type:"datetime-local",value:e.dateFrom,onChange:e=>F({dateFrom:e.target.value}),className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"To"}),(0,s.jsx)("input",{type:"datetime-local",value:e.dateTo,onChange:e=>F({dateTo:e.target.value}),className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30"})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs",children:[(0,s.jsx)("span",{className:"text-text-muted",children:"Limit"}),(0,s.jsxs)("select",{value:e.limit,onChange:e=>F({limit:e.target.value}),className:"rounded-xl border border-border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary/30",children:[(0,s.jsx)("option",{value:"25",children:"25"}),(0,s.jsx)("option",{value:"50",children:"50"}),(0,s.jsx)("option",{value:"100",children:"100"}),(0,s.jsx)("option",{value:"200",children:"200"})]})]}),(0,s.jsxs)("div",{className:"flex items-end gap-2",children:[(0,s.jsx)("button",{onClick:()=>t({keyword:"",model:"",stage:"",sourceTool:"",clientIp:"",sessionId:"",dateFrom:"",dateTo:"",limit:"50",offset:"0"}),className:"rounded-xl border border-border px-3 py-2 text-sm hover:bg-background",children:"Reset"}),(0,s.jsx)("button",{onClick:D,className:"rounded-xl bg-primary px-3 py-2 text-sm font-medium text-white",children:"Search"})]})]})}),(0,s.jsxs)("div",{className:"overflow-hidden rounded-2xl border border-border bg-surface shadow-sm",children:[(0,s.jsx)("div",{className:"overflow-x-auto",children:(0,s.jsxs)("table",{className:"w-full min-w-[1450px] text-left text-sm",children:[(0,s.jsx)("thead",{className:"border-b border-border bg-background/60 text-xs uppercase tracking-wide text-text-muted",children:(0,s.jsxs)("tr",{children:[(0,s.jsx)("th",{className:"w-[150px] px-4 py-3",children:"Time"}),(0,s.jsx)("th",{className:"w-[130px] px-4 py-3",children:"Stage"}),(0,s.jsx)("th",{className:"w-[150px] px-4 py-3",children:"Tool"}),(0,s.jsx)("th",{className:"w-[130px] px-4 py-3",children:"Client IP"}),(0,s.jsx)("th",{className:"w-[110px] px-4 py-3",children:"Model"}),(0,s.jsx)("th",{className:"w-[190px] px-4 py-3",children:"Session"}),(0,s.jsx)("th",{className:"w-[390px] px-4 py-3",children:"Prompt preview"}),(0,s.jsx)("th",{className:"w-[130px] px-4 py-3",children:"Status/Error"}),(0,s.jsx)("th",{className:"sticky right-0 z-20 w-[95px] bg-background/95 px-4 py-3 text-right shadow-[-8px_0_12px_-12px_rgba(0,0,0,0.45)]",children:"Action"})]})}),(0,s.jsxs)("tbody",{children:[0===r.length&&(0,s.jsx)("tr",{children:(0,s.jsx)("td",{colSpan:9,className:"px-4 py-10 text-center text-text-muted",children:"No prompt logs found."})}),r.map(e=>(0,s.jsxs)("tr",{className:"border-b border-border/70 hover:bg-background/50",children:[(0,s.jsx)("td",{className:"whitespace-nowrap px-4 py-3 text-xs text-text-muted",children:d(e.created_at)}),(0,s.jsx)("td",{className:"px-4 py-3",children:(0,s.jsx)(b,{stage:e.stage})}),(0,s.jsx)("td",{className:"px-4 py-3",children:(0,s.jsx)("span",{className:"inline-flex max-w-[180px] items-center truncate rounded-full border border-border bg-surface/70 px-2.5 py-1 text-xs font-medium text-text-main",children:e.source_tool_label||e.source_tool||e.source_format||"-"})}),(0,s.jsx)("td",{className:"max-w-[150px] truncate px-4 py-3 font-mono text-xs text-text-muted",children:e.client_ip||"-"}),(0,s.jsx)("td",{className:"max-w-[260px] truncate px-4 py-3 font-mono text-xs",title:c(e),children:c(e)}),(0,s.jsx)("td",{className:"max-w-[180px] truncate px-4 py-3 font-mono text-xs text-text-muted",children:e.session_id||"-"}),(0,s.jsx)("td",{className:"min-w-[360px] px-4 py-3 text-xs",children:n(e.prompt_preview,420)||(0,s.jsx)("span",{className:"text-text-muted",children:"No prompt text"})}),(0,s.jsx)("td",{className:"max-w-[220px] px-4 py-3 text-xs",children:e.error_text?(0,s.jsx)("span",{className:"text-red-500",children:n(e.error_text,160)}):e.status_code||(0,s.jsx)("span",{className:"text-text-muted",children:"-"})}),(0,s.jsx)("td",{className:"sticky right-0 z-10 bg-surface px-4 py-3 text-right shadow-[-8px_0_12px_-12px_rgba(0,0,0,0.35)]",children:(0,s.jsx)("button",{onClick:()=>O(e.id),className:"rounded-lg bg-primary px-3 py-1.5 text-xs font-medium text-white",children:"View"})})]},e.id))]})]})}),(0,s.jsxs)("div",{className:"flex items-center justify-between border-t border-border p-3 text-sm",children:[(0,s.jsxs)("div",{className:"text-text-muted",children:["Showing ",r.length," of ",N,". Page ",$,"."]}),(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("button",{onClick:()=>{let r=Number(e.limit||50),s=Number(e.offset||0);t(e=>({...e,offset:String(Math.max(0,s-r))}))},disabled:0>=Number(e.offset||0),className:"rounded-xl border border-border px-3 py-1.5 disabled:opacity-50",children:"Previous"}),(0,s.jsx)("button",{onClick:()=>{let r=Number(e.limit||50),s=Number(e.offset||0);s+r>=N||t(e=>({...e,offset:String(s+r)}))},disabled:Number(e.offset||0)+Number(e.limit||50)>=N,className:"rounded-xl border border-border px-3 py-1.5 disabled:opacity-50",children:"Next"})]})]})]}),T&&(0,s.jsx)("div",{className:"fixed inset-0 z-[99999] isolate flex items-start justify-center overflow-hidden bg-black/60 p-3 pt-8 md:p-5 md:pt-10",children:(0,s.jsxs)("div",{className:"relative z-[100000] flex h-[78vh] min-h-[520px] max-h-[760px] w-full max-w-[1080px] flex-col overflow-hidden rounded-3xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-700 dark:bg-zinc-950",children:[(0,s.jsxs)("div",{className:"flex flex-none items-start justify-between gap-4 border-b border-zinc-200 bg-white px-3 py-2 dark:border-zinc-700 dark:bg-zinc-950",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Prompt Log Detail"}),(0,s.jsx)(b,{stage:T.stage})]}),(0,s.jsxs)("div",{className:"mt-1 truncate text-xs text-text-muted",children:[d(T.created_at)," \xb7 ",c(T)," \xb7"," ",T.session_id||"-"]})]}),(0,s.jsx)("button",{onClick:()=>P(null),className:"rounded-xl border border-zinc-200 bg-white px-3 py-2 text-sm font-medium text-zinc-900 shadow-sm hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:hover:bg-zinc-800",children:"Close"})]}),(0,s.jsxs)("div",{className:"grid min-h-0 flex-1 grid-cols-1 overflow-hidden bg-zinc-100 dark:bg-zinc-900 lg:grid-cols-[260px_minmax(0,1fr)]",children:[(0,s.jsx)("aside",{className:"min-h-0 overflow-y-auto border-b border-zinc-200 bg-zinc-100 p-3 dark:border-zinc-700 dark:bg-zinc-900 lg:border-b-0 lg:border-r",children:(0,s.jsxs)("div",{className:"grid gap-3",children:[(0,s.jsx)(h,{label:"ID",value:T.id}),(0,s.jsx)(h,{label:"Session",value:T.session_id}),(0,s.jsx)(h,{label:"Model",value:c(T)}),(0,s.jsx)(h,{label:"Provider",value:x(T)||T.provider_url||T.endpoint}),(0,s.jsx)(h,{label:"Source Tool",value:T.source_tool_label||T.source_tool||T.source_format}),(0,s.jsx)(h,{label:"Source Host",value:T.source_host}),(0,s.jsx)(h,{label:"Client IP",value:T.client_ip}),(0,s.jsx)(h,{label:"Client Port",value:T.client_port}),(0,s.jsx)(h,{label:"Client Host",value:T.client_host}),(0,s.jsx)(h,{label:"User Agent",value:T.client_user_agent}),(0,s.jsx)(h,{label:"Endpoint",value:T.endpoint||T.provider_url}),(0,s.jsx)(h,{label:"Source -> Target",value:`${T.source_format||"-"} -> ${T.target_format||"-"}`}),(0,s.jsx)(h,{label:"Status / Error",value:T.error_text||T.status_code||"-"}),(0,s.jsxs)("div",{className:"grid gap-2 pt-2",children:[(0,s.jsx)("button",{onClick:()=>q(T.prompt_text),className:"rounded-xl border border-zinc-200 bg-white px-3 py-2 text-sm font-medium text-zinc-900 shadow-sm hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:hover:bg-zinc-800",children:"Copy prompt"}),(0,s.jsx)("button",{onClick:()=>q(T.full_request_json),className:"rounded-xl border border-zinc-200 bg-white px-3 py-2 text-sm font-medium text-zinc-900 shadow-sm hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:hover:bg-zinc-800",children:"Copy request JSON"}),(0,s.jsx)("button",{onClick:L,className:"rounded-xl border border-red-500/40 bg-red-500/10 px-3 py-2 text-sm font-medium text-red-500 shadow-inner hover:bg-red-500/20",children:"Delete row"})]})]})}),(0,s.jsxs)("main",{className:"flex min-h-0 flex-col overflow-hidden bg-zinc-50 dark:bg-zinc-950",children:[(0,s.jsx)("div",{className:"flex flex-none gap-2 overflow-x-auto border-b border-zinc-200 bg-white px-3 py-2 dark:border-zinc-700 dark:bg-zinc-950",children:[["prompt","Prompt"],["request","Request JSON"],["response","Response"],["meta","Metadata"]].map(([e,t])=>(0,s.jsx)("button",{onClick:()=>M(e),className:`whitespace-nowrap rounded-xl px-3 py-2 text-sm ${E===e?"bg-primary text-white shadow-sm":"border border-border bg-surface text-text-main hover:bg-background"}`,children:t},e))}),(0,s.jsxs)("div",{className:"min-h-0 flex-1 overflow-y-auto bg-zinc-50 p-3 dark:bg-zinc-950",children:["prompt"===E&&(0,s.jsxs)("section",{children:[(0,s.jsx)("h3",{className:"mb-2 text-sm font-semibold text-text-main",children:"Extracted prompt text"}),(0,s.jsx)(p,{value:T.prompt_text,empty:"No prompt text"})]}),"request"===E&&(0,s.jsxs)("section",{children:[(0,s.jsx)("h3",{className:"mb-2 text-sm font-semibold text-text-main",children:"Full request JSON"}),(0,s.jsx)(m,{value:T.full_request_json})]}),"response"===E&&(0,s.jsxs)("section",{children:[(0,s.jsx)("h3",{className:"mb-2 text-sm font-semibold text-text-main",children:"Response text"}),(0,s.jsx)(p,{value:T.response_text,empty:"No response text stored for this stage"})]}),"meta"===E&&(0,s.jsxs)("section",{children:[(0,s.jsx)("h3",{className:"mb-2 text-sm font-semibold text-text-main",children:"Metadata JSON"}),(0,s.jsx)(m,{value:T.meta_json})]})]})]})]})]})})]})}},79705:(e,t,r)=>{Promise.resolve().then(r.bind(r,55478))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=79705)),_N_E=e.O()}]);
package/app/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bluerouter-app",
3
- "version": "2.0.87",
3
+ "version": "2.0.89",
4
4
  "description": "Router web dashboard",
5
5
  "private": false,
6
6
  "scripts": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jheavenknows/bluerouter",
3
- "version": "2.0.87",
3
+ "version": "2.0.89",
4
4
  "description": "Bluerouter CLI - Start and manage Bluerouter server",
5
5
  "bin": {
6
6
  "bluerouter": "./cli.js"
@@ -1,81 +0,0 @@
1
- "use strict";exports.id=6050,exports.ids=[6050],exports.modules={50122:(a,b,c)=>{c.d(b,{k:()=>e});let d=[];for(let a=0;a<256;++a)d.push((a+256).toString(16).slice(1));function e(a,b=0){return(d[a[b+0]]+d[a[b+1]]+d[a[b+2]]+d[a[b+3]]+"-"+d[a[b+4]]+d[a[b+5]]+"-"+d[a[b+6]]+d[a[b+7]]+"-"+d[a[b+8]]+d[a[b+9]]+"-"+d[a[b+10]]+d[a[b+11]]+d[a[b+12]]+d[a[b+13]]+d[a[b+14]]+d[a[b+15]]).toLowerCase()}},94755:(a,b,c)=>{c.d(b,{A:()=>i});var d=c(77598);let e={randomUUID:d.randomUUID},f=new Uint8Array(256),g=f.length;var h=c(50122);let i=function(a,b,c){if(e.randomUUID&&!b&&!a)return e.randomUUID();var i=a,j=c;let k=(i=i||{}).random??i.rng?.()??(g>f.length-16&&((0,d.randomFillSync)(f),g=0),f.slice(g,g+=16));if(k.length<16)throw Error("Random bytes length must be >= 16");if(k[6]=15&k[6]|64,k[8]=63&k[8]|128,b){if((j=j||0)<0||j+16>b.length)throw RangeError(`UUID byte range ${j}:${j+15} is out of buffer bounds`);for(let a=0;a<16;++a)b[j+a]=k[a];return b}return(0,h.k)(k)}},97242:(a,b,c)=>{c.d(b,{DU:()=>z,Ws:()=>A,_3:()=>C,nv:()=>B});var d=c(29021),e=c.n(d),f=c(33873),g=c.n(f),h=c(45903);let i=new Set;function j(a,b,c=null){let d=Number(a);if(!Number.isFinite(d)||d<0)return b;let e=Math.floor(d);return c?Math.min(e,c):e}function k(a){return String(a||"").trim()}async function l(){let a=(0,h.I6)(await (0,h.L7)());return a.sqlitePath||(a.sqlitePath=g().join(process.env.DATA_DIR||"/var/lib/bluerouter","logs","promptLogs.sqlite")),a}async function m(a){try{let b=await Promise.resolve().then(c.t.bind(c,87550,23)),d=new(b.default||b)(a);return d.pragma("busy_timeout = 5000"),{all:(a,b={})=>d.prepare(a).all(b),get:(a,b={})=>d.prepare(a).get(b),run:(a,b={})=>d.prepare(a).run(b),close:()=>d.close()}}catch{let b=new(await Promise.resolve().then(c.t.bind(c,80099,23))).DatabaseSync(a);return b.exec("PRAGMA busy_timeout = 5000"),{all:(a,c={})=>b.prepare(a).all(c),get:(a,c={})=>b.prepare(a).get(c),run:(a,c={})=>b.prepare(a).run(c),close:()=>b.close()}}}async function n(a){let b=new(await Promise.resolve().then(c.bind(c,64939))).Client({host:a.host,port:Number(a.port||5432),database:a.database,user:a.username,password:a.password,ssl:!!a.ssl&&{rejectUnauthorized:!1}});return await b.connect(),{query:async(a,c=[])=>(await b.query(a,c)).rows,queryOne:async(a,c=[])=>(await b.query(a,c)).rows[0]||null,async exec(a,c=[]){await b.query(a,c)},async close(){await b.end()}}}async function o(a){let b=await c.e(8491).then(c.t.bind(c,38491,19)),d=await b.createConnection({host:a.host,port:Number(a.port||3306),database:a.database,user:a.username,password:a.password,ssl:a.ssl?{}:void 0,dateStrings:!0,connectTimeout:3e3});return{async query(a,b=[]){let[c]=await d.query(a,b);return c},async queryOne(a,b=[]){let[c]=await d.query(a,b);return c[0]||null},async exec(a,b=[]){await d.query(a,b)},async close(){await d.end()}}}async function p(a,b){if(!b||b.full_request_json)return b;let c=function(a={}){return String(a.payload_hash||function(a){if(!a)return{};if("object"==typeof a)return a;try{return JSON.parse(a)}catch{return{}}}(a.meta_json).payloadHash||"").trim()}(b);if(!c)return b;try{let d=await a.queryOne("SELECT COUNT(1) AS count FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prompt_log_payloads'");if(0===Number(d?.count||0))return b;let e=await a.queryOne("SELECT payload_json FROM prompt_log_payloads WHERE payload_hash = ?",[c]);if(!e)return b;let f=e.payload_json;return{...b,full_request_json:"string"==typeof f?f:JSON.stringify(f)}}catch{return b}}async function q(a){if(!e().existsSync(a.sqlitePath))return;let b=await m(a.sqlitePath);try{if(!b.get("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'prompt_logs'"))return;for(let a of["CREATE INDEX IF NOT EXISTS idx_prompt_logs_created_id ON prompt_logs(created_at DESC, id)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_stage_created_at ON prompt_logs(stage, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_model_created_at ON prompt_logs(model, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_display_model_created_at ON prompt_logs(display_model, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_session_created_at ON prompt_logs(session_id, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_client_ip_created_at ON prompt_logs(client_ip, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_source_tool_created_at ON prompt_logs(source_tool, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_connection_created_at ON prompt_logs(connection_id, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_account_created_at ON prompt_logs(account_name, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_provider_created_at ON prompt_logs(provider, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_status_created_at ON prompt_logs(status_code, created_at DESC)"])b.run(a)}finally{b.close()}}async function r(a){let b=await n(a);try{for(let a of["CREATE INDEX IF NOT EXISTS idx_prompt_logs_created_id ON prompt_logs (created_at DESC, id)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_stage_created_at ON prompt_logs (stage, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_model_created_at ON prompt_logs (model, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_display_model_created_at ON prompt_logs (display_model, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_session_created_at ON prompt_logs (session_id, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_client_ip_created_at ON prompt_logs (client_ip, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_source_tool_created_at ON prompt_logs (source_tool, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_connection_created_at ON prompt_logs (connection_id, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_account_created_at ON prompt_logs (account_name, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_provider_created_at ON prompt_logs (provider, created_at DESC)","CREATE INDEX IF NOT EXISTS idx_prompt_logs_status_created_at ON prompt_logs (status_code, created_at DESC)"])await b.exec(a)}finally{await b.close()}}async function s(a,b,c){let d=await a.queryOne("SELECT COUNT(1) AS count FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prompt_logs' AND INDEX_NAME = ?",[b]);0===Number(d?.count||0)&&await a.exec(c)}async function t(a){let b=await o(a);try{let a=await b.queryOne("SELECT COUNT(1) AS count FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prompt_logs'");if(0===Number(a?.count||0))return;for(let[a,c]of[["idx_prompt_logs_created_id","CREATE INDEX idx_prompt_logs_created_id ON prompt_logs (created_at DESC, id)"],["idx_prompt_logs_stage_created_at","CREATE INDEX idx_prompt_logs_stage_created_at ON prompt_logs (stage, created_at DESC)"],["idx_prompt_logs_model_created_at","CREATE INDEX idx_prompt_logs_model_created_at ON prompt_logs (model, created_at DESC)"],["idx_prompt_logs_display_model_created_at","CREATE INDEX idx_prompt_logs_display_model_created_at ON prompt_logs (display_model, created_at DESC)"],["idx_prompt_logs_session_created_at","CREATE INDEX idx_prompt_logs_session_created_at ON prompt_logs (session_id, created_at DESC)"],["idx_prompt_logs_client_ip_created_at","CREATE INDEX idx_prompt_logs_client_ip_created_at ON prompt_logs (client_ip, created_at DESC)"],["idx_prompt_logs_source_tool_created_at","CREATE INDEX idx_prompt_logs_source_tool_created_at ON prompt_logs (source_tool, created_at DESC)"],["idx_prompt_logs_connection_created_at","CREATE INDEX idx_prompt_logs_connection_created_at ON prompt_logs (connection_id, created_at DESC)"],["idx_prompt_logs_account_created_at","CREATE INDEX idx_prompt_logs_account_created_at ON prompt_logs (account_name, created_at DESC)"],["idx_prompt_logs_provider_created_at","CREATE INDEX idx_prompt_logs_provider_created_at ON prompt_logs (provider, created_at DESC)"],["idx_prompt_logs_status_created_at","CREATE INDEX idx_prompt_logs_status_created_at ON prompt_logs (status_code, created_at DESC)"],["idx_prompt_logs_payload_hash","CREATE INDEX idx_prompt_logs_payload_hash ON prompt_logs (payload_hash)"]])await s(b,a,c)}finally{await b.close()}}async function u(a){if(!a.enabled)return;let b="sqlite"===a.type?`sqlite:${a.sqlitePath}`:`${a.type}:${a.host||""}:${a.port||""}:${a.database||""}`;if(!i.has(b))try{"sqlite"===a.type?await q(a):"postgres"===a.type?await r(a):"mysql"===a.type&&await t(a),i.add(b)}catch(a){console.warn("[prompt-logs] Unable to ensure query indexes:",a.message)}}async function v(a){if(!e().existsSync(a.sqlitePath))return{models:[],stages:[],missing:!0,dbInfo:{type:"sqlite",sqlitePath:a.sqlitePath}};let b=await m(a.sqlitePath);try{if(!b.get("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'prompt_logs'"))return{models:[],stages:[],missing:!0,dbInfo:{type:"sqlite",sqlitePath:a.sqlitePath}};let c=b.all("SELECT DISTINCT COALESCE(NULLIF(display_model, ''), model) AS model FROM prompt_logs WHERE model IS NOT NULL AND model <> '' ORDER BY model LIMIT 300").map(a=>a.model),d=b.all("SELECT DISTINCT stage FROM prompt_logs WHERE stage IS NOT NULL AND stage <> '' ORDER BY stage LIMIT 100").map(a=>a.stage);return{models:c,stages:d,dbInfo:{type:"sqlite",sqlitePath:a.sqlitePath}}}finally{b.close()}}async function w(a){let b="postgres"===a.type?await n(a):await o(a);try{let c=(await b.query("SELECT DISTINCT COALESCE(NULLIF(display_model, ''), model) AS model FROM prompt_logs WHERE model IS NOT NULL AND model <> '' ORDER BY model LIMIT 300")).map(a=>a.model),d=(await b.query("SELECT DISTINCT stage FROM prompt_logs WHERE stage IS NOT NULL AND stage <> '' ORDER BY stage LIMIT 100")).map(a=>a.stage);return{models:c,stages:d,dbInfo:{type:a.type,host:a.host,database:a.database}}}finally{await b.close()}}async function x(a,b){if(!e().existsSync(a.sqlitePath))return{rows:[],total:0,models:[],stages:[],missing:!0,dbInfo:{type:"sqlite",sqlitePath:a.sqlitePath}};let c=await m(a.sqlitePath);try{let d,e;if(!c.get("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'prompt_logs'"))return{rows:[],total:0,models:[],stages:[],missing:!0,dbInfo:{type:"sqlite",sqlitePath:a.sqlitePath}};let{clause:f,params:g}=(d=[],e={limit:b.limit,offset:b.offset},b.keyword&&(d.push(`(
2
- prompt_text LIKE @keyword OR
3
- response_text LIKE @keyword OR
4
- error_text LIKE @keyword OR
5
- model LIKE @keyword OR
6
- endpoint LIKE @keyword OR
7
- provider_url LIKE @keyword OR
8
- provider LIKE @keyword OR
9
- account_name LIKE @keyword OR
10
- connection_id LIKE @keyword OR
11
- display_model LIKE @keyword OR
12
- session_id LIKE @keyword OR
13
- client_ip LIKE @keyword OR
14
- client_host LIKE @keyword OR
15
- client_user_agent LIKE @keyword OR
16
- source_tool LIKE @keyword OR
17
- source_tool_label LIKE @keyword OR
18
- source_host LIKE @keyword
19
- )`),e.keyword=`%${b.keyword}%`),b.model&&(d.push("(model = @model OR display_model = @model)"),e.model=b.model),b.stage&&(d.push("stage = @stage"),e.stage=b.stage),b.sessionId&&(d.push("session_id = @sessionId"),e.sessionId=b.sessionId),b.clientIp&&(d.push("client_ip LIKE @clientIp"),e.clientIp=`%${b.clientIp}%`),b.sourceTool&&(d.push("(source_tool LIKE @sourceTool OR source_tool_label LIKE @sourceTool OR source_host LIKE @sourceTool)"),e.sourceTool=`%${b.sourceTool}%`),b.dateFrom&&(d.push("created_at >= @dateFrom"),e.dateFrom=b.dateFrom),b.dateTo&&(d.push("created_at <= @dateTo"),e.dateTo=b.dateTo),{clause:d.length?`WHERE ${d.join(" AND ")}`:"",params:e}),h=c.get(`SELECT COUNT(*) AS count FROM prompt_logs ${f}`,g)?.count||0,i=c.all(`
20
- SELECT
21
- id,
22
- created_at,
23
- session_id,
24
- source_format,
25
- target_format,
26
- model,
27
- endpoint,
28
- stage,
29
- provider_url,
30
- provider,
31
- account_name,
32
- connection_id,
33
- display_model,
34
- client_ip,
35
- client_port,
36
- client_user_agent,
37
- client_host,
38
- source_tool,
39
- source_tool_label,
40
- source_host,
41
- substr(coalesce(prompt_text,''), 1, 900) AS prompt_preview,
42
- length(coalesce(prompt_text,'')) AS prompt_length,
43
- substr(coalesce(response_text,''), 1, 400) AS response_preview,
44
- status_code,
45
- error_text
46
- FROM prompt_logs
47
- ${f}
48
- ORDER BY created_at DESC
49
- LIMIT @limit OFFSET @offset
50
- `,g),j=[],k=[];if(b.includeOptions){let b=await v(a);j=b.models,k=b.stages}return{rows:i,total:h,models:j,stages:k,dbInfo:{type:"sqlite",sqlitePath:a.sqlitePath}}}finally{c.close()}}async function y(a,b){let c=a.type,d="postgres"===c?await n(a):await o(a);try{let e=function(a,b){let c=[],d=[],e=a=>(d.push(a),"postgres"===b)?`$${d.length}`:"?",f="postgres"===b?"ILIKE":"LIKE";if(a.keyword){let b=`%${a.keyword}%`;c.push(`(${["prompt_text","response_text","error_text","model","endpoint","provider_url","provider","account_name","connection_id","display_model","session_id","client_ip","client_host","client_user_agent","source_tool","source_tool_label","source_host"].map(a=>`${a} ${f} ${e(b)}`).join(" OR ")})`)}if(a.model&&c.push(`(model = ${e(a.model)} OR display_model = ${e(a.model)})`),a.stage&&c.push(`stage = ${e(a.stage)}`),a.sessionId&&c.push(`session_id = ${e(a.sessionId)}`),a.clientIp&&c.push(`client_ip ${f} ${e(`%${a.clientIp}%`)}`),a.sourceTool){let b=`%${a.sourceTool}%`;c.push(`(source_tool ${f} ${e(b)} OR source_tool_label ${f} ${e(b)} OR source_host ${f} ${e(b)})`)}return a.dateFrom&&c.push(`created_at >= ${e(a.dateFrom)}`),a.dateTo&&c.push(`created_at <= ${e(a.dateTo)}`),{clause:c.length?`WHERE ${c.join(" AND ")}`:"",params:d,add:e}}(b,c),f=[...e.params],g=await d.queryOne(`SELECT COUNT(*) AS count FROM prompt_logs ${e.clause}`,f),h=e.add(b.limit),i=e.add(b.offset),j="postgres"===c?"LEFT(coalesce(prompt_text,''), 900)":"SUBSTRING(coalesce(prompt_text,''), 1, 900)",k="postgres"===c?"char_length(coalesce(prompt_text,''))":"CHAR_LENGTH(coalesce(prompt_text,''))",l="postgres"===c?"LEFT(coalesce(response_text,''), 400)":"SUBSTRING(coalesce(response_text,''), 1, 400)",m=await d.query(`
51
- SELECT
52
- id,
53
- created_at,
54
- session_id,
55
- source_format,
56
- target_format,
57
- model,
58
- endpoint,
59
- stage,
60
- provider_url,
61
- provider,
62
- account_name,
63
- connection_id,
64
- display_model,
65
- client_ip,
66
- client_port,
67
- client_user_agent,
68
- client_host,
69
- source_tool,
70
- source_tool_label,
71
- source_host,
72
- ${j} AS prompt_preview,
73
- ${k} AS prompt_length,
74
- ${l} AS response_preview,
75
- status_code,
76
- error_text
77
- FROM prompt_logs
78
- ${e.clause}
79
- ORDER BY created_at DESC
80
- LIMIT ${h} OFFSET ${i}
81
- `,e.params),n=[],o=[];if(b.includeOptions){let b=await w(a);n=b.models,o=b.stages}return{rows:m,total:Number(g?.count||0),models:n,stages:o,dbInfo:{type:a.type,host:a.host,database:a.database}}}finally{await d.close()}}async function z(){let a=await l();if(!a.enabled)return{disabled:!0,models:[],stages:[],dbInfo:{type:a.type}};if(await u(a),"sqlite"===a.type)return v(a);if("postgres"===a.type||"mysql"===a.type)return w(a);throw Error(`Unsupported prompt log database type: ${a.type}`)}async function A(a={}){let b=await l(),c=function(a={}){return{keyword:k(a.keyword),model:k(a.model),stage:k(a.stage),sessionId:k(a.sessionId),clientIp:k(a.clientIp),sourceTool:k(a.sourceTool),dateFrom:k(a.dateFrom),dateTo:k(a.dateTo),limit:j(a.limit,50,200),offset:j(a.offset,0),includeOptions:!0===a.includeOptions}}(a);if(!b.enabled)return{disabled:!0,rows:[],total:0,models:[],stages:[],dbInfo:{type:b.type}};if(await u(b),"sqlite"===b.type)return x(b,c);if("postgres"===b.type||"mysql"===b.type)return y(b,c);throw Error(`Unsupported prompt log database type: ${b.type}`)}async function B(a){let b=await l();if("sqlite"===b.type){if(!e().existsSync(b.sqlitePath))return null;let c=await m(b.sqlitePath);try{return c.get("SELECT * FROM prompt_logs WHERE id = @id",{id:a})||null}finally{c.close()}}if("postgres"===b.type){let c=await n(b);try{return await c.queryOne("SELECT * FROM prompt_logs WHERE id = $1",[a])}finally{await c.close()}}if("mysql"===b.type){let c=await o(b);try{let b=await c.queryOne("SELECT * FROM prompt_logs WHERE id = ?",[a]);return await p(c,b)}finally{await c.close()}}throw Error(`Unsupported prompt log database type: ${b.type}`)}async function C(a){let b=await l();if("sqlite"===b.type){if(!e().existsSync(b.sqlitePath))return{changed:0};let c=await m(b.sqlitePath);try{return{changed:c.run("DELETE FROM prompt_logs WHERE id = @id",{id:a}).changes||0}}finally{c.close()}}if("postgres"===b.type){let c=await n(b);try{let b=await c.queryOne("SELECT COUNT(*) AS count FROM prompt_logs WHERE id = $1",[a]);return await c.exec("DELETE FROM prompt_logs WHERE id = $1",[a]),{changed:Number(b?.count||0)}}finally{await c.close()}}if("mysql"===b.type){let c=await o(b);try{return await c.exec("DELETE FROM prompt_logs WHERE id = ?",[a]),{changed:1}}finally{await c.close()}}throw Error(`Unsupported prompt log database type: ${b.type}`)}}};
@@ -1 +0,0 @@
1
- (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8978],{39944:(e,t,s)=>{Promise.resolve().then(s.bind(s,70959))},70959:(e,t,s)=>{"use strict";s.d(t,{default:()=>z});var l=s(95155),r=s(12115);let n=[{value:"today",label:"H\xf4m nay"},{value:"yesterday",label:"H\xf4m qua"},{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ả"},{value:"custom",label:"T\xf9y chọn"}],a=[{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"}];function o(e,t=0){return Number(e||0).toLocaleString("vi-VN",{maximumFractionDigits:t})}function i(e){let t=Number(e||0);return Intl.NumberFormat("vi-VN",{notation:"compact",maximumFractionDigits:1}).format(t)}function d(e){let t=100*Number(e||0);return`${t.toLocaleString("vi-VN",{maximumFractionDigits:1})}%`}function c(e){let t=Number(e||0);return t?`$${t.toLocaleString("vi-VN",{minimumFractionDigits:4,maximumFractionDigits:6})}`:"$0"}function x(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 m(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 u(e){return null==e||Number.isNaN(Number(e))?"-":`${Number(e).toLocaleString("vi-VN",{maximumFractionDigits:0})}/100`}function h(e){if(!e)return"-";try{let t=new Date(e);if(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 p(e){if(!e)return"";try{let t=new Date(e);if(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 b(...e){return e.filter(Boolean).join(" ")}function g(e,t={}){let s=new URLSearchParams;return Object.entries({...e,...t}).forEach(([e,t])=>{let l=String(t??"").trim();l&&s.set(e,l)}),s.toString()}function j({children:e,className:t=""}){return(0,l.jsx)("div",{className:b("rounded-2xl border border-border bg-surface p-5 shadow-sm",t),children:e})}function v({icon:e,label:t,value:s,hint:r,tone:n="blue"}){return(0,l.jsx)(j,{className:"min-h-[126px]",children:(0,l.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"text-sm font-medium text-text-muted",children:t}),(0,l.jsx)("div",{className:"mt-2 text-2xl font-semibold text-text-main",children:s}),r?(0,l.jsx)("div",{className:"mt-2 text-xs text-text-muted",children:r}):null]}),(0,l.jsx)("div",{className:b("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"}[n]||"bg-blue-500/10 text-blue-600 dark:text-blue-300"),children:(0,l.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:e})})]})})}function y({label:e,children:t}){return(0,l.jsxs)("label",{className:"space-y-1.5 text-xs font-medium text-text-muted",children:[(0,l.jsx)("span",{children:e}),t]})}function k({value:e,onChange:t,children:s}){return(0,l.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 N({value:e,onChange:t,placeholder:s="",type:r="text"}){return(0,l.jsx)("input",{value:e||"",type:r,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 f(){return(0,l.jsxs)("div",{className:"space-y-4",children:[(0,l.jsx)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:Array.from({length:8}).map((e,t)=>(0,l.jsx)("div",{className:"h-32 animate-pulse rounded-2xl border border-border bg-surface"},t))}),(0,l.jsx)("div",{className:"h-80 animate-pulse rounded-2xl border border-border bg-surface"})]})}function T({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,l.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,l.jsx)("span",{className:"material-symbols-outlined text-4xl text-text-muted",children:"database_off"}),(0,l.jsx)("div",{className:"mt-3 text-sm font-semibold text-text-main",children:e}),(0,l.jsx)("div",{className:"mt-1 max-w-xl text-sm text-text-muted",children:t})]})}function w({data:e=[],valueKey:t="totalTokens",secondaryKey:s="requests",height:r=220}){let n=e||[],a=Math.max(...n.map(e=>Number(e[t]||0)),1),i=Math.max(...n.map(e=>Number(e[s]||0)),1);return 0===n.length?(0,l.jsx)(T,{description:"Chưa c\xf3 time-series trong khoảng thời gian n\xe0y."}):(0,l.jsx)("div",{className:"overflow-x-auto",children:(0,l.jsxs)("div",{className:"min-w-[720px]",children:[(0,l.jsx)("div",{className:"flex items-end gap-1",style:{height:r},children:n.map((e,n)=>{let d=Math.max(2,Number(e[t]||0)/a*(r-42)),c=Math.max(2,Number(e[s]||0)/i*(r-42));return(0,l.jsx)("div",{className:"group flex flex-1 flex-col items-center justify-end gap-1",children:(0,l.jsxs)("div",{className:"relative flex h-full w-full max-w-[34px] items-end justify-center gap-0.5",children:[(0,l.jsx)("div",{className:"w-2 rounded-t bg-primary/70",style:{height:d}}),(0,l.jsx)("div",{className:"w-2 rounded-t bg-amber-500/70",style:{height:c}}),(0,l.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,l.jsx)("div",{className:"font-semibold text-text-main",children:p(e.label)}),(0,l.jsxs)("div",{className:"mt-1 text-text-muted",children:["Request: ",o(e.requests)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Input token: ",o(e.promptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Output token: ",o(e.completionTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Tổng token: ",o(e.totalTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Lỗi: ",o(e.errors)]})]})]})},`${e.label}-${n}`)})}),(0,l.jsxs)("div",{className:"mt-3 flex justify-between gap-2 text-[11px] text-text-muted",children:[(0,l.jsx)("span",{children:p(n[0]?.label)}),(0,l.jsx)("span",{children:p(n[Math.floor(n.length/2)]?.label)}),(0,l.jsx)("span",{children:p(n[n.length-1]?.label)})]})]})})}function P(){return(0,l.jsxs)("div",{className:"flex flex-wrap gap-3 text-xs text-text-muted",children:[(0,l.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,l.jsx)("span",{className:"h-2.5 w-2.5 rounded-sm bg-primary/70"}),"Token"]}),(0,l.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,l.jsx)("span",{className:"h-2.5 w-2.5 rounded-sm bg-amber-500/70"}),"Request"]})]})}function q({columns:e,rows:t,empty:s="Kh\xf4ng c\xf3 dữ liệu"}){return t&&0!==t.length?(0,l.jsx)("div",{className:"overflow-x-auto rounded-2xl border border-border",children:(0,l.jsxs)("table",{className:"min-w-full divide-y divide-border text-sm",children:[(0,l.jsx)("thead",{className:"bg-background/70",children:(0,l.jsx)("tr",{children:e.map(e=>(0,l.jsx)("th",{className:b("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,l.jsx)("tbody",{className:"divide-y divide-border bg-surface",children:t.map((t,s)=>(0,l.jsx)("tr",{className:"hover:bg-background/60",children:e.map(e=>(0,l.jsx)("td",{className:b("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,l.jsx)(T,{title:s})}function S({items:e=[]}){return e&&0!==e.length?(0,l.jsx)("div",{className:"flex max-w-[360px] flex-wrap gap-1.5",children:e.slice(0,3).map(e=>(0,l.jsxs)("span",{className:"rounded-full bg-primary/10 px-2 py-0.5 text-xs text-primary",children:[e.label||e.key," \xb7 ",o(e.count??e.requests??e.totalTokens??0)]},e.key))}):(0,l.jsx)("span",{className:"text-text-muted",children:"-"})}function I({row:e}){return(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{className:"font-semibold text-text-main",children:[i(e.totalTokens)," token"]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["In ",i(e.promptTokens)," / Out ",i(e.completionTokens)]})]})}function R({value:e}){let t=Number(e||0);return(0,l.jsx)("span",{className:b("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:d(t)})}function L({level:e,label:t}){let s=String(e||"none");return(0,l.jsx)("span",{className:b("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 M({level:e,label:t}){let s=String(e||"normal");return(0,l.jsx)("span",{className:b("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 C({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,l.jsx)("span",{className:b("rounded-full px-2 py-1 text-xs font-semibold",s.cls),children:s.label})}function K({row:e}){let t=e.sampleMessage||e.errorMessageShort||"";return t?(0,l.jsx)("span",{className:"block max-w-[360px] truncate text-xs text-text-muted",title:t,children:t}):(0,l.jsx)("span",{className:"text-text-muted",children:"-"})}function $({icon:e,label:t,value:s,hint:r,tone:n="slate"}){return(0,l.jsx)("div",{className:b("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"}[n]||"border-border bg-surface text-text-main"),children:(0,l.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide opacity-75",children:t}),(0,l.jsx)("div",{className:"mt-2 text-2xl font-bold",children:o(s)}),r?(0,l.jsx)("div",{className:"mt-1 text-xs opacity-80",children:r}):null]}),(0,l.jsx)("span",{className:"material-symbols-outlined text-[24px] opacity-80",children:e})]})})}function A({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,l.jsx)("div",{className:b("rounded-2xl border p-4",t),children:(0,l.jsxs)("div",{className:"flex gap-3",children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:s}),(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.title}),(0,l.jsx)("div",{className:"mt-1 text-sm opacity-90",children:e.detail})]})]})})}function E({notes:e=[]}){return e.length?(0,l.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,l.jsxs)("div",{className:"flex gap-2",children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"info"}),(0,l.jsx)("span",{children:e})]},t))}):null}function F({filters:e,setFilters:t,options:s,onRefresh:r,onExportCsv:a,loading:o}){let i=(e,s)=>t(t=>({...t,[e]:s}));return(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"grid gap-3 md:grid-cols-2 xl:grid-cols-6",children:[(0,l.jsx)(y,{label:"Khoảng thời gian",children:(0,l.jsx)(k,{value:e.period,onChange:e=>i("period",e),children:n.map(e=>(0,l.jsx)("option",{value:e.value,children:e.label},e.value))})}),(0,l.jsx)(y,{label:"Từ ng\xe0y",children:(0,l.jsx)(N,{type:"datetime-local",value:e.dateFrom,onChange:e=>i("dateFrom",e)})}),(0,l.jsx)(y,{label:"Đến ng\xe0y",children:(0,l.jsx)(N,{type:"datetime-local",value:e.dateTo,onChange:e=>i("dateTo",e)})}),(0,l.jsx)(y,{label:"Provider",children:(0,l.jsxs)(k,{value:e.provider,onChange:e=>i("provider",e),children:[(0,l.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,l.jsx)("option",{value:t,children:s},t)})]})}),(0,l.jsx)(y,{label:"Model",children:(0,l.jsxs)(k,{value:e.model,onChange:e=>i("model",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả model"}),(s.models||[]).map(e=>(0,l.jsx)("option",{value:e,children:e},e))]})}),(0,l.jsx)(y,{label:"Provider account",children:(0,l.jsxs)(k,{value:e.connectionId,onChange:e=>i("connectionId",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả account"}),(s.connections||[]).map(e=>(0,l.jsx)("option",{value:e.value,children:e.label},e.value))]})}),(0,l.jsx)(y,{label:"API key",children:(0,l.jsxs)(k,{value:e.apiKey,onChange:e=>i("apiKey",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả API key"}),(s.apiKeys||[]).map(e=>(0,l.jsx)("option",{value:e.value,children:e.label},e.value))]})}),(0,l.jsx)(y,{label:"Source IP",children:(0,l.jsx)(N,{value:e.clientIp,onChange:e=>i("clientIp",e),placeholder:"172.16.253.1"})}),(0,l.jsx)(y,{label:"Source tool",children:(0,l.jsx)(N,{value:e.sourceTool,onChange:e=>i("sourceTool",e),placeholder:"copilot, antigravity..."})}),(0,l.jsx)(y,{label:"Endpoint",children:(0,l.jsxs)(k,{value:e.endpoint,onChange:e=>i("endpoint",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả endpoint"}),(s.endpoints||[]).map(e=>(0,l.jsx)("option",{value:e,children:e},e))]})}),(0,l.jsx)(y,{label:"Status",children:(0,l.jsxs)(k,{value:e.status,onChange:e=>i("status",e),children:[(0,l.jsx)("option",{value:"",children:"Tất cả status"}),(s.statuses||[]).map(e=>(0,l.jsx)("option",{value:e,children:e},e))]})}),(0,l.jsx)(y,{label:"Session / keyword",children:(0,l.jsx)(N,{value:e.sessionId||e.keyword,onChange:e=>i("keyword",e),placeholder:"session, prompt, error..."})})]}),(0,l.jsxs)("div",{className:"mt-4 flex flex-wrap items-center justify-between gap-3",children:[(0,l.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,l.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,l.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,l.jsxs)("button",{onClick:a,className:"rounded-xl border border-border px-3 py-2 text-sm font-medium text-text-main hover:bg-background",children:[(0,l.jsx)("span",{className:"material-symbols-outlined mr-1 align-[-4px] text-[18px]",children:"download"}),"Export CSV"]}),(0,l.jsxs)("button",{onClick:r,disabled:o,className:"rounded-xl bg-primary px-4 py-2 text-sm font-semibold text-white shadow-sm disabled:opacity-60",children:[(0,l.jsx)("span",{className:"material-symbols-outlined mr-1 align-[-4px] text-[18px]",children:"refresh"}),o?"Đang tải...":"Refresh"]})]})]})]})}function _({data:e}){let t=e.overview||{},s=e.latency||{},r=e.experience||{};return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,l.jsx)(v,{icon:"call_made",label:"Tổng request",value:o(t.requests),hint:`${o(t.requestsPerMinute,2)} request/ph\xfat`}),(0,l.jsx)(v,{icon:"check_circle",label:"Th\xe0nh c\xf4ng",value:o(t.success),hint:`Tỷ lệ lỗi ${d(t.errorRate)}`,tone:"green"}),(0,l.jsx)(v,{icon:"dns",label:"Lỗi server/provider",value:o(t.serverErrorEvents),hint:`Server-impacting ${d(t.serverErrorRate)} \xb7 client ${o(t.clientErrorEvents)}`,tone:t.serverErrorEvents?"red":"green"}),(0,l.jsx)(v,{icon:"speed",label:"Trải nghiệm",value:u(r.score),hint:`${r.label||"-"} \xb7 ${o(r.samples)} mẫu`,tone:r.tone||"purple"}),(0,l.jsx)(v,{icon:"timer",label:"Latency P95",value:x(r.p95LatencyMs||s.p95Ms),hint:`AVG ${x(r.avgLatencyMs||s.avgMs)} \xb7 P50 ${x(r.p50LatencyMs||s.p50Ms)}`,tone:"purple"}),(0,l.jsx)(v,{icon:"bolt",label:"TTFT P95",value:x(r.p95TtftMs),hint:"Thời gian chờ token đầu ti\xean",tone:r.slowTtftRate>=.2?"amber":"blue"}),(0,l.jsx)(v,{icon:"input",label:"Input P95",value:i(r.p95PromptTokens||0),hint:`Avg ${i(r.avgPromptTokens||t.avgPromptTokens)} \xb7 >=30k ${d(r.longInputRate)}`}),(0,l.jsx)(v,{icon:"person_alert",label:"Top user nặng",value:t.topHeavyUser||"-",hint:`Chiếm ${d(t.topHeavyUserTokenShare)} tổng token`,tone:t.topHeavyUserTokenShare>=.35?"amber":"slate"}),(0,l.jsx)(v,{icon:"running_with_errors",label:"Request chậm",value:d(r.slowRequestRate),hint:`>= ${x(r.thresholds?.slowLatencyMs||45e3)} \xb7 max ${x(r.maxLatencyMs)}`,tone:r.slowRequestRate>=.2?"amber":"green"}),(0,l.jsx)(v,{icon:"output",label:"Output tokens",value:i(t.completionTokens),hint:`Avg ${o(t.avgCompletionTokens,1)} / request`}),(0,l.jsx)(v,{icon:"token",label:"Tổng tokens",value:i(t.totalTokens),hint:`${i(t.tokensPerMinute)} token/ph\xfat`,tone:"amber"}),(0,l.jsx)(v,{icon:"speed",label:"Output speed",value:m(r.decodeTokensPerSecond," tok/s"),hint:`Latency/10k input ${x(r.latencyMsPer10kInputTokens)}`,tone:"slate"}),(0,l.jsx)(v,{icon:"payments",label:"Cost ước t\xednh",value:c(t.cost),hint:"Dựa tr\xean pricing đ\xe3 cấu h\xecnh",tone:"green"})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-[2fr_1fr]",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Tần suất request & token theo thời gian"}),(0,l.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,l.jsx)(P,{})]}),(0,l.jsx)(w,{data:e.timeSeries||[]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"T\xf3m tắt active"}),(0,l.jsx)("div",{className:"mt-4 space-y-3",children:[["API key đang d\xf9ng",t.activeApiKeys],["Provider active",t.activeProviders],["Model active",t.activeModels],["Endpoint active",t.activeEndpoints],["Cached tokens",t.cachedTokens],["Reasoning tokens",t.reasoningTokens],["Latency AVG",x(r.avgLatencyMs||s.avgMs)],["Latency P50",x(r.p50LatencyMs||s.p50Ms)],["Latency P99",x(r.p99LatencyMs||s.p99Ms)],["TTFT P95",x(r.p95TtftMs)],["Input P95",i(r.p95PromptTokens||0)],["Long input >=30k",d(r.longInputRate)]].map(([e,t])=>(0,l.jsxs)("div",{className:"flex items-center justify-between rounded-xl bg-background px-3 py-2",children:[(0,l.jsx)("span",{className:"text-sm text-text-muted",children:e}),(0,l.jsx)("span",{className:"font-semibold text-text-main",children:"number"==typeof t?o(t):t})]},e))})]})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top API key d\xf9ng nhiều token"}),(0,l.jsx)(q,{rows:(e.clientRequests?.topApiKeysByTokens||e.groups?.apiKeys||[]).slice(0,8),columns:[{key:"name",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.name||e.label}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:[e.fingerprint||e.apiKeyFingerprint,e.ownerUser||e.apiKeyOwner?` \xb7 ${e.ownerUser||e.apiKeyOwner}`:""]})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"P95/Max input",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{children:i(e.p95PromptTokens||0)}),(0,l.jsxs)("div",{className:"text-text-muted",children:["max ",i(e.maxPromptTokens||0)]})]})}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top Source IP d\xf9ng nhiều token"}),(0,l.jsx)(q,{rows:(e.clientRequests?.topSourceIpsByTokens||[]).slice(0,8),columns:[{key:"label",label:"Source IP",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"heavy",label:"Nặng",render:e=>(0,l.jsxs)("span",{className:"text-xs text-text-muted",children:[o(e.heavyRequests||0)," req"]})}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]})]})]})}function O({data:e}){let t=e.clientRequests||{},s=t.summary||{},r=t.topHeavyUsers||[],n=t.topProblemClients||[],a=t.topApiKeysByTokens||[],c=t.topSourceIpsByTokens||[];t.topSourceIpsByHeavyRequests;let m=t.inputBuckets||[],u=e=>(0,l.jsxs)("div",{className:"min-w-[220px]",children:[(0,l.jsx)("div",{className:"font-semibold text-text-main",children:e.label}),(0,l.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.ownerUser?`Owner ${e.ownerUser}`:e.apiKeyName||"Kh\xf4ng c\xf3 owner"}),(0,l.jsx)("div",{className:"font-mono text-[11px] text-text-muted",children:e.apiKeyFingerprint||e.primaryClientIp||e.key})]}),p=e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["Nặng ",o(e.heavyRequests)," \xb7 ",d(e.heavyRequestRate)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["P95 input ",i(e.p95PromptTokens)," \xb7 Max ",i(e.maxPromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=70k ",o(e.extremeInputRequests)," \xb7 ",d(e.extremeInputRate)]})]});return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,l.jsx)(v,{icon:"person_alert",label:"Top user nặng nhất",value:s.topUserLabel||"-",hint:`${i(s.topUserTokens)} token \xb7 ${d(s.topUserTokenShare)} tổng token`,tone:s.topUserTokenShare>=.35?"amber":"slate"}),(0,l.jsx)(v,{icon:"vpn_key",label:"Top API key nhiều token",value:s.topApiKeyLabel||"-",hint:`${i(s.topApiKeyTokens)} token \xb7 ${d(s.topApiKeyTokenShare)} tổng token`,tone:s.topApiKeyTokenShare>=.35?"amber":"blue"}),(0,l.jsx)(v,{icon:"lan",label:"Top IP nhiều token",value:s.topSourceIpLabel||"-",hint:`${i(s.topSourceIpTokens)} token \xb7 ${d(s.topSourceIpTokenShare)} tổng token`,tone:s.topSourceIpTokenShare>=.35?"amber":"purple"}),(0,l.jsx)(v,{icon:"input",label:"Input d\xe0i >=30k",value:d(s.longInputBucketShare||0),hint:`>=70k ${d(s.extremeInputShare||0)}`,tone:(s.extremeInputShare||0)>=.1?"amber":"green"}),(0,l.jsx)(v,{icon:"groups",label:"User/API key được theo d\xf5i",value:o(s.trackedUsers||0),hint:"Theo owner/API key fingerprint/source IP",tone:"blue"}),(0,l.jsx)(v,{icon:"network_check",label:"Top IP request nặng",value:s.topSourceIpHeavyLabel||"-",hint:`${o(s.topSourceIpHeavyRequests||0)} request >=30k input/total`,tone:s.topSourceIpHeavyRequests?"amber":"slate"}),(0,l.jsx)(v,{icon:"report",label:"Client lỗi nhiều",value:o(s.problemClients||0),hint:"Nh\xf3m user/API key c\xf3 error rows",tone:s.problemClients?"amber":"green"})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top user/API key gửi request nặng nhất"}),(0,l.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,l.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,l.jsx)(q,{rows:r,columns:[{key:"user",label:"User/API key",render:u},{key:"quality",label:"\xc1p lực",render:e=>(0,l.jsx)(M,{level:e.level,label:e.pressureLabel})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"Input pressure",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["Avg ",i(e.avgPromptTokens)," \xb7 P95 ",i(e.p95PromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["Max ",i(e.maxPromptTokens)," \xb7 >=30k ",d(e.longInputRate)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=50k ",d(e.hugeInputRate)," \xb7 >=70k ",d(e.extremeInputRate)]})]})},{key:"latency",label:"Latency / TTFT",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["P95 ",x(e.p95LatencyMs)," \xb7 Max ",x(e.maxLatencyMs)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["TTFT P95 ",x(e.p95TtftMs)," \xb7 Slow ",d(e.slowRequestRate)]})]})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"topIps",label:"IP / Tool",render:e=>(0,l.jsxs)("div",{className:"space-y-1",children:[(0,l.jsx)(S,{items:e.topIps}),(0,l.jsx)(S,{items:e.topTools})]})},{key:"meta",label:"Meta",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs text-text-muted",children:[(0,l.jsxs)("div",{children:["Key ",o(e.apiKeyCount)," \xb7 IP ",o(e.sourceIpCount)," \xb7 Tool ",o(e.sourceToolCount)]}),(0,l.jsxs)("div",{children:["Session ",o(e.sessionCount)," \xb7 Last ",h(e.lastSeen)]})]})}],empty:"Kh\xf4ng c\xf3 request th\xe0nh c\xf4ng c\xf3 token trong khoảng lọc."})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top API key d\xf9ng nhiều token nhất"}),(0,l.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,l.jsx)(q,{rows:a,columns:[{key:"apiKey",label:"API key",render:e=>(0,l.jsxs)("div",{className:"min-w-[220px]",children:[(0,l.jsx)("div",{className:"font-semibold text-text-main",children:e.label}),(0,l.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:e.apiKeyOwner?`Owner ${e.apiKeyOwner}`:e.apiKeyName||e.primarySourceTool||"-"}),(0,l.jsx)("div",{className:"font-mono text-[11px] text-text-muted",children:e.apiKeyFingerprint||e.primaryClientIp||e.key})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"Input nặng",render:p},{key:"meta",label:"Nguồn",render:e=>(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:[(0,l.jsxs)("div",{children:["IP ",o(e.sourceIpCount)," \xb7 Tool ",o(e.sourceToolCount)]}),(0,l.jsxs)("div",{children:["Model ",o(e.modelCount)," \xb7 Provider ",o(e.providerCount)]})]})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 API key c\xf3 token trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top Source IP d\xf9ng nhiều token nhất"}),(0,l.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,l.jsx)(q,{rows:c,columns:[{key:"ip",label:"Source IP",render:e=>(0,l.jsxs)("div",{className:"min-w-[180px]",children:[(0,l.jsx)("div",{className:"font-mono text-sm font-semibold text-text-main",children:e.label}),(0,l.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:["Tool ",o(e.sourceToolCount)," \xb7 API key ",o(e.apiKeyCount)]}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:["Model ",o(e.modelCount)," \xb7 Provider ",o(e.providerCount)]})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"input",label:"Input nặng",render:p},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Ph\xe2n bố request theo k\xedch thước input"}),(0,l.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,l.jsx)(q,{rows:m,columns:[{key:"label",label:"Input bucket",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"share",label:"Tỷ trọng",render:e=>d(e.share)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"latency",label:"Latency P95/MAX",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{children:[x(e.p95LatencyMs)," / ",x(e.maxLatencyMs)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["TTFT P95 ",x(e.p95TtftMs)]})]})}],empty:"Kh\xf4ng c\xf3 dữ liệu bucket input."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Client/API key lỗi nhiều"}),(0,l.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,l.jsx)(q,{rows:n,columns:[{key:"user",label:"Client",render:u},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"source",label:"IP/Tool",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{className:"font-mono",children:e.primaryClientIp||"-"}),(0,l.jsx)("div",{className:"text-text-muted",children:e.primarySourceTool||"-"})]})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 client lỗi theo bộ lọc hiện tại."})]})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"G\xf3c nh\xecn monitor client n\xean d\xf9ng"}),(0,l.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,l.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,l.jsxs)("div",{className:"rounded-xl border border-border bg-background p-3",children:[(0,l.jsx)("div",{className:"font-semibold text-text-main",children:e}),(0,l.jsx)("div",{className:"mt-1 text-xs text-text-muted",children:t})]},e))})]})]})}function U({data:e}){return(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Thống k\xea theo API key"}),(0,l.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,l.jsx)(q,{rows:e.groups?.apiKeys||[],columns:[{key:"name",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.name}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:[e.fingerprint,e.ownerUser?` \xb7 Owner: ${e.ownerUser}`:""]})]})},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"success",label:"OK/Lỗi",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{className:"text-green-600",children:["OK ",o(e.success)]}),(0,l.jsxs)("div",{className:"text-red-600",children:["Lỗi ",o(e.errors)]})]})},{key:"tokens",label:"In/Out token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"topProviders",label:"Top provider",render:e=>(0,l.jsx)(S,{items:e.topProviders})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]})}function V({data:e}){let t=e.clientRequests?.topSourceIpsByTokens||[],s=e.clientRequests?.topSourceIpsByHeavyRequests||[],r=e=>(0,l.jsxs)("div",{className:"min-w-[180px]",children:[(0,l.jsx)("div",{className:"font-mono text-sm font-semibold text-text-main",children:e.label}),(0,l.jsxs)("div",{className:"mt-1 text-xs text-text-muted",children:["API key ",o(e.apiKeyCount)," \xb7 Tool ",o(e.sourceToolCount)]}),(0,l.jsxs)("div",{className:"text-xs text-text-muted",children:["Model ",o(e.modelCount)," \xb7 Provider ",o(e.providerCount)]})]});return(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top IP d\xf9ng nhiều token nhất"}),(0,l.jsx)("p",{className:"mt-1 text-sm text-text-muted",children:"Aggregate từ UsageHistory, xếp theo tổng input + output token."})]}),(0,l.jsx)(q,{rows:t,columns:[{key:"ip",label:"Source IP",render:r},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP c\xf3 token trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Top IP gửi request nặng nhất"}),(0,l.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,l.jsx)(q,{rows:s,columns:[{key:"ip",label:"Source IP",render:r},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"heavy",label:"Request nặng",render:e=>(0,l.jsxs)("div",{className:"space-y-1 text-xs",children:[(0,l.jsxs)("div",{children:["Nặng ",o(e.heavyRequests)," \xb7 ",d(e.heavyRequestRate)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["P95 input ",i(e.p95PromptTokens)," \xb7 Max ",i(e.maxPromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=70k ",o(e.extremeInputRequests)," \xb7 ",d(e.extremeInputRate)]})]})},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 Source IP gửi request nặng trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Source IP từ Prompt Logs"}),(0,l.jsx)(q,{rows:e.promptLogs?.topClientIps||[],columns:[{key:"label",label:"IP",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Logs",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topTools",label:"Tools",render:e=>(0,l.jsx)(S,{items:e.topTools})},{key:"topModels",label:"Models",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Source tool"}),(0,l.jsx)(q,{rows:e.promptLogs?.topSourceTools||[],columns:[{key:"label",label:"Tool",render:e=>(0,l.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Logs",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topIps",label:"Top IP",render:e=>(0,l.jsx)(S,{items:e.topIps})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)(j,{className:"xl:col-span-2",children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Session nhiều hoạt động"}),(0,l.jsx)(q,{rows:e.promptLogs?.topSessions||[],columns:[{key:"label",label:"Session",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Logs",render:e=>o(e.requests)},{key:"errors",label:"Lỗi",render:e=>o(e.errors)},{key:"topIps",label:"IP",render:e=>(0,l.jsx)(S,{items:e.topIps})},{key:"topTools",label:"Tool",render:e=>(0,l.jsx)(S,{items:e.topTools})},{key:"topModels",label:"Model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]})]})}function D({data:e}){return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Provider"}),(0,l.jsx)(q,{rows:e.groups?.providers||[],columns:[{key:"label",label:"Provider",render:e=>(0,l.jsx)("span",{className:"font-semibold",children:e.label})},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"topModels",label:"Top model",render:e=>(0,l.jsx)(S,{items:e.topModels})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Model"}),(0,l.jsx)(q,{rows:e.groups?.models||[],columns:[{key:"label",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"errorRate",label:"Lỗi",render:e=>(0,l.jsx)(R,{value:e.errorRate})}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Provider account / connection"}),(0,l.jsx)(q,{rows:e.groups?.providerAccounts||[],columns:[{key:"label",label:"Account",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.label}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.provider||e.connectionId})]})},{key:"requests",label:"Req",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"errorRate",label:"Lỗi",render:e=>(0,l.jsx)(R,{value:e.errorRate})}]})]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Endpoint"}),(0,l.jsx)(q,{rows:e.groups?.endpoints||[],columns:[{key:"label",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.label})},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]})]})}function H({data:e}){let t=e.experience||{},s=t.thresholds||{},r=t.byModel||[],n=t.slowestRequests||[];return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-4",children:[(0,l.jsx)(v,{icon:"verified",label:"Đ\xe1nh gi\xe1 tổng",value:u(t.score),hint:`${t.label||"-"} \xb7 ${o(t.samples)} mẫu success c\xf3 token`,tone:t.tone||"slate"}),(0,l.jsx)(v,{icon:"timer",label:"Latency AVG / P95",value:`${x(t.avgLatencyMs)} / ${x(t.p95LatencyMs)}`,hint:`P50 ${x(t.p50LatencyMs)} \xb7 P99 ${x(t.p99LatencyMs)}`,tone:"purple"}),(0,l.jsx)(v,{icon:"bolt",label:"TTFT AVG / P95",value:`${x(t.avgTtftMs)} / ${x(t.p95TtftMs)}`,hint:"TTFT cao thường l\xe0 queue/prompt eval/input d\xe0i",tone:t.slowTtftRate>=.2?"amber":"blue"}),(0,l.jsx)(v,{icon:"keyboard_double_arrow_up",label:"Input AVG / P95",value:`${i(t.avgPromptTokens)} / ${i(t.p95PromptTokens)}`,hint:`>=30k ${d(t.longInputRate)} \xb7 >=50k ${d(t.hugeInputRate)}`}),(0,l.jsx)(v,{icon:"running_with_errors",label:"Slow request",value:d(t.slowRequestRate),hint:`Latency >= ${x(s.slowLatencyMs||45e3)} \xb7 rất chậm ${d(t.verySlowRequestRate)}`,tone:t.slowRequestRate>=.2?"amber":"green"}),(0,l.jsx)(v,{icon:"pending_actions",label:"Slow TTFT",value:d(t.slowTtftRate),hint:`TTFT >= ${x(s.slowTtftMs||2e4)}`,tone:t.slowTtftRate>=.2?"amber":"green"}),(0,l.jsx)(v,{icon:"speed",label:"Output tốc độ",value:m(t.decodeTokensPerSecond," tok/s"),hint:`Output/latency ${m(t.outputTokensPerSecond," tok/s")}`,tone:"slate"}),(0,l.jsx)(v,{icon:"data_usage",label:"Latency / 10k input",value:x(t.latencyMsPer10kInputTokens),hint:"Hữu \xedch khi VS Code gửi 30k–70k token",tone:"slate"})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"C\xe1ch đọc trải nghiệm user"}),(0,l.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,l.jsxs)("div",{className:"grid gap-3 md:grid-cols-3",children:[(0,l.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"Nhanh/chậm thực tế"}),(0,l.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,l.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"Queue hoặc prompt eval"}),(0,l.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,l.jsxs)("div",{className:"rounded-2xl bg-background p-4",children:[(0,l.jsx)("div",{className:"text-xs font-semibold uppercase tracking-wide text-text-muted",children:"VS Code / agent"}),(0,l.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,l.jsxs)(j,{children:[(0,l.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,l.jsx)(q,{rows:r,empty:"Chưa c\xf3 mẫu latency cho model trong khoảng lọc.",columns:[{key:"model",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.providerLabel||e.provider})]})},{key:"quality",label:"Đ\xe1nh gi\xe1",render:e=>(0,l.jsxs)("div",{className:"space-y-1",children:[(0,l.jsx)(L,{level:e.level,label:e.labelQuality}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:u(e.score)})]})},{key:"samples",label:"Mẫu",render:e=>o(e.samples)},{key:"latency",label:"Latency P50/P95/MAX",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{children:[x(e.p50LatencyMs)," / ",x(e.p95LatencyMs)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:["max ",x(e.maxLatencyMs)]})]})},{key:"ttft",label:"TTFT P95",render:e=>x(e.p95TtftMs)},{key:"input",label:"Input avg/P95",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsxs)("div",{children:[i(e.avgPromptTokens)," / ",i(e.p95PromptTokens)]}),(0,l.jsxs)("div",{className:"text-text-muted",children:[">=30k ",d(e.longInputRate)]})]})},{key:"slow",label:"Chậm",render:e=>(0,l.jsx)(R,{value:e.slowRequestRate})},{key:"speed",label:"Output tok/s",render:e=>m(e.outputTokensPerSecond," tok/s")}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Request chậm nhất"}),(0,l.jsx)(q,{rows:n,empty:"Kh\xf4ng c\xf3 request chậm trong khoảng lọc.",columns:[{key:"timestamp",label:"Time",render:e=>h(e.timestamp)},{key:"model",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.provider})]})},{key:"latency",label:"Latency / TTFT",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{className:"font-semibold",children:x(e.latencyMs)}),(0,l.jsxs)("div",{className:"text-text-muted",children:["TTFT ",x(e.ttftMs)]})]})},{key:"tokens",label:"In / Out",render:e=>(0,l.jsx)(I,{row:e})},{key:"apiKeyName",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:e.apiKeyName}),(0,l.jsx)("div",{className:"font-mono text-xs text-text-muted",children:e.apiKeyFingerprint})]})},{key:"sourceTool",label:"Tool/IP",render:e=>(0,l.jsxs)("div",{className:"text-xs",children:[(0,l.jsx)("div",{children:e.sourceTool||"-"}),(0,l.jsx)("div",{className:"font-mono text-text-muted",children:e.clientIp||"-"})]})},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint||"-"})}]})]})]})}function B({data:e}){let t=e.requestErrors||{},s=t.summary||{},r=e.overview||{},n=Number(r.serverErrorRate||0),a=Number(r.clientErrorRate||0),i=Number(r.rateLimitErrorRate||0),c=[{key:"faultOwner",label:"Loại",render:e=>(0,l.jsx)(C,{value:e.faultOwner})},{key:"status",label:"Status",render:e=>(0,l.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"},{key:"model",label:"Model"},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"requests",label:"Lỗi",render:e=>o(e.errors||e.requests)},{key:"errorType",label:"Type",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.errorType||e.errorCode||"-"})},{key:"sampleMessage",label:"Sample",render:e=>(0,l.jsx)(K,{row:e})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}];return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-5",children:[(0,l.jsx)($,{icon:"dns",label:"Server/provider",value:s.serverImpacting||0,hint:`${d(n)} tr\xean tổng request`,tone:s.serverImpacting?"red":"green"}),(0,l.jsx)($,{icon:"cloud_off",label:"Upstream",value:s.upstream||0,hint:"Provider/model server, timeout, network, 5xx",tone:s.upstream?"red":"green"}),(0,l.jsx)($,{icon:"router",label:"Gateway",value:s.gateway||0,hint:"Lỗi nội bộ BlueRouter/gateway",tone:s.gateway?"purple":"green"}),(0,l.jsx)($,{icon:"integration_instructions",label:"Client/request",value:s.client||0,hint:`${d(a)} do endpoint/model/body/auth`,tone:s.client?"slate":"green"}),(0,l.jsx)($,{icon:"speed",label:"Rate/quota",value:s.rateLimit||0,hint:`${d(i)} rate-limit/quota`,tone:s.rateLimit?"amber":"green"})]}),(0,l.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,l.jsxs)("div",{className:"flex gap-3",children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:"rule_settings"}),(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:"Ph\xe2n loại lỗi đ\xe3 t\xe1ch client khỏi server/provider"}),(0,l.jsxs)("div",{className:"mt-1 opacity-90",children:["Cảnh b\xe1o vận h\xe0nh n\xean ưu ti\xean nh\xf3m ",(0,l.jsx)("b",{children:"Server/provider"})," gồm gateway, upstream, timeout, network v\xe0 5xx. Nh\xf3m ",(0,l.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,l.jsx)("div",{className:"grid gap-4 xl:grid-cols-2",children:e.anomalies.map((e,t)=>(0,l.jsx)(A,{anomaly:e},t))}):(0,l.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,l.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,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4 flex flex-wrap items-start justify-between gap-3",children:[(0,l.jsxs)("div",{children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Lỗi server/provider cần xử l\xfd"}),(0,l.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,l.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:[o(s.serverImpacting||0)," lỗi"]})]}),(0,l.jsx)(q,{rows:t.topServerErrors||[],columns:c,empty:"Kh\xf4ng c\xf3 lỗi server/provider trong khoảng lọc."})]}),(0,l.jsxs)("div",{className:"grid gap-5 xl:grid-cols-2",children:[(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Lỗi client/request sai"}),(0,l.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,l.jsx)(q,{rows:t.topClientErrors||[],columns:c.filter(e=>!["sampleMessage"].includes(e.key)),empty:"Kh\xf4ng c\xf3 lỗi client/request trong khoảng lọc."})]}),(0,l.jsxs)(j,{children:[(0,l.jsxs)("div",{className:"mb-4",children:[(0,l.jsx)("h2",{className:"text-lg font-semibold text-text-main",children:"Ph\xe2n bố loại lỗi"}),(0,l.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,l.jsx)(q,{rows:t.byFaultOwner||[],columns:[{key:"faultOwner",label:"Loại",render:e=>(0,l.jsx)(C,{value:e.faultOwner||e.key})},{key:"requests",label:"Số lỗi",render:e=>o(e.requests)},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}],empty:"Kh\xf4ng c\xf3 lỗi để ph\xe2n loại."})]})]}),t.topRateLimitErrors?.length?(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Rate limit / quota"}),(0,l.jsx)(q,{rows:t.topRateLimitErrors||[],columns:c})]}):null,(0,l.jsxs)(j,{children:[(0,l.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,l.jsx)(q,{rows:e.groups?.errors||[],columns:[{key:"faultOwner",label:"Loại",render:e=>(0,l.jsx)(C,{value:e.faultOwner})},{key:"status",label:"Status",render:e=>(0,l.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"},{key:"model",label:"Model"},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"requests",label:"Lỗi",render:e=>o(e.errors||e.requests)},{key:"apiKey",label:"API key",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.apiKey})},{key:"lastSeen",label:"Last seen",render:e=>h(e.lastSeen)}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Status distribution"}),(0,l.jsx)(q,{rows:e.groups?.statuses||[],columns:[{key:"label",label:"Status"},{key:"requests",label:"Requests",render:e=>o(e.requests)},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"errorRate",label:"Error %",render:e=>(0,l.jsx)(R,{value:e.errorRate})}]})]})]})}function G({data:e}){return(0,l.jsxs)("div",{className:"space-y-5",children:[(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Top request nặng token"}),(0,l.jsx)(q,{rows:e.heavyRequests||[],columns:[{key:"timestamp",label:"Time",render:e=>h(e.timestamp)},{key:"model",label:"Model",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{className:"font-semibold",children:e.model}),(0,l.jsx)("div",{className:"text-xs text-text-muted",children:e.provider})]})},{key:"apiKeyName",label:"API key",render:e=>(0,l.jsxs)("div",{children:[(0,l.jsx)("div",{children:e.apiKeyName}),(0,l.jsx)("div",{className:"font-mono text-xs text-text-muted",children:e.apiKeyFingerprint})]})},{key:"accountName",label:"Account"},{key:"endpoint",label:"Endpoint",render:e=>(0,l.jsx)("span",{className:"font-mono text-xs",children:e.endpoint})},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"status",label:"Status"}]})]}),(0,l.jsxs)(j,{children:[(0,l.jsx)("h2",{className:"mb-4 text-lg font-semibold text-text-main",children:"Recent usage"}),(0,l.jsx)(q,{rows:e.recentUsage||[],columns:[{key:"timestamp",label:"Time",render:e=>h(e.timestamp)},{key:"provider",label:"Provider"},{key:"model",label:"Model"},{key:"apiKeyName",label:"API key"},{key:"tokens",label:"Token",render:e=>(0,l.jsx)(I,{row:e})},{key:"cost",label:"Cost",render:e=>c(e.cost)},{key:"status",label:"Status"}]})]})]})}function z(){let[e,t]=(0,r.useState)({period:"today",dateFrom:"",dateTo:"",provider:"",model:"",connectionId:"",status:"",endpoint:"",apiKey:"",clientIp:"",sourceTool:"",sessionId:"",keyword:""}),[s,n]=(0,r.useState)(null),[o,i]=(0,r.useState)(!0),[d,c]=(0,r.useState)(""),[x,m]=(0,r.useState)("overview"),[u,p]=(0,r.useState)(!1),j=function(e,t=450){let[s,l]=(0,r.useState)(e);return(0,r.useEffect)(()=>{let s=setTimeout(()=>l(e),t);return()=>clearTimeout(s)},[e,t]),s}(e,450),v=(0,r.useCallback)(async()=>{i(!0),c("");try{let e=g(j),t=await fetch(`/api/dashboard/analytics?${e}`,{cache:"no-store"}),s=await t.json().catch(()=>({}));if(!t.ok)throw Error(s.error||"Kh\xf4ng tải được dữ liệu analytics");n(s)}catch(e){c(e.message||"Kh\xf4ng tải được dữ liệu analytics")}finally{i(!1)}},[j]);(0,r.useEffect)(()=>{v()},[v]),(0,r.useEffect)(()=>{if(!u)return;let e=setInterval(()=>v(),1e4);return()=>clearInterval(e)},[u,v]);let y=s?.options||{},k=(0,r.useMemo)(()=>s?.generatedAt?h(s.generatedAt):"-",[s]);return(0,l.jsxs)("div",{className:"space-y-5 p-4 md:p-6",children:[(0,l.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{className:"flex items-center gap-2 text-primary",children:[(0,l.jsx)("span",{className:"material-symbols-outlined",children:"monitoring"}),(0,l.jsx)("span",{className:"text-sm font-semibold uppercase tracking-wide",children:"BlueRouter Analytics"})]}),(0,l.jsx)("h1",{className:"mt-2 text-2xl font-bold text-text-main",children:"Thống k\xea sử dụng Gateway"}),(0,l.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,l.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,l.jsx)("span",{className:"material-symbols-outlined text-[20px]",children:"schedule"}),(0,l.jsxs)("div",{children:[(0,l.jsxs)("div",{children:["Generated: ",k]}),(0,l.jsxs)("label",{className:"mt-1 flex cursor-pointer items-center gap-2 text-xs",children:[(0,l.jsx)("input",{type:"checkbox",checked:u,onChange:e=>p(e.target.checked)}),"Auto refresh 10s"]})]})]})]}),(0,l.jsx)(F,{filters:e,setFilters:t,options:y,onRefresh:v,onExportCsv:()=>{let e=g(j,{format:"csv"});window.open(`/api/dashboard/analytics?${e}`,"_blank","noopener,noreferrer")},loading:o}),d?(0,l.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,l.jsx)("span",{className:"material-symbols-outlined mr-2 align-[-5px]",children:"error"}),d]}):null,s?.qualityNotes?.length?(0,l.jsx)(E,{notes:s.qualityNotes}):null,(0,l.jsx)("div",{className:"flex flex-wrap gap-2 rounded-2xl border border-border bg-surface p-2",children:a.map(e=>(0,l.jsxs)("button",{onClick:()=>m(e.value),className:b("flex items-center gap-2 rounded-xl px-3 py-2 text-sm font-medium transition",x===e.value?"bg-primary text-white shadow-sm":"text-text-muted hover:bg-background hover:text-text-main"),children:[(0,l.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:e.icon}),e.label]},e.value))}),o&&!s?(0,l.jsx)(f,{}):null,!o&&s&&s.overview?.requests===0&&0===(s.promptLogs?.total||0)?(0,l.jsx)(T,{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,s?(0,l.jsxs)(l.Fragment,{children:["overview"===x?(0,l.jsx)(_,{data:s}):null,"apiKeys"===x?(0,l.jsx)(U,{data:s}):null,"clients"===x?(0,l.jsx)(O,{data:s}):null,"sources"===x?(0,l.jsx)(V,{data:s}):null,"providers"===x?(0,l.jsx)(D,{data:s}):null,"experience"===x?(0,l.jsx)(H,{data:s}):null,"errors"===x?(0,l.jsx)(B,{data:s}):null,"raw"===x?(0,l.jsx)(G,{data:s}):null]}):null]})}}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=39944)),_N_E=e.O()}]);