zevairouter 1.0.91 → 1.0.92

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 (328) hide show
  1. package/cli/app/.next-cli-build/BUILD_ID +1 -1
  2. package/cli/app/.next-cli-build/app-path-routes-manifest.json +5 -5
  3. package/cli/app/.next-cli-build/build-manifest.json +2 -2
  4. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/automation/page_client-reference-manifest.js +1 -1
  5. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  6. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  7. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  8. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  9. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  10. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/context/page_client-reference-manifest.js +1 -1
  11. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  12. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  13. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  14. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  15. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  16. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  17. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  18. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/playground/page_client-reference-manifest.js +1 -1
  19. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  20. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  21. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  22. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  23. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  24. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/pxpipe/page_client-reference-manifest.js +1 -1
  25. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page.js +1 -1
  26. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  27. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/terminal/page_client-reference-manifest.js +1 -1
  28. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
  29. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  30. package/cli/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  31. package/cli/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
  32. package/cli/app/.next-cli-build/server/app/_global-error.html +1 -1
  33. package/cli/app/.next-cli-build/server/app/_global-error.rsc +1 -1
  34. package/cli/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
  35. package/cli/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  36. package/cli/app/.next-cli-build/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  37. package/cli/app/.next-cli-build/server/app/_global-error.segments/_head.segment.rsc +1 -1
  38. package/cli/app/.next-cli-build/server/app/_global-error.segments/_index.segment.rsc +1 -1
  39. package/cli/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  40. package/cli/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
  41. package/cli/app/.next-cli-build/server/app/_not-found.html +1 -1
  42. package/cli/app/.next-cli-build/server/app/_not-found.rsc +3 -3
  43. package/cli/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +3 -3
  44. package/cli/app/.next-cli-build/server/app/_not-found.segments/_head.segment.rsc +1 -1
  45. package/cli/app/.next-cli-build/server/app/_not-found.segments/_index.segment.rsc +3 -3
  46. package/cli/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  47. package/cli/app/.next-cli-build/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  48. package/cli/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  49. package/cli/app/.next-cli-build/server/app/api/models/route.js +1 -1
  50. package/cli/app/.next-cli-build/server/app/api/models/test/route.js +1 -1
  51. package/cli/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js +1 -1
  52. package/cli/app/.next-cli-build/server/app/api/providers/route.js +1 -1
  53. package/cli/app/.next-cli-build/server/app/api/providers/validate/route.js +1 -1
  54. package/cli/app/.next-cli-build/server/app/api/terminal/session/[id]/input/route.js.nft.json +1 -1
  55. package/cli/app/.next-cli-build/server/app/api/terminal/session/[id]/resize/route.js.nft.json +1 -1
  56. package/cli/app/.next-cli-build/server/app/api/terminal/session/[id]/route.js.nft.json +1 -1
  57. package/cli/app/.next-cli-build/server/app/api/terminal/session/[id]/stream/route.js.nft.json +1 -1
  58. package/cli/app/.next-cli-build/server/app/api/terminal/session/route.js.nft.json +1 -1
  59. package/cli/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
  60. package/cli/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
  61. package/cli/app/.next-cli-build/server/app/api/usage/aggregate/route.js +1 -1
  62. package/cli/app/.next-cli-build/server/app/api/version/route.js +1 -1
  63. package/cli/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
  64. package/cli/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
  65. package/cli/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
  66. package/cli/app/.next-cli-build/server/app/callback.html +1 -1
  67. package/cli/app/.next-cli-build/server/app/callback.rsc +3 -3
  68. package/cli/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +3 -3
  69. package/cli/app/.next-cli-build/server/app/callback.segments/_head.segment.rsc +1 -1
  70. package/cli/app/.next-cli-build/server/app/callback.segments/_index.segment.rsc +3 -3
  71. package/cli/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +1 -1
  72. package/cli/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  73. package/cli/app/.next-cli-build/server/app/callback.segments/callback.segment.rsc +1 -1
  74. package/cli/app/.next-cli-build/server/app/dashboard/automation.html +1 -1
  75. package/cli/app/.next-cli-build/server/app/dashboard/automation.rsc +5 -5
  76. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk/dashboard/automation/__PAGE__.segment.rsc +2 -2
  77. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk/dashboard/automation.segment.rsc +1 -1
  78. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  79. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  80. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_full.segment.rsc +5 -5
  81. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_head.segment.rsc +1 -1
  82. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_index.segment.rsc +3 -3
  83. package/cli/app/.next-cli-build/server/app/dashboard/automation.segments/_tree.segment.rsc +1 -1
  84. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
  85. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +5 -5
  86. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
  87. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
  88. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  89. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  90. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +5 -5
  91. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
  92. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_index.segment.rsc +3 -3
  93. package/cli/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
  94. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
  95. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +5 -5
  96. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  97. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  98. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  99. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  100. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +5 -5
  101. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  102. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
  103. package/cli/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
  104. package/cli/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
  105. package/cli/app/.next-cli-build/server/app/dashboard/combos.rsc +5 -5
  106. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  107. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  108. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  109. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  110. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
  111. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  112. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
  113. package/cli/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
  114. package/cli/app/.next-cli-build/server/app/dashboard/context.html +1 -1
  115. package/cli/app/.next-cli-build/server/app/dashboard/context.rsc +5 -5
  116. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk/dashboard/context/__PAGE__.segment.rsc +2 -2
  117. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk/dashboard/context.segment.rsc +1 -1
  118. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  119. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  120. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_full.segment.rsc +5 -5
  121. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_head.segment.rsc +1 -1
  122. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_index.segment.rsc +3 -3
  123. package/cli/app/.next-cli-build/server/app/dashboard/context.segments/_tree.segment.rsc +1 -1
  124. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
  125. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.rsc +5 -5
  126. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  127. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  128. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  129. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  130. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +5 -5
  131. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  132. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
  133. package/cli/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
  134. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
  135. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +5 -5
  136. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
  137. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
  138. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
  139. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  140. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  141. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +5 -5
  142. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
  143. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +3 -3
  144. package/cli/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
  145. package/cli/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
  146. package/cli/app/.next-cli-build/server/app/dashboard/mitm.rsc +5 -5
  147. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  148. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  149. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  150. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  151. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
  152. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  153. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
  154. package/cli/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
  155. package/cli/app/.next-cli-build/server/app/dashboard/playground.html +1 -1
  156. package/cli/app/.next-cli-build/server/app/dashboard/playground.rsc +5 -5
  157. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk/dashboard/playground/__PAGE__.segment.rsc +2 -2
  158. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk/dashboard/playground.segment.rsc +1 -1
  159. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  160. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  161. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_full.segment.rsc +5 -5
  162. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_head.segment.rsc +1 -1
  163. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_index.segment.rsc +3 -3
  164. package/cli/app/.next-cli-build/server/app/dashboard/playground.segments/_tree.segment.rsc +1 -1
  165. package/cli/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
  166. package/cli/app/.next-cli-build/server/app/dashboard/profile.rsc +5 -5
  167. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
  168. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  169. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  170. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  171. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +5 -5
  172. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  173. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
  174. package/cli/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
  175. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
  176. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.rsc +5 -5
  177. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  178. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  179. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  180. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  181. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  182. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
  183. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  184. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
  185. package/cli/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
  186. package/cli/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
  187. package/cli/app/.next-cli-build/server/app/dashboard/providers.rsc +5 -5
  188. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  189. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  190. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  191. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  192. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
  193. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  194. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
  195. package/cli/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
  196. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
  197. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +5 -5
  198. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  199. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  200. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  201. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  202. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
  203. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  204. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
  205. package/cli/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
  206. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.html +1 -1
  207. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.rsc +5 -5
  208. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe/__PAGE__.segment.rsc +2 -2
  209. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe.segment.rsc +1 -1
  210. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  211. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  212. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_full.segment.rsc +5 -5
  213. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_head.segment.rsc +1 -1
  214. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_index.segment.rsc +3 -3
  215. package/cli/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_tree.segment.rsc +1 -1
  216. package/cli/app/.next-cli-build/server/app/dashboard/quota.html +2 -2
  217. package/cli/app/.next-cli-build/server/app/dashboard/quota.rsc +6 -6
  218. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
  219. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  220. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  221. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  222. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +6 -6
  223. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  224. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
  225. package/cli/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
  226. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  227. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
  228. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +3 -3
  229. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
  230. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  231. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
  232. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
  233. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  234. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  235. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  236. package/cli/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  237. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.html +1 -1
  238. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.rsc +5 -5
  239. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +2 -2
  240. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver.segment.rsc +1 -1
  241. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  242. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  243. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_full.segment.rsc +5 -5
  244. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_head.segment.rsc +1 -1
  245. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_index.segment.rsc +3 -3
  246. package/cli/app/.next-cli-build/server/app/dashboard/token-saver.segments/_tree.segment.rsc +1 -1
  247. package/cli/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
  248. package/cli/app/.next-cli-build/server/app/dashboard/translator.rsc +5 -5
  249. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  250. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  251. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  252. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  253. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
  254. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  255. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
  256. package/cli/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
  257. package/cli/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
  258. package/cli/app/.next-cli-build/server/app/dashboard/usage.rsc +5 -5
  259. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  260. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  261. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  262. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  263. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
  264. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  265. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
  266. package/cli/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
  267. package/cli/app/.next-cli-build/server/app/dashboard.html +1 -1
  268. package/cli/app/.next-cli-build/server/app/dashboard.rsc +5 -5
  269. package/cli/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  270. package/cli/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  271. package/cli/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  272. package/cli/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +5 -5
  273. package/cli/app/.next-cli-build/server/app/dashboard.segments/_head.segment.rsc +1 -1
  274. package/cli/app/.next-cli-build/server/app/dashboard.segments/_index.segment.rsc +3 -3
  275. package/cli/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +1 -1
  276. package/cli/app/.next-cli-build/server/app/index.html +1 -1
  277. package/cli/app/.next-cli-build/server/app/index.rsc +3 -3
  278. package/cli/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  279. package/cli/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +3 -3
  280. package/cli/app/.next-cli-build/server/app/index.segments/_head.segment.rsc +1 -1
  281. package/cli/app/.next-cli-build/server/app/index.segments/_index.segment.rsc +3 -3
  282. package/cli/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +1 -1
  283. package/cli/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
  284. package/cli/app/.next-cli-build/server/app/landing.html +1 -1
  285. package/cli/app/.next-cli-build/server/app/landing.rsc +3 -3
  286. package/cli/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +3 -3
  287. package/cli/app/.next-cli-build/server/app/landing.segments/_head.segment.rsc +1 -1
  288. package/cli/app/.next-cli-build/server/app/landing.segments/_index.segment.rsc +3 -3
  289. package/cli/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +1 -1
  290. package/cli/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  291. package/cli/app/.next-cli-build/server/app/landing.segments/landing.segment.rsc +1 -1
  292. package/cli/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
  293. package/cli/app/.next-cli-build/server/app/login.html +1 -1
  294. package/cli/app/.next-cli-build/server/app/login.rsc +4 -4
  295. package/cli/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +4 -4
  296. package/cli/app/.next-cli-build/server/app/login.segments/_head.segment.rsc +1 -1
  297. package/cli/app/.next-cli-build/server/app/login.segments/_index.segment.rsc +3 -3
  298. package/cli/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +1 -1
  299. package/cli/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  300. package/cli/app/.next-cli-build/server/app/login.segments/login.segment.rsc +1 -1
  301. package/cli/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
  302. package/cli/app/.next-cli-build/server/app-paths-manifest.json +5 -5
  303. package/cli/app/.next-cli-build/server/chunks/3155.js +1 -1
  304. package/cli/app/.next-cli-build/server/chunks/3407.js +1 -1
  305. package/cli/app/.next-cli-build/server/chunks/3831.js +1 -1
  306. package/cli/app/.next-cli-build/server/chunks/4746.js +1 -1
  307. package/cli/app/.next-cli-build/server/chunks/5681.js +1 -1
  308. package/cli/app/.next-cli-build/server/chunks/6896.js +1 -1
  309. package/cli/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
  310. package/cli/app/.next-cli-build/server/pages/404.html +1 -1
  311. package/cli/app/.next-cli-build/server/pages/500.html +1 -1
  312. package/cli/app/.next-cli-build/static/chunks/{3702-30e147d7f8aa1b1e.js → 3702-dce896e3750d4f6f.js} +1 -1
  313. package/cli/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/quota/page-f3b77e4749e85bd8.js +1 -0
  314. package/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/cli/app/src/lib/terminal/ptyBridge.py +163 -0
  315. package/cli/app/package.json +1 -1
  316. package/cli/package.json +1 -1
  317. package/open-sse/services/usage.js +105 -2
  318. package/package.json +1 -1
  319. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/ProviderLimitCard.js +9 -11
  320. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/QuotaProgressBar.js +10 -10
  321. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/QuotaTable.js +4 -2
  322. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.js +41 -9
  323. package/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.js +47 -8
  324. package/src/app/api/usage/aggregate/route.js +16 -1
  325. package/src/shared/constants/providers.js +3 -0
  326. package/cli/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/quota/page-c58270853707170e.js +0 -1
  327. /package/cli/app/.next-cli-build/static/{DeYkfR7AtoBKt2sT-D-8h → jba0lkzn4LzfXxHBpLKVZ}/_buildManifest.js +0 -0
  328. /package/cli/app/.next-cli-build/static/{DeYkfR7AtoBKt2sT-D-8h → jba0lkzn4LzfXxHBpLKVZ}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ (self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3826],{5498:(e,t,a)=>{Promise.resolve().then(a.bind(a,75095)),Promise.resolve().then(a.bind(a,25086))},75095:(e,t,a)=>{"use strict";a.d(t,{default:()=>P});var r=a(95155),n=a(12115),s=a(57250),i=a(42793);function l(e,t){return t&&0!==t?!e||e<0?100:e>=t?0:Math.round((t-e)/t*100):0}function o(e,t){if(!t||"object"!=typeof t)return[];let a=[];try{switch(e.toLowerCase()){case"github":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:e,used:t.used||0,total:t.total||0,resetAt:t.resetAt||null})});break;case"antigravity":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:t.displayName||e,modelKey:e,used:t.used||0,total:t.total||0,resetAt:t.resetAt||null,remainingPercentage:t.remainingPercentage})});break;case"codex":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:e,used:t.used||0,total:t.total||0,remaining:t.remaining,resetAt:t.resetAt||null})});break;case"kiro":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:e,used:t.used||0,total:t.total||0,resetAt:t.resetAt||null})});break;case"qoder":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{("organization"!==e||t&&0!==(Number(t.total)||0))&&a.push({name:"user"===e?"Personal":"organization"===e?"Organization":e,used:t.used||0,total:t.total||0,unit:t.unit,resetAt:t.resetAt||null})});break;case"autoclaw":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:"points"===e?"Points":e,used:t.used||0,total:t.total||0,unit:t.unit,resetAt:t.resetAt||null})});break;case"claude":t.message?a.push({name:"error",used:0,total:0,resetAt:null,message:t.message}):t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:e,used:t.used||0,total:t.total||0,resetAt:t.resetAt||null})});break;case"grok-cli":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{let r=!0===t.unlimited||!(t.total>0)&&t.remainingPercentage>0;a.push({name:e,used:t.used||0,total:r?0:t.total||0,resetAt:t.resetAt||null,remainingPercentage:null!=t.remainingPercentage?t.remainingPercentage:r?100:void 0,unlimited:r})});break;case"cloudflare-ai":t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{let r=!0===t.unlimited||!(t.total>0);a.push({name:e,used:t.used||0,total:r?0:t.total||0,resetAt:t.resetAt||null,remainingPercentage:null!=t.remainingPercentage?t.remainingPercentage:100*!!r,unlimited:r})});break;default:t.quotas&&Object.entries(t.quotas).forEach(([e,t])=>{a.push({name:e,used:t.used||0,total:t.total||0,resetAt:t.resetAt||null,...null!=t.remainingPercentage?{remainingPercentage:t.remainingPercentage}:{},...!0===t.unlimited?{unlimited:!0}:{}})})}}catch(t){return console.error(`Error parsing quota data for ${e}:`,t),[]}let r=(0,i.KC)(e);if(r.length>0){let e=new Map(r.map((e,t)=>[e.id,t]));a.sort((t,a)=>{let r=t.modelKey||t.name,n=a.modelKey||a.name;return(e.get(r)??999)-(e.get(n)??999)})}return a}function c({quotas:e=[],compact:t=!1,sortMode:a="default",showSortLabel:s=!1}){let[i,o]=(0,n.useState)(1),d=(0,n.useMemo)(()=>e.map((e,t)=>({...e,index:t,remaining:function(e){if(e?.unlimited===!0)return e?.remainingPercentage!==void 0&&Number.isFinite(Number(e.remainingPercentage))?Math.max(0,Math.min(100,Math.round(Number(e.remainingPercentage)))):100;if(e?.remainingPercentage!==void 0&&Number.isFinite(Number(e.remainingPercentage)))return Math.max(0,Math.min(100,Math.round(Number(e.remainingPercentage))));if(e?.remaining!==void 0&&Number.isFinite(Number(e.remaining))){let t=Number(e.remaining);if(t>=0&&t<=100&&!(e.total>100&&t<=100&&null!=e.used))return e.total>0?l(e.used,e.total):Math.round(t)}return l(e?.used,e?.total)}(e)})),[e]),u=(0,n.useMemo)(()=>"remaining-asc"===a?[...d].sort((e,t)=>e.remaining-t.remaining||e.name.localeCompare(t.name)):"remaining-desc"===a?[...d].sort((e,t)=>t.remaining-e.remaining||e.name.localeCompare(t.name)):d,[d,a]),m=Math.max(1,Math.ceil(u.length/10));if((0,n.useEffect)(()=>{o(1)},[a,e]),(0,n.useEffect)(()=>{o(e=>Math.min(e,m))},[m]),!e||0===e.length)return null;let x=u.slice((i-1)*10,10*i),h=0===u.length?0:(i-1)*10+1,b=Math.min(10*i,u.length),p=t?"py-1 px-1.5":"py-2 px-3",g=t?"text-[11px]":"text-sm",f=t?"text-[11px]":"text-sm",v=t?"text-[10px] leading-tight":"text-xs";return(0,r.jsxs)("div",{className:"space-y-2",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,r.jsxs)("div",{className:"text-[10px] text-text-muted",children:[u.length," quota",u.length>1?"s":""]}),s&&(0,r.jsx)("div",{className:"rounded-md border border-black/10 bg-black/[0.02] px-2 py-1 text-[10px] text-text-muted dark:border-white/10 dark:bg-white/[0.03]",children:"Sorted by account remaining"})]}),(0,r.jsx)("div",{className:"overflow-x-auto",children:(0,r.jsx)("table",{className:"w-full table-fixed text-left",children:(0,r.jsx)("tbody",{children:x.map(e=>{var a;let n=(a=e.remaining)>70?{text:"text-green-600 dark:text-green-400",bg:"bg-green-500",bgLight:"bg-green-500/10",emoji:"\uD83D\uDFE2"}:a>=30?{text:"text-yellow-600 dark:text-yellow-400",bg:"bg-yellow-500",bgLight:"bg-yellow-500/10",emoji:"\uD83D\uDFE1"}:{text:"text-red-600 dark:text-red-400",bg:"bg-red-500",bgLight:"bg-red-500/10",emoji:"\uD83D\uDD34"},s=function(e){if(!e)return"-";try{let t="string"==typeof e?new Date(e):e,a=new Date,r=t-a;if(r<=0)return"-";let n=Math.ceil(r/6e4);if(n<60)return`${n}m`;let s=Math.floor(n/60),i=n%60;if(s<24)return`${s}h ${i}m`;let l=Math.floor(s/24);return`${l}d ${s%24}h ${i}m`}catch(e){return"-"}}(e.resetAt),i=function(e){if(!e)return null;try{let t=new Date(e),a=new Date,r=new Date(a.getFullYear(),a.getMonth(),a.getDate()),n=new Date(r);n.setDate(n.getDate()+1);let s="";s=t>=r&&t<n?"Today":t>=n&&t<new Date(n.getTime()+864e5)?"Tomorrow":t.toLocaleDateString("en-US",{month:"short",day:"numeric"});let i=t.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",hour12:!0});return`${s}, ${i}`}catch{return null}}(e.resetAt);return(0,r.jsxs)("tr",{className:"border-b border-black/5 dark:border-white/5 hover:bg-black/[0.02] dark:hover:bg-white/[0.02] transition-colors",children:[(0,r.jsx)("td",{className:`${p} w-[30%]`,children:(0,r.jsxs)("div",{className:"flex items-center gap-1.5 min-w-0",children:[(0,r.jsx)("span",{className:"text-[10px] shrink-0",children:n.emoji}),(0,r.jsx)("span",{className:`${g} font-medium text-text-primary truncate`,children:e.name})]})}),(0,r.jsx)("td",{className:`${p} w-[45%]`,children:(0,r.jsxs)("div",{className:t?"space-y-1":"space-y-1.5",children:[(0,r.jsx)("div",{className:`${t?"h-1":"h-1.5"} rounded-full overflow-hidden border ${n.bgLight} ${0===e.remaining?"border-black/10 dark:border-white/10":"border-transparent"}`,children:(0,r.jsx)("div",{className:`h-full transition-all duration-300 ${n.bg}`,style:{width:`${Math.min(e.remaining,100)}%`}})}),(0,r.jsxs)("div",{className:`flex items-center justify-between ${t?"text-[10px]":"text-xs"}`,children:[(0,r.jsx)("span",{className:"text-text-muted",children:!0!==e.unlimited&&e.total>0?`${e.used.toLocaleString()} / ${e.total.toLocaleString()}`:!0===e.unlimited?"Included / ∞":`${e.used.toLocaleString()} / ∞`}),(0,r.jsx)("span",{className:`font-medium ${n.text}`,children:Number.isFinite(e.remaining)?`${e.remaining}%`:"—"})]})]})}),(0,r.jsx)("td",{className:`${p} w-[25%]`,children:"-"!==s||i?t?(0,r.jsx)("div",{className:`${f} text-text-primary font-medium truncate`,title:i||"",children:"-"!==s?`in ${s}`:i}):(0,r.jsxs)("div",{className:"space-y-0.5",children:["-"!==s&&(0,r.jsxs)("div",{className:`${f} text-text-primary font-medium`,children:["in ",s]}),i&&(0,r.jsx)("div",{className:`${v} text-text-muted`,children:i})]}):(0,r.jsx)("div",{className:`${f} text-text-muted italic`,children:"N/A"})})]},`${e.name}-${e.index}`)})})})}),m>1&&(0,r.jsxs)("div",{className:"rounded-md border border-black/10 bg-black/[0.02] px-2 py-1.5 dark:border-white/10 dark:bg-white/[0.03]",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2 text-[10px] text-text-muted",children:[(0,r.jsxs)("span",{children:["Showing ",h,"-",b," of ",u.length]}),(0,r.jsxs)("span",{children:["Page ",i," / ",m]})]}),(0,r.jsxs)("div",{className:"mt-1.5 flex items-center justify-end gap-1",children:[(0,r.jsx)("button",{type:"button",onClick:()=>o(e=>Math.max(1,e-1)),disabled:1===i,className:"flex h-6 items-center rounded-md border border-black/10 px-2 text-[10px] text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"Prev"}),(0,r.jsx)("button",{type:"button",onClick:()=>o(e=>Math.min(m,e+1)),disabled:i===m,className:"flex h-6 items-center rounded-md border border-black/10 px-2 text-[10px] text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"Next"})]})]})]})}var d=a(98542),u=a(84588),m=a(35497),x=a(52679);function h(e){let t=e=>"string"==typeof e&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);return t(e.email)?e.email:(t(e.name),e.name)}function b(e,t){let a=t[e.id]?.quotas?.[0];return a&&"number"==typeof a.remaining?a.remaining:1/0}function p(e){return x.Q2[e]?.name||e}function g(e){let t={};return e.forEach(e=>{t[e.id]=!0}),t}function f(e,t){let a=new Set(t.map(e=>e.id));return Object.fromEntries(Object.entries(e).filter(([e])=>a.has(e)))}async function v(e,t){return await e(t)}let y="quotaCacheData";function k(){try{let e=window.localStorage.getItem(y);return e?JSON.parse(e):{}}catch(e){return console.error("Error reading quota cache:",e),{}}}function w(e,t){try{let a=k();a[e]={...t,cachedAt:new Date().toISOString()},window.localStorage.setItem(y,JSON.stringify(a))}catch(e){console.error("Error writing quota cache:",e)}}let j="quotaAutoRefresh",N=[{value:"all",label:"All accounts"},{value:"active",label:"Active"},{value:"inactive",label:"Turned off"}],S=[{value:"single",label:"Satuan",icon:"account_circle"},{value:"bulk",label:"Bulk",icon:"stacks"}],C=[{value:"default",label:"Default quota order"},{value:"remaining-asc",label:"% quota: low to high"},{value:"remaining-desc",label:"% quota: high to low"}],$=[10,20,50,100];function P(){let[e,t]=(0,n.useState)([]),[a,i]=(0,n.useState)({}),[P,A]=(0,n.useState)({}),[q,E]=(0,n.useState)({}),[M,D]=(0,n.useState)(!0),[O,I]=(0,n.useState)(null),[T,_]=(0,n.useState)(!1),[F,L]=(0,n.useState)(!1),[z,U]=(0,n.useState)(60),[R,J]=(0,n.useState)(!0),[K,B]=(0,n.useState)(null),[Q,W]=(0,n.useState)(null),[G,H]=(0,n.useState)(!1),[Y,V]=(0,n.useState)(null),[X,Z]=(0,n.useState)([]),[ee,et]=(0,n.useState)("all"),[ea,er]=(0,n.useState)([]),[en,es]=(0,n.useState)("single"),[ei,el]=(0,n.useState)("all"),[eo,ec]=(0,n.useState)("default"),[ed,eu]=(0,n.useState)(!1),[em,ex]=(0,n.useState)(!1),[eh,eb]=(0,n.useState)(!1),[ep,eg]=(0,n.useState)({}),[ef,ev]=(0,n.useState)({}),[ey,ek]=(0,n.useState)(1),[ew,ej]=(0,n.useState)(20),[eN,eS]=(0,n.useState)(String(20)),[eC,e$]=(0,n.useState)({page:1,pageSize:20,total:0,totalPages:1}),[eP,eA]=(0,n.useState)({eligibleConnections:0,providerFilteredConnections:0}),eq=(0,n.useRef)(null),eE=(0,n.useRef)(null),eM=(0,n.useCallback)(async(e=ey)=>{try{var a,r;let n=new URLSearchParams({page:String(e),pageSize:String(ew),accountStatus:ei,sort:"priority"});"all"!==ee&&n.set("provider",ee);let s=await fetch(`/api/providers/client?${n.toString()}`);if(!s.ok)throw Error("Failed to fetch connections");let i=await s.json(),l=i.connections||[],o=(a=i.pagination,a||{page:1,pageSize:ew,total:0,totalPages:1}),c=function(e,t=0){return e||{eligibleConnections:t,providerFilteredConnections:t}}(i.totals,l.length);return t(l),er(i.providerOptions||[]),e$(o),eA(c),ek((r=i.pagination,r?.page||e)),l}catch(e){return console.error("Error fetching connections:",e),t([]),er([]),e$({page:1,pageSize:ew,total:0,totalPages:1}),eA({eligibleConnections:0,providerFilteredConnections:0}),[]}},[ei,ey,ew,ee]),eD=(0,n.useCallback)(async(e,t,a=!1)=>{A(t=>({...t,[e]:!0})),E(t=>({...t,[e]:null}));try{console.log(`[ProviderLimits] Fetching quota for ${t} (${e})`);let r=await fetch(`/api/usage/${e}${a?"?refresh=1":""}`);if(!r.ok){let a=(await r.json().catch(()=>({}))).error||r.statusText;if(404===r.status)return void console.warn(`[ProviderLimits] Connection not found for ${t}, skipping`);if(401===r.status){console.warn(`[ProviderLimits] Auth error for ${t}:`,a);let r={quotas:[],message:a};i(t=>({...t,[e]:r})),w(e,r);return}throw Error(`HTTP ${r.status}: ${a}`)}let n=await r.json();console.log(`[ProviderLimits] Got quota for ${t}:`,n);let s={quotas:o(t,n),plan:n.plan||null,message:n.message||null,raw:n};i(t=>({...t,[e]:s})),w(e,s)}catch(a){console.error(`[ProviderLimits] Error fetching quota for ${t} (${e}):`,a),E(t=>({...t,[e]:a.message||"Failed to fetch quota"}))}finally{A(t=>({...t,[e]:!1}))}},[]),eO=(0,n.useCallback)(async(e,t)=>{await eD(e,t),I(new Date)},[eD]),eI=(0,n.useCallback)(async(e,t=!1)=>{if(e&&"all"!==e){ev(t=>({...t,[e]:!0}));try{let a=`/api/usage/aggregate?provider=${encodeURIComponent(e)}${t?"&refresh=1":""}`,r=await fetch(a);if(!r.ok)throw Error("Failed to fetch aggregate");let n=await r.json(),s=o(e,n);eg(t=>({...t,[e]:{quotas:s,plan:n.plan||null,accountCount:n.accountCount||0,accountsWithQuota:n.accountsWithQuota||0,deadCount:n.deadCount||0}}))}catch(t){console.error(`[ProviderLimits] Aggregate fetch error for ${e}:`,t)}finally{ev(t=>({...t,[e]:!1}))}}},[]),eT=(0,n.useCallback)(async(e,t)=>{if("bulk"===en&&t){await eI(t,!0),I(new Date);return}e?.length&&(A(t=>({...t,...Object.fromEntries(e.map(e=>[e,!0]))})),await Promise.all(e.map(e=>eD(e,t))),I(new Date))},[eD,en,eI]),e_=(0,n.useCallback)(async e=>{if(confirm("Delete this connection?")){B(e);try{if((await fetch(`/api/providers/${e}`,{method:"DELETE"})).ok){i(t=>{let a={...t};return delete a[e],a}),A(t=>{let a={...t};return delete a[e],a}),E(t=>{let a={...t};return delete a[e],a});try{let t=k();t[e]&&(delete t[e],window.localStorage.setItem(y,JSON.stringify(t)))}catch(e){console.error("Error deleting cache entry:",e)}await v(eM,ey)}}catch(e){console.error("Error deleting connection:",e)}finally{B(null)}}},[eM,ey]),eF=(0,n.useCallback)(async(e,t)=>{W(e);try{(await fetch(`/api/providers/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:t})})).ok&&(i(e=>({...e})),await v(eM,ey))}catch(e){console.error("Error updating connection status:",e)}finally{W(null)}},[eM,ey]),eL=(0,n.useCallback)(async e=>{if(!Y?.id)return;let t=Y.id,a=Y.provider;try{(await fetch(`/api/providers/${t}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).ok&&(await eM(),H(!1),V(null),x.wb.includes(a)&&await eD(t,a))}catch(e){console.error("Error saving connection:",e)}},[Y,eM,eD]);(0,n.useEffect)(()=>{let e=!1;return fetch("/api/proxy-pools?isActive=true",{cache:"no-store"}).then(e=>e.json()).then(t=>{!e&&t?.proxyPools&&Z(t.proxyPools)}).catch(()=>{}),()=>{e=!0}},[]);let ez=(0,n.useCallback)(async()=>{if(!F){L(!0),U(60);try{let e=await eM(ey);A(g(e)),E(t=>f(t,e)),i(t=>f(t,e)),await Promise.all(e.map(e=>eD(e.id,e.provider,!0))),"bulk"===en&&("all"!==ee?[ee]:ea.map(e=>e.value||e).filter(e=>"all"!==e)).forEach(e=>eI(e,!0)),I(new Date)}catch(e){console.error("Error refreshing all providers:",e)}finally{L(!1)}}},[F,eM,eD,ey,en,ee,ea,eI]);(0,n.useEffect)(()=>{(async()=>{J(!0);let e=await eM(ey);J(!1),A(g(e)),E(t=>f(t,e)),i(t=>f(t,e)),await Promise.all(e.map(e=>eD(e.id,e.provider))),I(new Date)})()},[eM,eD,ey]),(0,n.useEffect)(()=>{"bulk"!==en||("all"!==ee?[ee]:ea.map(e=>e.value||e).filter(e=>"all"!==e)).forEach(e=>eI(e))},[en,ee,ea,eI]),(0,n.useEffect)(()=>{let e=window.localStorage.getItem(j);D(null===e||"true"===e),_(!0)},[]),(0,n.useEffect)(()=>{T&&window.localStorage.setItem(j,String(M))},[M,T]),(0,n.useEffect)(()=>{if(!T||!M){eq.current&&(clearInterval(eq.current),eq.current=null),eE.current&&(clearInterval(eE.current),eE.current=null);return}return eq.current=setInterval(()=>{ez()},6e4),eE.current=setInterval(()=>{U(e=>e<=1?60:e-1)},1e3),()=>{eq.current&&clearInterval(eq.current),eE.current&&clearInterval(eE.current)}},[M,ez,T]),(0,n.useEffect)(()=>{let e=()=>{document.hidden?(eq.current&&(clearInterval(eq.current),eq.current=null),eE.current&&(clearInterval(eE.current),eE.current=null)):M&&T&&(eq.current=setInterval(ez,6e4),eE.current=setInterval(()=>{U(e=>e<=1?60:e-1)},1e3))};return document.addEventListener("visibilitychange",e),()=>{document.removeEventListener("visibilitychange",e)}},[M,ez,T]);let eU=(0,n.useMemo)(()=>(function(e,t,a,r,n){if("codex"===r&&"default"!==n)return[...e].sort((e,a)=>{let r=b(e,t),s=b(a,t),i="remaining-asc"===n?r-s:s-r;return 0!==i?i:(h(e)||"").localeCompare(h(a)||"")});if(!a)return e;let s=e=>{let a=(t[e.id]?.quotas||[]).map(e=>e.resetAt?new Date(e.resetAt).getTime():1/0).filter(e=>Number.isFinite(e));return a.length>0?Math.min(...a):1/0};return[...e].sort((e,t)=>{let a=s(e)-s(t);return 0!==a?a:(e.provider||"").localeCompare(t.provider||"")||(h(e)||"").localeCompare(h(t)||"")})})(e,a,ed,ee,eo),[e,a,ed,ee,eo]),eR=(0,n.useMemo)(()=>{let e;return e=new Map,eU.forEach(t=>{t.provider&&(e.has(t.provider)||e.set(t.provider,[]),e.get(t.provider).push(t))}),[...e.entries()].map(([e,t])=>(function(e,t,a,r,n){if(!t.length)return null;let s=[],i=[],l=null,o=!1;return t.forEach(e=>{let t=a[e.id];Array.isArray(t?.quotas)&&s.push(...t.quotas),t?.message&&!l&&(l=t.message),n[e.id]&&i.push(n[e.id]),r[e.id]&&(o=!0)}),{id:`${e}-aggregate`,provider:e,name:p(e),email:`${t.length} accounts`,isActive:t.some(e=>e.isActive??!0),isAggregate:!0,quota:{quotas:function(e=[]){let t=new Map;return e.forEach(e=>{if(!e?.name)return;let a=t.get(e.name)||{name:e.name,used:0,total:0,resetAt:e.resetAt||null,remainingPercentage:null,unlimited:!1,_pctSum:0,_pctCount:0};a.used+=Number(e.used)||0,a.total+=Number(e.total)||0,!0===e.unlimited&&(a.unlimited=!0),null!=e.remainingPercentage&&Number.isFinite(Number(e.remainingPercentage))&&(a._pctSum+=Number(e.remainingPercentage),a._pctCount+=1),e.resetAt&&(!a.resetAt||new Date(e.resetAt).getTime()<new Date(a.resetAt).getTime())&&(a.resetAt=e.resetAt),t.set(e.name,a)}),[...t.values()].map(e=>{let{_pctSum:t,_pctCount:a,...r}=e;return r.unlimited?(r.remainingPercentage=100,r.total=0):r.total>0?r.remainingPercentage=(r.total-r.used)/r.total*100:a>0?r.remainingPercentage=t/a:r.remainingPercentage=0,r})}(s),message:0===s.length&&l||null},isLoading:o,error:!s.length&&i.length>0?i[0]:null,connectionIds:t.map(e=>e.id)}})(e,t,a,P,q)).filter(Boolean)},[eU,a,P,q]),eJ=(0,n.useMemo)(()=>Object.keys(ep).length?eR.map(e=>{let t=ep[e.provider];return t&&t.quotas?.length?{...e,email:`${t.accountCount||e.connectionIds?.length||0} accounts`,quota:{...e.quota,quotas:t.quotas,message:null},isLoading:ef[e.provider]||!1}:e}):eR,[eR,ep,ef]),eK=(0,n.useMemo)(()=>"bulk"===en?eJ:eU,[en,eJ,eU]),eB=e=>{let t=a[e.id]?.quotas;return!!t?.length&&t.some(e=>!!e.total&&!(e.total<=0)&&5>=l(e.used,e.total))},eQ=(0,n.useCallback)(async(e,t)=>{if(e.length&&!eh){eb(!0);try{await Promise.all(e.map(e=>fetch(`/api/providers/${e}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({isActive:t})}))),await v(eM,ey)}catch(e){console.error("Error bulk toggling connections:",e)}finally{eb(!1)}}},[eh,eM,ey]),eW="all"===ee?"All providers":ee,eG=eP.eligibleConnections>0,eH=eK.length>0,eY=eP.eligibleConnections?eP.providerFilteredConnections?{icon:"filter_alt_off",title:"No Accounts On This Page",description:"Try moving to another page or refreshing the current filters."}:{icon:"filter_alt_off",title:"No Accounts Match Current Filters",description:"all"===ee?"Try changing the account status filter to see more quota trackers.":`No ${"inactive"===ei?"turned off":"active"===ei?"active":"matching"} accounts found for ${ee}.`}:{icon:"cloud_off",title:"No Providers Connected",description:"Connect to providers with OAuth to track your API quota limits and usage."},eV=function(e){var t;let{start:a,end:r}=(t=e).total?{start:(t.page-1)*t.pageSize+1,end:Math.min(t.page*t.pageSize,t.total)}:{start:0,end:0};return`Showing ${a}-${r} of ${e.total}`}(eC),eX=!$.includes(ew);return R||eG?R||eH?(0,r.jsxs)("div",{className:"space-y-6",children:[(0,r.jsx)("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-end",children:(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-1.5",children:[(0,r.jsxs)("div",{className:"relative",children:[(0,r.jsxs)("button",{type:"button",onClick:()=>ex(e=>!e),className:"flex h-8 items-center justify-between gap-1 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-haspopup":"menu","aria-expanded":em,title:"Filter quota providers",children:[(0,r.jsxs)("span",{className:"flex min-w-0 items-center gap-1.5",children:["all"===ee?(0,r.jsx)("span",{className:"material-symbols-outlined text-[14px] text-text-muted",children:"apps"}):(0,r.jsx)(s.A,{src:`/providers/${ee}.png`,alt:ee,size:18,className:"size-[18px] rounded object-contain",fallbackText:ee.slice(0,2).toUpperCase()}),(0,r.jsx)("span",{className:"truncate capitalize hidden lg:inline",children:eW})]}),(0,r.jsx)("span",{className:"material-symbols-outlined text-[14px] text-text-muted",children:"expand_more"})]}),em&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("button",{type:"button",className:"fixed inset-0 z-30 bg-transparent","aria-label":"Close provider filter",onClick:()=>ex(!1)}),(0,r.jsxs)("div",{className:"absolute left-0 z-40 mt-2 w-64 overflow-hidden rounded-2xl border border-black/10 bg-surface/95 p-1.5 shadow-xl shadow-black/10 backdrop-blur dark:border-white/10 dark:bg-surface/95 sm:w-72",children:[(0,r.jsxs)("button",{type:"button",onClick:()=>{"all"!==ee&&ek(1),et("all"),ex(!1)},className:`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm transition-colors ${"all"===ee?"bg-primary/10 text-primary":"text-text-primary hover:bg-black/5 dark:hover:bg-white/10"}`,children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[22px]",children:"apps"}),(0,r.jsx)("span",{className:"font-medium",children:"All providers"}),"all"===ee&&(0,r.jsx)("span",{className:"material-symbols-outlined ml-auto text-[20px]",children:"check"})]}),(0,r.jsx)("div",{className:"my-1 h-px bg-black/10 dark:bg-white/10"}),(0,r.jsx)("div",{className:"max-h-72 overflow-y-auto pr-1",children:ea.map(e=>(0,r.jsxs)("button",{type:"button",onClick:()=>{ee!==e&&ek(1),et(e),ex(!1)},className:`flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm transition-colors ${ee===e?"bg-primary/10 text-primary":"text-text-primary hover:bg-black/5 dark:hover:bg-white/10"}`,children:[(0,r.jsx)(s.A,{src:`/providers/${e}.png`,alt:e,size:24,className:"size-6 rounded-md object-contain",fallbackText:e.slice(0,2).toUpperCase()}),(0,r.jsx)("span",{className:"font-medium capitalize",children:e}),ee===e&&(0,r.jsx)("span",{className:"material-symbols-outlined ml-auto text-[20px]",children:"check"})]},e))})]})]})]}),(0,r.jsx)("div",{className:"inline-flex h-8 overflow-hidden rounded-lg border border-black/10 bg-black/[0.02] dark:border-white/10 dark:bg-white/[0.03]",children:S.map(e=>(0,r.jsxs)("button",{type:"button",onClick:()=>es(e.value),"aria-pressed":en===e.value,className:`flex h-full items-center gap-1.5 px-2 text-xs transition-colors ${en===e.value?"bg-primary text-white":"text-text-primary hover:bg-black/5 dark:hover:bg-white/10"}`,title:`Show quota in ${e.label} mode`,children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:e.icon}),(0,r.jsx)("span",{className:"hidden sm:inline",children:e.label})]},e.value))}),(0,r.jsx)("select",{value:ei,onChange:e=>{let t=e.target.value;ei!==t&&ek(1),el(t)},className:"h-8 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Filter accounts by status",children:N.map(e=>(0,r.jsx)("option",{value:e.value,children:e.label},e.value))}),"codex"===ee&&(0,r.jsx)("select",{value:eo,onChange:e=>ec(e.target.value),className:"h-8 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Sort Codex quotas by remaining",children:C.map(e=>(0,r.jsx)("option",{value:e.value,children:e.label},e.value))}),(0,r.jsxs)("button",{type:"button",onClick:()=>eu(e=>!e),"aria-pressed":ed,className:`flex h-8 shrink-0 items-center gap-1 rounded-lg border px-2 text-xs transition-colors ${ed?"border-amber-500/40 bg-amber-500/10 text-amber-500":"border-black/10 text-text-primary hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5"}`,title:"Sort accounts by earliest quota reset time",children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"hourglass_top"}),(0,r.jsx)("span",{className:"hidden sm:inline",children:"Expiring first"})]}),(0,r.jsxs)("button",{type:"button",onClick:()=>{eQ(eU.filter(e=>(e.isActive??!0)&&eB(e)).map(e=>e.id),!1)},disabled:eh,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-red-500/30 px-2 text-xs text-red-500 transition-colors hover:bg-red-500/10 disabled:opacity-50",title:"Disable connections with depleted quota on the current page",children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"block"}),(0,r.jsx)("span",{className:"hidden sm:inline",children:"Turn off Empty"})]}),(0,r.jsxs)("button",{type:"button",onClick:()=>{eQ(eU.filter(e=>!(e.isActive??!0)&&!eB(e)).map(e=>e.id),!0)},disabled:eh,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-emerald-500/30 px-2 text-xs text-emerald-500 transition-colors hover:bg-emerald-500/10 disabled:opacity-50",title:"Enable connections that still have quota on the current page",children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[14px]",children:"check_circle"}),(0,r.jsx)("span",{className:"hidden sm:inline",children:"Turn on Available"})]}),(0,r.jsxs)("button",{onClick:()=>D(e=>!e),className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-black/10 px-2 text-xs transition-colors hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5",title:M?"Disable auto-refresh":"Enable auto-refresh",children:[(0,r.jsx)("span",{className:`material-symbols-outlined text-[14px] ${M?"text-primary":"text-text-muted"}`,children:M?"toggle_on":"toggle_off"}),(0,r.jsx)("span",{className:"hidden text-text-primary sm:inline",children:"Auto-refresh"}),M&&(0,r.jsxs)("span",{className:"text-[10px] text-text-muted tabular-nums",children:["(",z,"s)"]})]}),(0,r.jsx)("button",{type:"button",onClick:ez,disabled:F,className:"flex h-8 shrink-0 items-center gap-1 rounded-lg border border-black/10 px-2 text-xs text-text-primary transition-colors hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5 disabled:opacity-50",title:"Refresh all",children:(0,r.jsx)("span",{className:`material-symbols-outlined text-[14px] ${F?"animate-spin":""}`,children:"refresh"})})]})}),ed&&(0,r.jsx)("div",{className:"rounded-xl border border-amber-500/20 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-300",children:"Expiring-first currently reorders accounts inside the current page. Cross-page ordering still follows backend pagination."}),(0,r.jsx)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:eK.map(e=>{let t=!0===e.isAggregate,n=t?e.quota:a[e.id],i=t?e.isLoading:P[e.id],l=t?e.error:q[e.id],o=!1===e.isActive,m=!t&&(K===e.id||Q===e.id);return(0,r.jsxs)(u.default,{padding:"none",className:`min-w-0 ${o?"opacity-60":""}`,children:[(0,r.jsx)("div",{className:"px-3 py-2 border-b border-black/10 dark:border-white/10",children:(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,r.jsxs)("div",{className:"flex items-center gap-2 min-w-0",children:[(0,r.jsx)("div",{className:"w-8 h-8 shrink-0 rounded-md flex items-center justify-center overflow-hidden",children:(0,r.jsx)(s.A,{src:`/providers/${e.provider}.png`,alt:e.provider,size:32,className:"object-contain",fallbackText:e.provider?.slice(0,2).toUpperCase()||"PR"})}),(0,r.jsxs)("div",{className:"min-w-0",children:[(0,r.jsx)("h3",{className:"text-sm font-semibold text-text-primary capitalize truncate",children:e.name||p(e.provider)}),h(e)?(0,r.jsx)("p",{className:"text-xs text-text-muted truncate",children:h(e)}):null]})]}),(0,r.jsxs)("div",{className:"flex items-center gap-1 shrink-0",children:[(0,r.jsx)("button",{type:"button",onClick:()=>t?eT(e.connectionIds,e.provider):eO(e.id,e.provider),disabled:i||m,"aria-label":"Refresh quota",className:"p-1.5 rounded-lg hover:bg-black/5 dark:hover:bg-white/5 transition-colors disabled:opacity-50",title:"Refresh quota",children:(0,r.jsx)("span",{className:`material-symbols-outlined text-[18px] text-text-muted ${i?"animate-spin":""}`,children:"refresh"})}),!t&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("button",{type:"button",onClick:()=>{V(e),H(!0)},disabled:m,"aria-label":"Edit connection",className:"p-1.5 rounded-lg hover:bg-black/5 dark:hover:bg-white/5 text-text-muted hover:text-primary transition-colors disabled:opacity-50",title:"Edit connection",children:(0,r.jsx)("span",{className:"material-symbols-outlined text-[18px]",children:"edit"})}),(0,r.jsx)("button",{type:"button",onClick:()=>e_(e.id),disabled:m,"aria-label":"Delete connection",className:"p-1.5 rounded-lg hover:bg-red-500/10 text-red-500 transition-colors disabled:opacity-50",title:"Delete connection",children:(0,r.jsx)("span",{className:`material-symbols-outlined text-[18px] ${K===e.id?"animate-pulse":""}`,children:"delete"})}),(0,r.jsx)("div",{className:"inline-flex items-center pl-0.5",title:e.isActive??!0?"Disable connection":"Enable connection",children:(0,r.jsx)(d.default,{size:"sm",checked:e.isActive??!0,disabled:m,onChange:t=>eF(e.id,t)})})]})]})]})}),(0,r.jsx)("div",{className:"px-2 py-1.5",children:i?(0,r.jsx)("div",{className:"text-center py-5 text-text-muted",children:(0,r.jsx)("span",{className:"material-symbols-outlined text-[28px] animate-spin",children:"progress_activity"})}):l?(0,r.jsxs)("div",{className:"text-center py-5",children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[28px] text-red-500",children:"error"}),(0,r.jsx)("p",{className:"mt-1.5 text-xs text-text-muted",children:l})]}):n?.quotas?.length>0?(0,r.jsxs)("div",{className:"space-y-2",children:[(0,r.jsx)(c,{quotas:n.quotas,compact:!0,sortMode:"default",showSortLabel:"codex"===e.provider&&"default"!==eo}),n?.message?(0,r.jsx)("p",{className:"px-1 text-[10px] text-text-muted",children:n.message}):null]}):n?.message?(0,r.jsx)("div",{className:"text-center py-5",children:(0,r.jsx)("p",{className:"text-xs text-text-muted",children:n.message})}):(0,r.jsx)("div",{className:"text-center py-5 text-text-muted",children:(0,r.jsx)("p",{className:"text-xs",children:"No quota data available"})})})]},e.id)})}),(0,r.jsx)("div",{className:"rounded-xl border border-black/10 bg-black/[0.02] px-3 py-2 dark:border-white/10 dark:bg-white/[0.03]",children:(0,r.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-text-muted",children:eV}),(0,r.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,r.jsxs)("select",{value:eX?"custom":String(ew),onChange:e=>{let t=e.target.value;if("custom"===t)return;let a=Number.parseInt(t,10);Number.isFinite(a)&&(ek(1),ej(a),eS(String(a)))},className:"h-8 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Accounts per page",children:[$.map(e=>(0,r.jsxs)("option",{value:String(e),children:[e," / page"]},e)),(0,r.jsx)("option",{value:"custom",children:"Custom"})]}),(0,r.jsx)("input",{type:"number",min:"1",max:String(500),inputMode:"numeric",value:eN,onChange:e=>eS(e.target.value),onBlur:()=>{let e=Number.parseInt(eN,10);if(!Number.isFinite(e))return void eS(String(ew));let t=Math.min(500,Math.max(1,e));ek(1),ej(t),eS(String(t))},onKeyDown:e=>{if("Enter"!==e.key)return;let t=Number.parseInt(eN,10);if(!Number.isFinite(t))return void eS(String(ew));let a=Math.min(500,Math.max(1,t));ek(1),ej(a),eS(String(a))},className:"h-8 w-20 rounded-lg border border-black/10 bg-black/[0.02] px-2 text-xs text-text-primary outline-none transition-colors hover:bg-black/5 dark:border-white/10 dark:bg-white/[0.03] dark:hover:bg-white/10","aria-label":"Custom accounts per page",placeholder:"Custom"}),(0,r.jsxs)("span",{className:"text-xs text-text-muted",children:["Page ",eC.page," / ",eC.totalPages]})]}),(0,r.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,r.jsx)("button",{type:"button",onClick:()=>ek(1),disabled:eC.page<=1||R||F,className:"flex h-8 items-center rounded-lg border border-black/10 px-3 text-xs text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"First Page"}),(0,r.jsx)("button",{type:"button",onClick:()=>ek(e=>Math.max(1,e-1)),disabled:eC.page<=1||R||F,className:"flex h-8 w-8 items-center justify-center rounded-lg border border-black/10 text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5","aria-label":"Previous accounts page",children:(0,r.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"chevron_left"})}),(0,r.jsx)("button",{type:"button",onClick:()=>ek(e=>Math.min(eC.totalPages,e+1)),disabled:eC.page>=eC.totalPages||R||F,className:"flex h-8 w-8 items-center justify-center rounded-lg border border-black/10 text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5","aria-label":"Next accounts page",children:(0,r.jsx)("span",{className:"material-symbols-outlined text-[16px]",children:"chevron_right"})}),(0,r.jsx)("button",{type:"button",onClick:()=>ek(eC.totalPages),disabled:eC.page>=eC.totalPages||R||F,className:"flex h-8 items-center rounded-lg border border-black/10 px-3 text-xs text-text-primary transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-40 dark:border-white/10 dark:hover:bg-white/5",children:"Last Page"})]})]})}),(0,r.jsx)(m.wI,{isOpen:G,connection:Y,proxyPools:X,onSave:eL,onClose:()=>{H(!1),V(null)}})]}):(0,r.jsx)(u.default,{padding:"lg",children:(0,r.jsxs)("div",{className:"text-center py-12",children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[64px] text-text-muted opacity-20",children:eY.icon}),(0,r.jsx)("h3",{className:"mt-4 text-lg font-semibold text-text-primary",children:eY.title}),(0,r.jsx)("p",{className:"mt-2 text-sm text-text-muted max-w-md mx-auto",children:eY.description})]})}):(0,r.jsx)(u.default,{padding:"lg",children:(0,r.jsxs)("div",{className:"text-center py-12",children:[(0,r.jsx)("span",{className:"material-symbols-outlined text-[64px] text-text-muted opacity-20",children:"cloud_off"}),(0,r.jsx)("h3",{className:"mt-4 text-lg font-semibold text-text-primary",children:"No Providers Connected"}),(0,r.jsx)("p",{className:"mt-2 text-sm text-text-muted max-w-md mx-auto",children:"Connect to providers with OAuth to track your API quota limits and usage."})]})})}}},e=>{e.O(0,[2574,3862,4343,3702,5497,8441,3794,7358],()=>e(e.s=5498)),_N_E=e.O()}]);
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Minimal PTY bridge for ZevaiRouter web terminal.
4
+
5
+ stdin -> PTY master (keystrokes)
6
+ stdout <- PTY master (shell output), raw binary
7
+ stderr = control / errors (utf-8 text lines)
8
+
9
+ Optional control on a side channel is not needed: resize arrives as
10
+ OSC-like escape on stdin: \\x1b]9999;<cols>;<rows>\\x07
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import errno
15
+ import fcntl
16
+ import os
17
+ import select
18
+ import signal
19
+ import struct
20
+ import sys
21
+ import termios
22
+
23
+
24
+ def set_winsize(fd: int, rows: int, cols: int) -> None:
25
+ try:
26
+ packed = struct.pack("HHHH", max(5, rows), max(20, cols), 0, 0)
27
+ fcntl.ioctl(fd, termios.TIOCSWINSZ, packed)
28
+ except Exception:
29
+ pass
30
+
31
+
32
+ def main() -> int:
33
+ cols = int(sys.argv[1]) if len(sys.argv) > 1 else 120
34
+ rows = int(sys.argv[2]) if len(sys.argv) > 2 else 40
35
+ shell = os.environ.get("SHELL") or ("/bin/bash" if os.path.exists("/bin/bash") else "/bin/sh")
36
+ cwd = os.path.expanduser("~")
37
+
38
+ pid, master = pty_fork = _fork_pty()
39
+ if pid == 0:
40
+ # child
41
+ try:
42
+ os.chdir(cwd)
43
+ except Exception:
44
+ pass
45
+ os.environ.setdefault("TERM", "xterm-256color")
46
+ os.environ.setdefault("COLORTERM", "truecolor")
47
+ os.environ.setdefault("FORCE_COLOR", "1")
48
+ try:
49
+ os.execv(shell, [shell, "-il"])
50
+ except Exception:
51
+ os.execv("/bin/sh", ["/bin/sh", "-i"])
52
+ return 1
53
+
54
+ set_winsize(master, rows, cols)
55
+
56
+ # Non-blocking master + stdin
57
+ for fd in (master, sys.stdin.fileno()):
58
+ fl = fcntl.fcntl(fd, fcntl.F_GETFL)
59
+ fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
60
+
61
+ # Binary stdout
62
+ stdout = sys.stdout.buffer
63
+ stdin = sys.stdin.buffer
64
+
65
+ resize_buf = b""
66
+
67
+ def handle_resize_escape(chunk: bytes) -> bytes:
68
+ """Strip and apply embedded resize escapes, return remaining bytes."""
69
+ nonlocal resize_buf
70
+ data = resize_buf + chunk
71
+ out = bytearray()
72
+ i = 0
73
+ while i < len(data):
74
+ # ESC ] 9999 ; cols ; rows BEL
75
+ if data[i] == 0x1B and data[i : i + 6] == b"\x1b]9999;":
76
+ end = data.find(b"\x07", i + 6)
77
+ if end < 0:
78
+ resize_buf = data[i:]
79
+ return bytes(out)
80
+ payload = data[i + 6 : end].decode("ascii", "ignore")
81
+ try:
82
+ c_s, r_s = payload.split(";", 1)
83
+ set_winsize(master, int(r_s), int(c_s))
84
+ except Exception:
85
+ pass
86
+ i = end + 1
87
+ resize_buf = b""
88
+ continue
89
+ out.append(data[i])
90
+ i += 1
91
+ resize_buf = b""
92
+ return bytes(out)
93
+
94
+ alive = True
95
+
96
+ def on_chld(signum, frame): # noqa: ARG001
97
+ nonlocal alive
98
+ alive = False
99
+
100
+ signal.signal(signal.SIGCHLD, on_chld)
101
+
102
+ try:
103
+ while alive:
104
+ try:
105
+ r, _, _ = select.select([master, sys.stdin.fileno()], [], [], 0.25)
106
+ except InterruptedError:
107
+ continue
108
+
109
+ if master in r:
110
+ try:
111
+ data = os.read(master, 8192)
112
+ except OSError as e:
113
+ if e.errno in (errno.EIO, errno.EAGAIN, errno.EWOULDBLOCK):
114
+ data = b""
115
+ else:
116
+ break
117
+ if not data:
118
+ # EIO often means child exited
119
+ if not alive:
120
+ break
121
+ else:
122
+ stdout.write(data)
123
+ stdout.flush()
124
+
125
+ if sys.stdin.fileno() in r:
126
+ try:
127
+ data = stdin.read(8192)
128
+ except Exception:
129
+ data = b""
130
+ if data is None:
131
+ data = b""
132
+ if data == b"" and not alive:
133
+ break
134
+ if data:
135
+ cleaned = handle_resize_escape(data)
136
+ if cleaned:
137
+ try:
138
+ os.write(master, cleaned)
139
+ except OSError:
140
+ break
141
+ finally:
142
+ try:
143
+ os.close(master)
144
+ except Exception:
145
+ pass
146
+ try:
147
+ os.waitpid(pid, 0)
148
+ except Exception:
149
+ pass
150
+ return 0
151
+
152
+
153
+ def _fork_pty():
154
+ import pty
155
+
156
+ return pty.fork()
157
+
158
+
159
+ if __name__ == "__main__":
160
+ try:
161
+ raise SystemExit(main())
162
+ except KeyboardInterrupt:
163
+ raise SystemExit(0)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zevairouter",
3
- "version": "1.0.91",
3
+ "version": "1.0.92",
4
4
  "description": "Self-hosted AI router: many providers, one OpenAI-compatible /v1 endpoint and dashboard",
5
5
  "bin": {
6
6
  "zevai": "./cli/cli.js"
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zevairouter-cli",
3
- "version": "1.0.91",
3
+ "version": "1.0.92",
4
4
  "description": "ZevaiRouter CLI - Start and manage ZevaiRouter server",
5
5
  "bin": {
6
6
  "zevai": "./cli.js"
@@ -131,6 +131,8 @@ export async function getUsageForProvider(connection, proxyOptions = null) {
131
131
  return await getMiniMaxUsage(apiKey, provider, proxyOptions);
132
132
  case "grok-cli":
133
133
  return await getGrokCliUsage(accessToken, providerSpecificData, proxyOptions);
134
+ case "cloudflare-ai":
135
+ return await getCloudflareAiUsage(apiKey || accessToken, providerSpecificData, proxyOptions);
134
136
  case "xai":
135
137
  return await getXaiUsage(accessToken || apiKey, providerSpecificData, proxyOptions);
136
138
  case "cline":
@@ -1814,6 +1816,94 @@ async function getAutoclawUsage(accessToken, proxyOptions = null, connection = n
1814
1816
  }
1815
1817
  }
1816
1818
 
1819
+ // ─── Cloudflare Workers AI ──────────────────────────────────────────────────
1820
+
1821
+ /**
1822
+ * Cloudflare does not expose remaining free-tier "neurons" via a public API.
1823
+ * Verify the token + account and surface a clear "Workers AI free tier" row so
1824
+ * the quota page is not blank for cloudflare-ai connections.
1825
+ */
1826
+ export async function getCloudflareAiUsage(apiKey, providerSpecificData = null, proxyOptions = null) {
1827
+ const token = String(apiKey || "").trim();
1828
+ const accountId = String(providerSpecificData?.accountId || "").trim();
1829
+ if (!token) {
1830
+ return { message: "Cloudflare API token not available." };
1831
+ }
1832
+ if (!accountId) {
1833
+ return { message: "Cloudflare account ID missing. Re-import or edit the connection." };
1834
+ }
1835
+
1836
+ try {
1837
+ const verifyRes = await proxyAwareFetch(
1838
+ "https://api.cloudflare.com/client/v4/user/tokens/verify",
1839
+ {
1840
+ method: "GET",
1841
+ headers: {
1842
+ Authorization: `Bearer ${token}`,
1843
+ Accept: "application/json",
1844
+ },
1845
+ },
1846
+ proxyOptions,
1847
+ );
1848
+
1849
+ if (verifyRes.status === 401 || verifyRes.status === 403) {
1850
+ return { message: "Cloudflare API token invalid or expired. Re-import the account." };
1851
+ }
1852
+
1853
+ if (!verifyRes.ok) {
1854
+ const errText = await verifyRes.text().catch(() => "");
1855
+ return {
1856
+ message: `Cloudflare token verify failed (${verifyRes.status})${errText ? `: ${errText.slice(0, 160)}` : ""}`,
1857
+ };
1858
+ }
1859
+
1860
+ const verifyBody = await verifyRes.json().catch(() => null);
1861
+ const status = verifyBody?.result?.status || (verifyBody?.success ? "active" : "unknown");
1862
+
1863
+ // Light account touch — confirms accountId + Workers AI scope without spending neurons.
1864
+ const acctRes = await proxyAwareFetch(
1865
+ `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(accountId)}`,
1866
+ {
1867
+ method: "GET",
1868
+ headers: {
1869
+ Authorization: `Bearer ${token}`,
1870
+ Accept: "application/json",
1871
+ },
1872
+ },
1873
+ proxyOptions,
1874
+ ).catch(() => null);
1875
+
1876
+ let accountName = providerSpecificData?.accountName || "";
1877
+ if (acctRes?.ok) {
1878
+ const acctBody = await acctRes.json().catch(() => null);
1879
+ accountName = acctBody?.result?.name || accountName;
1880
+ } else if (acctRes && (acctRes.status === 401 || acctRes.status === 403)) {
1881
+ return {
1882
+ message: "Cloudflare token cannot access this account. Check accountId / token permissions.",
1883
+ };
1884
+ }
1885
+
1886
+ return {
1887
+ plan: accountName ? `Workers AI · ${accountName}` : "Workers AI Free Tier",
1888
+ quotas: {
1889
+ "Workers AI": {
1890
+ used: 0,
1891
+ total: 0,
1892
+ remainingPercentage: 100,
1893
+ resetAt: null,
1894
+ unlimited: true,
1895
+ },
1896
+ },
1897
+ message:
1898
+ status && status !== "active"
1899
+ ? `Token status: ${status}. Cloudflare does not publish remaining free-tier neurons via API.`
1900
+ : "Cloudflare does not publish remaining free-tier neurons via API. Token is valid — per-model rate limits still apply.",
1901
+ };
1902
+ } catch (error) {
1903
+ return { message: `Cloudflare usage error: ${error.message}` };
1904
+ }
1905
+ }
1906
+
1817
1907
  // ─── Grok CLI / Grok Build usage (cli-chat-proxy.grok.com) ─────────────────
1818
1908
 
1819
1909
  function unwrapGrokCliVal(value, fallback = 0) {
@@ -1931,8 +2021,21 @@ export function parseGrokCliBilling(billing, user = null) {
1931
2021
  const hasIncludedAccess =
1932
2022
  user?.hasGrokCodeAccess === true || config?.isUnifiedBillingUser === true;
1933
2023
 
1934
- if (Object.keys(quotas).length === 0 && hasIncludedAccess) {
1935
- // Soft "included" pool so UI shows green / usable, not red 0%.
2024
+ // Always surface Grok Code / included access when the account still has it —
2025
+ // even if On-demand/Prepaid rows also exist. Previously we only added this
2026
+ // when quotas was empty, so free Grok Code looked like "no quota data".
2027
+ if (hasIncludedAccess) {
2028
+ quotas["Grok Code"] = {
2029
+ used: 0,
2030
+ total: 0,
2031
+ remainingPercentage: 100,
2032
+ resetAt: periodEnd,
2033
+ unlimited: true,
2034
+ };
2035
+ }
2036
+
2037
+ // Soft fallback when billing returns nothing usable (no caps, no access flags).
2038
+ if (Object.keys(quotas).length === 0) {
1936
2039
  quotas["Included"] = {
1937
2040
  used: 0,
1938
2041
  total: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zevairouter",
3
- "version": "1.0.91",
3
+ "version": "1.0.92",
4
4
  "description": "Self-hosted AI router: many providers, one OpenAI-compatible /v1 endpoint and dashboard",
5
5
  "bin": {
6
6
  "zevai": "./cli/cli.js"
@@ -5,7 +5,7 @@ import Card from "@/shared/components/Card";
5
5
  import ProviderIcon from "@/shared/components/ProviderIcon";
6
6
  import Badge from "@/shared/components/Badge";
7
7
  import QuotaProgressBar from "./QuotaProgressBar";
8
- import { calculatePercentage } from "./utils";
8
+ import { getRemainingPercentage } from "./utils";
9
9
 
10
10
  const planVariants = {
11
11
  free: "default",
@@ -145,16 +145,14 @@ export default function ProviderLimitCard({
145
145
  </div>
146
146
  )}
147
147
 
148
- {/* Quota Progress Bars */}
149
- {!loading && !error && !message && quotas?.length > 0 && (
148
+ {/* Quota Progress Bars — show even when a soft info message is present */}
149
+ {!loading && !error && quotas?.length > 0 && (
150
150
  <div className="space-y-4">
151
151
  {quotas.map((quota, index) => {
152
- // For Antigravity, use remainingPercentage if available, otherwise calculate
153
- const percentage =
154
- quota.remainingPercentage !== undefined
155
- ? Math.round(((quota.total - quota.used) / quota.total) * 100)
156
- : calculatePercentage(quota.used, quota.total);
157
- const unlimited = quota.total === 0 || quota.total === null;
152
+ const unlimited =
153
+ quota.unlimited === true || quota.total === 0 || quota.total === null;
154
+ // Never recompute from used/total when total is 0 (NaN) — use remainingPercentage.
155
+ const percentage = getRemainingPercentage(quota);
158
156
 
159
157
  return (
160
158
  <QuotaProgressBar
@@ -162,7 +160,7 @@ export default function ProviderLimitCard({
162
160
  label={quota.name}
163
161
  used={quota.used}
164
162
  total={quota.total}
165
- percentage={percentage}
163
+ percentage={Number.isFinite(percentage) ? percentage : unlimited ? 100 : 0}
166
164
  unlimited={unlimited}
167
165
  resetTime={quota.resetAt}
168
166
  />
@@ -172,7 +170,7 @@ export default function ProviderLimitCard({
172
170
  )}
173
171
 
174
172
  {/* Empty State */}
175
- {!loading && !error && !message && quotas?.length === 0 && (
173
+ {!loading && !error && !message && (!quotas || quotas.length === 0) && (
176
174
  <div className="text-center py-8 text-text-muted">
177
175
  <span className="material-symbols-outlined text-[48px] opacity-20">
178
176
  data_usage
@@ -93,20 +93,20 @@ export default function QuotaProgressBar({
93
93
  </div>
94
94
  </div>
95
95
 
96
- {/* Progress bar */}
97
- {!unlimited && (
98
- <div className={cn("h-2 rounded-full overflow-hidden", colors.bgLight)}>
99
- <div
100
- className={cn("h-full transition-all duration-300", colors.bg)}
101
- style={{ width: `${Math.min(remaining, 100)}%` }}
102
- />
103
- </div>
104
- )}
96
+ {/* Progress bar — unlimited pools still show a full green bar so quota is visible */}
97
+ <div className={cn("h-2 rounded-full overflow-hidden", colors.bgLight)}>
98
+ <div
99
+ className={cn("h-full transition-all duration-300", colors.bg)}
100
+ style={{ width: `${Math.min(Math.max(remaining, unlimited ? 100 : 0), 100)}%` }}
101
+ />
102
+ </div>
105
103
 
106
104
  {/* Usage details and countdown */}
107
105
  <div className="flex items-center justify-between text-xs text-text-muted">
108
106
  <span>
109
- {used.toLocaleString()} / {total.toLocaleString()} requests
107
+ {unlimited
108
+ ? "Included / unlimited"
109
+ : `${used.toLocaleString()} / ${total > 0 ? total.toLocaleString() : "∞"}`}
110
110
  </span>
111
111
  {countdown !== "-" && (
112
112
  <div className="flex items-center gap-1">
@@ -181,10 +181,12 @@ export default function QuotaTable({
181
181
 
182
182
  <div className={`flex items-center justify-between ${compact ? "text-[10px]" : "text-xs"}`}>
183
183
  <span className="text-text-muted">
184
- {quota.used.toLocaleString()} / {quota.total > 0 ? quota.total.toLocaleString() : "∞"}
184
+ {quota.unlimited === true || !(quota.total > 0)
185
+ ? (quota.unlimited === true ? "Included / ∞" : `${quota.used.toLocaleString()} / ∞`)
186
+ : `${quota.used.toLocaleString()} / ${quota.total.toLocaleString()}`}
185
187
  </span>
186
188
  <span className={`font-medium ${colors.text}`}>
187
- {quota.remaining}%
189
+ {Number.isFinite(quota.remaining) ? `${quota.remaining}%` : "—"}
188
190
  </span>
189
191
  </div>
190
192
  </div>
@@ -38,10 +38,20 @@ function mergeQuotaRows(rows = []) {
38
38
  used: 0,
39
39
  total: 0,
40
40
  resetAt: quota.resetAt || null,
41
+ remainingPercentage: null,
42
+ unlimited: false,
43
+ _pctSum: 0,
44
+ _pctCount: 0,
41
45
  };
42
46
 
43
47
  current.used += Number(quota.used) || 0;
44
48
  current.total += Number(quota.total) || 0;
49
+ if (quota.unlimited === true) current.unlimited = true;
50
+
51
+ if (quota.remainingPercentage != null && Number.isFinite(Number(quota.remainingPercentage))) {
52
+ current._pctSum += Number(quota.remainingPercentage);
53
+ current._pctCount += 1;
54
+ }
45
55
 
46
56
  if (quota.resetAt) {
47
57
  if (!current.resetAt || new Date(quota.resetAt).getTime() < new Date(current.resetAt).getTime()) {
@@ -52,7 +62,20 @@ function mergeQuotaRows(rows = []) {
52
62
  merged.set(quota.name, current);
53
63
  });
54
64
 
55
- return [...merged.values()];
65
+ return [...merged.values()].map((row) => {
66
+ const { _pctSum, _pctCount, ...rest } = row;
67
+ if (rest.unlimited) {
68
+ rest.remainingPercentage = 100;
69
+ rest.total = 0;
70
+ } else if (rest.total > 0) {
71
+ rest.remainingPercentage = ((rest.total - rest.used) / rest.total) * 100;
72
+ } else if (_pctCount > 0) {
73
+ rest.remainingPercentage = _pctSum / _pctCount;
74
+ } else {
75
+ rest.remainingPercentage = 0;
76
+ }
77
+ return rest;
78
+ });
56
79
  }
57
80
 
58
81
  function getProviderDisplayName(provider) {
@@ -1311,19 +1334,28 @@ export default function ProviderLimits() {
1311
1334
  </span>
1312
1335
  <p className="mt-1.5 text-xs text-text-muted">{error}</p>
1313
1336
  </div>
1337
+ ) : (quota?.quotas?.length > 0) ? (
1338
+ <div className="space-y-2">
1339
+ <QuotaTable
1340
+ quotas={quota.quotas}
1341
+ compact
1342
+ sortMode="default"
1343
+ showSortLabel={
1344
+ conn.provider === "codex" && quotaSortMode !== "default"
1345
+ }
1346
+ />
1347
+ {quota?.message ? (
1348
+ <p className="px-1 text-[10px] text-text-muted">{quota.message}</p>
1349
+ ) : null}
1350
+ </div>
1314
1351
  ) : quota?.message ? (
1315
1352
  <div className="text-center py-5">
1316
1353
  <p className="text-xs text-text-muted">{quota.message}</p>
1317
1354
  </div>
1318
1355
  ) : (
1319
- <QuotaTable
1320
- quotas={quota?.quotas}
1321
- compact
1322
- sortMode="default"
1323
- showSortLabel={
1324
- conn.provider === "codex" && quotaSortMode !== "default"
1325
- }
1326
- />
1356
+ <div className="text-center py-5 text-text-muted">
1357
+ <p className="text-xs">No quota data available</p>
1358
+ </div>
1327
1359
  )}
1328
1360
  </div>
1329
1361
  </Card>