n9router 0.3.91 → 0.3.94

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 (499) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/routes-manifest.json +6 -0
  5. package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page.js +1 -1
  6. package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page.js +1 -1
  9. package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page.js +1 -1
  12. package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
  13. package/.next/standalone/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  14. package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page.js +1 -1
  15. package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
  16. package/.next/standalone/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  17. package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page.js +1 -1
  18. package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page.js +1 -1
  21. package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/(dashboard)/dashboard/page.js +1 -1
  24. package/.next/standalone/.next/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page.js +1 -1
  27. package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js +1 -1
  30. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page.js +1 -1
  33. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  35. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page.js +1 -1
  36. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  38. package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js +1 -1
  39. package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  41. package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page.js +1 -1
  42. package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page.js +1 -1
  45. package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page.js +1 -1
  48. package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/_global-error/page.js +1 -1
  51. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  53. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  54. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  55. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  57. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  58. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  59. package/.next/standalone/.next/server/app/_not-found/page.js +1 -1
  60. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  63. package/.next/standalone/.next/server/app/_not-found.rsc +11 -11
  64. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +11 -11
  65. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  66. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +6 -6
  67. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  68. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  69. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  70. package/.next/standalone/.next/server/app/api/antigravity-tools/import/route.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route/app-paths-manifest.json +3 -0
  72. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route/build-manifest.json +9 -0
  73. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route/server-reference-manifest.json +4 -0
  74. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route.js +11 -0
  75. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route.js.map +5 -0
  76. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route.js.nft.json +1 -0
  77. package/.next/standalone/.next/server/app/api/antigravity-tools/import-refresh-tokens/route_client-reference-manifest.js +3 -0
  78. package/.next/standalone/.next/server/app/api/auth/login/route.js +1 -1
  79. package/.next/standalone/.next/server/app/api/auth/login/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js +1 -1
  81. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
  83. package/.next/standalone/.next/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/cli-tools/claude-settings/route.js +1 -1
  85. package/.next/standalone/.next/server/app/api/cli-tools/claude-settings/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/cli-tools/codex-settings/route.js +1 -1
  87. package/.next/standalone/.next/server/app/api/cli-tools/codex-settings/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/cli-tools/droid-settings/route.js +1 -1
  89. package/.next/standalone/.next/server/app/api/cli-tools/droid-settings/route.js.nft.json +1 -1
  90. package/.next/standalone/.next/server/app/api/cli-tools/openclaw-settings/route.js +1 -1
  91. package/.next/standalone/.next/server/app/api/cli-tools/openclaw-settings/route.js.nft.json +1 -1
  92. package/.next/standalone/.next/server/app/api/cli-tools/opencode-settings/route.js +1 -1
  93. package/.next/standalone/.next/server/app/api/cli-tools/opencode-settings/route.js.nft.json +1 -1
  94. package/.next/standalone/.next/server/app/api/cloud/auth/route.js +1 -1
  95. package/.next/standalone/.next/server/app/api/cloud/auth/route.js.nft.json +1 -1
  96. package/.next/standalone/.next/server/app/api/cloud/credentials/update/route.js +1 -1
  97. package/.next/standalone/.next/server/app/api/cloud/credentials/update/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/cloud/model/resolve/route.js +1 -1
  99. package/.next/standalone/.next/server/app/api/cloud/model/resolve/route.js.nft.json +1 -1
  100. package/.next/standalone/.next/server/app/api/cloud/models/alias/route.js +1 -1
  101. package/.next/standalone/.next/server/app/api/cloud/models/alias/route.js.nft.json +1 -1
  102. package/.next/standalone/.next/server/app/api/combos/[id]/route.js +1 -1
  103. package/.next/standalone/.next/server/app/api/combos/[id]/route.js.nft.json +1 -1
  104. package/.next/standalone/.next/server/app/api/combos/route.js +1 -1
  105. package/.next/standalone/.next/server/app/api/combos/route.js.nft.json +1 -1
  106. package/.next/standalone/.next/server/app/api/init/route.js.nft.json +1 -1
  107. package/.next/standalone/.next/server/app/api/internal/request-detail/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/internal/usage/route.js.nft.json +1 -1
  109. package/.next/standalone/.next/server/app/api/keys/[id]/route.js +1 -1
  110. package/.next/standalone/.next/server/app/api/keys/[id]/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/keys/route.js +1 -1
  112. package/.next/standalone/.next/server/app/api/keys/route.js.nft.json +1 -1
  113. package/.next/standalone/.next/server/app/api/models/alias/route.js +1 -1
  114. package/.next/standalone/.next/server/app/api/models/alias/route.js.nft.json +1 -1
  115. package/.next/standalone/.next/server/app/api/models/availability/route.js +1 -1
  116. package/.next/standalone/.next/server/app/api/models/availability/route.js.nft.json +1 -1
  117. package/.next/standalone/.next/server/app/api/models/route.js +1 -1
  118. package/.next/standalone/.next/server/app/api/models/route.js.nft.json +1 -1
  119. package/.next/standalone/.next/server/app/api/models/test/route.js +1 -1
  120. package/.next/standalone/.next/server/app/api/models/test/route.js.nft.json +1 -1
  121. package/.next/standalone/.next/server/app/api/oauth/[provider]/[action]/route.js +1 -1
  122. package/.next/standalone/.next/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/oauth/cursor/auto-import/route.js +1 -1
  124. package/.next/standalone/.next/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/oauth/cursor/import/route.js +1 -1
  126. package/.next/standalone/.next/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/api/oauth/gitlab/pat/route.js +1 -1
  128. package/.next/standalone/.next/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
  129. package/.next/standalone/.next/server/app/api/oauth/iflow/cookie/route.js +1 -1
  130. package/.next/standalone/.next/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
  131. package/.next/standalone/.next/server/app/api/oauth/kiro/import/route.js +1 -1
  132. package/.next/standalone/.next/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
  133. package/.next/standalone/.next/server/app/api/oauth/kiro/social-exchange/route.js +1 -1
  134. package/.next/standalone/.next/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/pricing/route.js +1 -1
  136. package/.next/standalone/.next/server/app/api/pricing/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/provider-nodes/[id]/route.js +1 -1
  138. package/.next/standalone/.next/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
  139. package/.next/standalone/.next/server/app/api/provider-nodes/route.js +1 -1
  140. package/.next/standalone/.next/server/app/api/provider-nodes/route.js.nft.json +1 -1
  141. package/.next/standalone/.next/server/app/api/providers/[id]/models/route.js +4 -4
  142. package/.next/standalone/.next/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/providers/[id]/route.js +1 -1
  144. package/.next/standalone/.next/server/app/api/providers/[id]/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/providers/[id]/test/route.js +1 -1
  146. package/.next/standalone/.next/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
  147. package/.next/standalone/.next/server/app/api/providers/[id]/test-models/route.js +1 -1
  148. package/.next/standalone/.next/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/providers/client/route.js +1 -1
  150. package/.next/standalone/.next/server/app/api/providers/client/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/providers/route.js +1 -1
  152. package/.next/standalone/.next/server/app/api/providers/route.js.nft.json +1 -1
  153. package/.next/standalone/.next/server/app/api/providers/test-batch/route.js +1 -1
  154. package/.next/standalone/.next/server/app/api/providers/test-batch/route.js.nft.json +1 -1
  155. package/.next/standalone/.next/server/app/api/providers/validate/route.js +1 -1
  156. package/.next/standalone/.next/server/app/api/providers/validate/route.js.nft.json +1 -1
  157. package/.next/standalone/.next/server/app/api/proxy-pools/[id]/route.js +1 -1
  158. package/.next/standalone/.next/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
  159. package/.next/standalone/.next/server/app/api/proxy-pools/[id]/test/route.js +1 -1
  160. package/.next/standalone/.next/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
  161. package/.next/standalone/.next/server/app/api/proxy-pools/route.js +1 -1
  162. package/.next/standalone/.next/server/app/api/proxy-pools/route.js.nft.json +1 -1
  163. package/.next/standalone/.next/server/app/api/settings/database/route.js +1 -1
  164. package/.next/standalone/.next/server/app/api/settings/database/route.js.nft.json +1 -1
  165. package/.next/standalone/.next/server/app/api/settings/require-login/route.js +1 -1
  166. package/.next/standalone/.next/server/app/api/settings/require-login/route.js.nft.json +1 -1
  167. package/.next/standalone/.next/server/app/api/settings/route.js +1 -1
  168. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
  169. package/.next/standalone/.next/server/app/api/translator/send/route.js.nft.json +1 -1
  170. package/.next/standalone/.next/server/app/api/translator/translate/route.js +1 -1
  171. package/.next/standalone/.next/server/app/api/translator/translate/route.js.nft.json +1 -1
  172. package/.next/standalone/.next/server/app/api/tunnel/disable/route.js +1 -1
  173. package/.next/standalone/.next/server/app/api/tunnel/disable/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/tunnel/enable/route.js +1 -1
  175. package/.next/standalone/.next/server/app/api/tunnel/enable/route.js.nft.json +1 -1
  176. package/.next/standalone/.next/server/app/api/tunnel/status/route.js +1 -1
  177. package/.next/standalone/.next/server/app/api/tunnel/status/route.js.nft.json +1 -1
  178. package/.next/standalone/.next/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
  179. package/.next/standalone/.next/server/app/api/usage/chart/route.js.nft.json +1 -1
  180. package/.next/standalone/.next/server/app/api/usage/history/route.js.nft.json +1 -1
  181. package/.next/standalone/.next/server/app/api/usage/logs/route.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/api/usage/providers/route.js +1 -1
  183. package/.next/standalone/.next/server/app/api/usage/providers/route.js.nft.json +1 -1
  184. package/.next/standalone/.next/server/app/api/usage/request-details/route.js.nft.json +1 -1
  185. package/.next/standalone/.next/server/app/api/usage/request-logs/route.js.nft.json +1 -1
  186. package/.next/standalone/.next/server/app/api/usage/stats/route.js.nft.json +1 -1
  187. package/.next/standalone/.next/server/app/api/usage/stream/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/v1/api/chat/route.js +2 -2
  189. package/.next/standalone/.next/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/v1/chat/completions/route.js +4 -4
  191. package/.next/standalone/.next/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  192. package/.next/standalone/.next/server/app/api/v1/embeddings/route.js +4 -4
  193. package/.next/standalone/.next/server/app/api/v1/embeddings/route.js.nft.json +1 -1
  194. package/.next/standalone/.next/server/app/api/v1/messages/route.js +2 -2
  195. package/.next/standalone/.next/server/app/api/v1/messages/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/v1/models/route.js.nft.json +1 -1
  197. package/.next/standalone/.next/server/app/api/v1/responses/route.js +2 -2
  198. package/.next/standalone/.next/server/app/api/v1/responses/route.js.nft.json +1 -1
  199. package/.next/standalone/.next/server/app/api/v1beta/models/[...path]/route.js +3 -3
  200. package/.next/standalone/.next/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  201. package/.next/standalone/.next/server/app/api/version/route.js +2 -2
  202. package/.next/standalone/.next/server/app/callback/page.js +1 -1
  203. package/.next/standalone/.next/server/app/callback/page.js.nft.json +1 -1
  204. package/.next/standalone/.next/server/app/callback/page_client-reference-manifest.js +1 -1
  205. package/.next/standalone/.next/server/app/callback.html +1 -1
  206. package/.next/standalone/.next/server/app/callback.rsc +13 -13
  207. package/.next/standalone/.next/server/app/callback.segments/_full.segment.rsc +13 -13
  208. package/.next/standalone/.next/server/app/callback.segments/_head.segment.rsc +4 -4
  209. package/.next/standalone/.next/server/app/callback.segments/_index.segment.rsc +6 -6
  210. package/.next/standalone/.next/server/app/callback.segments/_tree.segment.rsc +2 -2
  211. package/.next/standalone/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +4 -4
  212. package/.next/standalone/.next/server/app/callback.segments/callback.segment.rsc +3 -3
  213. package/.next/standalone/.next/server/app/dashboard/basic-chat.html +1 -1
  214. package/.next/standalone/.next/server/app/dashboard/basic-chat.rsc +14 -14
  215. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +3 -3
  216. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +3 -3
  217. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  218. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  219. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_full.segment.rsc +14 -14
  220. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_head.segment.rsc +4 -4
  221. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_index.segment.rsc +6 -6
  222. package/.next/standalone/.next/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +2 -2
  223. package/.next/standalone/.next/server/app/dashboard/cli-tools.html +1 -1
  224. package/.next/standalone/.next/server/app/dashboard/cli-tools.rsc +14 -14
  225. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +3 -3
  226. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +3 -3
  227. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  228. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  229. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +14 -14
  230. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +4 -4
  231. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +6 -6
  232. package/.next/standalone/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
  233. package/.next/standalone/.next/server/app/dashboard/combos.html +1 -1
  234. package/.next/standalone/.next/server/app/dashboard/combos.rsc +15 -15
  235. package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +4 -4
  236. package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +3 -3
  237. package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  238. package/.next/standalone/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  239. package/.next/standalone/.next/server/app/dashboard/combos.segments/_full.segment.rsc +15 -15
  240. package/.next/standalone/.next/server/app/dashboard/combos.segments/_head.segment.rsc +4 -4
  241. package/.next/standalone/.next/server/app/dashboard/combos.segments/_index.segment.rsc +6 -6
  242. package/.next/standalone/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
  243. package/.next/standalone/.next/server/app/dashboard/endpoint.html +1 -1
  244. package/.next/standalone/.next/server/app/dashboard/endpoint.rsc +14 -14
  245. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +3 -3
  246. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +3 -3
  247. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  248. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  249. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +14 -14
  250. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +4 -4
  251. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +6 -6
  252. package/.next/standalone/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
  253. package/.next/standalone/.next/server/app/dashboard/mitm.html +1 -1
  254. package/.next/standalone/.next/server/app/dashboard/mitm.rsc +14 -14
  255. package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +3 -3
  256. package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +3 -3
  257. package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  258. package/.next/standalone/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  259. package/.next/standalone/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +14 -14
  260. package/.next/standalone/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +4 -4
  261. package/.next/standalone/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +6 -6
  262. package/.next/standalone/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
  263. package/.next/standalone/.next/server/app/dashboard/profile.html +1 -1
  264. package/.next/standalone/.next/server/app/dashboard/profile.rsc +15 -15
  265. package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +4 -4
  266. package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +3 -3
  267. package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  268. package/.next/standalone/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  269. package/.next/standalone/.next/server/app/dashboard/profile.segments/_full.segment.rsc +15 -15
  270. package/.next/standalone/.next/server/app/dashboard/profile.segments/_head.segment.rsc +4 -4
  271. package/.next/standalone/.next/server/app/dashboard/profile.segments/_index.segment.rsc +6 -6
  272. package/.next/standalone/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
  273. package/.next/standalone/.next/server/app/dashboard/providers/new.html +1 -1
  274. package/.next/standalone/.next/server/app/dashboard/providers/new.rsc +15 -15
  275. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +4 -4
  276. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +3 -3
  277. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +3 -3
  278. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  279. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  280. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +15 -15
  281. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +4 -4
  282. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +6 -6
  283. package/.next/standalone/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
  284. package/.next/standalone/.next/server/app/dashboard/providers.html +1 -1
  285. package/.next/standalone/.next/server/app/dashboard/providers.rsc +15 -15
  286. package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +4 -4
  287. package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +3 -3
  288. package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  289. package/.next/standalone/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  290. package/.next/standalone/.next/server/app/dashboard/providers.segments/_full.segment.rsc +15 -15
  291. package/.next/standalone/.next/server/app/dashboard/providers.segments/_head.segment.rsc +4 -4
  292. package/.next/standalone/.next/server/app/dashboard/providers.segments/_index.segment.rsc +6 -6
  293. package/.next/standalone/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
  294. package/.next/standalone/.next/server/app/dashboard/proxy-pools.html +1 -1
  295. package/.next/standalone/.next/server/app/dashboard/proxy-pools.rsc +15 -15
  296. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +4 -4
  297. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +3 -3
  298. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  299. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  300. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +15 -15
  301. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +4 -4
  302. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +6 -6
  303. package/.next/standalone/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
  304. package/.next/standalone/.next/server/app/dashboard/quota.html +2 -2
  305. package/.next/standalone/.next/server/app/dashboard/quota.rsc +15 -15
  306. package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +4 -4
  307. package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +3 -3
  308. package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  309. package/.next/standalone/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  310. package/.next/standalone/.next/server/app/dashboard/quota.segments/_full.segment.rsc +15 -15
  311. package/.next/standalone/.next/server/app/dashboard/quota.segments/_head.segment.rsc +4 -4
  312. package/.next/standalone/.next/server/app/dashboard/quota.segments/_index.segment.rsc +6 -6
  313. package/.next/standalone/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
  314. package/.next/standalone/.next/server/app/dashboard/settings/pricing/page.js +1 -1
  315. package/.next/standalone/.next/server/app/dashboard/settings/pricing/page.js.nft.json +1 -1
  316. package/.next/standalone/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  317. package/.next/standalone/.next/server/app/dashboard/settings/pricing.html +1 -1
  318. package/.next/standalone/.next/server/app/dashboard/settings/pricing.rsc +13 -13
  319. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +13 -13
  320. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +4 -4
  321. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +6 -6
  322. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
  323. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +4 -4
  324. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +3 -3
  325. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +3 -3
  326. package/.next/standalone/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +3 -3
  327. package/.next/standalone/.next/server/app/dashboard/translator.html +1 -1
  328. package/.next/standalone/.next/server/app/dashboard/translator.rsc +15 -15
  329. package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +4 -4
  330. package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +3 -3
  331. package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  332. package/.next/standalone/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  333. package/.next/standalone/.next/server/app/dashboard/translator.segments/_full.segment.rsc +15 -15
  334. package/.next/standalone/.next/server/app/dashboard/translator.segments/_head.segment.rsc +4 -4
  335. package/.next/standalone/.next/server/app/dashboard/translator.segments/_index.segment.rsc +6 -6
  336. package/.next/standalone/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
  337. package/.next/standalone/.next/server/app/dashboard/usage.html +1 -1
  338. package/.next/standalone/.next/server/app/dashboard/usage.rsc +15 -15
  339. package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +4 -4
  340. package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +3 -3
  341. package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  342. package/.next/standalone/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  343. package/.next/standalone/.next/server/app/dashboard/usage.segments/_full.segment.rsc +15 -15
  344. package/.next/standalone/.next/server/app/dashboard/usage.segments/_head.segment.rsc +4 -4
  345. package/.next/standalone/.next/server/app/dashboard/usage.segments/_index.segment.rsc +6 -6
  346. package/.next/standalone/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
  347. package/.next/standalone/.next/server/app/dashboard.html +1 -1
  348. package/.next/standalone/.next/server/app/dashboard.rsc +14 -14
  349. package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +3 -3
  350. package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +3 -3
  351. package/.next/standalone/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +4 -4
  352. package/.next/standalone/.next/server/app/dashboard.segments/_full.segment.rsc +14 -14
  353. package/.next/standalone/.next/server/app/dashboard.segments/_head.segment.rsc +4 -4
  354. package/.next/standalone/.next/server/app/dashboard.segments/_index.segment.rsc +6 -6
  355. package/.next/standalone/.next/server/app/dashboard.segments/_tree.segment.rsc +2 -2
  356. package/.next/standalone/.next/server/app/index.html +1 -1
  357. package/.next/standalone/.next/server/app/index.rsc +11 -11
  358. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  359. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +11 -11
  360. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  361. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +6 -6
  362. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  363. package/.next/standalone/.next/server/app/landing/page.js +1 -1
  364. package/.next/standalone/.next/server/app/landing/page.js.nft.json +1 -1
  365. package/.next/standalone/.next/server/app/landing/page_client-reference-manifest.js +1 -1
  366. package/.next/standalone/.next/server/app/landing.html +1 -1
  367. package/.next/standalone/.next/server/app/landing.rsc +13 -13
  368. package/.next/standalone/.next/server/app/landing.segments/_full.segment.rsc +13 -13
  369. package/.next/standalone/.next/server/app/landing.segments/_head.segment.rsc +4 -4
  370. package/.next/standalone/.next/server/app/landing.segments/_index.segment.rsc +6 -6
  371. package/.next/standalone/.next/server/app/landing.segments/_tree.segment.rsc +2 -2
  372. package/.next/standalone/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +4 -4
  373. package/.next/standalone/.next/server/app/landing.segments/landing.segment.rsc +3 -3
  374. package/.next/standalone/.next/server/app/login/page.js +1 -1
  375. package/.next/standalone/.next/server/app/login/page.js.nft.json +1 -1
  376. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  377. package/.next/standalone/.next/server/app/login.html +1 -1
  378. package/.next/standalone/.next/server/app/login.rsc +13 -13
  379. package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +13 -13
  380. package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +4 -4
  381. package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +6 -6
  382. package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  383. package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  384. package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +3 -3
  385. package/.next/standalone/.next/server/app/page.js +1 -1
  386. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  387. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  388. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  389. package/.next/standalone/.next/server/chunks/0zjb_server_app_api_antigravity-tools_import-refresh-tokens_route_actions_0jn9smo.js +3 -0
  390. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0mpe9.-._.js → [root-of-the-server]__0-ztp63._.js} +2 -2
  391. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0ha8pqz._.js → [root-of-the-server]__0.yvcis._.js} +2 -2
  392. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0nkly1e._.js → [root-of-the-server]__0148t9m._.js} +2 -2
  393. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0u8dezo._.js → [root-of-the-server]__01dhv3a._.js} +2 -2
  394. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01rpshu._.js +3 -0
  395. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0ec61.d._.js → [root-of-the-server]__04o67.c._.js} +2 -2
  396. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0fsp-sk._.js → [root-of-the-server]__04phkrb._.js} +2 -2
  397. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0p8vmzj._.js → [root-of-the-server]__0_8pmqq._.js} +2 -2
  398. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0f59x8f._.js → [root-of-the-server]__0_8qd4-._.js} +2 -2
  399. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0tw0zvj._.js → [root-of-the-server]__0_a3mp3._.js} +2 -2
  400. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0t-7jzt._.js → [root-of-the-server]__0_qom9~._.js} +2 -2
  401. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0poxwxp._.js → [root-of-the-server]__0a4rwvw._.js} +2 -2
  402. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0evci68._.js → [root-of-the-server]__0b0hngg._.js} +2 -2
  403. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0b802lh._.js +1 -1
  404. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0bdtalb._.js → [root-of-the-server]__0c-qn~s._.js} +2 -2
  405. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sy.n8z._.js → [root-of-the-server]__0cix-zv._.js} +2 -2
  406. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__03of64y._.js → [root-of-the-server]__0d-p9ea._.js} +2 -2
  407. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0c09lpw._.js → [root-of-the-server]__0drf.ui._.js} +2 -2
  408. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e27kvj._.js +3 -0
  409. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0e4os.p._.js → [root-of-the-server]__0eyrvzj._.js} +2 -2
  410. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0_5bxb7._.js → [root-of-the-server]__0gglkh-._.js} +2 -2
  411. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0a_9~cg._.js → [root-of-the-server]__0ggqrke._.js} +2 -2
  412. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0pf0kam._.js → [root-of-the-server]__0gicxvd._.js} +2 -2
  413. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__06n~wts._.js → [root-of-the-server]__0i_45tv._.js} +2 -2
  414. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0inxxu0._.js +3 -0
  415. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__091ltaw._.js → [root-of-the-server]__0jd9t2e._.js} +2 -2
  416. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ju9vfb._.js +3 -0
  417. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kpc-o6._.js +1 -1
  418. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lc~.sk._.js +1 -1
  419. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lp_pm5._.js +1 -1
  420. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0jpee3.._.js → [root-of-the-server]__0n1xjjj._.js} +2 -2
  421. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0e7y8w~._.js → [root-of-the-server]__0ntxb7l._.js} +2 -2
  422. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0fa8rg9._.js → [root-of-the-server]__0ob~5~z._.js} +2 -2
  423. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__02.ogtw._.js → [root-of-the-server]__0pwrfp1._.js} +2 -2
  424. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0yf_zm4._.js → [root-of-the-server]__0q6qi87._.js} +2 -2
  425. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0xilem_._.js → [root-of-the-server]__0qbud9-._.js} +2 -2
  426. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0x6j5ov._.js → [root-of-the-server]__0s078yi._.js} +2 -2
  427. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0_zm3dg._.js → [root-of-the-server]__0shx3oz._.js} +2 -2
  428. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0szv.g3._.js +3 -0
  429. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0ldzewe._.js → [root-of-the-server]__0tdx4rw._.js} +2 -2
  430. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0y3xqc0._.js → [root-of-the-server]__0uc~.ow._.js} +2 -2
  431. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0nab92j._.js → [root-of-the-server]__0uilpvk._.js} +2 -2
  432. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uw3x8s._.js +1 -1
  433. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0wczue6._.js → [root-of-the-server]__0wn37_w._.js} +2 -2
  434. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0442-5c._.js → [root-of-the-server]__0wor~wi._.js} +2 -2
  435. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__00_sy8a._.js → [root-of-the-server]__0wu_jyu._.js} +2 -2
  436. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0xls6ee._.js → [root-of-the-server]__0wzaoyn._.js} +2 -2
  437. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0y.reft._.js +1 -1
  438. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__01n7vgb._.js → [root-of-the-server]__0y5ae.7._.js} +2 -2
  439. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__06ogl04._.js → [root-of-the-server]__0ygxf8q._.js} +2 -2
  440. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1365t9j._.js → [root-of-the-server]__0yk.b~x._.js} +2 -2
  441. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0d7obnq._.js → [root-of-the-server]__0yqcvre._.js} +2 -2
  442. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__04c-kkd._.js → [root-of-the-server]__0yye~im._.js} +2 -2
  443. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-th9q.._.js → [root-of-the-server]__0z-kiuj._.js} +2 -2
  444. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0zgc10n._.js → [root-of-the-server]__0z-slhf._.js} +2 -2
  445. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__00w1-vt._.js → [root-of-the-server]__0~0444n._.js} +2 -2
  446. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__02ez_-~._.js → [root-of-the-server]__11ddaxt._.js} +2 -2
  447. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__11x4~za._.js → [root-of-the-server]__120yp9v._.js} +2 -2
  448. package/.next/standalone/.next/server/chunks/_0__-aqg._.js +3 -0
  449. package/.next/standalone/.next/server/chunks/_0_ovl1h._.js +3 -0
  450. package/.next/standalone/.next/server/chunks/{_0fqqr7l._.js → _0vq-0-m._.js} +2 -2
  451. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__04f0xi0._.js → [root-of-the-server]__0c6sbbj._.js} +2 -2
  452. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_0x_me2y._.js → _04v6e-j._.js} +2 -2
  453. package/.next/standalone/.next/server/chunks/ssr/_0c8m5sm._.js +1 -1
  454. package/.next/standalone/.next/server/chunks/ssr/_0fd4.es._.js +5 -0
  455. package/.next/standalone/.next/server/chunks/ssr/_13z1.b_._.js +1 -1
  456. package/.next/standalone/.next/server/chunks/ssr/src_0_xhepz._.js +1 -1
  457. package/.next/standalone/.next/server/chunks/ssr/src_app_(dashboard)_dashboard_providers_[id]_page_0-3xvzc.js +4 -1
  458. package/.next/standalone/.next/server/chunks/ssr/src_shared_constants_cliTools_09iru_o.js +1 -1
  459. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  460. package/.next/standalone/.next/server/pages/404.html +1 -1
  461. package/.next/standalone/.next/server/pages/500.html +1 -1
  462. package/.next/{static/chunks/0ggs~59p2zyrg.js → standalone/.next/static/chunks/02suuzz60dp3d.js} +1 -1
  463. package/.next/standalone/.next/static/chunks/0h~4je-_gk7-5.css +1 -0
  464. package/.next/standalone/.next/static/chunks/{17~_6lx17xr8z.js → 0j6650zqytl.z.js} +1 -1
  465. package/.next/{static/chunks/0pwbnjvdm7lt_.js → standalone/.next/static/chunks/0lqwk82lneihh.js} +2 -2
  466. package/.next/{static/chunks/148_2lu2ra629.js → standalone/.next/static/chunks/11jq77q6zkl40.js} +1 -1
  467. package/.next/standalone/.next/static/chunks/127zo11qzv8-9.js +4 -0
  468. package/.next/{static/chunks/06l6ck_q1o~m9.js → standalone/.next/static/chunks/16r2wq4pvci67.js} +1 -1
  469. package/.next/standalone/AGENTS.md +136 -0
  470. package/.next/standalone/docs/token_swap_guide.md +2 -0
  471. package/.next/standalone/mitm/server.js +165 -111
  472. package/.next/standalone/mitm/tokenPool.js +61 -13
  473. package/.next/standalone/package-lock.json +2 -2
  474. package/.next/standalone/package.json +1 -1
  475. package/.next/standalone/src/app/(dashboard)/dashboard/providers/[id]/page.js +123 -8
  476. package/.next/standalone/src/app/api/antigravity-tools/import-refresh-tokens/route.js +218 -0
  477. package/.next/standalone/src/mitm/server.js +165 -111
  478. package/.next/standalone/src/mitm/tokenPool.js +61 -13
  479. package/.next/{standalone/.next/static/chunks/0ggs~59p2zyrg.js → static/chunks/02suuzz60dp3d.js} +1 -1
  480. package/.next/static/chunks/0h~4je-_gk7-5.css +1 -0
  481. package/.next/static/chunks/{17~_6lx17xr8z.js → 0j6650zqytl.z.js} +1 -1
  482. package/.next/{standalone/.next/static/chunks/0pwbnjvdm7lt_.js → static/chunks/0lqwk82lneihh.js} +2 -2
  483. package/.next/{standalone/.next/static/chunks/148_2lu2ra629.js → static/chunks/11jq77q6zkl40.js} +1 -1
  484. package/.next/static/chunks/127zo11qzv8-9.js +4 -0
  485. package/.next/{standalone/.next/static/chunks/06l6ck_q1o~m9.js → static/chunks/16r2wq4pvci67.js} +1 -1
  486. package/package.json +1 -1
  487. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jlk7i0._.js +0 -3
  488. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0m42-i~._.js +0 -3
  489. package/.next/standalone/.next/server/chunks/_019vwuu._.js +0 -3
  490. package/.next/standalone/.next/static/chunks/026p3rpdycbyo.css +0 -1
  491. package/.next/standalone/.next/static/chunks/0b285gqd-hcvu.js +0 -1
  492. package/.next/static/chunks/026p3rpdycbyo.css +0 -1
  493. package/.next/static/chunks/0b285gqd-hcvu.js +0 -1
  494. /package/.next/standalone/.next/static/{G51gMWWv_zPc_nZoCBESi → SBId4_Ewcg0cJ2p2zlKeg}/_buildManifest.js +0 -0
  495. /package/.next/standalone/.next/static/{G51gMWWv_zPc_nZoCBESi → SBId4_Ewcg0cJ2p2zlKeg}/_clientMiddlewareManifest.js +0 -0
  496. /package/.next/standalone/.next/static/{G51gMWWv_zPc_nZoCBESi → SBId4_Ewcg0cJ2p2zlKeg}/_ssgManifest.js +0 -0
  497. /package/.next/static/{G51gMWWv_zPc_nZoCBESi → SBId4_Ewcg0cJ2p2zlKeg}/_buildManifest.js +0 -0
  498. /package/.next/static/{G51gMWWv_zPc_nZoCBESi → SBId4_Ewcg0cJ2p2zlKeg}/_clientMiddlewareManifest.js +0 -0
  499. /package/.next/static/{G51gMWWv_zPc_nZoCBESi → SBId4_Ewcg0cJ2p2zlKeg}/_ssgManifest.js +0 -0
@@ -0,0 +1,136 @@
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ 9Router is a self-hosted AI routing gateway built on Next.js 16 + React 19. It acts as a local proxy between AI coding tools (Codex, Cursor, Codex, Gemini CLI, etc.) and 40+ upstream AI providers. It provides format translation (OpenAI <-> Codex <-> Gemini <-> etc.), multi-account fallback, quota tracking, and usage monitoring. The app exposes an OpenAI-compatible endpoint at `/v1/*` and a web dashboard at `/dashboard`.
8
+
9
+ ## Common Commands
10
+
11
+ ```bash
12
+ # Development
13
+ cp .env.example .env # first time only
14
+ npm install
15
+ PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
16
+
17
+ # Production build
18
+ npm run build
19
+ PORT=20128 HOSTNAME=0.0.0.0 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run start
20
+
21
+ # Bun alternative
22
+ npm run dev:bun
23
+ npm run build:bun
24
+ npm run start:bun
25
+
26
+ # Linting
27
+ npx eslint .
28
+
29
+ # Tests (Vitest must be installed separately in /tmp)
30
+ cd /tmp && npm install vitest # one-time setup
31
+ cd tests/ && npm test # run all tests
32
+
33
+ # Run a single test file
34
+ cd tests/ && NODE_PATH=/tmp/node_modules /tmp/node_modules/.bin/vitest run unit/embeddingsCore.test.js --reporter=verbose
35
+
36
+ # Docker
37
+ docker build -t 9router .
38
+ docker run -d --name 9router -p 20128:20128 --env-file .env -v 9router-data:/app/data 9router
39
+ ```
40
+
41
+ ## Architecture
42
+
43
+ ### Two-Layer Routing Core
44
+
45
+ The system has a split routing architecture:
46
+
47
+ - **`src/sse/`** — App-level SSE handlers. Entry point is `src/sse/handlers/chat.js`. Handles model/combo resolution, credential selection, and delegates to the core.
48
+ - **`open-sse/`** — Shared, provider-agnostic routing engine (publishable as a separate package). Contains the core chat orchestration (`handlers/chatCore.js`), provider executors, format translators, and stream utilities.
49
+
50
+ Request flow: `API route → src/sse/handlers/chat.js → open-sse/handlers/chatCore.js → executor → upstream provider → response translator → client`
51
+
52
+ ### Path Aliases
53
+
54
+ Defined in `jsconfig.json`:
55
+ - `@/*` → `./src/*`
56
+ - `open-sse` / `open-sse/*` → `./open-sse/*`
57
+
58
+ ### API Routes (`src/app/api/`)
59
+
60
+ Two categories of API routes:
61
+
62
+ 1. **Compatibility APIs** (consumed by CLI tools):
63
+ - `/v1/chat/completions` — OpenAI-format chat (main entry point)
64
+ - `/v1/messages` — Anthropic Codex format
65
+ - `/v1/responses` — OpenAI Responses API format
66
+ - `/v1/embeddings`, `/v1/models`, `/v1beta/models`
67
+ - URL rewrites in `next.config.mjs` map `/v1/*` → `/api/v1/*`
68
+
69
+ 2. **Management APIs** (consumed by the dashboard):
70
+ - `/api/providers*`, `/api/provider-nodes*` — provider CRUD
71
+ - `/api/oauth/*` — OAuth flows for provider connections
72
+ - `/api/keys*`, `/api/combos*`, `/api/models/alias` — API keys, model combos, aliases
73
+ - `/api/settings/*`, `/api/auth/*`, `/api/usage/*`, `/api/sync/*`
74
+
75
+ ### Format Translation System (`open-sse/translator/`)
76
+
77
+ Translates between provider-specific formats. Source format is auto-detected from the request endpoint and body shape (see `formats.js`). Supported formats: `openai`, `openai-responses`, `Codex`, `gemini`, `vertex`, `codex`, `antigravity`, `kiro`, `cursor`, `ollama`.
78
+
79
+ - `translator/request/` — Inbound translation (e.g., `openai-to-Codex.js`)
80
+ - `translator/response/` — Outbound translation (e.g., `Codex-to-openai.js`)
81
+
82
+ ### Provider Executors (`open-sse/executors/`)
83
+
84
+ Each executor handles a specific provider's auth, API endpoint construction, and credential refresh. Examples: `codex.js`, `cursor.js`, `gemini-cli.js`, `kiro.js`, `iflow.js`, `antigravity.js`, `vertex.js`. The `default.js` executor handles standard OpenAI-compatible providers.
85
+
86
+ ### Combo + Account Fallback
87
+
88
+ - **Combos**: Named sequences of models tried in order (e.g., subscription → cheap → free)
89
+ - **Account fallback**: Multiple accounts per provider, round-robin with cooldown on failure
90
+ - Logic in `open-sse/services/accountFallback.js` and `src/sse/handlers/chat.js` (combo orchestration)
91
+
92
+ ### Persistence
93
+
94
+ - **State DB**: `src/lib/localDb.js` → `${DATA_DIR}/db.json` (or `~/.n9router/db.json`). Uses lowdb. Stores provider connections, nodes, aliases, combos, API keys, settings, pricing.
95
+ - **Usage DB**: `src/lib/usageDb.js` → `~/.n9router/usage.json` + `~/.n9router/log.txt`. Independent from `DATA_DIR`.
96
+
97
+ ### Frontend
98
+
99
+ - Next.js App Router with dashboard pages under `src/app/(dashboard)/dashboard/`
100
+ - Zustand stores in `src/store/` (providerStore, userStore, themeStore, notificationStore)
101
+ - UI components in `src/shared/components/`
102
+ - Tailwind CSS v4 via PostCSS plugin
103
+
104
+ ### MITM Proxy (`src/mitm/`)
105
+
106
+ Separate child process for intercepting HTTPS traffic from CLI tools. Has its own cert generation (`cert/`), DNS handling, and Express server.
107
+
108
+ ### Cloud Worker (`cloud/`)
109
+
110
+ Cloudflare Workers deployment for optional cloud sync relay. Has its own `wrangler.toml`, `package.json`, and separate source in `cloud/src/`.
111
+
112
+ ## Key Environment Variables
113
+
114
+ | Variable | Purpose |
115
+ |----------|---------|
116
+ | `JWT_SECRET` | Required. Signs dashboard auth tokens |
117
+ | `INITIAL_PASSWORD` | Required. Dashboard login password |
118
+ | `DATA_DIR` | Persistent storage directory (default: `~/.n9router`) |
119
+ | `PORT` | Server port (default: 20128) |
120
+ | `NEXT_PUBLIC_BASE_URL` | Public URL for the instance |
121
+ | `REQUIRE_API_KEY` | Enforce API key on `/v1/*` routes |
122
+ | `ENABLE_REQUEST_LOGS` | Log full request/response bodies |
123
+
124
+ ## Testing Notes
125
+
126
+ - Tests live in `tests/unit/` and use Vitest v4
127
+ - Vitest is installed in `/tmp/node_modules` to avoid conflicts with the root Next.js project's hoisting
128
+ - Test config is at `tests/vitest.config.js` — it aliases `open-sse` to the local package
129
+ - Current coverage: embeddings core, cloud worker handler, OAuth cursor auto-import, OpenAI-to-Codex translation, provider validation, translator request normalization
130
+
131
+ ## CI/CD
132
+
133
+ - GitHub Actions workflow at `.github/workflows/docker-publish.yml`
134
+ - Triggers on version tags (`v*`) and manual dispatch
135
+ - Builds and pushes Docker image to `ghcr.io`
136
+ - Docker uses multi-stage build with `node:20-alpine`, standalone Next.js output
@@ -16,4 +16,6 @@ Toàn bộ việc quản lý cũng được gom vào một chỗ. Bạn có th
16
16
 
17
17
  Cách bật cũng khá đơn giản: khởi động MITM Server, bật DNS Redirect cho Antigravity, rồi bật Token Rotation trong dashboard. Sau đó chỉ cần thêm nhiều account Antigravity vào pool là dùng được.
18
18
 
19
+ Nếu chưa muốn thêm account bằng tay, có thể dùng luôn nút import accounts từ Antigravity Management Tools trong phần provider Antigravity để đưa account vào pool nhanh hơn.
20
+
19
21
  Nói ngắn gọn, Antigravity Token Swap không phải là một tính năng kiểu “cho vui”. Nó là thứ giúp biến nhiều account Antigravity thành một lớp quota pool thực thụ, để công việc không bị phụ thuộc vào giới hạn của từng account riêng lẻ.
@@ -7,7 +7,7 @@ const { log, err } = require("./logger");
7
7
  const { TARGET_HOSTS, URL_PATTERNS, getToolForHost } = require("./config");
8
8
  const { DATA_DIR, MITM_DIR } = require("./paths");
9
9
  const { isTokenSwapEnabled, getAllActiveConnections, triggerRefreshIfNeeded,
10
- setCooldown, setModelCooldown, getTokenSwapStrategy,
10
+ forceRefreshConnection, setCooldown, setAuthCooldown, setModelCooldown, getTokenSwapStrategy,
11
11
  parseQuotaCooldown, markAccountUsed, getConnectionLabel } = require("./tokenPool");
12
12
  const { getCertForDomain } = require("./cert/generate");
13
13
  const { buildInputOnlyRequestDetail, createTokenSwapUsageObserver, generateDetailId } = require("./usageTracker");
@@ -187,120 +187,144 @@ async function tokenSwapForward(req, res, bodyBuffer, connections, model, strate
187
187
 
188
188
  for (let i = 0; i < connections.length; i++) {
189
189
  const originalConn = connections[i];
190
- const conn = await triggerRefreshIfNeeded(originalConn);
191
-
192
- const label = getConnectionLabel(conn);
193
- const modelTag = model ? ` model=${model}` : "";
194
- const posTag = connections.length > 1 ? ` [${i + 1}/${connections.length}]` : "";
195
- const useTag = conn.consecutiveUseCount > 1 ? ` uses=${conn.consecutiveUseCount}` : "";
196
- log(`🔑 [token-swap]${posTag} trying "${label}"${modelTag}${useTag}`);
197
-
198
- const swappedHeaders = {
199
- ...req.headers,
200
- host: targetHost,
201
- authorization: `Bearer ${conn.accessToken}`
202
- };
203
-
204
- try {
205
- const result = await new Promise((resolve, reject) => {
206
- const forwardReq = https.request({
207
- hostname: targetIP,
208
- port: 443,
209
- path: req.url,
210
- method: req.method,
211
- headers: swappedHeaders,
212
- servername: targetHost,
213
- rejectUnauthorized: false
214
- }, (forwardRes) => {
215
- if (forwardRes.statusCode === 429 || forwardRes.statusCode === 503) {
216
- // Buffer the short error body to parse cooldown duration
217
- const chunks = [];
218
- forwardRes.on("data", c => chunks.push(c));
219
- forwardRes.on("end", () => {
220
- const body = Buffer.concat(chunks).toString();
221
- resolve({ retry: true, body, statusCode: forwardRes.statusCode });
222
- });
190
+ let conn = await triggerRefreshIfNeeded(originalConn);
191
+ let authRefreshAttempted = false;
192
+
193
+ while (true) {
194
+ const label = getConnectionLabel(conn);
195
+ const modelTag = model ? ` model=${model}` : "";
196
+ const posTag = connections.length > 1 ? ` [${i + 1}/${connections.length}]` : "";
197
+ const useTag = conn.consecutiveUseCount > 1 ? ` uses=${conn.consecutiveUseCount}` : "";
198
+ log(`🔑 [token-swap]${posTag} trying "${label}"${modelTag}${useTag}`);
199
+
200
+ const swappedHeaders = {
201
+ ...req.headers,
202
+ host: targetHost,
203
+ authorization: `Bearer ${conn.accessToken}`
204
+ };
205
+
206
+ try {
207
+ const result = await new Promise((resolve, reject) => {
208
+ const forwardReq = https.request({
209
+ hostname: targetIP,
210
+ port: 443,
211
+ path: req.url,
212
+ method: req.method,
213
+ headers: swappedHeaders,
214
+ servername: targetHost,
215
+ rejectUnauthorized: false
216
+ }, (forwardRes) => {
217
+ if (forwardRes.statusCode === 429 || forwardRes.statusCode === 503 || forwardRes.statusCode === 401) {
218
+ const chunks = [];
219
+ forwardRes.on("data", c => chunks.push(c));
220
+ forwardRes.on("end", () => {
221
+ const body = Buffer.concat(chunks).toString();
222
+ const retryType = forwardRes.statusCode === 401 ? "auth" : "quota";
223
+ resolve({ retry: true, retryType, body, headers: forwardRes.headers, statusCode: forwardRes.statusCode });
224
+ });
225
+ } else {
226
+ resolve({ retry: false, response: forwardRes });
227
+ }
228
+ });
229
+ forwardReq.on("error", reject);
230
+ if (bodyBuffer.length > 0) forwardReq.write(bodyBuffer);
231
+ forwardReq.end();
232
+ });
233
+
234
+ if (result.retry && result.retryType === "quota") {
235
+ const cooldownMs = parseQuotaCooldown(result.body);
236
+ const cdLabel = cooldownMs ? ` cooldown=${Math.ceil(cooldownMs / 60000)}m` : "";
237
+ if (strategy === "sticky" && model) {
238
+ setModelCooldown(conn.id, model, cooldownMs);
239
+ log(`⚠️ [token-swap] "${label}" → ${result.statusCode} model=${model} quota exhausted${cdLabel}, trying next...`);
223
240
  } else {
224
- // Success or non-quota error → pipe to client
225
- resolve({ retry: false, response: forwardRes });
241
+ setCooldown(conn.id, cooldownMs);
242
+ log(`⚠️ [token-swap] "${label}" ${result.statusCode} account quota exhausted${cdLabel}, trying next...`);
226
243
  }
227
- });
228
- forwardReq.on("error", reject);
229
- if (bodyBuffer.length > 0) forwardReq.write(bodyBuffer);
230
- forwardReq.end();
231
- });
232
-
233
- if (result.retry) {
234
- const cooldownMs = parseQuotaCooldown(result.body);
235
- const cdLabel = cooldownMs ? ` cooldown=${Math.ceil(cooldownMs / 60000)}m` : "";
236
- if (strategy === "sticky" && model) {
237
- // Sticky: mark only this account+model as exhausted, not the whole account
238
- setModelCooldown(conn.id, model, cooldownMs);
239
- log(`⚠️ [token-swap] "${label}" → ${result.statusCode} model=${model} quota exhausted${cdLabel}, trying next...`);
240
- } else {
241
- // Round-robin: put whole account on cooldown
242
- setCooldown(conn.id, cooldownMs);
243
- log(`⚠️ [token-swap] "${label}" → ${result.statusCode} account quota exhausted${cdLabel}, trying next...`);
244
+ break;
244
245
  }
245
- continue;
246
- }
247
246
 
248
- const newCount = (conn.consecutiveUseCount || 0) + 1;
249
- const statusCode = result.response.statusCode || 0;
250
- const successModelTag = model ? ` model=${model}` : "";
251
- const successStrategyTag = strategy === "sticky" ? ` sticky(use #${newCount})` : ` rr`;
252
- log(`✅ [token-swap] "${label}" → ${statusCode}${successModelTag}${successStrategyTag}`);
253
- markAccountUsed(conn.id);
254
- res.writeHead(statusCode, result.response.headers);
255
-
256
- const detailId = generateDetailId(model);
257
- const inputOnlyDetail = buildInputOnlyRequestDetail({
258
- detailId,
259
- provider,
260
- model,
261
- connectionId: conn.id,
262
- bodyBuffer
263
- });
264
- fetch("http://127.0.0.1:20128/api/internal/request-detail", {
265
- method: "POST",
266
- headers: {
267
- "Content-Type": "application/json",
268
- [INTERNAL_REQUEST_HEADER.name]: INTERNAL_REQUEST_HEADER.value
269
- },
270
- body: JSON.stringify(inputOnlyDetail)
271
- }).catch((detailError) => {
272
- err(`[token-swap] failed to create request detail for "${label}": ${detailError.message}`);
273
- });
274
-
275
- const usageObserver = createTokenSwapUsageObserver({
276
- provider,
277
- model,
278
- connectionId: conn.id,
279
- accountLabel: label,
280
- bodyBuffer,
281
- contentType: result.response.headers["content-type"] || "",
282
- contentEncoding: result.response.headers["content-encoding"] || "",
283
- statusCode,
284
- detailRecord: inputOnlyDetail,
285
- requestStartTime
286
- });
287
-
288
- result.response.on("data", (chunk) => {
289
- usageObserver.onChunk(chunk);
290
- res.write(chunk);
291
- });
292
- result.response.on("end", () => {
293
- res.end();
294
- usageObserver.onEnd().catch(() => {});
295
- });
296
- result.response.on("error", (streamError) => {
297
- err(`[token-swap] upstream stream error for "${label}": ${streamError.message}`);
298
- if (!res.writableEnded) res.end();
299
- });
300
- return true;
301
- } catch (e) {
302
- err(`[token-swap] error for "${label}": ${e.message}`);
303
- continue;
247
+ if (result.retry && result.retryType === "auth") {
248
+ const retryableAuth = isRetryableAuthFailure(result.statusCode, result.headers, result.body);
249
+ if (!retryableAuth) {
250
+ res.writeHead(result.statusCode, result.headers);
251
+ res.end(result.body);
252
+ return true;
253
+ }
254
+
255
+ if (!authRefreshAttempted && conn.refreshToken) {
256
+ authRefreshAttempted = true;
257
+ log(`⚠️ [token-swap] "${label}" → 401 invalid_token, forcing refresh...`);
258
+ const refreshResult = await forceRefreshConnection(conn);
259
+ conn = refreshResult.connection || conn;
260
+ if (refreshResult.refreshed) {
261
+ log(`↻ [token-swap] "${label}" refreshed, retrying same account...`);
262
+ continue;
263
+ }
264
+ }
265
+
266
+ setAuthCooldown(conn.id);
267
+ log(`⚠️ [token-swap] "${label}" → 401 invalid_token, trying next...`);
268
+ break;
269
+ }
270
+
271
+ const newCount = (conn.consecutiveUseCount || 0) + 1;
272
+ const statusCode = result.response.statusCode || 0;
273
+ const successModelTag = model ? ` model=${model}` : "";
274
+ const successStrategyTag = strategy === "sticky" ? ` sticky(use #${newCount})` : ` rr`;
275
+ log(`✅ [token-swap] "${label}" → ${statusCode}${successModelTag}${successStrategyTag}`);
276
+ markAccountUsed(conn.id);
277
+ res.writeHead(statusCode, result.response.headers);
278
+
279
+ const detailId = generateDetailId(model);
280
+ const inputOnlyDetail = buildInputOnlyRequestDetail({
281
+ detailId,
282
+ provider,
283
+ model,
284
+ connectionId: conn.id,
285
+ bodyBuffer
286
+ });
287
+ fetch("http://127.0.0.1:20128/api/internal/request-detail", {
288
+ method: "POST",
289
+ headers: {
290
+ "Content-Type": "application/json",
291
+ [INTERNAL_REQUEST_HEADER.name]: INTERNAL_REQUEST_HEADER.value
292
+ },
293
+ body: JSON.stringify(inputOnlyDetail)
294
+ }).catch((detailError) => {
295
+ err(`[token-swap] failed to create request detail for "${label}": ${detailError.message}`);
296
+ });
297
+
298
+ const usageObserver = createTokenSwapUsageObserver({
299
+ provider,
300
+ model,
301
+ connectionId: conn.id,
302
+ accountLabel: label,
303
+ bodyBuffer,
304
+ contentType: result.response.headers["content-type"] || "",
305
+ contentEncoding: result.response.headers["content-encoding"] || "",
306
+ statusCode,
307
+ detailRecord: inputOnlyDetail,
308
+ requestStartTime
309
+ });
310
+
311
+ result.response.on("data", (chunk) => {
312
+ usageObserver.onChunk(chunk);
313
+ res.write(chunk);
314
+ });
315
+ result.response.on("end", () => {
316
+ res.end();
317
+ usageObserver.onEnd().catch(() => {});
318
+ });
319
+ result.response.on("error", (streamError) => {
320
+ err(`[token-swap] upstream stream error for "${label}": ${streamError.message}`);
321
+ if (!res.writableEnded) res.end();
322
+ });
323
+ return true;
324
+ } catch (e) {
325
+ err(`[token-swap] error for "${label}": ${e.message}`);
326
+ break;
327
+ }
304
328
  }
305
329
  }
306
330
 
@@ -308,6 +332,36 @@ async function tokenSwapForward(req, res, bodyBuffer, connections, model, strate
308
332
  return false;
309
333
  }
310
334
 
335
+ function getHeaderValue(headers, name) {
336
+ const value = headers?.[String(name).toLowerCase()];
337
+ if (Array.isArray(value)) return value.join(", ");
338
+ return typeof value === "string" ? value : "";
339
+ }
340
+
341
+ function isRetryableAuthFailure(statusCode, headers, body) {
342
+ if (statusCode !== 401) return false;
343
+
344
+ const authHeader = getHeaderValue(headers, "www-authenticate").toLowerCase();
345
+ if (authHeader.includes("invalid_token")) return true;
346
+
347
+ try {
348
+ const parsed = JSON.parse(body || "{}");
349
+ const status = String(parsed?.error?.status || parsed?.status || "").toUpperCase();
350
+ const message = String(parsed?.error?.message || parsed?.message || "").toLowerCase();
351
+ if (status === "UNAUTHENTICATED") return true;
352
+ if (message.includes("invalid authentication credentials")) return true;
353
+ if (message.includes("invalid token")) return true;
354
+ if (message.includes("unauthenticated")) return true;
355
+ } catch {
356
+ const fallback = String(body || "").toLowerCase();
357
+ if (fallback.includes("invalid authentication credentials")) return true;
358
+ if (fallback.includes("invalid token")) return true;
359
+ if (fallback.includes("unauthenticated")) return true;
360
+ }
361
+
362
+ return false;
363
+ }
364
+
311
365
  // ── Request handler ───────────────────────────────────────────
312
366
 
313
367
  const server = https.createServer(sslOptions, async (req, res) => {
@@ -14,6 +14,7 @@ const DB_FILE = path.join(DATA_DIR, "db.json");
14
14
  const TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1000; // refresh 5min before expiry
15
15
  const ROUTER_PORT = process.env.PORT || 20128;
16
16
  const DEFAULT_COOLDOWN_MS = 5 * 60 * 1000;
17
+ const DEFAULT_AUTH_COOLDOWN_MS = 10 * 60 * 1000;
17
18
 
18
19
  // ── In-memory state ──────────────────────────────────────────
19
20
  const cooldownMap = {}; // { [connectionId]: expiresTimestamp }
@@ -28,6 +29,12 @@ function setCooldown(connId, durationMs) {
28
29
  log(`⏸ [token-pool] cooldown: ${connId.slice(0, 8)}… for ${Math.ceil(ms / 60000)}m`);
29
30
  }
30
31
 
32
+ function setAuthCooldown(connId, durationMs) {
33
+ const ms = durationMs || DEFAULT_AUTH_COOLDOWN_MS;
34
+ cooldownMap[connId] = Date.now() + ms;
35
+ log(`🔒 [token-pool] auth-cooldown: ${connId.slice(0, 8)}… for ${Math.ceil(ms / 60000)}m`);
36
+ }
37
+
31
38
  function isInCooldown(connId) {
32
39
  if (!cooldownMap[connId]) return false;
33
40
  if (Date.now() > cooldownMap[connId]) {
@@ -287,41 +294,82 @@ function markAccountUsed(connId) {
287
294
  // checks expiry, refreshes token automatically, then returns the
288
295
  // latest persisted connection snapshot for the current request.
289
296
 
290
- async function triggerRefreshIfNeeded(connection) {
291
- if (!connection?.expiresAt || !connection?.refreshToken) return connection;
292
- const expiresAt = new Date(connection.expiresAt).getTime();
293
- if (Date.now() + TOKEN_EXPIRY_BUFFER_MS < expiresAt) return connection;
294
-
295
- log(`🔄 [token-pool] near-expiry refresh → ${getConnectionLabel(connection).slice(0, 20)}`);
297
+ async function runConnectionTest(connection) {
296
298
  return await new Promise((resolve) => {
299
+ if (!connection?.id) {
300
+ resolve({ connection, refreshed: false, valid: false });
301
+ return;
302
+ }
303
+
304
+ let responseBody = "";
305
+
297
306
  try {
298
307
  const req = http.request(
299
308
  { hostname: "127.0.0.1", port: ROUTER_PORT, path: `/api/providers/${connection.id}/test`, method: "POST" },
300
309
  (res) => {
301
- res.on("data", () => {});
310
+ res.on("data", (chunk) => {
311
+ responseBody += chunk.toString();
312
+ });
302
313
  res.on("end", () => {
303
- const refreshed = getConnectionById(connection.id);
304
- if (refreshed?.accessToken && refreshed.accessToken !== connection.accessToken) {
305
- log(`♻️ [token-pool] refreshed token applied → ${getConnectionLabel(connection).slice(0, 20)}`);
314
+ let payload = {};
315
+ try {
316
+ payload = JSON.parse(responseBody || "{}");
317
+ } catch {
318
+ payload = {};
306
319
  }
307
- resolve(refreshed || connection);
320
+
321
+ const refreshedConnection = getConnectionById(connection.id);
322
+ const tokenChanged = !!(refreshedConnection?.accessToken && refreshedConnection.accessToken !== connection.accessToken);
323
+ resolve({
324
+ connection: refreshedConnection || connection,
325
+ refreshed: !!payload.refreshed || tokenChanged,
326
+ valid: !!payload.valid,
327
+ });
308
328
  });
309
329
  }
310
330
  );
311
- req.on("error", () => resolve(connection));
331
+ req.on("error", () => resolve({ connection, refreshed: false, valid: false }));
312
332
  req.end();
313
333
  } catch {
314
- resolve(connection);
334
+ resolve({ connection, refreshed: false, valid: false });
315
335
  }
316
336
  });
317
337
  }
318
338
 
339
+ async function triggerRefreshIfNeeded(connection) {
340
+ if (!connection?.expiresAt || !connection?.refreshToken) return connection;
341
+ const expiresAt = new Date(connection.expiresAt).getTime();
342
+ if (Date.now() + TOKEN_EXPIRY_BUFFER_MS < expiresAt) return connection;
343
+
344
+ log(`🔄 [token-pool] near-expiry refresh → ${getConnectionLabel(connection).slice(0, 20)}`);
345
+ const result = await runConnectionTest(connection);
346
+ if (result.refreshed) {
347
+ log(`♻️ [token-pool] refreshed token applied → ${getConnectionLabel(connection).slice(0, 20)}`);
348
+ }
349
+ return result.connection || connection;
350
+ }
351
+
352
+ async function forceRefreshConnection(connection) {
353
+ if (!connection?.refreshToken) {
354
+ return { connection, refreshed: false, valid: false };
355
+ }
356
+
357
+ log(`🔄 [token-pool] auth refresh → ${getConnectionLabel(connection).slice(0, 20)}`);
358
+ const result = await runConnectionTest(connection);
359
+ if (result.refreshed) {
360
+ log(`♻️ [token-pool] refreshed token applied → ${getConnectionLabel(connection).slice(0, 20)}`);
361
+ }
362
+ return result;
363
+ }
364
+
319
365
  module.exports = {
320
366
  isTokenSwapEnabled,
321
367
  getNextConnection,
322
368
  getAllActiveConnections,
323
369
  triggerRefreshIfNeeded,
370
+ forceRefreshConnection,
324
371
  setCooldown,
372
+ setAuthCooldown,
325
373
  setModelCooldown,
326
374
  isModelExhausted,
327
375
  getTokenSwapStrategy,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "n9router",
3
- "version": "0.3.91",
3
+ "version": "0.3.94",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "n9router",
9
- "version": "0.3.91",
9
+ "version": "0.3.94",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@monaco-editor/react": "^4.7.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n9router",
3
- "version": "0.3.91",
3
+ "version": "0.3.94",
4
4
  "description": "Self-hosted AI routing gateway — local proxy for Claude, Gemini, OpenAI and 40+ providers",
5
5
  "keywords": [
6
6
  "ai",