@rsalmn/extremerouter 0.8.2 → 0.8.3

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 (855) hide show
  1. package/README.md +89 -89
  2. package/app/.next-cli-build/BUILD_ID +1 -1
  3. package/app/.next-cli-build/app-path-routes-manifest.json +9 -9
  4. package/app/.next-cli-build/build-manifest.json +4 -4
  5. package/app/.next-cli-build/prerender-manifest.json +3 -3
  6. package/app/.next-cli-build/react-loadable-manifest.json +1 -13
  7. package/app/.next-cli-build/required-server-files.json +23 -23
  8. package/app/.next-cli-build/server/app/(dashboard)/dashboard/alerts/page.js +2 -2
  9. package/app/.next-cli-build/server/app/(dashboard)/dashboard/alerts/page.js.nft.json +1 -1
  10. package/app/.next-cli-build/server/app/(dashboard)/dashboard/alerts/page_client-reference-manifest.js +1 -1
  11. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page.js +2 -2
  12. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page.js.nft.json +1 -1
  13. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  14. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js +3 -3
  15. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page.js.nft.json +1 -1
  16. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  17. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js +2 -2
  18. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page.js.nft.json +1 -1
  19. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  20. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page.js +3 -3
  21. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page.js.nft.json +1 -1
  22. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  23. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page.js +2 -2
  24. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page.js.nft.json +1 -1
  25. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  26. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js +2 -2
  27. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page.js.nft.json +1 -1
  28. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  29. package/app/.next-cli-build/server/app/(dashboard)/dashboard/health/page.js +2 -2
  30. package/app/.next-cli-build/server/app/(dashboard)/dashboard/health/page.js.nft.json +1 -1
  31. package/app/.next-cli-build/server/app/(dashboard)/dashboard/health/page_client-reference-manifest.js +1 -1
  32. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +3 -3
  33. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js.nft.json +1 -1
  34. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  35. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js +2 -2
  36. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page.js.nft.json +1 -1
  37. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  38. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js +3 -3
  39. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page.js.nft.json +1 -1
  40. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  41. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page.js +2 -2
  42. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page.js.nft.json +1 -1
  43. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  44. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page.js +2 -2
  45. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page.js.nft.json +1 -1
  46. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  47. package/app/.next-cli-build/server/app/(dashboard)/dashboard/overview/page.js +2 -2
  48. package/app/.next-cli-build/server/app/(dashboard)/dashboard/overview/page.js.nft.json +1 -1
  49. package/app/.next-cli-build/server/app/(dashboard)/dashboard/overview/page_client-reference-manifest.js +1 -1
  50. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js +2 -2
  51. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page.js.nft.json +1 -1
  52. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  53. package/app/.next-cli-build/server/app/(dashboard)/dashboard/playground/page.js +2 -2
  54. package/app/.next-cli-build/server/app/(dashboard)/dashboard/playground/page.js.nft.json +1 -1
  55. package/app/.next-cli-build/server/app/(dashboard)/dashboard/playground/page_client-reference-manifest.js +1 -1
  56. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page.js +2 -2
  57. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page.js.nft.json +1 -1
  58. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  59. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js +3 -3
  60. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js.nft.json +1 -1
  61. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  62. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page.js +2 -2
  63. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page.js.nft.json +1 -1
  64. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  65. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page.js +2 -2
  66. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page.js.nft.json +1 -1
  67. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  68. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page.js +3 -3
  69. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page.js.nft.json +1 -1
  70. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  71. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page.js +2 -2
  72. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page.js.nft.json +1 -1
  73. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  74. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page.js +2 -2
  75. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page.js.nft.json +1 -1
  76. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  77. package/app/.next-cli-build/server/app/(dashboard)/dashboard/swarm/page.js +2 -2
  78. package/app/.next-cli-build/server/app/(dashboard)/dashboard/swarm/page.js.nft.json +1 -1
  79. package/app/.next-cli-build/server/app/(dashboard)/dashboard/swarm/page_client-reference-manifest.js +1 -1
  80. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page.js +2 -2
  81. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page.js.nft.json +1 -1
  82. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
  83. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page.js +2 -2
  84. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page.js.nft.json +1 -1
  85. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  86. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page.js +2 -2
  87. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page.js.nft.json +1 -1
  88. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  89. package/app/.next-cli-build/server/app/_global-error/page.js +3 -3
  90. package/app/.next-cli-build/server/app/_global-error/page.js.nft.json +1 -1
  91. package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
  92. package/app/.next-cli-build/server/app/_global-error.html +1 -1
  93. package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
  94. package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/app/.next-cli-build/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/app/.next-cli-build/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/app/.next-cli-build/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/app/.next-cli-build/server/app/_not-found/page.js +2 -2
  101. package/app/.next-cli-build/server/app/_not-found/page.js.nft.json +1 -1
  102. package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
  103. package/app/.next-cli-build/server/app/_not-found.html +1 -1
  104. package/app/.next-cli-build/server/app/_not-found.rsc +7 -6
  105. package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +7 -6
  106. package/app/.next-cli-build/server/app/_not-found.segments/_head.segment.rsc +1 -1
  107. package/app/.next-cli-build/server/app/_not-found.segments/_index.segment.rsc +6 -6
  108. package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  109. package/app/.next-cli-build/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  110. package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +3 -2
  111. package/app/.next-cli-build/server/app/api/alerts/test/route.js +2 -2
  112. package/app/.next-cli-build/server/app/api/alerts/test/route.js.nft.json +1 -1
  113. package/app/.next-cli-build/server/app/api/alerts/test/route_client-reference-manifest.js +1 -1
  114. package/app/.next-cli-build/server/app/api/auth/login/route.js +1 -1
  115. package/app/.next-cli-build/server/app/api/auth/login/route.js.nft.json +1 -1
  116. package/app/.next-cli-build/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  117. package/app/.next-cli-build/server/app/api/auth/logout/route.js +1 -1
  118. package/app/.next-cli-build/server/app/api/auth/logout/route.js.nft.json +1 -1
  119. package/app/.next-cli-build/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  120. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js +1 -1
  121. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route.js.nft.json +1 -1
  122. package/app/.next-cli-build/server/app/api/auth/oidc/callback/route_client-reference-manifest.js +1 -1
  123. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js +1 -1
  124. package/app/.next-cli-build/server/app/api/auth/oidc/start/route.js.nft.json +1 -1
  125. package/app/.next-cli-build/server/app/api/auth/oidc/start/route_client-reference-manifest.js +1 -1
  126. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js +1 -1
  127. package/app/.next-cli-build/server/app/api/auth/oidc/test/route.js.nft.json +1 -1
  128. package/app/.next-cli-build/server/app/api/auth/oidc/test/route_client-reference-manifest.js +1 -1
  129. package/app/.next-cli-build/server/app/api/auth/reset-password/route.js +1 -1
  130. package/app/.next-cli-build/server/app/api/auth/reset-password/route.js.nft.json +1 -1
  131. package/app/.next-cli-build/server/app/api/auth/reset-password/route_client-reference-manifest.js +1 -1
  132. package/app/.next-cli-build/server/app/api/auth/status/route.js +1 -1
  133. package/app/.next-cli-build/server/app/api/auth/status/route.js.nft.json +1 -1
  134. package/app/.next-cli-build/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
  135. package/app/.next-cli-build/server/app/api/breaker/route.js +1 -1
  136. package/app/.next-cli-build/server/app/api/breaker/route.js.nft.json +1 -1
  137. package/app/.next-cli-build/server/app/api/breaker/route_client-reference-manifest.js +1 -1
  138. package/app/.next-cli-build/server/app/api/cache/route.js +1 -1
  139. package/app/.next-cli-build/server/app/api/cache/route.js.nft.json +1 -1
  140. package/app/.next-cli-build/server/app/api/cache/route_client-reference-manifest.js +1 -1
  141. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js +4 -4
  142. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js.nft.json +1 -1
  143. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route_client-reference-manifest.js +1 -1
  144. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js +2 -2
  145. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route.js.nft.json +1 -1
  146. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/alias/route_client-reference-manifest.js +1 -1
  147. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
  148. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route.js.nft.json +1 -1
  149. package/app/.next-cli-build/server/app/api/cli-tools/antigravity-mitm/route_client-reference-manifest.js +1 -1
  150. package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route.js +2 -2
  151. package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route.js.nft.json +1 -1
  152. package/app/.next-cli-build/server/app/api/cli-tools/claude-settings/route_client-reference-manifest.js +1 -1
  153. package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route.js +1 -1
  154. package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route.js.nft.json +1 -1
  155. package/app/.next-cli-build/server/app/api/cli-tools/cline-settings/route_client-reference-manifest.js +1 -1
  156. package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js +1 -1
  157. package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route.js.nft.json +1 -1
  158. package/app/.next-cli-build/server/app/api/cli-tools/codex-settings/route_client-reference-manifest.js +1 -1
  159. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js +2 -2
  160. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route.js.nft.json +1 -1
  161. package/app/.next-cli-build/server/app/api/cli-tools/copilot-settings/route_client-reference-manifest.js +1 -1
  162. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route.js +2 -2
  163. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route.js.nft.json +1 -1
  164. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-registry/route_client-reference-manifest.js +1 -1
  165. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route.js +2 -2
  166. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route.js.nft.json +1 -1
  167. package/app/.next-cli-build/server/app/api/cli-tools/cowork-mcp-tools/route_client-reference-manifest.js +1 -1
  168. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js +2 -2
  169. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route.js.nft.json +1 -1
  170. package/app/.next-cli-build/server/app/api/cli-tools/cowork-settings/route_client-reference-manifest.js +1 -1
  171. package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route.js +3 -3
  172. package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route.js.nft.json +1 -1
  173. package/app/.next-cli-build/server/app/api/cli-tools/deepseek-tui-settings/route_client-reference-manifest.js +1 -1
  174. package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route.js +1 -1
  175. package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route.js.nft.json +1 -1
  176. package/app/.next-cli-build/server/app/api/cli-tools/droid-settings/route_client-reference-manifest.js +1 -1
  177. package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route.js +3 -3
  178. package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route.js.nft.json +1 -1
  179. package/app/.next-cli-build/server/app/api/cli-tools/hermes-settings/route_client-reference-manifest.js +1 -1
  180. package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route.js +2 -2
  181. package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route.js.nft.json +1 -1
  182. package/app/.next-cli-build/server/app/api/cli-tools/jcode-settings/route_client-reference-manifest.js +1 -1
  183. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js +2 -2
  184. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js.nft.json +1 -1
  185. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route_client-reference-manifest.js +1 -1
  186. package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route.js +2 -2
  187. package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route.js.nft.json +1 -1
  188. package/app/.next-cli-build/server/app/api/cli-tools/openclaw-settings/route_client-reference-manifest.js +1 -1
  189. package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route.js +1 -1
  190. package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route.js.nft.json +1 -1
  191. package/app/.next-cli-build/server/app/api/cli-tools/opencode-settings/route_client-reference-manifest.js +1 -1
  192. package/app/.next-cli-build/server/app/api/combos/[id]/route.js +1 -1
  193. package/app/.next-cli-build/server/app/api/combos/[id]/route.js.nft.json +1 -1
  194. package/app/.next-cli-build/server/app/api/combos/[id]/route_client-reference-manifest.js +1 -1
  195. package/app/.next-cli-build/server/app/api/combos/route.js +1 -1
  196. package/app/.next-cli-build/server/app/api/combos/route.js.nft.json +1 -1
  197. package/app/.next-cli-build/server/app/api/combos/route_client-reference-manifest.js +1 -1
  198. package/app/.next-cli-build/server/app/api/combos/validate-roles/route.js +1 -1
  199. package/app/.next-cli-build/server/app/api/combos/validate-roles/route.js.nft.json +1 -1
  200. package/app/.next-cli-build/server/app/api/combos/validate-roles/route_client-reference-manifest.js +1 -1
  201. package/app/.next-cli-build/server/app/api/dashboard/stream/route.js +2 -2
  202. package/app/.next-cli-build/server/app/api/dashboard/stream/route.js.nft.json +1 -1
  203. package/app/.next-cli-build/server/app/api/dashboard/stream/route_client-reference-manifest.js +1 -1
  204. package/app/.next-cli-build/server/app/api/headroom/start/route.js +1 -1
  205. package/app/.next-cli-build/server/app/api/headroom/start/route.js.nft.json +1 -1
  206. package/app/.next-cli-build/server/app/api/headroom/start/route_client-reference-manifest.js +1 -1
  207. package/app/.next-cli-build/server/app/api/headroom/status/route.js +1 -1
  208. package/app/.next-cli-build/server/app/api/headroom/status/route.js.nft.json +1 -1
  209. package/app/.next-cli-build/server/app/api/headroom/status/route_client-reference-manifest.js +1 -1
  210. package/app/.next-cli-build/server/app/api/headroom/stop/route.js +2 -2
  211. package/app/.next-cli-build/server/app/api/headroom/stop/route.js.nft.json +1 -1
  212. package/app/.next-cli-build/server/app/api/headroom/stop/route_client-reference-manifest.js +1 -1
  213. package/app/.next-cli-build/server/app/api/health/providers/route.js +1 -1
  214. package/app/.next-cli-build/server/app/api/health/providers/route.js.nft.json +1 -1
  215. package/app/.next-cli-build/server/app/api/health/providers/route_client-reference-manifest.js +1 -1
  216. package/app/.next-cli-build/server/app/api/health/route.js +1 -1
  217. package/app/.next-cli-build/server/app/api/health/route.js.nft.json +1 -1
  218. package/app/.next-cli-build/server/app/api/health/route_client-reference-manifest.js +1 -1
  219. package/app/.next-cli-build/server/app/api/health/stream/route.js +2 -2
  220. package/app/.next-cli-build/server/app/api/health/stream/route.js.nft.json +1 -1
  221. package/app/.next-cli-build/server/app/api/health/stream/route_client-reference-manifest.js +1 -1
  222. package/app/.next-cli-build/server/app/api/init/route.js +1 -1
  223. package/app/.next-cli-build/server/app/api/init/route.js.nft.json +1 -1
  224. package/app/.next-cli-build/server/app/api/init/route_client-reference-manifest.js +1 -1
  225. package/app/.next-cli-build/server/app/api/keys/[id]/route.js +1 -1
  226. package/app/.next-cli-build/server/app/api/keys/[id]/route.js.nft.json +1 -1
  227. package/app/.next-cli-build/server/app/api/keys/[id]/route_client-reference-manifest.js +1 -1
  228. package/app/.next-cli-build/server/app/api/keys/route.js +1 -1
  229. package/app/.next-cli-build/server/app/api/keys/route.js.nft.json +1 -1
  230. package/app/.next-cli-build/server/app/api/keys/route_client-reference-manifest.js +1 -1
  231. package/app/.next-cli-build/server/app/api/locale/route.js +1 -1
  232. package/app/.next-cli-build/server/app/api/locale/route.js.nft.json +1 -1
  233. package/app/.next-cli-build/server/app/api/locale/route_client-reference-manifest.js +1 -1
  234. package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js +2 -2
  235. package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route.js.nft.json +1 -1
  236. package/app/.next-cli-build/server/app/api/mcp/[plugin]/message/route_client-reference-manifest.js +1 -1
  237. package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js +2 -2
  238. package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route.js.nft.json +1 -1
  239. package/app/.next-cli-build/server/app/api/mcp/[plugin]/sse/route_client-reference-manifest.js +1 -1
  240. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js +1 -1
  241. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route.js.nft.json +1 -1
  242. package/app/.next-cli-build/server/app/api/media-providers/tts/deepgram/voices/route_client-reference-manifest.js +1 -1
  243. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js +1 -1
  244. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route.js.nft.json +1 -1
  245. package/app/.next-cli-build/server/app/api/media-providers/tts/elevenlabs/voices/route_client-reference-manifest.js +1 -1
  246. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js +1 -1
  247. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route.js.nft.json +1 -1
  248. package/app/.next-cli-build/server/app/api/media-providers/tts/inworld/voices/route_client-reference-manifest.js +1 -1
  249. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js +1 -1
  250. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route.js.nft.json +1 -1
  251. package/app/.next-cli-build/server/app/api/media-providers/tts/minimax/voices/route_client-reference-manifest.js +1 -1
  252. package/app/.next-cli-build/server/app/api/media-providers/tts/voices/route.js +1 -1
  253. package/app/.next-cli-build/server/app/api/media-providers/tts/voices/route.js.nft.json +1 -1
  254. package/app/.next-cli-build/server/app/api/media-providers/tts/voices/route_client-reference-manifest.js +1 -1
  255. package/app/.next-cli-build/server/app/api/models/alias/route.js +1 -1
  256. package/app/.next-cli-build/server/app/api/models/alias/route.js.nft.json +1 -1
  257. package/app/.next-cli-build/server/app/api/models/alias/route_client-reference-manifest.js +1 -1
  258. package/app/.next-cli-build/server/app/api/models/availability/route.js +1 -1
  259. package/app/.next-cli-build/server/app/api/models/availability/route.js.nft.json +1 -1
  260. package/app/.next-cli-build/server/app/api/models/availability/route_client-reference-manifest.js +1 -1
  261. package/app/.next-cli-build/server/app/api/models/custom/route.js +1 -1
  262. package/app/.next-cli-build/server/app/api/models/custom/route.js.nft.json +1 -1
  263. package/app/.next-cli-build/server/app/api/models/custom/route_client-reference-manifest.js +1 -1
  264. package/app/.next-cli-build/server/app/api/models/disabled/route.js +1 -1
  265. package/app/.next-cli-build/server/app/api/models/disabled/route.js.nft.json +1 -1
  266. package/app/.next-cli-build/server/app/api/models/disabled/route_client-reference-manifest.js +1 -1
  267. package/app/.next-cli-build/server/app/api/models/route.js +1 -1
  268. package/app/.next-cli-build/server/app/api/models/route.js.nft.json +1 -1
  269. package/app/.next-cli-build/server/app/api/models/route_client-reference-manifest.js +1 -1
  270. package/app/.next-cli-build/server/app/api/models/test/route.js +1 -1
  271. package/app/.next-cli-build/server/app/api/models/test/route.js.nft.json +1 -1
  272. package/app/.next-cli-build/server/app/api/models/test/route_client-reference-manifest.js +1 -1
  273. package/app/.next-cli-build/server/app/api/oauth/1min/import/route.js +1 -1
  274. package/app/.next-cli-build/server/app/api/oauth/1min/import/route.js.nft.json +1 -1
  275. package/app/.next-cli-build/server/app/api/oauth/1min/import/route_client-reference-manifest.js +1 -1
  276. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js +1 -1
  277. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route.js.nft.json +1 -1
  278. package/app/.next-cli-build/server/app/api/oauth/[provider]/[action]/route_client-reference-manifest.js +1 -1
  279. package/app/.next-cli-build/server/app/api/oauth/codex/bulk-import/route.js +1 -1
  280. package/app/.next-cli-build/server/app/api/oauth/codex/bulk-import/route.js.nft.json +1 -1
  281. package/app/.next-cli-build/server/app/api/oauth/codex/bulk-import/route_client-reference-manifest.js +1 -1
  282. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js +1 -1
  283. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route.js.nft.json +1 -1
  284. package/app/.next-cli-build/server/app/api/oauth/codex/import-token/route_client-reference-manifest.js +1 -1
  285. package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js +2 -2
  286. package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route.js.nft.json +1 -1
  287. package/app/.next-cli-build/server/app/api/oauth/cursor/auto-import/route_client-reference-manifest.js +1 -1
  288. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js +1 -1
  289. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route.js.nft.json +1 -1
  290. package/app/.next-cli-build/server/app/api/oauth/cursor/import/route_client-reference-manifest.js +1 -1
  291. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js +1 -1
  292. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route.js.nft.json +1 -1
  293. package/app/.next-cli-build/server/app/api/oauth/gitlab/pat/route_client-reference-manifest.js +1 -1
  294. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js +1 -1
  295. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route.js.nft.json +1 -1
  296. package/app/.next-cli-build/server/app/api/oauth/iflow/cookie/route_client-reference-manifest.js +1 -1
  297. package/app/.next-cli-build/server/app/api/oauth/kiro/api-key/route.js +1 -1
  298. package/app/.next-cli-build/server/app/api/oauth/kiro/api-key/route.js.nft.json +1 -1
  299. package/app/.next-cli-build/server/app/api/oauth/kiro/api-key/route_client-reference-manifest.js +1 -1
  300. package/app/.next-cli-build/server/app/api/oauth/kiro/auto-import/route.js +1 -1
  301. package/app/.next-cli-build/server/app/api/oauth/kiro/auto-import/route.js.nft.json +1 -1
  302. package/app/.next-cli-build/server/app/api/oauth/kiro/auto-import/route_client-reference-manifest.js +1 -1
  303. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js +1 -1
  304. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route.js.nft.json +1 -1
  305. package/app/.next-cli-build/server/app/api/oauth/kiro/import/route_client-reference-manifest.js +1 -1
  306. package/app/.next-cli-build/server/app/api/oauth/kiro/import-cli-proxy/route.js +1 -1
  307. package/app/.next-cli-build/server/app/api/oauth/kiro/import-cli-proxy/route.js.nft.json +1 -1
  308. package/app/.next-cli-build/server/app/api/oauth/kiro/import-cli-proxy/route_client-reference-manifest.js +1 -1
  309. package/app/.next-cli-build/server/app/api/oauth/kiro/social-authorize/route.js +1 -1
  310. package/app/.next-cli-build/server/app/api/oauth/kiro/social-authorize/route.js.nft.json +1 -1
  311. package/app/.next-cli-build/server/app/api/oauth/kiro/social-authorize/route_client-reference-manifest.js +1 -1
  312. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js +1 -1
  313. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route.js.nft.json +1 -1
  314. package/app/.next-cli-build/server/app/api/oauth/kiro/social-exchange/route_client-reference-manifest.js +1 -1
  315. package/app/.next-cli-build/server/app/api/oauth/qwen/import/route.js +1 -1
  316. package/app/.next-cli-build/server/app/api/oauth/qwen/import/route.js.nft.json +1 -1
  317. package/app/.next-cli-build/server/app/api/oauth/qwen/import/route_client-reference-manifest.js +1 -1
  318. package/app/.next-cli-build/server/app/api/oauth/wp-studio/import/route.js +1 -1
  319. package/app/.next-cli-build/server/app/api/oauth/wp-studio/import/route.js.nft.json +1 -1
  320. package/app/.next-cli-build/server/app/api/oauth/wp-studio/import/route_client-reference-manifest.js +1 -1
  321. package/app/.next-cli-build/server/app/api/oauth/zed/auto-import/route.js +38 -2
  322. package/app/.next-cli-build/server/app/api/oauth/zed/auto-import/route.js.nft.json +1 -1
  323. package/app/.next-cli-build/server/app/api/oauth/zed/auto-import/route_client-reference-manifest.js +1 -1
  324. package/app/.next-cli-build/server/app/api/oauth/zed/import/route.js +1 -1
  325. package/app/.next-cli-build/server/app/api/oauth/zed/import/route.js.nft.json +1 -1
  326. package/app/.next-cli-build/server/app/api/oauth/zed/import/route_client-reference-manifest.js +1 -1
  327. package/app/.next-cli-build/server/app/api/pricing/route.js +1 -1
  328. package/app/.next-cli-build/server/app/api/pricing/route.js.nft.json +1 -1
  329. package/app/.next-cli-build/server/app/api/pricing/route_client-reference-manifest.js +1 -1
  330. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js +1 -1
  331. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route.js.nft.json +1 -1
  332. package/app/.next-cli-build/server/app/api/provider-nodes/[id]/route_client-reference-manifest.js +1 -1
  333. package/app/.next-cli-build/server/app/api/provider-nodes/route.js +1 -1
  334. package/app/.next-cli-build/server/app/api/provider-nodes/route.js.nft.json +1 -1
  335. package/app/.next-cli-build/server/app/api/provider-nodes/route_client-reference-manifest.js +1 -1
  336. package/app/.next-cli-build/server/app/api/provider-nodes/validate/route.js +1 -1
  337. package/app/.next-cli-build/server/app/api/provider-nodes/validate/route.js.nft.json +1 -1
  338. package/app/.next-cli-build/server/app/api/provider-nodes/validate/route_client-reference-manifest.js +1 -1
  339. package/app/.next-cli-build/server/app/api/providers/[id]/agnes-profile/route.js +1 -1
  340. package/app/.next-cli-build/server/app/api/providers/[id]/agnes-profile/route.js.nft.json +1 -1
  341. package/app/.next-cli-build/server/app/api/providers/[id]/agnes-profile/route_client-reference-manifest.js +1 -1
  342. package/app/.next-cli-build/server/app/api/providers/[id]/freebuff-profile/route.js +1 -1
  343. package/app/.next-cli-build/server/app/api/providers/[id]/freebuff-profile/route.js.nft.json +1 -1
  344. package/app/.next-cli-build/server/app/api/providers/[id]/freebuff-profile/route_client-reference-manifest.js +1 -1
  345. package/app/.next-cli-build/server/app/api/providers/[id]/health-timeline/route.js +1 -1
  346. package/app/.next-cli-build/server/app/api/providers/[id]/health-timeline/route.js.nft.json +1 -1
  347. package/app/.next-cli-build/server/app/api/providers/[id]/health-timeline/route_client-reference-manifest.js +1 -1
  348. package/app/.next-cli-build/server/app/api/providers/[id]/inxora-profile/route.js +1 -1
  349. package/app/.next-cli-build/server/app/api/providers/[id]/inxora-profile/route.js.nft.json +1 -1
  350. package/app/.next-cli-build/server/app/api/providers/[id]/inxora-profile/route_client-reference-manifest.js +1 -1
  351. package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js +1 -1
  352. package/app/.next-cli-build/server/app/api/providers/[id]/models/route.js.nft.json +1 -1
  353. package/app/.next-cli-build/server/app/api/providers/[id]/models/route_client-reference-manifest.js +1 -1
  354. package/app/.next-cli-build/server/app/api/providers/[id]/onemin-api-profile/route.js +1 -1
  355. package/app/.next-cli-build/server/app/api/providers/[id]/onemin-api-profile/route.js.nft.json +1 -1
  356. package/app/.next-cli-build/server/app/api/providers/[id]/onemin-api-profile/route_client-reference-manifest.js +1 -1
  357. package/app/.next-cli-build/server/app/api/providers/[id]/onemin-profile/route.js +1 -1
  358. package/app/.next-cli-build/server/app/api/providers/[id]/onemin-profile/route.js.nft.json +1 -1
  359. package/app/.next-cli-build/server/app/api/providers/[id]/onemin-profile/route_client-reference-manifest.js +1 -1
  360. package/app/.next-cli-build/server/app/api/providers/[id]/qwencloud-profile/route.js +1 -1
  361. package/app/.next-cli-build/server/app/api/providers/[id]/qwencloud-profile/route.js.nft.json +1 -1
  362. package/app/.next-cli-build/server/app/api/providers/[id]/qwencloud-profile/route_client-reference-manifest.js +1 -1
  363. package/app/.next-cli-build/server/app/api/providers/[id]/route.js +1 -1
  364. package/app/.next-cli-build/server/app/api/providers/[id]/route.js.nft.json +1 -1
  365. package/app/.next-cli-build/server/app/api/providers/[id]/route_client-reference-manifest.js +1 -1
  366. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js +1 -1
  367. package/app/.next-cli-build/server/app/api/providers/[id]/test/route.js.nft.json +1 -1
  368. package/app/.next-cli-build/server/app/api/providers/[id]/test/route_client-reference-manifest.js +1 -1
  369. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js +1 -1
  370. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route.js.nft.json +1 -1
  371. package/app/.next-cli-build/server/app/api/providers/[id]/test-models/route_client-reference-manifest.js +1 -1
  372. package/app/.next-cli-build/server/app/api/providers/[id]/v0-profile/route.js +1 -1
  373. package/app/.next-cli-build/server/app/api/providers/[id]/v0-profile/route.js.nft.json +1 -1
  374. package/app/.next-cli-build/server/app/api/providers/[id]/v0-profile/route_client-reference-manifest.js +1 -1
  375. package/app/.next-cli-build/server/app/api/providers/[id]/vault-pool/route.js +1 -1
  376. package/app/.next-cli-build/server/app/api/providers/[id]/vault-pool/route.js.nft.json +1 -1
  377. package/app/.next-cli-build/server/app/api/providers/[id]/vault-pool/route_client-reference-manifest.js +1 -1
  378. package/app/.next-cli-build/server/app/api/providers/[id]/zenmux-plans/route.js +1 -1
  379. package/app/.next-cli-build/server/app/api/providers/[id]/zenmux-plans/route.js.nft.json +1 -1
  380. package/app/.next-cli-build/server/app/api/providers/[id]/zenmux-plans/route_client-reference-manifest.js +1 -1
  381. package/app/.next-cli-build/server/app/api/providers/client/route.js +1 -1
  382. package/app/.next-cli-build/server/app/api/providers/client/route.js.nft.json +1 -1
  383. package/app/.next-cli-build/server/app/api/providers/client/route_client-reference-manifest.js +1 -1
  384. package/app/.next-cli-build/server/app/api/providers/kilo/free-models/route.js +1 -1
  385. package/app/.next-cli-build/server/app/api/providers/kilo/free-models/route.js.nft.json +1 -1
  386. package/app/.next-cli-build/server/app/api/providers/kilo/free-models/route_client-reference-manifest.js +1 -1
  387. package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
  388. package/app/.next-cli-build/server/app/api/providers/route.js.nft.json +1 -1
  389. package/app/.next-cli-build/server/app/api/providers/route_client-reference-manifest.js +1 -1
  390. package/app/.next-cli-build/server/app/api/providers/suggested-models/route.js +1 -1
  391. package/app/.next-cli-build/server/app/api/providers/suggested-models/route.js.nft.json +1 -1
  392. package/app/.next-cli-build/server/app/api/providers/suggested-models/route_client-reference-manifest.js +1 -1
  393. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js +1 -1
  394. package/app/.next-cli-build/server/app/api/providers/test-batch/route.js.nft.json +1 -1
  395. package/app/.next-cli-build/server/app/api/providers/test-batch/route_client-reference-manifest.js +1 -1
  396. package/app/.next-cli-build/server/app/api/providers/validate/route.js +1 -1
  397. package/app/.next-cli-build/server/app/api/providers/validate/route.js.nft.json +1 -1
  398. package/app/.next-cli-build/server/app/api/providers/validate/route_client-reference-manifest.js +1 -1
  399. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js +1 -1
  400. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route.js.nft.json +1 -1
  401. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/route_client-reference-manifest.js +1 -1
  402. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js +1 -1
  403. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route.js.nft.json +1 -1
  404. package/app/.next-cli-build/server/app/api/proxy-pools/[id]/test/route_client-reference-manifest.js +1 -1
  405. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js +2 -2
  406. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route.js.nft.json +1 -1
  407. package/app/.next-cli-build/server/app/api/proxy-pools/cloudflare-deploy/route_client-reference-manifest.js +1 -1
  408. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js +2 -2
  409. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route.js.nft.json +1 -1
  410. package/app/.next-cli-build/server/app/api/proxy-pools/deno-deploy/route_client-reference-manifest.js +1 -1
  411. package/app/.next-cli-build/server/app/api/proxy-pools/route.js +1 -1
  412. package/app/.next-cli-build/server/app/api/proxy-pools/route.js.nft.json +1 -1
  413. package/app/.next-cli-build/server/app/api/proxy-pools/route_client-reference-manifest.js +1 -1
  414. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js +2 -2
  415. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route.js.nft.json +1 -1
  416. package/app/.next-cli-build/server/app/api/proxy-pools/vercel-deploy/route_client-reference-manifest.js +1 -1
  417. package/app/.next-cli-build/server/app/api/pxpipe/install/route.js +2 -2
  418. package/app/.next-cli-build/server/app/api/pxpipe/install/route.js.nft.json +1 -1
  419. package/app/.next-cli-build/server/app/api/pxpipe/install/route_client-reference-manifest.js +1 -1
  420. package/app/.next-cli-build/server/app/api/pxpipe/status/route.js +2 -2
  421. package/app/.next-cli-build/server/app/api/pxpipe/status/route.js.nft.json +1 -1
  422. package/app/.next-cli-build/server/app/api/pxpipe/status/route_client-reference-manifest.js +1 -1
  423. package/app/.next-cli-build/server/app/api/settings/database/route.js +1 -1
  424. package/app/.next-cli-build/server/app/api/settings/database/route.js.nft.json +1 -1
  425. package/app/.next-cli-build/server/app/api/settings/database/route_client-reference-manifest.js +1 -1
  426. package/app/.next-cli-build/server/app/api/settings/proxy-test/route.js +1 -1
  427. package/app/.next-cli-build/server/app/api/settings/proxy-test/route.js.nft.json +1 -1
  428. package/app/.next-cli-build/server/app/api/settings/proxy-test/route_client-reference-manifest.js +1 -1
  429. package/app/.next-cli-build/server/app/api/settings/require-login/route.js +1 -1
  430. package/app/.next-cli-build/server/app/api/settings/require-login/route.js.nft.json +1 -1
  431. package/app/.next-cli-build/server/app/api/settings/require-login/route_client-reference-manifest.js +1 -1
  432. package/app/.next-cli-build/server/app/api/settings/route.js +1 -1
  433. package/app/.next-cli-build/server/app/api/settings/route.js.nft.json +1 -1
  434. package/app/.next-cli-build/server/app/api/settings/route_client-reference-manifest.js +1 -1
  435. package/app/.next-cli-build/server/app/api/shutdown/route.js +1 -1
  436. package/app/.next-cli-build/server/app/api/shutdown/route.js.nft.json +1 -1
  437. package/app/.next-cli-build/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  438. package/app/.next-cli-build/server/app/api/swarm/active/route.js +1 -1
  439. package/app/.next-cli-build/server/app/api/swarm/active/route.js.nft.json +1 -1
  440. package/app/.next-cli-build/server/app/api/swarm/active/route_client-reference-manifest.js +1 -1
  441. package/app/.next-cli-build/server/app/api/swarm/stream/route.js +2 -2
  442. package/app/.next-cli-build/server/app/api/swarm/stream/route.js.nft.json +1 -1
  443. package/app/.next-cli-build/server/app/api/swarm/stream/route_client-reference-manifest.js +1 -1
  444. package/app/.next-cli-build/server/app/api/tags/route.js +1 -1
  445. package/app/.next-cli-build/server/app/api/tags/route.js.nft.json +1 -1
  446. package/app/.next-cli-build/server/app/api/tags/route_client-reference-manifest.js +1 -1
  447. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
  448. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js.nft.json +1 -1
  449. package/app/.next-cli-build/server/app/api/translator/console-logs/route_client-reference-manifest.js +1 -1
  450. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +2 -2
  451. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js.nft.json +1 -1
  452. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route_client-reference-manifest.js +1 -1
  453. package/app/.next-cli-build/server/app/api/translator/load/route.js +1 -1
  454. package/app/.next-cli-build/server/app/api/translator/load/route.js.nft.json +1 -1
  455. package/app/.next-cli-build/server/app/api/translator/load/route_client-reference-manifest.js +1 -1
  456. package/app/.next-cli-build/server/app/api/translator/save/route.js +1 -1
  457. package/app/.next-cli-build/server/app/api/translator/save/route.js.nft.json +1 -1
  458. package/app/.next-cli-build/server/app/api/translator/save/route_client-reference-manifest.js +1 -1
  459. package/app/.next-cli-build/server/app/api/translator/send/route.js +1 -1
  460. package/app/.next-cli-build/server/app/api/translator/send/route.js.nft.json +1 -1
  461. package/app/.next-cli-build/server/app/api/translator/send/route_client-reference-manifest.js +1 -1
  462. package/app/.next-cli-build/server/app/api/translator/translate/route.js +1 -1
  463. package/app/.next-cli-build/server/app/api/translator/translate/route.js.nft.json +1 -1
  464. package/app/.next-cli-build/server/app/api/translator/translate/route_client-reference-manifest.js +1 -1
  465. package/app/.next-cli-build/server/app/api/tunnel/disable/route.js +1 -1
  466. package/app/.next-cli-build/server/app/api/tunnel/disable/route.js.nft.json +1 -1
  467. package/app/.next-cli-build/server/app/api/tunnel/disable/route_client-reference-manifest.js +1 -1
  468. package/app/.next-cli-build/server/app/api/tunnel/enable/route.js +1 -1
  469. package/app/.next-cli-build/server/app/api/tunnel/enable/route.js.nft.json +1 -1
  470. package/app/.next-cli-build/server/app/api/tunnel/enable/route_client-reference-manifest.js +1 -1
  471. package/app/.next-cli-build/server/app/api/tunnel/status/route.js +1 -1
  472. package/app/.next-cli-build/server/app/api/tunnel/status/route.js.nft.json +1 -1
  473. package/app/.next-cli-build/server/app/api/tunnel/status/route_client-reference-manifest.js +1 -1
  474. package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route.js +1 -1
  475. package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route.js.nft.json +1 -1
  476. package/app/.next-cli-build/server/app/api/tunnel/tailscale-check/route_client-reference-manifest.js +1 -1
  477. package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route.js +1 -1
  478. package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route.js.nft.json +1 -1
  479. package/app/.next-cli-build/server/app/api/tunnel/tailscale-disable/route_client-reference-manifest.js +1 -1
  480. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js +1 -1
  481. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js.nft.json +1 -1
  482. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route_client-reference-manifest.js +1 -1
  483. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js +2 -2
  484. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route.js.nft.json +1 -1
  485. package/app/.next-cli-build/server/app/api/tunnel/tailscale-install/route_client-reference-manifest.js +1 -1
  486. package/app/.next-cli-build/server/app/api/usage/[connectionId]/codex-reset-credits/route.js +1 -1
  487. package/app/.next-cli-build/server/app/api/usage/[connectionId]/codex-reset-credits/route.js.nft.json +1 -1
  488. package/app/.next-cli-build/server/app/api/usage/[connectionId]/codex-reset-credits/route_client-reference-manifest.js +1 -1
  489. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js +1 -1
  490. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route.js.nft.json +1 -1
  491. package/app/.next-cli-build/server/app/api/usage/[connectionId]/route_client-reference-manifest.js +1 -1
  492. package/app/.next-cli-build/server/app/api/usage/chart/route.js +1 -1
  493. package/app/.next-cli-build/server/app/api/usage/chart/route.js.nft.json +1 -1
  494. package/app/.next-cli-build/server/app/api/usage/chart/route_client-reference-manifest.js +1 -1
  495. package/app/.next-cli-build/server/app/api/usage/history/route.js +1 -1
  496. package/app/.next-cli-build/server/app/api/usage/history/route.js.nft.json +1 -1
  497. package/app/.next-cli-build/server/app/api/usage/history/route_client-reference-manifest.js +1 -1
  498. package/app/.next-cli-build/server/app/api/usage/leaderboard/route.js +1 -1
  499. package/app/.next-cli-build/server/app/api/usage/leaderboard/route.js.nft.json +1 -1
  500. package/app/.next-cli-build/server/app/api/usage/leaderboard/route_client-reference-manifest.js +1 -1
  501. package/app/.next-cli-build/server/app/api/usage/logs/route.js +1 -1
  502. package/app/.next-cli-build/server/app/api/usage/logs/route.js.nft.json +1 -1
  503. package/app/.next-cli-build/server/app/api/usage/logs/route_client-reference-manifest.js +1 -1
  504. package/app/.next-cli-build/server/app/api/usage/meta/route.js +1 -1
  505. package/app/.next-cli-build/server/app/api/usage/meta/route.js.nft.json +1 -1
  506. package/app/.next-cli-build/server/app/api/usage/meta/route_client-reference-manifest.js +1 -1
  507. package/app/.next-cli-build/server/app/api/usage/providers/route.js +1 -1
  508. package/app/.next-cli-build/server/app/api/usage/providers/route.js.nft.json +1 -1
  509. package/app/.next-cli-build/server/app/api/usage/providers/route_client-reference-manifest.js +1 -1
  510. package/app/.next-cli-build/server/app/api/usage/request-details/route.js +1 -1
  511. package/app/.next-cli-build/server/app/api/usage/request-details/route.js.nft.json +1 -1
  512. package/app/.next-cli-build/server/app/api/usage/request-details/route_client-reference-manifest.js +1 -1
  513. package/app/.next-cli-build/server/app/api/usage/request-logs/route.js +1 -1
  514. package/app/.next-cli-build/server/app/api/usage/request-logs/route.js.nft.json +1 -1
  515. package/app/.next-cli-build/server/app/api/usage/request-logs/route_client-reference-manifest.js +1 -1
  516. package/app/.next-cli-build/server/app/api/usage/retry-stats/route.js +1 -1
  517. package/app/.next-cli-build/server/app/api/usage/retry-stats/route.js.nft.json +1 -1
  518. package/app/.next-cli-build/server/app/api/usage/retry-stats/route_client-reference-manifest.js +1 -1
  519. package/app/.next-cli-build/server/app/api/usage/stats/route.js +1 -1
  520. package/app/.next-cli-build/server/app/api/usage/stats/route.js.nft.json +1 -1
  521. package/app/.next-cli-build/server/app/api/usage/stats/route_client-reference-manifest.js +1 -1
  522. package/app/.next-cli-build/server/app/api/usage/stream/route.js +2 -2
  523. package/app/.next-cli-build/server/app/api/usage/stream/route.js.nft.json +1 -1
  524. package/app/.next-cli-build/server/app/api/usage/stream/route_client-reference-manifest.js +1 -1
  525. package/app/.next-cli-build/server/app/api/v1/api/chat/route.js +1 -1
  526. package/app/.next-cli-build/server/app/api/v1/api/chat/route.js.nft.json +1 -1
  527. package/app/.next-cli-build/server/app/api/v1/api/chat/route_client-reference-manifest.js +1 -1
  528. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js +1 -1
  529. package/app/.next-cli-build/server/app/api/v1/audio/speech/route.js.nft.json +1 -1
  530. package/app/.next-cli-build/server/app/api/v1/audio/speech/route_client-reference-manifest.js +1 -1
  531. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js +1 -1
  532. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route.js.nft.json +1 -1
  533. package/app/.next-cli-build/server/app/api/v1/audio/transcriptions/route_client-reference-manifest.js +1 -1
  534. package/app/.next-cli-build/server/app/api/v1/audio/voices/route.js +1 -1
  535. package/app/.next-cli-build/server/app/api/v1/audio/voices/route.js.nft.json +1 -1
  536. package/app/.next-cli-build/server/app/api/v1/audio/voices/route_client-reference-manifest.js +1 -1
  537. package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js +1 -1
  538. package/app/.next-cli-build/server/app/api/v1/chat/completions/route.js.nft.json +1 -1
  539. package/app/.next-cli-build/server/app/api/v1/chat/completions/route_client-reference-manifest.js +1 -1
  540. package/app/.next-cli-build/server/app/api/v1/embeddings/route.js +1 -1
  541. package/app/.next-cli-build/server/app/api/v1/embeddings/route.js.nft.json +1 -1
  542. package/app/.next-cli-build/server/app/api/v1/embeddings/route_client-reference-manifest.js +1 -1
  543. package/app/.next-cli-build/server/app/api/v1/images/generations/route.js +1 -1
  544. package/app/.next-cli-build/server/app/api/v1/images/generations/route.js.nft.json +1 -1
  545. package/app/.next-cli-build/server/app/api/v1/images/generations/route_client-reference-manifest.js +1 -1
  546. package/app/.next-cli-build/server/app/api/v1/messages/count_tokens/route.js +1 -1
  547. package/app/.next-cli-build/server/app/api/v1/messages/count_tokens/route.js.nft.json +1 -1
  548. package/app/.next-cli-build/server/app/api/v1/messages/count_tokens/route_client-reference-manifest.js +1 -1
  549. package/app/.next-cli-build/server/app/api/v1/messages/route.js +1 -1
  550. package/app/.next-cli-build/server/app/api/v1/messages/route.js.nft.json +1 -1
  551. package/app/.next-cli-build/server/app/api/v1/messages/route_client-reference-manifest.js +1 -1
  552. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js +1 -1
  553. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route.js.nft.json +1 -1
  554. package/app/.next-cli-build/server/app/api/v1/models/[kind]/route_client-reference-manifest.js +1 -1
  555. package/app/.next-cli-build/server/app/api/v1/models/info/route.js +1 -1
  556. package/app/.next-cli-build/server/app/api/v1/models/info/route.js.nft.json +1 -1
  557. package/app/.next-cli-build/server/app/api/v1/models/info/route_client-reference-manifest.js +1 -1
  558. package/app/.next-cli-build/server/app/api/v1/models/route.js +1 -1
  559. package/app/.next-cli-build/server/app/api/v1/models/route.js.nft.json +1 -1
  560. package/app/.next-cli-build/server/app/api/v1/models/route_client-reference-manifest.js +1 -1
  561. package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js +1 -1
  562. package/app/.next-cli-build/server/app/api/v1/responses/compact/route.js.nft.json +1 -1
  563. package/app/.next-cli-build/server/app/api/v1/responses/compact/route_client-reference-manifest.js +1 -1
  564. package/app/.next-cli-build/server/app/api/v1/responses/route.js +1 -1
  565. package/app/.next-cli-build/server/app/api/v1/responses/route.js.nft.json +1 -1
  566. package/app/.next-cli-build/server/app/api/v1/responses/route_client-reference-manifest.js +1 -1
  567. package/app/.next-cli-build/server/app/api/v1/route.js +1 -1
  568. package/app/.next-cli-build/server/app/api/v1/route.js.nft.json +1 -1
  569. package/app/.next-cli-build/server/app/api/v1/route_client-reference-manifest.js +1 -1
  570. package/app/.next-cli-build/server/app/api/v1/search/route.js +1 -1
  571. package/app/.next-cli-build/server/app/api/v1/search/route.js.nft.json +1 -1
  572. package/app/.next-cli-build/server/app/api/v1/search/route_client-reference-manifest.js +1 -1
  573. package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js +1 -1
  574. package/app/.next-cli-build/server/app/api/v1/web/fetch/route.js.nft.json +1 -1
  575. package/app/.next-cli-build/server/app/api/v1/web/fetch/route_client-reference-manifest.js +1 -1
  576. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js +1 -1
  577. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route.js.nft.json +1 -1
  578. package/app/.next-cli-build/server/app/api/v1beta/models/[...path]/route_client-reference-manifest.js +1 -1
  579. package/app/.next-cli-build/server/app/api/v1beta/models/route.js +1 -1
  580. package/app/.next-cli-build/server/app/api/v1beta/models/route.js.nft.json +1 -1
  581. package/app/.next-cli-build/server/app/api/v1beta/models/route_client-reference-manifest.js +1 -1
  582. package/app/.next-cli-build/server/app/api/version/route.js +1 -1
  583. package/app/.next-cli-build/server/app/api/version/route.js.nft.json +1 -1
  584. package/app/.next-cli-build/server/app/api/version/route_client-reference-manifest.js +1 -1
  585. package/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
  586. package/app/.next-cli-build/server/app/api/version/shutdown/route.js.nft.json +1 -1
  587. package/app/.next-cli-build/server/app/api/version/shutdown/route_client-reference-manifest.js +1 -1
  588. package/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
  589. package/app/.next-cli-build/server/app/api/version/update/route.js.nft.json +1 -1
  590. package/app/.next-cli-build/server/app/api/version/update/route_client-reference-manifest.js +1 -1
  591. package/app/.next-cli-build/server/app/callback/page.js +2 -2
  592. package/app/.next-cli-build/server/app/callback/page.js.nft.json +1 -1
  593. package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
  594. package/app/.next-cli-build/server/app/callback.html +1 -1
  595. package/app/.next-cli-build/server/app/callback.rsc +8 -7
  596. package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +8 -7
  597. package/app/.next-cli-build/server/app/callback.segments/_head.segment.rsc +1 -1
  598. package/app/.next-cli-build/server/app/callback.segments/_index.segment.rsc +6 -6
  599. package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +3 -2
  600. package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +2 -2
  601. package/app/.next-cli-build/server/app/callback.segments/callback.segment.rsc +1 -1
  602. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page.js +2 -2
  603. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page.js.nft.json +1 -1
  604. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  605. package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
  606. package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +8 -7
  607. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +8 -7
  608. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  609. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +6 -6
  610. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +3 -2
  611. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +2 -2
  612. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  613. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  614. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  615. package/app/.next-cli-build/server/app/favicon.ico/route.js +1 -1
  616. package/app/.next-cli-build/server/app/favicon.ico/route.js.nft.json +1 -1
  617. package/app/.next-cli-build/server/app/index.html +1 -1
  618. package/app/.next-cli-build/server/app/index.rsc +7 -6
  619. package/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  620. package/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +7 -6
  621. package/app/.next-cli-build/server/app/index.segments/_head.segment.rsc +1 -1
  622. package/app/.next-cli-build/server/app/index.segments/_index.segment.rsc +6 -6
  623. package/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +3 -2
  624. package/app/.next-cli-build/server/app/landing/page.js +2 -2
  625. package/app/.next-cli-build/server/app/landing/page.js.nft.json +1 -1
  626. package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
  627. package/app/.next-cli-build/server/app/landing.html +1 -1
  628. package/app/.next-cli-build/server/app/landing.rsc +8 -7
  629. package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +8 -7
  630. package/app/.next-cli-build/server/app/landing.segments/_head.segment.rsc +1 -1
  631. package/app/.next-cli-build/server/app/landing.segments/_index.segment.rsc +6 -6
  632. package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +3 -2
  633. package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +2 -2
  634. package/app/.next-cli-build/server/app/landing.segments/landing.segment.rsc +1 -1
  635. package/app/.next-cli-build/server/app/login/page.js +2 -2
  636. package/app/.next-cli-build/server/app/login/page.js.nft.json +1 -1
  637. package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
  638. package/app/.next-cli-build/server/app/login.html +1 -1
  639. package/app/.next-cli-build/server/app/login.rsc +8 -7
  640. package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +8 -7
  641. package/app/.next-cli-build/server/app/login.segments/_head.segment.rsc +1 -1
  642. package/app/.next-cli-build/server/app/login.segments/_index.segment.rsc +6 -6
  643. package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +3 -2
  644. package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  645. package/app/.next-cli-build/server/app/login.segments/login.segment.rsc +1 -1
  646. package/app/.next-cli-build/server/app/manifest.webmanifest/route.js +2 -2
  647. package/app/.next-cli-build/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  648. package/app/.next-cli-build/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  649. package/app/.next-cli-build/server/app/page.js +2 -2
  650. package/app/.next-cli-build/server/app/page.js.nft.json +1 -1
  651. package/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
  652. package/app/.next-cli-build/server/app-paths-manifest.json +9 -9
  653. package/app/.next-cli-build/server/chunks/1212.js +1 -0
  654. package/app/.next-cli-build/server/chunks/1241.js +1 -1
  655. package/app/.next-cli-build/server/chunks/1350.js +1 -1
  656. package/app/.next-cli-build/server/chunks/1719.js +1 -1
  657. package/app/.next-cli-build/server/chunks/212.js +1 -1
  658. package/app/.next-cli-build/server/chunks/2231.js +1 -1
  659. package/app/.next-cli-build/server/chunks/319.js +3 -3
  660. package/app/.next-cli-build/server/chunks/{2926.js → 3437.js} +9 -9
  661. package/app/.next-cli-build/server/chunks/3735.js +1 -1
  662. package/app/.next-cli-build/server/chunks/4046.js +1 -0
  663. package/app/.next-cli-build/server/chunks/5330.js +66 -66
  664. package/app/.next-cli-build/server/chunks/5612.js +1 -1
  665. package/app/.next-cli-build/server/chunks/5615.js +1 -1
  666. package/app/.next-cli-build/server/chunks/5852.js +1 -1
  667. package/app/.next-cli-build/server/chunks/5961.js +1 -1
  668. package/app/.next-cli-build/server/chunks/6070.js +1 -1
  669. package/app/.next-cli-build/server/chunks/{7152.js → 6482.js} +2 -2
  670. package/app/.next-cli-build/server/chunks/6686.js +1 -1
  671. package/app/.next-cli-build/server/chunks/6777.js +1 -1
  672. package/app/.next-cli-build/server/chunks/7187.js +1 -1
  673. package/app/.next-cli-build/server/chunks/7218.js +1 -0
  674. package/app/.next-cli-build/server/chunks/7410.js +1 -0
  675. package/app/.next-cli-build/server/chunks/7566.js +3 -0
  676. package/app/.next-cli-build/server/chunks/7774.js +18 -18
  677. package/app/.next-cli-build/server/chunks/7872.js +1 -1
  678. package/app/.next-cli-build/server/chunks/7965.js +1 -1
  679. package/app/.next-cli-build/server/chunks/8238.js +1 -1
  680. package/app/.next-cli-build/server/chunks/8271.js +1 -1
  681. package/app/.next-cli-build/server/chunks/8520.js +1 -1
  682. package/app/.next-cli-build/server/chunks/8802.js +2 -0
  683. package/app/.next-cli-build/server/chunks/8895.js +6 -6
  684. package/app/.next-cli-build/server/chunks/{4502.js → 8955.js} +2 -2
  685. package/app/.next-cli-build/server/chunks/9422.js +1 -1
  686. package/app/.next-cli-build/server/chunks/9609.js +1 -1
  687. package/app/.next-cli-build/server/chunks/9703.js +1 -1
  688. package/app/.next-cli-build/server/chunks/9903.js +1 -1
  689. package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
  690. package/app/.next-cli-build/server/middleware-react-loadable-manifest.js +1 -1
  691. package/app/.next-cli-build/server/middleware.js +5 -5
  692. package/app/.next-cli-build/server/next-font-manifest.js +1 -1
  693. package/app/.next-cli-build/server/next-font-manifest.json +1 -1
  694. package/app/.next-cli-build/server/pages/404.html +1 -1
  695. package/app/.next-cli-build/server/pages/500.html +1 -1
  696. package/app/.next-cli-build/server/server-reference-manifest.js +1 -1
  697. package/app/.next-cli-build/server/server-reference-manifest.json +1 -1
  698. package/app/.next-cli-build/static/chunks/{1321-aa0d45362a7ebc08.js → 1321-5792bb21361dcd65.js} +1 -1
  699. package/app/.next-cli-build/static/chunks/705-cfe5cd65ea2dc6f1.js +1 -0
  700. package/app/.next-cli-build/static/chunks/8105-37d0f6450b27ac6b.js +1 -0
  701. package/app/.next-cli-build/static/chunks/{8720-bbafc2ad7d186ebd.js → 8982-6d1803817450bcd4.js} +2 -2
  702. package/app/.next-cli-build/static/chunks/981-777b2911f938c030.js +3 -0
  703. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/alerts/{page-920869c698a8b3cf.js → page-c263cd784e69e6f1.js} +1 -1
  704. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/basic-chat/{page-75247ad22e97f7cc.js → page-ecd3a85a40e51c66.js} +1 -1
  705. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/cli-tools/[toolId]/page-3c3074cf3f61df46.js +1 -0
  706. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/cli-tools/{page-8b043b8296199edb.js → page-f7cdc992cb310077.js} +1 -1
  707. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/combos/page-648e105b4f37fef0.js +3 -0
  708. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/console-log/page-959b3ee3c662de33.js +1 -0
  709. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/endpoint/page-5689c88f2746c37a.js +1 -0
  710. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/health/{page-ec1dc4e44702257d.js → page-133cf1aa2ce53c87.js} +1 -1
  711. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/media-providers/[kind]/[id]/{page-b635b8b051acb5a5.js → page-3828106aa4f490c1.js} +2 -2
  712. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/media-providers/[kind]/{page-d9958dfec1d2e28e.js → page-e086fed7677d4852.js} +1 -1
  713. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/media-providers/combo/[id]/{page-a36b3b632d16f4cb.js → page-f36e5ac11783fd1e.js} +2 -2
  714. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/media-providers/web/page-e794909abbc7a09a.js +1 -0
  715. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/mitm/page-1d972fd3baee7474.js +1 -0
  716. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/overview/page-2dae733c8e1582bf.js +1 -0
  717. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/page-7325c65533e4cf60.js +1 -0
  718. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/playground/{page-dc8e49b1fe778d9c.js → page-e7ba910803086460.js} +1 -1
  719. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/profile/page-0f877a8a2550a1ea.js +1 -0
  720. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/[id]/{page-2e82495d63f499e9.js → page-201ce34cf7a0a9ed.js} +1 -1
  721. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/new/{page-8965749fb7d0fac3.js → page-bcf9d97ab4dc20d9.js} +1 -1
  722. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/page-5b11b61863963cad.js +1 -0
  723. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/proxy-pools/{page-843c810c0818ce1b.js → page-58d8d0fa5523ff95.js} +1 -1
  724. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/quota/{page-9a44fa1600f3ff42.js → page-0be4cac4f06ef3e2.js} +1 -1
  725. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/skills/{page-97c920b552343488.js → page-a8b151d5ae9004ea.js} +1 -1
  726. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/swarm/page-594a59006196a03a.js +1 -0
  727. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/token-saver/page-d57c129c03c9cb36.js +1 -0
  728. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/translator/{page-a8af04fbd6293d2f.js → page-61d162d7a7f88a11.js} +1 -1
  729. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/usage/{page-bd421513fd2dc28a.js → page-483f01fd35d212f5.js} +1 -1
  730. package/app/.next-cli-build/static/chunks/app/(dashboard)/{layout-9144cc5f6a208199.js → layout-d62e22634bbd6c94.js} +1 -1
  731. package/app/.next-cli-build/static/chunks/app/_not-found/{page-732ac0fa56005849.js → page-0161671512f52984.js} +1 -1
  732. package/app/.next-cli-build/static/chunks/app/callback/{page-4e8ab9d9128acffb.js → page-20e990994d8da6d3.js} +1 -1
  733. package/app/.next-cli-build/static/chunks/app/dashboard/settings/pricing/{page-d4eb2ba84eef2143.js → page-bb9f307074c5c23a.js} +1 -1
  734. package/app/.next-cli-build/static/chunks/app/landing/{page-ade86a48ca5749f4.js → page-468c5cb1d127c02a.js} +1 -1
  735. package/app/.next-cli-build/static/chunks/app/layout-10bff7b57a2a3c2c.js +1 -0
  736. package/app/.next-cli-build/static/chunks/app/login/page-32ab5d7c75651107.js +1 -0
  737. package/app/.next-cli-build/static/chunks/main-ab3c4d38db15f747.js +5 -0
  738. package/app/.next-cli-build/static/chunks/main-app-f661afc91c813cfe.js +1 -0
  739. package/app/.next-cli-build/static/chunks/next/dist/client/components/builtin/global-error-8fecb2690f5e9ae2.js +1 -0
  740. package/app/.next-cli-build/static/chunks/webpack-c2bac8d80aa27536.js +1 -0
  741. package/app/.next-cli-build/static/css/27a3eadf22014a5b.css +1 -0
  742. package/app/custom-server.js +9 -0
  743. package/app/package.json +5 -4
  744. package/app/public/i18n/literals/ar.json +195 -195
  745. package/app/public/i18n/literals/bn.json +195 -195
  746. package/app/public/i18n/literals/cs.json +195 -195
  747. package/app/public/i18n/literals/da.json +195 -195
  748. package/app/public/i18n/literals/de.json +195 -195
  749. package/app/public/i18n/literals/el.json +195 -195
  750. package/app/public/i18n/literals/es.json +195 -195
  751. package/app/public/i18n/literals/fi.json +195 -195
  752. package/app/public/i18n/literals/fr.json +195 -195
  753. package/app/public/i18n/literals/he.json +195 -195
  754. package/app/public/i18n/literals/hi.json +195 -195
  755. package/app/public/i18n/literals/hu.json +195 -195
  756. package/app/public/i18n/literals/id.json +195 -195
  757. package/app/public/i18n/literals/it.json +195 -195
  758. package/app/public/i18n/literals/ja.json +195 -195
  759. package/app/public/i18n/literals/ko.json +195 -195
  760. package/app/public/i18n/literals/nl.json +195 -195
  761. package/app/public/i18n/literals/no.json +195 -195
  762. package/app/public/i18n/literals/pl.json +195 -195
  763. package/app/public/i18n/literals/pt-BR.json +195 -195
  764. package/app/public/i18n/literals/pt-PT.json +195 -195
  765. package/app/public/i18n/literals/ro.json +195 -195
  766. package/app/public/i18n/literals/ru.json +195 -195
  767. package/app/public/i18n/literals/sv.json +195 -195
  768. package/app/public/i18n/literals/th.json +195 -195
  769. package/app/public/i18n/literals/tl.json +195 -195
  770. package/app/public/i18n/literals/tr.json +195 -195
  771. package/app/public/i18n/literals/uk.json +195 -195
  772. package/app/public/i18n/literals/ur.json +195 -195
  773. package/app/public/i18n/literals/vi.json +195 -195
  774. package/app/public/i18n/literals/zh-CN.json +773 -773
  775. package/app/public/i18n/literals/zh-TW.json +195 -195
  776. package/app/public/providers/agnes-api.svg +6 -6
  777. package/app/public/providers/agnes-web.svg +6 -6
  778. package/app/public/providers/alibaba-cn.svg +11 -11
  779. package/app/public/providers/alibaba.svg +11 -11
  780. package/app/public/providers/bynara.svg +22 -22
  781. package/app/public/providers/devin.svg +5 -5
  782. package/app/public/providers/featherless.svg +8 -8
  783. package/app/public/providers/forge.svg +9 -9
  784. package/app/public/providers/freebuff-web.svg +6 -6
  785. package/app/public/providers/hcnsec.svg +10 -10
  786. package/app/public/providers/inxorastudio-web.svg +4 -4
  787. package/app/public/providers/inxorastudio.svg +4 -4
  788. package/app/public/providers/moonshot.svg +8 -8
  789. package/app/public/providers/openvecta.svg +7 -7
  790. package/app/public/providers/perplexity-agent.svg +13 -13
  791. package/app/public/providers/qwen-cloud.svg +1 -1
  792. package/app/public/providers/qwencloud.svg +6 -6
  793. package/app/public/providers/stepfun.svg +53 -53
  794. package/app/public/providers/tokenrouter.svg +15 -15
  795. package/app/public/providers/wp-studio.svg +11 -11
  796. package/app/public/providers/zed.svg +11 -11
  797. package/app/public/providers/zenmux-free.svg +9 -9
  798. package/app/server.js +1 -1
  799. package/app/src/lib/db/adapters/sqljsAdapter.js +115 -115
  800. package/app/src/lib/db/migrate.js +286 -286
  801. package/app/src/lib/network/pickProxyPoolId.js +38 -38
  802. package/app/src/lib/updater/updater.js +235 -235
  803. package/app/src/mitm/server.js +2 -2
  804. package/cli.js +830 -830
  805. package/package.json +66 -66
  806. package/src/cli/api/client.js +556 -556
  807. package/src/cli/menus/cliTools.js +618 -618
  808. package/src/cli/terminalUI.js +121 -121
  809. package/src/cli/tray/autostart.js +306 -306
  810. package/src/cli/tray/tray.js +322 -322
  811. package/src/cli/tray/tray.ps1 +130 -130
  812. package/app/.next-cli-build/server/chunks/1051.js +0 -1
  813. package/app/.next-cli-build/server/chunks/1216.js +0 -3
  814. package/app/.next-cli-build/server/chunks/541.js +0 -1
  815. package/app/.next-cli-build/server/chunks/6316.js +0 -2
  816. package/app/.next-cli-build/server/chunks/9140.js +0 -1
  817. package/app/.next-cli-build/server/chunks/9630.js +0 -1
  818. package/app/.next-cli-build/static/chunks/1696-bafe4b44a7a0439e.js +0 -3
  819. package/app/.next-cli-build/static/chunks/1966.b8f83f7ba376c962.js +0 -1
  820. package/app/.next-cli-build/static/chunks/3899.3f761f7e3a944e8c.js +0 -1
  821. package/app/.next-cli-build/static/chunks/705-b7d7b61f41806f0d.js +0 -1
  822. package/app/.next-cli-build/static/chunks/8105-204edc780a329497.js +0 -1
  823. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/cli-tools/[toolId]/page-cd77e53dbcd46b6c.js +0 -1
  824. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/combos/page-dbf52954681b093c.js +0 -3
  825. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/console-log/page-a8c4d8c681e19868.js +0 -1
  826. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/endpoint/page-408845bd809806a6.js +0 -1
  827. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/media-providers/web/page-92a0799a23d869b3.js +0 -1
  828. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/mitm/page-a67cd1c5f77da355.js +0 -1
  829. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/overview/page-262fa6911888d4f1.js +0 -1
  830. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/page-f644da989b8878c3.js +0 -1
  831. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/profile/page-aa26b25a26b5dac8.js +0 -1
  832. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/page-96d3eb0dfde0711b.js +0 -1
  833. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/swarm/page-9739651f4f19cec6.js +0 -1
  834. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/token-saver/page-2f3b8761d7b32ec0.js +0 -1
  835. package/app/.next-cli-build/static/chunks/app/layout-16b611f4f5717ccd.js +0 -1
  836. package/app/.next-cli-build/static/chunks/app/login/page-0831b035aa4c0f17.js +0 -1
  837. package/app/.next-cli-build/static/chunks/main-28015457a328b97c.js +0 -5
  838. package/app/.next-cli-build/static/chunks/main-app-705d8c306f358a5f.js +0 -1
  839. package/app/.next-cli-build/static/chunks/next/dist/client/components/builtin/global-error-22e44aa316880902.js +0 -1
  840. package/app/.next-cli-build/static/chunks/webpack-a990cabb6976f421.js +0 -1
  841. package/app/.next-cli-build/static/css/68d66160ca549ddc.css +0 -1
  842. package/app/cli/.build-home/AppData/Local/npm-cache/_update-notifier-last-checked +0 -0
  843. package/app/cli/.build-home/AppData/Roaming/extremerouter/.migrated-from +0 -1
  844. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/backups/schema-3-to-4-0.8.0-20260802-152036/data.sqlite +0 -0
  845. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/backups/upgrade-0.7.8-to-0.7.9-0.7.9-20260729-181011/data.sqlite +0 -0
  846. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/backups/upgrade-0.7.9-to-0.8.0-0.8.0-20260729-213634/data.sqlite +0 -0
  847. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/backups/upgrade-0.8.0-to-0.8.1-0.8.1-20260802-152517/data.sqlite +0 -0
  848. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/data.sqlite +0 -0
  849. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/data.sqlite-shm +0 -0
  850. package/app/cli/.build-home/AppData/Roaming/extremerouter/db/data.sqlite-wal +0 -0
  851. package/app/cli/.build-home/AppData/Roaming/extremerouter/jwt-secret +0 -1
  852. package/app/cli/.build-home/AppData/Roaming/extremerouter/machine-id +0 -1
  853. package/app/cli/.build-home/AppData/Roaming/nextjs-nodejs/Config/config.json +0 -7
  854. /package/app/.next-cli-build/static/{S-pbWChrUiCkwFyfx4Su3 → j7bBgtavtSkTBPfbmetr9}/_buildManifest.js +0 -0
  855. /package/app/.next-cli-build/static/{S-pbWChrUiCkwFyfx4Su3 → j7bBgtavtSkTBPfbmetr9}/_ssgManifest.js +0 -0
package/cli.js CHANGED
@@ -1,830 +1,830 @@
1
- #!/usr/bin/env node
2
-
3
- const { spawn, exec, execSync } = require("child_process");
4
- const path = require("path");
5
- const fs = require("fs");
6
- const https = require("https");
7
- const os = require("os");
8
-
9
- // Native spinner - no external dependency
10
- function createSpinner(text) {
11
- const frames = ["ā ‹", "ā ™", "ā ¹", "ā ø", "ā ¼", "ā “", "ā ¦", "ā §", "ā ‡", "ā "];
12
- let i = 0;
13
- let interval = null;
14
- let currentText = text;
15
- return {
16
- start() {
17
- if (process.stdout.isTTY) {
18
- process.stdout.write(`\r${frames[0]} ${currentText}`);
19
- interval = setInterval(() => {
20
- process.stdout.write(`\r${frames[i++ % frames.length]} ${currentText}`);
21
- }, 80);
22
- }
23
- return this;
24
- },
25
- stop() {
26
- if (interval) {
27
- clearInterval(interval);
28
- interval = null;
29
- }
30
- if (process.stdout.isTTY) {
31
- process.stdout.write("\r\x1b[K");
32
- }
33
- },
34
- succeed(msg) {
35
- this.stop();
36
- console.log(`āœ… ${msg}`);
37
- },
38
- fail(msg) {
39
- this.stop();
40
- console.log(`āŒ ${msg}`);
41
- }
42
- };
43
- }
44
-
45
- const pkg = require("./package.json");
46
- const { ensureSqliteRuntime, buildEnvWithRuntime } = require("./hooks/sqliteRuntime");
47
- const { ensureTrayRuntime } = require("./hooks/trayRuntime");
48
- const args = process.argv.slice(2);
49
-
50
- // Self-heal SQLite runtime deps (sql.js + better-sqlite3) into ~/.extremerouter/runtime
51
- // so the server can resolve them via NODE_PATH. Best-effort — sql.js is required,
52
- // better-sqlite3 is optional. Logs to stderr only on failure.
53
- try { ensureSqliteRuntime({ silent: true }); } catch {}
54
-
55
- // Self-heal tray runtime (systray for macOS/Linux only). Windows skipped.
56
- try { ensureTrayRuntime({ silent: true }); } catch {}
57
-
58
- // Configuration constants
59
- const APP_NAME = pkg.name; // Use from package.json
60
- const INSTALL_CMD_LATEST = `npm i -g ${APP_NAME}@latest --prefer-online`;
61
-
62
- const DEFAULT_PORT = 20128;
63
- const DEFAULT_HOST = "0.0.0.0";
64
-
65
- // First non-internal IPv4 — the address remote peers actually reach when bound to 0.0.0.0.
66
- function getLanIp() {
67
- for (const ifaces of Object.values(os.networkInterfaces())) {
68
- for (const i of ifaces || []) {
69
- if (i.family === "IPv4" && !i.internal) return i.address;
70
- }
71
- }
72
- return null;
73
- }
74
-
75
- // Local URL stays "localhost"; warn separately when bound to all interfaces (network-exposed).
76
- function getDisplayHost() {
77
- return host === DEFAULT_HOST ? "localhost" : host;
78
- }
79
- const MAX_PORT_ATTEMPTS = 10;
80
- // Identifiers for killAllAppProcesses - only kill extremerouter specifically
81
- const PROCESS_IDENTIFIERS = [
82
- 'extremerouter' // Only package name - avoid killing other apps
83
- ];
84
-
85
- // Parse arguments
86
- let port = DEFAULT_PORT;
87
- let host = DEFAULT_HOST;
88
- let noBrowser = false;
89
- let skipUpdate = false;
90
- let showLog = false;
91
- let trayMode = false;
92
-
93
- for (let i = 0; i < args.length; i++) {
94
- if (args[i] === "--port" || args[i] === "-p") {
95
- port = parseInt(args[i + 1], 10) || DEFAULT_PORT;
96
- i++;
97
- } else if (args[i] === "--host" || args[i] === "-H") {
98
- host = args[i + 1] || DEFAULT_HOST;
99
- i++;
100
- } else if (args[i] === "--no-browser" || args[i] === "-n") {
101
- noBrowser = true;
102
- } else if (args[i] === "--log" || args[i] === "-l") {
103
- showLog = true;
104
- } else if (args[i] === "--skip-update") {
105
- skipUpdate = true;
106
- } else if (args[i] === "--tray" || args[i] === "-t") {
107
- trayMode = true;
108
- process.env.TRAY_MODE = "1";
109
- } else if (args[i] === "--help" || args[i] === "-h") {
110
- console.log(`
111
- Usage: ${APP_NAME} [options]
112
-
113
- Options:
114
- -p, --port <port> Port to run the server (default: ${DEFAULT_PORT})
115
- -H, --host <host> Host to bind (default: ${DEFAULT_HOST})
116
- -n, --no-browser Don't open browser automatically
117
- -l, --log Show server logs (default: hidden)
118
- -t, --tray Run in system tray mode (background)
119
- --skip-update Skip auto-update check
120
- -h, --help Show this help message
121
- -v, --version Show version
122
- `);
123
- process.exit(0);
124
- } else if (args[i] === "--version" || args[i] === "-v") {
125
- console.log(pkg.version);
126
- process.exit(0);
127
- }
128
- }
129
-
130
- // Auto-relaunch after update: detached process has no TTY → fallback to tray
131
- if (skipUpdate && !trayMode && !process.stdin.isTTY) {
132
- trayMode = true;
133
- process.env.TRAY_MODE = "1";
134
- }
135
-
136
- // Always use Node.js runtime with absolute path
137
- const RUNTIME = process.execPath;
138
-
139
- // Compare semver versions: returns 1 if a > b, -1 if a < b, 0 if equal
140
- function compareVersions(a, b) {
141
- const partsA = a.split(".").map(Number);
142
- const partsB = b.split(".").map(Number);
143
- for (let i = 0; i < 3; i++) {
144
- if (partsA[i] > partsB[i]) return 1;
145
- if (partsA[i] < partsB[i]) return -1;
146
- }
147
- return 0;
148
- }
149
-
150
- // Get app data dir (matches app/src/lib/dataDir.js convention)
151
- function getAppDataDir() {
152
- return process.platform === "win32"
153
- ? path.join(process.env.APPDATA || "", "extremerouter")
154
- : path.join(os.homedir(), ".extremerouter");
155
- }
156
-
157
- // Kill PID from file (best-effort, removes file after)
158
- function killByPidFile(pidFile) {
159
- try {
160
- if (!fs.existsSync(pidFile)) return;
161
- const pid = parseInt(fs.readFileSync(pidFile, "utf8").trim(), 10);
162
- if (!pid) return;
163
- try {
164
- if (process.platform === "win32") {
165
- execSync(`taskkill /F /T /PID ${pid}`, { stdio: "ignore", windowsHide: true, timeout: 3000 });
166
- } else {
167
- process.kill(pid, "SIGKILL");
168
- }
169
- } catch { }
170
- try { fs.unlinkSync(pidFile); } catch { }
171
- } catch { }
172
- }
173
-
174
- // Kill tunnel processes (cloudflared/tailscale) by their PID files
175
- function killTunnelByPidFile() {
176
- const tunnelDir = path.join(getAppDataDir(), "tunnel");
177
- killByPidFile(path.join(tunnelDir, "cloudflared.pid"));
178
- killByPidFile(path.join(tunnelDir, "tailscale.pid"));
179
- }
180
-
181
- // Kill cloudflared whose --url targets this app's port (covers stale PID file case)
182
- function killCloudflaredByAppPort(appPort) {
183
- if (!appPort) return [];
184
- const portMatchers = [`localhost:${appPort}`, `127.0.0.1:${appPort}`];
185
- const pids = [];
186
- try {
187
- if (process.platform === "win32") {
188
- const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"cloudflared.exe\\"' | Select-Object ProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
189
- const output = execSync(psCmd, { encoding: "utf8", windowsHide: true, timeout: 5000 });
190
- const lines = output.split("\n").slice(1).filter(l => l.trim());
191
- lines.forEach(line => {
192
- if (portMatchers.some(m => line.includes(m))) {
193
- const match = line.match(/^"(\d+)"/);
194
- if (match && match[1]) pids.push(match[1]);
195
- }
196
- });
197
- } else {
198
- const output = execSync("ps -eo pid,command 2>/dev/null", { encoding: "utf8", timeout: 5000 });
199
- output.split("\n").forEach(line => {
200
- if (line.includes("cloudflared") && portMatchers.some(m => line.includes(m))) {
201
- const parts = line.trim().split(/\s+/);
202
- const pid = parts[0];
203
- if (pid && !isNaN(pid)) pids.push(pid);
204
- }
205
- });
206
- }
207
- } catch { }
208
- return pids;
209
- }
210
-
211
- // Kill all extremerouter processes
212
- function killAllAppProcesses(appPort) {
213
- return new Promise((resolve) => {
214
- try {
215
- // Kill MIT first (privileged process, needs special handling)
216
- killProxyByPidFile();
217
- // Kill cloudflared/tailscale by PID file (precise, only this app's tunnel)
218
- killTunnelByPidFile();
219
-
220
- const platform = process.platform;
221
- let pids = [];
222
-
223
- // Catch stale PID files: kill cloudflared bound to this app's port
224
- pids.push(...killCloudflaredByAppPort(appPort));
225
-
226
- if (platform === "win32") {
227
- // Windows: use WMI to get full CommandLine (tasklist /V doesn't include it)
228
- try {
229
- const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"node.exe\\"' | Select-Object ProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
230
- const output = execSync(psCmd, {
231
- encoding: "utf8",
232
- windowsHide: true,
233
- timeout: 5000
234
- });
235
- const lines = output.split("\n").slice(1).filter(l => l.trim());
236
- lines.forEach(line => {
237
- // Whitelist: real node process running extremerouter/cli.js, or next-server.
238
- // Avoids killing editors/grep/strace/cursor that just have "extremerouter" in cmdline.
239
- const cmd = line.toLowerCase();
240
- const isAppProcess =
241
- (cmd.includes("node") && cmd.includes("extremerouter") && (cmd.includes("cli.js") || cmd.includes("\\extremerouter") || cmd.includes("/extremerouter")))
242
- || cmd.includes("next-server");
243
- if (isAppProcess) {
244
- const match = line.match(/^"(\d+)"/);
245
- if (match && match[1] && match[1] !== process.pid.toString()) {
246
- pids.push(match[1]);
247
- }
248
- }
249
- });
250
- } catch (e) {
251
- // No processes found or error - continue
252
- }
253
- } else {
254
- // macOS/Linux: use ps to find all matching processes
255
- try {
256
- const output = execSync('ps aux 2>/dev/null', {
257
- encoding: 'utf8',
258
- timeout: 5000
259
- });
260
- const lines = output.split('\n');
261
-
262
- lines.forEach(line => {
263
- // Whitelist: real node process running extremerouter/cli.js, or next-server.
264
- // Avoids killing grep/strace/editors/cursor that incidentally match "extremerouter".
265
- const cmd = line.toLowerCase();
266
- const isAppProcess =
267
- (cmd.includes("node") && cmd.includes("extremerouter") && (cmd.includes("cli.js") || cmd.includes("/extremerouter")))
268
- || cmd.includes("next-server");
269
- if (isAppProcess) {
270
- const parts = line.trim().split(/\s+/);
271
- const pid = parts[1];
272
- if (pid && !isNaN(pid) && pid !== process.pid.toString()) {
273
- pids.push(pid);
274
- }
275
- }
276
- });
277
- } catch (e) {
278
- // No processes found or error - continue
279
- }
280
- }
281
-
282
- // Kill all found processes
283
- if (pids.length > 0) {
284
- pids.forEach(pid => {
285
- try {
286
- if (platform === "win32") {
287
- execSync(`taskkill /F /PID ${pid} 2>nul`, { stdio: 'ignore', shell: true, windowsHide: true, timeout: 3000 });
288
- } else {
289
- execSync(`kill -9 ${pid} 2>/dev/null`, { stdio: 'ignore', timeout: 3000 });
290
- }
291
- } catch (err) {
292
- // Process already dead or can't kill - continue
293
- }
294
- });
295
-
296
- // Wait for processes to fully terminate
297
- setTimeout(() => resolve(), 1000);
298
- } else {
299
- resolve();
300
- }
301
- } catch (err) {
302
- // Silent fail - continue anyway
303
- resolve();
304
- }
305
- });
306
- }
307
-
308
- // Sleep helper using SharedArrayBuffer wait (sync, no busy-loop)
309
- function sleepSync(ms) {
310
- try { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); } catch { /* ignore */ }
311
- }
312
-
313
- // Wait until process dies or timeout reached
314
- function waitForExit(pid, timeoutMs) {
315
- const deadline = Date.now() + timeoutMs;
316
- while (Date.now() < deadline) {
317
- try { process.kill(pid, 0); } catch { return true; }
318
- sleepSync(100);
319
- }
320
- return false;
321
- }
322
-
323
- // Kill MIT server by PID file (runs privileged, needs special handling)
324
- // Sends SIGTERM first so MIT can clean up host entries before dying.
325
- function killProxyByPidFile() {
326
- try {
327
- const pidFile = path.join(getAppDataDir(), "mitm", ".mitm.pid");
328
- if (!fs.existsSync(pidFile)) return;
329
- const pid = parseInt(fs.readFileSync(pidFile, "utf8").trim(), 10);
330
- if (!pid) return;
331
-
332
- if (process.platform === "win32") {
333
- // Graceful first (lets server cleanup hosts), then force
334
- try { execSync(`taskkill /T /PID ${pid}`, { stdio: "ignore", windowsHide: true, timeout: 2000 }); } catch { }
335
- if (!waitForExit(pid, 1500)) {
336
- try { execSync(`taskkill /F /T /PID ${pid}`, { stdio: "ignore", windowsHide: true, timeout: 3000 }); } catch { }
337
- }
338
- // Last-resort: PowerShell Stop-Process (sometimes succeeds where taskkill fails on admin processes)
339
- if (!waitForExit(pid, 500)) {
340
- try { execSync(`powershell -NonInteractive -WindowStyle Hidden -Command "Stop-Process -Id ${pid} -Force"`, { stdio: "ignore", windowsHide: true, timeout: 3000 }); } catch { }
341
- }
342
- } else {
343
- // SIGTERM via cached sudo token first
344
- try { execSync(`sudo -n kill -TERM ${pid} 2>/dev/null`, { stdio: "ignore", timeout: 2000 }); }
345
- catch { try { process.kill(pid, "SIGTERM"); } catch { } }
346
- if (!waitForExit(pid, 1500)) {
347
- try { execSync(`sudo -n kill -9 ${pid} 2>/dev/null`, { stdio: "ignore", timeout: 2000 }); }
348
- catch { try { process.kill(pid, "SIGKILL"); } catch { } }
349
- }
350
- }
351
- try { fs.unlinkSync(pidFile); } catch { }
352
- } catch { }
353
- }
354
-
355
- // Kill any process on specific port
356
- function killProcessOnPort(port) {
357
- return new Promise((resolve) => {
358
- try {
359
- const platform = process.platform;
360
- let pid;
361
-
362
- if (platform === "win32") {
363
- try {
364
- const output = execSync(`netstat -ano | findstr :${port}`, {
365
- encoding: 'utf8',
366
- shell: true,
367
- windowsHide: true,
368
- timeout: 5000
369
- }).trim();
370
- const lines = output.split('\n').filter(l => l.includes('LISTENING'));
371
- if (lines.length > 0) {
372
- pid = lines[0].trim().split(/\s+/).pop();
373
- execSync(`taskkill /F /PID ${pid} 2>nul`, { stdio: 'ignore', shell: true, windowsHide: true, timeout: 3000 });
374
- }
375
- } catch (e) {
376
- // Port is free or error
377
- }
378
- } else {
379
- // macOS/Linux
380
- try {
381
- const pidOutput = execSync(`lsof -ti:${port}`, {
382
- encoding: 'utf8',
383
- stdio: ['pipe', 'pipe', 'ignore']
384
- }).trim();
385
- if (pidOutput) {
386
- pid = pidOutput.split('\n')[0];
387
- execSync(`kill -9 ${pid} 2>/dev/null`, { stdio: 'ignore', timeout: 3000 });
388
- }
389
- } catch (e) {
390
- // Port is free or error
391
- }
392
- }
393
-
394
- // Wait for port to be released
395
- setTimeout(() => resolve(), 500);
396
- } catch (err) {
397
- // Silent fail - continue anyway
398
- resolve();
399
- }
400
- });
401
- }
402
-
403
-
404
- // Detect if running in restricted environment (Codespaces, Docker)
405
- function isRestrictedEnvironment() {
406
- // Check for Codespaces
407
- if (process.env.CODESPACES === "true" || process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN) {
408
- return "GitHub Codespaces";
409
- }
410
-
411
- // Check for Docker
412
- if (fs.existsSync("/.dockerenv") || (fs.existsSync("/proc/1/cgroup") && fs.readFileSync("/proc/1/cgroup", "utf8").includes("docker"))) {
413
- return "Docker";
414
- }
415
-
416
- return null;
417
- }
418
-
419
- // Check if new version available, return latest version or null
420
- function checkForUpdate() {
421
- return new Promise((resolve) => {
422
- if (skipUpdate) {
423
- resolve(null);
424
- return;
425
- }
426
-
427
- const spinner = createSpinner("Checking for updates...").start();
428
- let resolved = false;
429
-
430
- const safetyTimeout = setTimeout(() => {
431
- if (!resolved) {
432
- resolved = true;
433
- spinner.stop();
434
- resolve(null);
435
- }
436
- }, 8000);
437
-
438
- const done = (version) => {
439
- if (resolved) return;
440
- resolved = true;
441
- clearTimeout(safetyTimeout);
442
- spinner.stop();
443
- resolve(version);
444
- };
445
-
446
- const req = https.get(`https://registry.npmjs.org/${pkg.name}/latest`, { timeout: 3000 }, (res) => {
447
- let data = "";
448
- res.on("data", chunk => data += chunk);
449
- res.on("end", () => {
450
- try {
451
- const latest = JSON.parse(data);
452
- if (latest.version && compareVersions(latest.version, pkg.version) > 0) {
453
- done(latest.version);
454
- } else {
455
- done(null);
456
- }
457
- } catch (e) {
458
- done(null);
459
- }
460
- });
461
- });
462
-
463
- req.on("error", () => done(null));
464
- req.on("timeout", () => { req.destroy(); done(null); });
465
- });
466
- }
467
-
468
- // Open browser
469
- function openBrowser(url) {
470
- const platform = process.platform;
471
- let cmd;
472
-
473
- if (platform === "darwin") {
474
- cmd = `open "${url}"`;
475
- } else if (platform === "win32") {
476
- cmd = `start "" "${url}"`;
477
- } else {
478
- cmd = `xdg-open "${url}"`;
479
- }
480
-
481
- exec(cmd, { windowsHide: true }, (err) => {
482
- if (err) {
483
- console.log(`Open browser manually: ${url}`);
484
- }
485
- });
486
- }
487
-
488
- // Find standalone server (bundled in bin/app for published package).
489
- // Prefer custom-server.js (injects real socket IP) when present.
490
- const standaloneDir = path.join(__dirname, "app");
491
- const customServerPath = path.join(standaloneDir, "custom-server.js");
492
- const serverPath = fs.existsSync(customServerPath)
493
- ? customServerPath
494
- : path.join(standaloneDir, "server.js");
495
-
496
- if (!fs.existsSync(serverPath)) {
497
- console.error("Error: Standalone build not found.");
498
- console.error("Please run 'npm run build:cli' first.");
499
- process.exit(1);
500
- }
501
-
502
- // Check for updates FIRST, then start server
503
- checkForUpdate().then((latestVersion) => {
504
- killAllAppProcesses(port).then(() => {
505
- return killProcessOnPort(port);
506
- }).then(() => {
507
- startServer(latestVersion);
508
- });
509
- });
510
-
511
- // Show interface selection menu
512
- async function showInterfaceMenu(latestVersion) {
513
- const { selectMenu } = require("./src/cli/utils/input");
514
- const { clearScreen } = require("./src/cli/utils/display");
515
- const { getEndpoint } = require("./src/cli/utils/endpoint");
516
-
517
- clearScreen();
518
-
519
- const displayHost = getDisplayHost();
520
-
521
- // Detect tunnel/local mode for server URL display
522
- let serverUrl;
523
- try {
524
- const { endpoint, tunnelEnabled } = await getEndpoint(port);
525
- serverUrl = tunnelEnabled ? endpoint.replace(/\/v1$/, "") : `http://${displayHost}:${port}`;
526
- } catch (e) {
527
- serverUrl = `http://${displayHost}:${port}`;
528
- }
529
-
530
- const subtitle = `šŸš€ Server: \x1b[32m${serverUrl}\x1b[0m`;
531
-
532
- const menuItems = [];
533
-
534
- if (latestVersion) {
535
- menuItems.push({ label: `Update to v${latestVersion} (current: v${pkg.version})`, icon: "⬆" });
536
- }
537
-
538
- menuItems.push(
539
- { label: "Web UI (Open in Browser)", icon: "🌐" },
540
- { label: "Terminal UI (Interactive CLI)", icon: "šŸ’»" },
541
- { label: "Hide to Tray (Background)", icon: "šŸ””" },
542
- { label: "Exit", icon: "🚪" }
543
- );
544
-
545
- const selected = await selectMenu(`Choose Interface (v${pkg.version})`, menuItems, 0, subtitle);
546
-
547
- const offset = latestVersion ? 1 : 0;
548
-
549
- if (latestVersion && selected === 0) return "update";
550
- if (selected === offset) return "web";
551
- if (selected === offset + 1) return "terminal";
552
- if (selected === offset + 2) return "hide";
553
- return "exit";
554
- }
555
-
556
- const MAX_RESTARTS = 2;
557
- const RESTART_RESET_MS = 30000; // Reset counter if alive > 30s
558
-
559
- function startServer(latestVersion) {
560
- const displayHost = getDisplayHost();
561
- const url = `http://${displayHost}:${port}/dashboard`;
562
- // Surface real network exposure when bound to all interfaces (default 0.0.0.0).
563
- if (host === DEFAULT_HOST) {
564
- const lanIp = getLanIp();
565
- if (lanIp) console.log(`\x1b[33m⚠ Network-exposed: reachable at http://${lanIp}:${port} (bound 0.0.0.0). Use --host 127.0.0.1 for local-only.\x1b[0m`);
566
- }
567
-
568
- let restartCount = 0;
569
- let serverStartTime = Date.now();
570
-
571
- const CRASH_LOG_LINES = 50;
572
- let crashLog = [];
573
-
574
- function spawnServer() {
575
- serverStartTime = Date.now();
576
- crashLog = [];
577
- const child = spawn(RUNTIME, ["--max-old-space-size=6144", serverPath], {
578
- cwd: standaloneDir,
579
- stdio: showLog ? "inherit" : ["ignore", "ignore", "pipe"],
580
- detached: true,
581
- windowsHide: true,
582
- env: {
583
- ...buildEnvWithRuntime(process.env),
584
- PORT: port.toString(),
585
- HOSTNAME: host
586
- }
587
- });
588
- if (!showLog && child.stderr) {
589
- child.stderr.on("data", (data) => {
590
- const lines = data.toString().split("\n").filter(Boolean);
591
- crashLog.push(...lines);
592
- if (crashLog.length > CRASH_LOG_LINES) crashLog = crashLog.slice(-CRASH_LOG_LINES);
593
- });
594
- }
595
- return child;
596
- }
597
-
598
- let server = spawnServer();
599
-
600
- // Cleanup function - force kill server process
601
- let isCleaningUp = false;
602
- function cleanup() {
603
- if (isCleaningUp) return;
604
- isCleaningUp = true;
605
- try {
606
- // Kill tray if running
607
- try {
608
- const { killTray } = require("./src/cli/tray/tray");
609
- killTray();
610
- } catch (e) { }
611
- // Kill MIT server (privileged process) via PID file
612
- killProxyByPidFile();
613
- // Kill cloudflared/tailscale via PID file (only this app's tunnel)
614
- killTunnelByPidFile();
615
- // Kill server process directly
616
- if (server.pid) {
617
- process.kill(server.pid, "SIGKILL");
618
- }
619
- // Also try to kill process group
620
- process.kill(-server.pid, "SIGKILL");
621
- } catch (e) { }
622
- }
623
-
624
- // Suppress all errors during shutdown (systray lib throws JSON parse errors)
625
- let isShuttingDown = false;
626
- process.on("uncaughtException", (err) => {
627
- if (isShuttingDown) return;
628
- console.error("Error:", err.message);
629
- });
630
-
631
- // Handle all exit scenarios
632
- process.on("SIGINT", () => {
633
- if (isShuttingDown) return;
634
- isShuttingDown = true;
635
- console.log("\nExiting...");
636
- cleanup();
637
- setTimeout(() => process.exit(0), 100);
638
- });
639
- process.on("SIGTERM", () => {
640
- if (isShuttingDown) return;
641
- isShuttingDown = true;
642
- cleanup();
643
- setTimeout(() => process.exit(0), 100);
644
- });
645
- process.on("SIGHUP", () => {
646
- if (isShuttingDown) return;
647
- isShuttingDown = true;
648
- cleanup();
649
- setTimeout(() => process.exit(0), 100);
650
- });
651
-
652
- // Initialize tray icon (runs alongside TUI)
653
- const initTrayIcon = () => {
654
- try {
655
- const { initTray } = require("./src/cli/tray/tray");
656
- initTray({
657
- port,
658
- onQuit: () => {
659
- isShuttingDown = true;
660
- console.log("\nšŸ‘‹ Shutting down from tray...");
661
- cleanup();
662
- setTimeout(() => process.exit(0), 100);
663
- },
664
- onOpenDashboard: () => openBrowser(url)
665
- });
666
- } catch (err) {
667
- // Tray not available - continue without it
668
- }
669
- };
670
-
671
- // Tray-only mode: no TUI, just tray icon
672
- if (trayMode) {
673
- // Ignore SIGHUP so macOS terminal close doesn't kill the background tray process
674
- process.removeAllListeners("SIGHUP");
675
- process.on("SIGHUP", () => {});
676
-
677
- console.log(`\nšŸš€ ${pkg.name} v${pkg.version}`);
678
- console.log(`Server: http://${displayHost}:${port}`);
679
-
680
- setTimeout(() => {
681
- initTrayIcon();
682
- console.log("\nšŸ’” Router is now running in system tray. Close this terminal if you want.");
683
- console.log(" Right-click tray icon to open dashboard or quit.\n");
684
- }, 2000);
685
-
686
- return;
687
- }
688
-
689
- // Wait for server to be ready, then show interface menu loop + tray
690
- setTimeout(async () => {
691
- // Start tray icon alongside TUI
692
- initTrayIcon();
693
-
694
- try {
695
- while (true) {
696
- const choice = await showInterfaceMenu(latestVersion);
697
-
698
- if (choice === "update") {
699
- isShuttingDown = true;
700
- const { clearScreen } = require("./src/cli/utils/display");
701
- clearScreen();
702
- console.log(`\n⬆ Update v${pkg.version} → v${latestVersion}\n`);
703
- console.log(`Run this after exit:\n`);
704
- console.log(` \x1b[33m${INSTALL_CMD_LATEST}\x1b[0m\n`);
705
- cleanup();
706
- await killAllAppProcesses(port);
707
- await killProcessOnPort(port);
708
- setTimeout(() => process.exit(0), 200);
709
- return;
710
- } else if (choice === "web") {
711
- openBrowser(url);
712
- // Wait for user to come back
713
- const { pause } = require("./src/cli/utils/input");
714
- await pause("\nPress Enter to go back to menu...");
715
- } else if (choice === "terminal") {
716
- // Start Terminal UI - it will return when user selects Back
717
- const { startTerminalUI } = require("./src/cli/terminalUI");
718
- await startTerminalUI(port);
719
- // Loop continues, show menu again
720
- } else if (choice === "hide") {
721
- const { clearScreen } = require("./src/cli/utils/display");
722
- clearScreen();
723
-
724
- // Enable auto startup on OS boot
725
- try {
726
- const { enableAutoStart } = require("./src/cli/tray/autostart");
727
- enableAutoStart(__filename);
728
- } catch (e) { }
729
-
730
- if (process.platform === "darwin") {
731
- // macOS: keep current process alive — spawning a detached child puts
732
- // it outside the login session so NSStatusItem silently fails.
733
- process.removeAllListeners("SIGHUP");
734
- process.on("SIGHUP", () => {});
735
-
736
- console.log(`\nā³ Switching to tray mode... (icon already visible in menu bar)`);
737
- console.log(`šŸ”” ExtremeRouter is running in tray (PID: ${process.pid})`);
738
- console.log(` Server: http://${displayHost}:${port}`);
739
- console.log(`\nšŸ’” You can close this terminal. Right-click tray icon to quit.\n`);
740
-
741
- // Tray already init'd at startup — just keep event loop alive.
742
- return;
743
- }
744
-
745
- // Windows/Linux: spawn detached bgProcess (systray works fine in child)
746
- console.log(`\nā³ Starting background process... (tray icon will appear in ~3s)`);
747
-
748
- const bgProcess = spawn(process.execPath, [__filename, "--tray", "--skip-update", "-p", port.toString()], {
749
- detached: true,
750
- stdio: "ignore",
751
- windowsHide: true,
752
- env: { ...process.env }
753
- });
754
- bgProcess.unref();
755
-
756
- console.log(`šŸ”” ExtremeRouter is now running in background (PID: ${bgProcess.pid})`);
757
- console.log(` Server: http://${displayHost}:${port}`);
758
- console.log(`\nšŸ’” You can close this terminal. Right-click tray icon to quit.\n`);
759
-
760
- // cleanup() kills server so bgProcess can claim the port fresh
761
- cleanup();
762
- process.exit(0);
763
- } else if (choice === "exit") {
764
- isShuttingDown = true;
765
- console.log("\nExiting...");
766
- cleanup();
767
- setTimeout(() => process.exit(0), 100);
768
- }
769
- }
770
- } catch (err) {
771
- console.error("Error:", err.message);
772
- cleanup();
773
- process.exit(1);
774
- }
775
- }, 3000);
776
-
777
- function attachServerEvents() {
778
- server.on("error", (err) => {
779
- console.error("Failed to start server:", err.message);
780
- if (!isShuttingDown) tryRestart();
781
- else { cleanup(); process.exit(1); }
782
- });
783
-
784
- server.on("close", (code) => {
785
- if (isShuttingDown || code === 0) {
786
- process.exit(code || 0);
787
- return;
788
- }
789
- tryRestart(code);
790
- });
791
- }
792
-
793
- function tryRestart(code) {
794
- const aliveMs = Date.now() - serverStartTime;
795
- // Reset counter if last run was stable
796
- if (aliveMs >= RESTART_RESET_MS) restartCount = 0;
797
-
798
- if (restartCount >= MAX_RESTARTS) {
799
- console.error(`\nāš ļø Server crashed ${MAX_RESTARTS} times. Disabling MIT and restarting...`);
800
- try {
801
- const dbPath = path.join(os.homedir(), process.platform === "win32" ? path.join("AppData", "Roaming", "extremerouter", "db.json") : path.join(".extremerouter", "db.json"));
802
- if (fs.existsSync(dbPath)) {
803
- const db = JSON.parse(fs.readFileSync(dbPath, "utf-8"));
804
- if (db.settings) db.settings.mitmEnabled = false;
805
- fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
806
- }
807
- } catch { /* best effort */ }
808
- restartCount = 0;
809
- server = spawnServer();
810
- attachServerEvents();
811
- return;
812
- }
813
-
814
- restartCount++;
815
- const delay = Math.min(1000 * restartCount, 10000);
816
- console.error(`\nāš ļø Server exited (code=${code ?? "unknown"}). Restarting in ${delay / 1000}s... (${restartCount}/${MAX_RESTARTS})`);
817
- if (crashLog.length) {
818
- console.error("\n--- Server crash log ---");
819
- crashLog.forEach(l => console.error(l));
820
- console.error("--- End crash log ---\n");
821
- }
822
-
823
- setTimeout(() => {
824
- server = spawnServer();
825
- attachServerEvents();
826
- }, delay);
827
- }
828
-
829
- attachServerEvents();
830
- }
1
+ #!/usr/bin/env node
2
+
3
+ const { spawn, exec, execSync } = require("child_process");
4
+ const path = require("path");
5
+ const fs = require("fs");
6
+ const https = require("https");
7
+ const os = require("os");
8
+
9
+ // Native spinner - no external dependency
10
+ function createSpinner(text) {
11
+ const frames = ["ā ‹", "ā ™", "ā ¹", "ā ø", "ā ¼", "ā “", "ā ¦", "ā §", "ā ‡", "ā "];
12
+ let i = 0;
13
+ let interval = null;
14
+ let currentText = text;
15
+ return {
16
+ start() {
17
+ if (process.stdout.isTTY) {
18
+ process.stdout.write(`\r${frames[0]} ${currentText}`);
19
+ interval = setInterval(() => {
20
+ process.stdout.write(`\r${frames[i++ % frames.length]} ${currentText}`);
21
+ }, 80);
22
+ }
23
+ return this;
24
+ },
25
+ stop() {
26
+ if (interval) {
27
+ clearInterval(interval);
28
+ interval = null;
29
+ }
30
+ if (process.stdout.isTTY) {
31
+ process.stdout.write("\r\x1b[K");
32
+ }
33
+ },
34
+ succeed(msg) {
35
+ this.stop();
36
+ console.log(`āœ… ${msg}`);
37
+ },
38
+ fail(msg) {
39
+ this.stop();
40
+ console.log(`āŒ ${msg}`);
41
+ }
42
+ };
43
+ }
44
+
45
+ const pkg = require("./package.json");
46
+ const { ensureSqliteRuntime, buildEnvWithRuntime } = require("./hooks/sqliteRuntime");
47
+ const { ensureTrayRuntime } = require("./hooks/trayRuntime");
48
+ const args = process.argv.slice(2);
49
+
50
+ // Self-heal SQLite runtime deps (sql.js + better-sqlite3) into ~/.extremerouter/runtime
51
+ // so the server can resolve them via NODE_PATH. Best-effort — sql.js is required,
52
+ // better-sqlite3 is optional. Logs to stderr only on failure.
53
+ try { ensureSqliteRuntime({ silent: true }); } catch {}
54
+
55
+ // Self-heal tray runtime (systray for macOS/Linux only). Windows skipped.
56
+ try { ensureTrayRuntime({ silent: true }); } catch {}
57
+
58
+ // Configuration constants
59
+ const APP_NAME = pkg.name; // Use from package.json
60
+ const INSTALL_CMD_LATEST = `npm i -g ${APP_NAME}@latest --prefer-online`;
61
+
62
+ const DEFAULT_PORT = 20128;
63
+ const DEFAULT_HOST = "0.0.0.0";
64
+
65
+ // First non-internal IPv4 — the address remote peers actually reach when bound to 0.0.0.0.
66
+ function getLanIp() {
67
+ for (const ifaces of Object.values(os.networkInterfaces())) {
68
+ for (const i of ifaces || []) {
69
+ if (i.family === "IPv4" && !i.internal) return i.address;
70
+ }
71
+ }
72
+ return null;
73
+ }
74
+
75
+ // Local URL stays "localhost"; warn separately when bound to all interfaces (network-exposed).
76
+ function getDisplayHost() {
77
+ return host === DEFAULT_HOST ? "localhost" : host;
78
+ }
79
+ const MAX_PORT_ATTEMPTS = 10;
80
+ // Identifiers for killAllAppProcesses - only kill extremerouter specifically
81
+ const PROCESS_IDENTIFIERS = [
82
+ 'extremerouter' // Only package name - avoid killing other apps
83
+ ];
84
+
85
+ // Parse arguments
86
+ let port = DEFAULT_PORT;
87
+ let host = DEFAULT_HOST;
88
+ let noBrowser = false;
89
+ let skipUpdate = false;
90
+ let showLog = false;
91
+ let trayMode = false;
92
+
93
+ for (let i = 0; i < args.length; i++) {
94
+ if (args[i] === "--port" || args[i] === "-p") {
95
+ port = parseInt(args[i + 1], 10) || DEFAULT_PORT;
96
+ i++;
97
+ } else if (args[i] === "--host" || args[i] === "-H") {
98
+ host = args[i + 1] || DEFAULT_HOST;
99
+ i++;
100
+ } else if (args[i] === "--no-browser" || args[i] === "-n") {
101
+ noBrowser = true;
102
+ } else if (args[i] === "--log" || args[i] === "-l") {
103
+ showLog = true;
104
+ } else if (args[i] === "--skip-update") {
105
+ skipUpdate = true;
106
+ } else if (args[i] === "--tray" || args[i] === "-t") {
107
+ trayMode = true;
108
+ process.env.TRAY_MODE = "1";
109
+ } else if (args[i] === "--help" || args[i] === "-h") {
110
+ console.log(`
111
+ Usage: ${APP_NAME} [options]
112
+
113
+ Options:
114
+ -p, --port <port> Port to run the server (default: ${DEFAULT_PORT})
115
+ -H, --host <host> Host to bind (default: ${DEFAULT_HOST})
116
+ -n, --no-browser Don't open browser automatically
117
+ -l, --log Show server logs (default: hidden)
118
+ -t, --tray Run in system tray mode (background)
119
+ --skip-update Skip auto-update check
120
+ -h, --help Show this help message
121
+ -v, --version Show version
122
+ `);
123
+ process.exit(0);
124
+ } else if (args[i] === "--version" || args[i] === "-v") {
125
+ console.log(pkg.version);
126
+ process.exit(0);
127
+ }
128
+ }
129
+
130
+ // Auto-relaunch after update: detached process has no TTY → fallback to tray
131
+ if (skipUpdate && !trayMode && !process.stdin.isTTY) {
132
+ trayMode = true;
133
+ process.env.TRAY_MODE = "1";
134
+ }
135
+
136
+ // Always use Node.js runtime with absolute path
137
+ const RUNTIME = process.execPath;
138
+
139
+ // Compare semver versions: returns 1 if a > b, -1 if a < b, 0 if equal
140
+ function compareVersions(a, b) {
141
+ const partsA = a.split(".").map(Number);
142
+ const partsB = b.split(".").map(Number);
143
+ for (let i = 0; i < 3; i++) {
144
+ if (partsA[i] > partsB[i]) return 1;
145
+ if (partsA[i] < partsB[i]) return -1;
146
+ }
147
+ return 0;
148
+ }
149
+
150
+ // Get app data dir (matches app/src/lib/dataDir.js convention)
151
+ function getAppDataDir() {
152
+ return process.platform === "win32"
153
+ ? path.join(process.env.APPDATA || "", "extremerouter")
154
+ : path.join(os.homedir(), ".extremerouter");
155
+ }
156
+
157
+ // Kill PID from file (best-effort, removes file after)
158
+ function killByPidFile(pidFile) {
159
+ try {
160
+ if (!fs.existsSync(pidFile)) return;
161
+ const pid = parseInt(fs.readFileSync(pidFile, "utf8").trim(), 10);
162
+ if (!pid) return;
163
+ try {
164
+ if (process.platform === "win32") {
165
+ execSync(`taskkill /F /T /PID ${pid}`, { stdio: "ignore", windowsHide: true, timeout: 3000 });
166
+ } else {
167
+ process.kill(pid, "SIGKILL");
168
+ }
169
+ } catch { }
170
+ try { fs.unlinkSync(pidFile); } catch { }
171
+ } catch { }
172
+ }
173
+
174
+ // Kill tunnel processes (cloudflared/tailscale) by their PID files
175
+ function killTunnelByPidFile() {
176
+ const tunnelDir = path.join(getAppDataDir(), "tunnel");
177
+ killByPidFile(path.join(tunnelDir, "cloudflared.pid"));
178
+ killByPidFile(path.join(tunnelDir, "tailscale.pid"));
179
+ }
180
+
181
+ // Kill cloudflared whose --url targets this app's port (covers stale PID file case)
182
+ function killCloudflaredByAppPort(appPort) {
183
+ if (!appPort) return [];
184
+ const portMatchers = [`localhost:${appPort}`, `127.0.0.1:${appPort}`];
185
+ const pids = [];
186
+ try {
187
+ if (process.platform === "win32") {
188
+ const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"cloudflared.exe\\"' | Select-Object ProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
189
+ const output = execSync(psCmd, { encoding: "utf8", windowsHide: true, timeout: 5000 });
190
+ const lines = output.split("\n").slice(1).filter(l => l.trim());
191
+ lines.forEach(line => {
192
+ if (portMatchers.some(m => line.includes(m))) {
193
+ const match = line.match(/^"(\d+)"/);
194
+ if (match && match[1]) pids.push(match[1]);
195
+ }
196
+ });
197
+ } else {
198
+ const output = execSync("ps -eo pid,command 2>/dev/null", { encoding: "utf8", timeout: 5000 });
199
+ output.split("\n").forEach(line => {
200
+ if (line.includes("cloudflared") && portMatchers.some(m => line.includes(m))) {
201
+ const parts = line.trim().split(/\s+/);
202
+ const pid = parts[0];
203
+ if (pid && !isNaN(pid)) pids.push(pid);
204
+ }
205
+ });
206
+ }
207
+ } catch { }
208
+ return pids;
209
+ }
210
+
211
+ // Kill all extremerouter processes
212
+ function killAllAppProcesses(appPort) {
213
+ return new Promise((resolve) => {
214
+ try {
215
+ // Kill MIT first (privileged process, needs special handling)
216
+ killProxyByPidFile();
217
+ // Kill cloudflared/tailscale by PID file (precise, only this app's tunnel)
218
+ killTunnelByPidFile();
219
+
220
+ const platform = process.platform;
221
+ let pids = [];
222
+
223
+ // Catch stale PID files: kill cloudflared bound to this app's port
224
+ pids.push(...killCloudflaredByAppPort(appPort));
225
+
226
+ if (platform === "win32") {
227
+ // Windows: use WMI to get full CommandLine (tasklist /V doesn't include it)
228
+ try {
229
+ const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"node.exe\\"' | Select-Object ProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
230
+ const output = execSync(psCmd, {
231
+ encoding: "utf8",
232
+ windowsHide: true,
233
+ timeout: 5000
234
+ });
235
+ const lines = output.split("\n").slice(1).filter(l => l.trim());
236
+ lines.forEach(line => {
237
+ // Whitelist: real node process running extremerouter/cli.js, or next-server.
238
+ // Avoids killing editors/grep/strace/cursor that just have "extremerouter" in cmdline.
239
+ const cmd = line.toLowerCase();
240
+ const isAppProcess =
241
+ (cmd.includes("node") && cmd.includes("extremerouter") && (cmd.includes("cli.js") || cmd.includes("\\extremerouter") || cmd.includes("/extremerouter")))
242
+ || cmd.includes("next-server");
243
+ if (isAppProcess) {
244
+ const match = line.match(/^"(\d+)"/);
245
+ if (match && match[1] && match[1] !== process.pid.toString()) {
246
+ pids.push(match[1]);
247
+ }
248
+ }
249
+ });
250
+ } catch (e) {
251
+ // No processes found or error - continue
252
+ }
253
+ } else {
254
+ // macOS/Linux: use ps to find all matching processes
255
+ try {
256
+ const output = execSync('ps aux 2>/dev/null', {
257
+ encoding: 'utf8',
258
+ timeout: 5000
259
+ });
260
+ const lines = output.split('\n');
261
+
262
+ lines.forEach(line => {
263
+ // Whitelist: real node process running extremerouter/cli.js, or next-server.
264
+ // Avoids killing grep/strace/editors/cursor that incidentally match "extremerouter".
265
+ const cmd = line.toLowerCase();
266
+ const isAppProcess =
267
+ (cmd.includes("node") && cmd.includes("extremerouter") && (cmd.includes("cli.js") || cmd.includes("/extremerouter")))
268
+ || cmd.includes("next-server");
269
+ if (isAppProcess) {
270
+ const parts = line.trim().split(/\s+/);
271
+ const pid = parts[1];
272
+ if (pid && !isNaN(pid) && pid !== process.pid.toString()) {
273
+ pids.push(pid);
274
+ }
275
+ }
276
+ });
277
+ } catch (e) {
278
+ // No processes found or error - continue
279
+ }
280
+ }
281
+
282
+ // Kill all found processes
283
+ if (pids.length > 0) {
284
+ pids.forEach(pid => {
285
+ try {
286
+ if (platform === "win32") {
287
+ execSync(`taskkill /F /PID ${pid} 2>nul`, { stdio: 'ignore', shell: true, windowsHide: true, timeout: 3000 });
288
+ } else {
289
+ execSync(`kill -9 ${pid} 2>/dev/null`, { stdio: 'ignore', timeout: 3000 });
290
+ }
291
+ } catch (err) {
292
+ // Process already dead or can't kill - continue
293
+ }
294
+ });
295
+
296
+ // Wait for processes to fully terminate
297
+ setTimeout(() => resolve(), 1000);
298
+ } else {
299
+ resolve();
300
+ }
301
+ } catch (err) {
302
+ // Silent fail - continue anyway
303
+ resolve();
304
+ }
305
+ });
306
+ }
307
+
308
+ // Sleep helper using SharedArrayBuffer wait (sync, no busy-loop)
309
+ function sleepSync(ms) {
310
+ try { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); } catch { /* ignore */ }
311
+ }
312
+
313
+ // Wait until process dies or timeout reached
314
+ function waitForExit(pid, timeoutMs) {
315
+ const deadline = Date.now() + timeoutMs;
316
+ while (Date.now() < deadline) {
317
+ try { process.kill(pid, 0); } catch { return true; }
318
+ sleepSync(100);
319
+ }
320
+ return false;
321
+ }
322
+
323
+ // Kill MIT server by PID file (runs privileged, needs special handling)
324
+ // Sends SIGTERM first so MIT can clean up host entries before dying.
325
+ function killProxyByPidFile() {
326
+ try {
327
+ const pidFile = path.join(getAppDataDir(), "mitm", ".mitm.pid");
328
+ if (!fs.existsSync(pidFile)) return;
329
+ const pid = parseInt(fs.readFileSync(pidFile, "utf8").trim(), 10);
330
+ if (!pid) return;
331
+
332
+ if (process.platform === "win32") {
333
+ // Graceful first (lets server cleanup hosts), then force
334
+ try { execSync(`taskkill /T /PID ${pid}`, { stdio: "ignore", windowsHide: true, timeout: 2000 }); } catch { }
335
+ if (!waitForExit(pid, 1500)) {
336
+ try { execSync(`taskkill /F /T /PID ${pid}`, { stdio: "ignore", windowsHide: true, timeout: 3000 }); } catch { }
337
+ }
338
+ // Last-resort: PowerShell Stop-Process (sometimes succeeds where taskkill fails on admin processes)
339
+ if (!waitForExit(pid, 500)) {
340
+ try { execSync(`powershell -NonInteractive -WindowStyle Hidden -Command "Stop-Process -Id ${pid} -Force"`, { stdio: "ignore", windowsHide: true, timeout: 3000 }); } catch { }
341
+ }
342
+ } else {
343
+ // SIGTERM via cached sudo token first
344
+ try { execSync(`sudo -n kill -TERM ${pid} 2>/dev/null`, { stdio: "ignore", timeout: 2000 }); }
345
+ catch { try { process.kill(pid, "SIGTERM"); } catch { } }
346
+ if (!waitForExit(pid, 1500)) {
347
+ try { execSync(`sudo -n kill -9 ${pid} 2>/dev/null`, { stdio: "ignore", timeout: 2000 }); }
348
+ catch { try { process.kill(pid, "SIGKILL"); } catch { } }
349
+ }
350
+ }
351
+ try { fs.unlinkSync(pidFile); } catch { }
352
+ } catch { }
353
+ }
354
+
355
+ // Kill any process on specific port
356
+ function killProcessOnPort(port) {
357
+ return new Promise((resolve) => {
358
+ try {
359
+ const platform = process.platform;
360
+ let pid;
361
+
362
+ if (platform === "win32") {
363
+ try {
364
+ const output = execSync(`netstat -ano | findstr :${port}`, {
365
+ encoding: 'utf8',
366
+ shell: true,
367
+ windowsHide: true,
368
+ timeout: 5000
369
+ }).trim();
370
+ const lines = output.split('\n').filter(l => l.includes('LISTENING'));
371
+ if (lines.length > 0) {
372
+ pid = lines[0].trim().split(/\s+/).pop();
373
+ execSync(`taskkill /F /PID ${pid} 2>nul`, { stdio: 'ignore', shell: true, windowsHide: true, timeout: 3000 });
374
+ }
375
+ } catch (e) {
376
+ // Port is free or error
377
+ }
378
+ } else {
379
+ // macOS/Linux
380
+ try {
381
+ const pidOutput = execSync(`lsof -ti:${port}`, {
382
+ encoding: 'utf8',
383
+ stdio: ['pipe', 'pipe', 'ignore']
384
+ }).trim();
385
+ if (pidOutput) {
386
+ pid = pidOutput.split('\n')[0];
387
+ execSync(`kill -9 ${pid} 2>/dev/null`, { stdio: 'ignore', timeout: 3000 });
388
+ }
389
+ } catch (e) {
390
+ // Port is free or error
391
+ }
392
+ }
393
+
394
+ // Wait for port to be released
395
+ setTimeout(() => resolve(), 500);
396
+ } catch (err) {
397
+ // Silent fail - continue anyway
398
+ resolve();
399
+ }
400
+ });
401
+ }
402
+
403
+
404
+ // Detect if running in restricted environment (Codespaces, Docker)
405
+ function isRestrictedEnvironment() {
406
+ // Check for Codespaces
407
+ if (process.env.CODESPACES === "true" || process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN) {
408
+ return "GitHub Codespaces";
409
+ }
410
+
411
+ // Check for Docker
412
+ if (fs.existsSync("/.dockerenv") || (fs.existsSync("/proc/1/cgroup") && fs.readFileSync("/proc/1/cgroup", "utf8").includes("docker"))) {
413
+ return "Docker";
414
+ }
415
+
416
+ return null;
417
+ }
418
+
419
+ // Check if new version available, return latest version or null
420
+ function checkForUpdate() {
421
+ return new Promise((resolve) => {
422
+ if (skipUpdate) {
423
+ resolve(null);
424
+ return;
425
+ }
426
+
427
+ const spinner = createSpinner("Checking for updates...").start();
428
+ let resolved = false;
429
+
430
+ const safetyTimeout = setTimeout(() => {
431
+ if (!resolved) {
432
+ resolved = true;
433
+ spinner.stop();
434
+ resolve(null);
435
+ }
436
+ }, 8000);
437
+
438
+ const done = (version) => {
439
+ if (resolved) return;
440
+ resolved = true;
441
+ clearTimeout(safetyTimeout);
442
+ spinner.stop();
443
+ resolve(version);
444
+ };
445
+
446
+ const req = https.get(`https://registry.npmjs.org/${pkg.name}/latest`, { timeout: 3000 }, (res) => {
447
+ let data = "";
448
+ res.on("data", chunk => data += chunk);
449
+ res.on("end", () => {
450
+ try {
451
+ const latest = JSON.parse(data);
452
+ if (latest.version && compareVersions(latest.version, pkg.version) > 0) {
453
+ done(latest.version);
454
+ } else {
455
+ done(null);
456
+ }
457
+ } catch (e) {
458
+ done(null);
459
+ }
460
+ });
461
+ });
462
+
463
+ req.on("error", () => done(null));
464
+ req.on("timeout", () => { req.destroy(); done(null); });
465
+ });
466
+ }
467
+
468
+ // Open browser
469
+ function openBrowser(url) {
470
+ const platform = process.platform;
471
+ let cmd;
472
+
473
+ if (platform === "darwin") {
474
+ cmd = `open "${url}"`;
475
+ } else if (platform === "win32") {
476
+ cmd = `start "" "${url}"`;
477
+ } else {
478
+ cmd = `xdg-open "${url}"`;
479
+ }
480
+
481
+ exec(cmd, { windowsHide: true }, (err) => {
482
+ if (err) {
483
+ console.log(`Open browser manually: ${url}`);
484
+ }
485
+ });
486
+ }
487
+
488
+ // Find standalone server (bundled in bin/app for published package).
489
+ // Prefer custom-server.js (injects real socket IP) when present.
490
+ const standaloneDir = path.join(__dirname, "app");
491
+ const customServerPath = path.join(standaloneDir, "custom-server.js");
492
+ const serverPath = fs.existsSync(customServerPath)
493
+ ? customServerPath
494
+ : path.join(standaloneDir, "server.js");
495
+
496
+ if (!fs.existsSync(serverPath)) {
497
+ console.error("Error: Standalone build not found.");
498
+ console.error("Please run 'npm run build:cli' first.");
499
+ process.exit(1);
500
+ }
501
+
502
+ // Check for updates FIRST, then start server
503
+ checkForUpdate().then((latestVersion) => {
504
+ killAllAppProcesses(port).then(() => {
505
+ return killProcessOnPort(port);
506
+ }).then(() => {
507
+ startServer(latestVersion);
508
+ });
509
+ });
510
+
511
+ // Show interface selection menu
512
+ async function showInterfaceMenu(latestVersion) {
513
+ const { selectMenu } = require("./src/cli/utils/input");
514
+ const { clearScreen } = require("./src/cli/utils/display");
515
+ const { getEndpoint } = require("./src/cli/utils/endpoint");
516
+
517
+ clearScreen();
518
+
519
+ const displayHost = getDisplayHost();
520
+
521
+ // Detect tunnel/local mode for server URL display
522
+ let serverUrl;
523
+ try {
524
+ const { endpoint, tunnelEnabled } = await getEndpoint(port);
525
+ serverUrl = tunnelEnabled ? endpoint.replace(/\/v1$/, "") : `http://${displayHost}:${port}`;
526
+ } catch (e) {
527
+ serverUrl = `http://${displayHost}:${port}`;
528
+ }
529
+
530
+ const subtitle = `šŸš€ Server: \x1b[32m${serverUrl}\x1b[0m`;
531
+
532
+ const menuItems = [];
533
+
534
+ if (latestVersion) {
535
+ menuItems.push({ label: `Update to v${latestVersion} (current: v${pkg.version})`, icon: "⬆" });
536
+ }
537
+
538
+ menuItems.push(
539
+ { label: "Web UI (Open in Browser)", icon: "🌐" },
540
+ { label: "Terminal UI (Interactive CLI)", icon: "šŸ’»" },
541
+ { label: "Hide to Tray (Background)", icon: "šŸ””" },
542
+ { label: "Exit", icon: "🚪" }
543
+ );
544
+
545
+ const selected = await selectMenu(`Choose Interface (v${pkg.version})`, menuItems, 0, subtitle);
546
+
547
+ const offset = latestVersion ? 1 : 0;
548
+
549
+ if (latestVersion && selected === 0) return "update";
550
+ if (selected === offset) return "web";
551
+ if (selected === offset + 1) return "terminal";
552
+ if (selected === offset + 2) return "hide";
553
+ return "exit";
554
+ }
555
+
556
+ const MAX_RESTARTS = 2;
557
+ const RESTART_RESET_MS = 30000; // Reset counter if alive > 30s
558
+
559
+ function startServer(latestVersion) {
560
+ const displayHost = getDisplayHost();
561
+ const url = `http://${displayHost}:${port}/dashboard`;
562
+ // Surface real network exposure when bound to all interfaces (default 0.0.0.0).
563
+ if (host === DEFAULT_HOST) {
564
+ const lanIp = getLanIp();
565
+ if (lanIp) console.log(`\x1b[33m⚠ Network-exposed: reachable at http://${lanIp}:${port} (bound 0.0.0.0). Use --host 127.0.0.1 for local-only.\x1b[0m`);
566
+ }
567
+
568
+ let restartCount = 0;
569
+ let serverStartTime = Date.now();
570
+
571
+ const CRASH_LOG_LINES = 50;
572
+ let crashLog = [];
573
+
574
+ function spawnServer() {
575
+ serverStartTime = Date.now();
576
+ crashLog = [];
577
+ const child = spawn(RUNTIME, ["--max-old-space-size=6144", serverPath], {
578
+ cwd: standaloneDir,
579
+ stdio: showLog ? "inherit" : ["ignore", "ignore", "pipe"],
580
+ detached: true,
581
+ windowsHide: true,
582
+ env: {
583
+ ...buildEnvWithRuntime(process.env),
584
+ PORT: port.toString(),
585
+ HOSTNAME: host
586
+ }
587
+ });
588
+ if (!showLog && child.stderr) {
589
+ child.stderr.on("data", (data) => {
590
+ const lines = data.toString().split("\n").filter(Boolean);
591
+ crashLog.push(...lines);
592
+ if (crashLog.length > CRASH_LOG_LINES) crashLog = crashLog.slice(-CRASH_LOG_LINES);
593
+ });
594
+ }
595
+ return child;
596
+ }
597
+
598
+ let server = spawnServer();
599
+
600
+ // Cleanup function - force kill server process
601
+ let isCleaningUp = false;
602
+ function cleanup() {
603
+ if (isCleaningUp) return;
604
+ isCleaningUp = true;
605
+ try {
606
+ // Kill tray if running
607
+ try {
608
+ const { killTray } = require("./src/cli/tray/tray");
609
+ killTray();
610
+ } catch (e) { }
611
+ // Kill MIT server (privileged process) via PID file
612
+ killProxyByPidFile();
613
+ // Kill cloudflared/tailscale via PID file (only this app's tunnel)
614
+ killTunnelByPidFile();
615
+ // Kill server process directly
616
+ if (server.pid) {
617
+ process.kill(server.pid, "SIGKILL");
618
+ }
619
+ // Also try to kill process group
620
+ process.kill(-server.pid, "SIGKILL");
621
+ } catch (e) { }
622
+ }
623
+
624
+ // Suppress all errors during shutdown (systray lib throws JSON parse errors)
625
+ let isShuttingDown = false;
626
+ process.on("uncaughtException", (err) => {
627
+ if (isShuttingDown) return;
628
+ console.error("Error:", err.message);
629
+ });
630
+
631
+ // Handle all exit scenarios
632
+ process.on("SIGINT", () => {
633
+ if (isShuttingDown) return;
634
+ isShuttingDown = true;
635
+ console.log("\nExiting...");
636
+ cleanup();
637
+ setTimeout(() => process.exit(0), 100);
638
+ });
639
+ process.on("SIGTERM", () => {
640
+ if (isShuttingDown) return;
641
+ isShuttingDown = true;
642
+ cleanup();
643
+ setTimeout(() => process.exit(0), 100);
644
+ });
645
+ process.on("SIGHUP", () => {
646
+ if (isShuttingDown) return;
647
+ isShuttingDown = true;
648
+ cleanup();
649
+ setTimeout(() => process.exit(0), 100);
650
+ });
651
+
652
+ // Initialize tray icon (runs alongside TUI)
653
+ const initTrayIcon = () => {
654
+ try {
655
+ const { initTray } = require("./src/cli/tray/tray");
656
+ initTray({
657
+ port,
658
+ onQuit: () => {
659
+ isShuttingDown = true;
660
+ console.log("\nšŸ‘‹ Shutting down from tray...");
661
+ cleanup();
662
+ setTimeout(() => process.exit(0), 100);
663
+ },
664
+ onOpenDashboard: () => openBrowser(url)
665
+ });
666
+ } catch (err) {
667
+ // Tray not available - continue without it
668
+ }
669
+ };
670
+
671
+ // Tray-only mode: no TUI, just tray icon
672
+ if (trayMode) {
673
+ // Ignore SIGHUP so macOS terminal close doesn't kill the background tray process
674
+ process.removeAllListeners("SIGHUP");
675
+ process.on("SIGHUP", () => {});
676
+
677
+ console.log(`\nšŸš€ ${pkg.name} v${pkg.version}`);
678
+ console.log(`Server: http://${displayHost}:${port}`);
679
+
680
+ setTimeout(() => {
681
+ initTrayIcon();
682
+ console.log("\nšŸ’” Router is now running in system tray. Close this terminal if you want.");
683
+ console.log(" Right-click tray icon to open dashboard or quit.\n");
684
+ }, 2000);
685
+
686
+ return;
687
+ }
688
+
689
+ // Wait for server to be ready, then show interface menu loop + tray
690
+ setTimeout(async () => {
691
+ // Start tray icon alongside TUI
692
+ initTrayIcon();
693
+
694
+ try {
695
+ while (true) {
696
+ const choice = await showInterfaceMenu(latestVersion);
697
+
698
+ if (choice === "update") {
699
+ isShuttingDown = true;
700
+ const { clearScreen } = require("./src/cli/utils/display");
701
+ clearScreen();
702
+ console.log(`\n⬆ Update v${pkg.version} → v${latestVersion}\n`);
703
+ console.log(`Run this after exit:\n`);
704
+ console.log(` \x1b[33m${INSTALL_CMD_LATEST}\x1b[0m\n`);
705
+ cleanup();
706
+ await killAllAppProcesses(port);
707
+ await killProcessOnPort(port);
708
+ setTimeout(() => process.exit(0), 200);
709
+ return;
710
+ } else if (choice === "web") {
711
+ openBrowser(url);
712
+ // Wait for user to come back
713
+ const { pause } = require("./src/cli/utils/input");
714
+ await pause("\nPress Enter to go back to menu...");
715
+ } else if (choice === "terminal") {
716
+ // Start Terminal UI - it will return when user selects Back
717
+ const { startTerminalUI } = require("./src/cli/terminalUI");
718
+ await startTerminalUI(port);
719
+ // Loop continues, show menu again
720
+ } else if (choice === "hide") {
721
+ const { clearScreen } = require("./src/cli/utils/display");
722
+ clearScreen();
723
+
724
+ // Enable auto startup on OS boot
725
+ try {
726
+ const { enableAutoStart } = require("./src/cli/tray/autostart");
727
+ enableAutoStart(__filename);
728
+ } catch (e) { }
729
+
730
+ if (process.platform === "darwin") {
731
+ // macOS: keep current process alive — spawning a detached child puts
732
+ // it outside the login session so NSStatusItem silently fails.
733
+ process.removeAllListeners("SIGHUP");
734
+ process.on("SIGHUP", () => {});
735
+
736
+ console.log(`\nā³ Switching to tray mode... (icon already visible in menu bar)`);
737
+ console.log(`šŸ”” ExtremeRouter is running in tray (PID: ${process.pid})`);
738
+ console.log(` Server: http://${displayHost}:${port}`);
739
+ console.log(`\nšŸ’” You can close this terminal. Right-click tray icon to quit.\n`);
740
+
741
+ // Tray already init'd at startup — just keep event loop alive.
742
+ return;
743
+ }
744
+
745
+ // Windows/Linux: spawn detached bgProcess (systray works fine in child)
746
+ console.log(`\nā³ Starting background process... (tray icon will appear in ~3s)`);
747
+
748
+ const bgProcess = spawn(process.execPath, [__filename, "--tray", "--skip-update", "-p", port.toString()], {
749
+ detached: true,
750
+ stdio: "ignore",
751
+ windowsHide: true,
752
+ env: { ...process.env }
753
+ });
754
+ bgProcess.unref();
755
+
756
+ console.log(`šŸ”” ExtremeRouter is now running in background (PID: ${bgProcess.pid})`);
757
+ console.log(` Server: http://${displayHost}:${port}`);
758
+ console.log(`\nšŸ’” You can close this terminal. Right-click tray icon to quit.\n`);
759
+
760
+ // cleanup() kills server so bgProcess can claim the port fresh
761
+ cleanup();
762
+ process.exit(0);
763
+ } else if (choice === "exit") {
764
+ isShuttingDown = true;
765
+ console.log("\nExiting...");
766
+ cleanup();
767
+ setTimeout(() => process.exit(0), 100);
768
+ }
769
+ }
770
+ } catch (err) {
771
+ console.error("Error:", err.message);
772
+ cleanup();
773
+ process.exit(1);
774
+ }
775
+ }, 3000);
776
+
777
+ function attachServerEvents() {
778
+ server.on("error", (err) => {
779
+ console.error("Failed to start server:", err.message);
780
+ if (!isShuttingDown) tryRestart();
781
+ else { cleanup(); process.exit(1); }
782
+ });
783
+
784
+ server.on("close", (code) => {
785
+ if (isShuttingDown || code === 0) {
786
+ process.exit(code || 0);
787
+ return;
788
+ }
789
+ tryRestart(code);
790
+ });
791
+ }
792
+
793
+ function tryRestart(code) {
794
+ const aliveMs = Date.now() - serverStartTime;
795
+ // Reset counter if last run was stable
796
+ if (aliveMs >= RESTART_RESET_MS) restartCount = 0;
797
+
798
+ if (restartCount >= MAX_RESTARTS) {
799
+ console.error(`\nāš ļø Server crashed ${MAX_RESTARTS} times. Disabling MIT and restarting...`);
800
+ try {
801
+ const dbPath = path.join(os.homedir(), process.platform === "win32" ? path.join("AppData", "Roaming", "extremerouter", "db.json") : path.join(".extremerouter", "db.json"));
802
+ if (fs.existsSync(dbPath)) {
803
+ const db = JSON.parse(fs.readFileSync(dbPath, "utf-8"));
804
+ if (db.settings) db.settings.mitmEnabled = false;
805
+ fs.writeFileSync(dbPath, JSON.stringify(db, null, 2));
806
+ }
807
+ } catch { /* best effort */ }
808
+ restartCount = 0;
809
+ server = spawnServer();
810
+ attachServerEvents();
811
+ return;
812
+ }
813
+
814
+ restartCount++;
815
+ const delay = Math.min(1000 * restartCount, 10000);
816
+ console.error(`\nāš ļø Server exited (code=${code ?? "unknown"}). Restarting in ${delay / 1000}s... (${restartCount}/${MAX_RESTARTS})`);
817
+ if (crashLog.length) {
818
+ console.error("\n--- Server crash log ---");
819
+ crashLog.forEach(l => console.error(l));
820
+ console.error("--- End crash log ---\n");
821
+ }
822
+
823
+ setTimeout(() => {
824
+ server = spawnServer();
825
+ attachServerEvents();
826
+ }, delay);
827
+ }
828
+
829
+ attachServerEvents();
830
+ }