9router 0.3.53 → 0.3.55

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 (327) hide show
  1. package/app/.next/BUILD_ID +1 -1
  2. package/app/.next/app-path-routes-manifest.json +45 -45
  3. package/app/.next/build-manifest.json +2 -2
  4. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  5. package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  6. package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  7. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  8. package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  9. package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  10. package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  11. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page.js +1 -1
  12. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  13. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  14. package/app/.next/server/app/(dashboard)/dashboard/providers/page.js +1 -1
  15. package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  16. package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  17. package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  18. package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  19. package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  20. package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  21. package/app/.next/server/app/_global-error.html +2 -2
  22. package/app/.next/server/app/_global-error.rsc +1 -1
  23. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  24. package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  25. package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  26. package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  27. package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  28. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  29. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  30. package/app/.next/server/app/_not-found.html +1 -1
  31. package/app/.next/server/app/_not-found.rsc +4 -4
  32. package/app/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
  33. package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  34. package/app/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
  35. package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  36. package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  37. package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  38. package/app/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
  39. package/app/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  40. package/app/.next/server/app/api/cli-tools/antigravity-mitm/alias/route_client-reference-manifest.js +1 -1
  41. package/app/.next/server/app/api/cli-tools/antigravity-mitm/route.js +1 -1
  42. package/app/.next/server/app/api/cli-tools/antigravity-mitm/route_client-reference-manifest.js +1 -1
  43. package/app/.next/server/app/api/cli-tools/claude-settings/route_client-reference-manifest.js +1 -1
  44. package/app/.next/server/app/api/cli-tools/codex-settings/route_client-reference-manifest.js +1 -1
  45. package/app/.next/server/app/api/cli-tools/copilot-settings/route_client-reference-manifest.js +1 -1
  46. package/app/.next/server/app/api/cli-tools/droid-settings/route_client-reference-manifest.js +1 -1
  47. package/app/.next/server/app/api/cli-tools/openclaw-settings/route_client-reference-manifest.js +1 -1
  48. package/app/.next/server/app/api/cli-tools/opencode-settings/route_client-reference-manifest.js +1 -1
  49. package/app/.next/server/app/api/cloud/auth/route_client-reference-manifest.js +1 -1
  50. package/app/.next/server/app/api/cloud/credentials/update/route_client-reference-manifest.js +1 -1
  51. package/app/.next/server/app/api/cloud/model/resolve/route_client-reference-manifest.js +1 -1
  52. package/app/.next/server/app/api/cloud/models/alias/route_client-reference-manifest.js +1 -1
  53. package/app/.next/server/app/api/combos/[id]/route_client-reference-manifest.js +1 -1
  54. package/app/.next/server/app/api/combos/route_client-reference-manifest.js +1 -1
  55. package/app/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
  56. package/app/.next/server/app/api/keys/[id]/route_client-reference-manifest.js +1 -1
  57. package/app/.next/server/app/api/keys/route_client-reference-manifest.js +1 -1
  58. package/app/.next/server/app/api/locale/route_client-reference-manifest.js +1 -1
  59. package/app/.next/server/app/api/models/alias/route_client-reference-manifest.js +1 -1
  60. package/app/.next/server/app/api/models/route.js +1 -1
  61. package/app/.next/server/app/api/models/route_client-reference-manifest.js +1 -1
  62. package/app/.next/server/app/api/models/test/route_client-reference-manifest.js +1 -1
  63. package/app/.next/server/app/api/oauth/[provider]/[action]/route_client-reference-manifest.js +1 -1
  64. package/app/.next/server/app/api/oauth/cursor/auto-import/route.js +1 -1
  65. package/app/.next/server/app/api/oauth/cursor/auto-import/route_client-reference-manifest.js +1 -1
  66. package/app/.next/server/app/api/oauth/cursor/import/route_client-reference-manifest.js +1 -1
  67. package/app/.next/server/app/api/oauth/iflow/cookie/route_client-reference-manifest.js +1 -1
  68. package/app/.next/server/app/api/oauth/kiro/auto-import/route_client-reference-manifest.js +1 -1
  69. package/app/.next/server/app/api/oauth/kiro/import/route_client-reference-manifest.js +1 -1
  70. package/app/.next/server/app/api/oauth/kiro/social-authorize/route_client-reference-manifest.js +1 -1
  71. package/app/.next/server/app/api/oauth/kiro/social-exchange/route_client-reference-manifest.js +1 -1
  72. package/app/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
  73. package/app/.next/server/app/api/provider-nodes/[id]/route_client-reference-manifest.js +1 -1
  74. package/app/.next/server/app/api/provider-nodes/route_client-reference-manifest.js +1 -1
  75. package/app/.next/server/app/api/provider-nodes/validate/route.js +1 -1
  76. package/app/.next/server/app/api/provider-nodes/validate/route_client-reference-manifest.js +1 -1
  77. package/app/.next/server/app/api/providers/[id]/models/route_client-reference-manifest.js +1 -1
  78. package/app/.next/server/app/api/providers/[id]/route_client-reference-manifest.js +1 -1
  79. package/app/.next/server/app/api/providers/[id]/test/route_client-reference-manifest.js +1 -1
  80. package/app/.next/server/app/api/providers/[id]/test-models/route_client-reference-manifest.js +1 -1
  81. package/app/.next/server/app/api/providers/client/route_client-reference-manifest.js +1 -1
  82. package/app/.next/server/app/api/providers/route.js +1 -1
  83. package/app/.next/server/app/api/providers/route_client-reference-manifest.js +1 -1
  84. package/app/.next/server/app/api/providers/test-batch/route_client-reference-manifest.js +1 -1
  85. package/app/.next/server/app/api/providers/validate/route_client-reference-manifest.js +1 -1
  86. package/app/.next/server/app/api/proxy-pools/[id]/route_client-reference-manifest.js +1 -1
  87. package/app/.next/server/app/api/proxy-pools/[id]/test/route_client-reference-manifest.js +1 -1
  88. package/app/.next/server/app/api/proxy-pools/route_client-reference-manifest.js +1 -1
  89. package/app/.next/server/app/api/settings/database/route_client-reference-manifest.js +1 -1
  90. package/app/.next/server/app/api/settings/proxy-test/route_client-reference-manifest.js +1 -1
  91. package/app/.next/server/app/api/settings/require-login/route_client-reference-manifest.js +1 -1
  92. package/app/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  93. package/app/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  94. package/app/.next/server/app/api/tags/route_client-reference-manifest.js +1 -1
  95. package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
  96. package/app/.next/server/app/api/translator/console-logs/route_client-reference-manifest.js +1 -1
  97. package/app/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
  98. package/app/.next/server/app/api/translator/console-logs/stream/route_client-reference-manifest.js +1 -1
  99. package/app/.next/server/app/api/translator/load/route.js.nft.json +1 -1
  100. package/app/.next/server/app/api/translator/load/route_client-reference-manifest.js +1 -1
  101. package/app/.next/server/app/api/translator/save/route.js.nft.json +1 -1
  102. package/app/.next/server/app/api/translator/save/route_client-reference-manifest.js +1 -1
  103. package/app/.next/server/app/api/translator/send/route_client-reference-manifest.js +1 -1
  104. package/app/.next/server/app/api/translator/translate/route_client-reference-manifest.js +1 -1
  105. package/app/.next/server/app/api/tunnel/disable/route.js +1 -1
  106. package/app/.next/server/app/api/tunnel/disable/route_client-reference-manifest.js +1 -1
  107. package/app/.next/server/app/api/tunnel/enable/route.js +1 -1
  108. package/app/.next/server/app/api/tunnel/enable/route_client-reference-manifest.js +1 -1
  109. package/app/.next/server/app/api/tunnel/status/route.js +1 -1
  110. package/app/.next/server/app/api/tunnel/status/route_client-reference-manifest.js +1 -1
  111. package/app/.next/server/app/api/usage/[connectionId]/route_client-reference-manifest.js +1 -1
  112. package/app/.next/server/app/api/usage/chart/route_client-reference-manifest.js +1 -1
  113. package/app/.next/server/app/api/usage/history/route_client-reference-manifest.js +1 -1
  114. package/app/.next/server/app/api/usage/providers/route_client-reference-manifest.js +1 -1
  115. package/app/.next/server/app/api/usage/request-details/route_client-reference-manifest.js +1 -1
  116. package/app/.next/server/app/api/usage/request-logs/route_client-reference-manifest.js +1 -1
  117. package/app/.next/server/app/api/usage/stats/route_client-reference-manifest.js +1 -1
  118. package/app/.next/server/app/api/usage/stream/route_client-reference-manifest.js +1 -1
  119. package/app/.next/server/app/api/v1/api/chat/route_client-reference-manifest.js +1 -1
  120. package/app/.next/server/app/api/v1/chat/completions/route_client-reference-manifest.js +1 -1
  121. package/app/.next/server/app/api/v1/embeddings/route_client-reference-manifest.js +1 -1
  122. package/app/.next/server/app/api/v1/messages/count_tokens/route_client-reference-manifest.js +1 -1
  123. package/app/.next/server/app/api/v1/messages/route_client-reference-manifest.js +1 -1
  124. package/app/.next/server/app/api/v1/models/route_client-reference-manifest.js +1 -1
  125. package/app/.next/server/app/api/v1/responses/route_client-reference-manifest.js +1 -1
  126. package/app/.next/server/app/api/v1/route_client-reference-manifest.js +1 -1
  127. package/app/.next/server/app/api/v1beta/models/[...path]/route_client-reference-manifest.js +1 -1
  128. package/app/.next/server/app/api/v1beta/models/route_client-reference-manifest.js +1 -1
  129. package/app/.next/server/app/api/version/route.js +1 -1
  130. package/app/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
  131. package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
  132. package/app/.next/server/app/callback.html +1 -1
  133. package/app/.next/server/app/callback.rsc +4 -4
  134. package/app/.next/server/app/callback.segments/_full.segment.rsc +4 -4
  135. package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
  136. package/app/.next/server/app/callback.segments/_index.segment.rsc +4 -4
  137. package/app/.next/server/app/callback.segments/_tree.segment.rsc +2 -2
  138. package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  139. package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
  140. package/app/.next/server/app/dashboard/cli-tools.html +1 -1
  141. package/app/.next/server/app/dashboard/cli-tools.rsc +6 -6
  142. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  143. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  144. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  145. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  146. package/app/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +6 -6
  147. package/app/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  148. package/app/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +4 -4
  149. package/app/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
  150. package/app/.next/server/app/dashboard/combos.html +1 -1
  151. package/app/.next/server/app/dashboard/combos.rsc +6 -6
  152. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  153. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  154. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  155. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  156. package/app/.next/server/app/dashboard/combos.segments/_full.segment.rsc +6 -6
  157. package/app/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  158. package/app/.next/server/app/dashboard/combos.segments/_index.segment.rsc +4 -4
  159. package/app/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
  160. package/app/.next/server/app/dashboard/endpoint.html +1 -1
  161. package/app/.next/server/app/dashboard/endpoint.rsc +6 -6
  162. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  163. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  164. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  165. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  166. package/app/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +6 -6
  167. package/app/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  168. package/app/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +4 -4
  169. package/app/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
  170. package/app/.next/server/app/dashboard/mitm.html +1 -1
  171. package/app/.next/server/app/dashboard/mitm.rsc +6 -6
  172. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  173. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  174. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  175. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  176. package/app/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +6 -6
  177. package/app/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  178. package/app/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +4 -4
  179. package/app/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
  180. package/app/.next/server/app/dashboard/profile.html +1 -1
  181. package/app/.next/server/app/dashboard/profile.rsc +6 -6
  182. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
  183. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  184. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  185. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  186. package/app/.next/server/app/dashboard/profile.segments/_full.segment.rsc +6 -6
  187. package/app/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  188. package/app/.next/server/app/dashboard/profile.segments/_index.segment.rsc +4 -4
  189. package/app/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
  190. package/app/.next/server/app/dashboard/providers/new.html +1 -1
  191. package/app/.next/server/app/dashboard/providers/new.rsc +6 -6
  192. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  193. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  194. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  195. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  196. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  197. package/app/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +6 -6
  198. package/app/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  199. package/app/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +4 -4
  200. package/app/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
  201. package/app/.next/server/app/dashboard/providers.html +1 -1
  202. package/app/.next/server/app/dashboard/providers.rsc +6 -6
  203. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  204. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  205. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  206. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  207. package/app/.next/server/app/dashboard/providers.segments/_full.segment.rsc +6 -6
  208. package/app/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  209. package/app/.next/server/app/dashboard/providers.segments/_index.segment.rsc +4 -4
  210. package/app/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
  211. package/app/.next/server/app/dashboard/proxy-pools.html +1 -1
  212. package/app/.next/server/app/dashboard/proxy-pools.rsc +6 -6
  213. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  214. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  215. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  216. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  217. package/app/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +6 -6
  218. package/app/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  219. package/app/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +4 -4
  220. package/app/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
  221. package/app/.next/server/app/dashboard/quota.html +2 -2
  222. package/app/.next/server/app/dashboard/quota.rsc +5 -5
  223. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +1 -1
  224. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  225. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  226. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  227. package/app/.next/server/app/dashboard/quota.segments/_full.segment.rsc +5 -5
  228. package/app/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  229. package/app/.next/server/app/dashboard/quota.segments/_index.segment.rsc +4 -4
  230. package/app/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
  231. package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  232. package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
  233. package/app/.next/server/app/dashboard/settings/pricing.rsc +4 -4
  234. package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +4 -4
  235. package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  236. package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +4 -4
  237. package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
  238. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  239. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  240. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  241. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  242. package/app/.next/server/app/dashboard/translator.html +1 -1
  243. package/app/.next/server/app/dashboard/translator.rsc +6 -6
  244. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  245. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  246. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  247. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  248. package/app/.next/server/app/dashboard/translator.segments/_full.segment.rsc +6 -6
  249. package/app/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  250. package/app/.next/server/app/dashboard/translator.segments/_index.segment.rsc +4 -4
  251. package/app/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
  252. package/app/.next/server/app/dashboard/usage.html +1 -1
  253. package/app/.next/server/app/dashboard/usage.rsc +6 -6
  254. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  255. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  256. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  257. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  258. package/app/.next/server/app/dashboard/usage.segments/_full.segment.rsc +6 -6
  259. package/app/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  260. package/app/.next/server/app/dashboard/usage.segments/_index.segment.rsc +4 -4
  261. package/app/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
  262. package/app/.next/server/app/dashboard.html +1 -1
  263. package/app/.next/server/app/dashboard.rsc +6 -6
  264. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  265. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  266. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  267. package/app/.next/server/app/dashboard.segments/_full.segment.rsc +6 -6
  268. package/app/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
  269. package/app/.next/server/app/dashboard.segments/_index.segment.rsc +4 -4
  270. package/app/.next/server/app/dashboard.segments/_tree.segment.rsc +2 -2
  271. package/app/.next/server/app/index.html +1 -1
  272. package/app/.next/server/app/index.rsc +4 -4
  273. package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  274. package/app/.next/server/app/index.segments/_full.segment.rsc +4 -4
  275. package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
  276. package/app/.next/server/app/index.segments/_index.segment.rsc +4 -4
  277. package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  278. package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
  279. package/app/.next/server/app/landing.html +1 -1
  280. package/app/.next/server/app/landing.rsc +4 -4
  281. package/app/.next/server/app/landing.segments/_full.segment.rsc +4 -4
  282. package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
  283. package/app/.next/server/app/landing.segments/_index.segment.rsc +4 -4
  284. package/app/.next/server/app/landing.segments/_tree.segment.rsc +2 -2
  285. package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  286. package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
  287. package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
  288. package/app/.next/server/app/login.html +1 -1
  289. package/app/.next/server/app/login.rsc +5 -5
  290. package/app/.next/server/app/login.segments/_full.segment.rsc +5 -5
  291. package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
  292. package/app/.next/server/app/login.segments/_index.segment.rsc +4 -4
  293. package/app/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  294. package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  295. package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
  296. package/app/.next/server/app/manifest.webmanifest/route.js.nft.json +1 -1
  297. package/app/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
  298. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  299. package/app/.next/server/app-paths-manifest.json +45 -45
  300. package/app/.next/server/chunks/1114.js +1 -1
  301. package/app/.next/server/chunks/1424.js +1 -1
  302. package/app/.next/server/chunks/318.js +1 -1
  303. package/app/.next/server/chunks/6182.js +4 -17
  304. package/app/.next/server/chunks/649.js +1 -1
  305. package/app/.next/server/chunks/9201.js +1 -1
  306. package/app/.next/server/pages/404.html +1 -1
  307. package/app/.next/server/pages/500.html +2 -2
  308. package/app/.next/server/server-reference-manifest.js +1 -1
  309. package/app/.next/server/server-reference-manifest.json +1 -1
  310. package/app/.next/static/chunks/{5497-2f4b5d7837ad4dc8.js → 5497-9933573cfe960e0c.js} +1 -1
  311. package/app/.next/static/chunks/{9242-3fb6423adcc6e277.js → 9242-3e0fdad972d9b35d.js} +2 -2
  312. package/app/.next/static/chunks/app/(dashboard)/dashboard/providers/[id]/{page-4ebc425afc0a221a.js → page-5e7e72628fe63cec.js} +1 -1
  313. package/app/.next/static/chunks/app/(dashboard)/dashboard/providers/page-bf901cec2b7f0ea0.js +1 -0
  314. package/app/.next/static/chunks/app/{layout-d66315546ced1415.js → layout-08e56eacc7acf9e1.js} +1 -1
  315. package/app/.next/static/css/{0c4f3a92a0a64981.css → 4016074f63f34af9.css} +1 -1
  316. package/app/package.json +1 -1
  317. package/app/src/mitm/cert/install.js +14 -14
  318. package/app/src/mitm/cert/rootCA.js +22 -2
  319. package/app/src/mitm/dns/dnsConfig.js +13 -66
  320. package/app/src/mitm/logger.js +8 -0
  321. package/app/src/mitm/manager.js +98 -78
  322. package/app/src/mitm/server.js +28 -17
  323. package/cli.js +6 -8
  324. package/package.json +1 -1
  325. package/app/.next/static/chunks/app/(dashboard)/dashboard/providers/page-3143d3dbb2dc3422.js +0 -1
  326. /package/app/.next/static/{2ABcpZEvM8MzFMmHIRKq0 → lSUZX6G8rzoxhxgvfuJ7I}/_buildManifest.js +0 -0
  327. /package/app/.next/static/{2ABcpZEvM8MzFMmHIRKq0 → lSUZX6G8rzoxhxgvfuJ7I}/_ssgManifest.js +0 -0
@@ -2,6 +2,7 @@ const { exec, spawn } = require("child_process");
2
2
  const fs = require("fs");
3
3
  const path = require("path");
4
4
  const os = require("os");
5
+ const { log, err } = require("../logger");
5
6
 
6
7
  // Per-tool DNS hosts mapping
7
8
  const TOOL_HOSTS = {
@@ -131,7 +132,7 @@ async function addDNSEntry(tool, sudoPassword) {
131
132
 
132
133
  const entriesToAdd = hosts.filter(h => !checkDNSEntry(h));
133
134
  if (entriesToAdd.length === 0) {
134
- console.log(`DNS entries for ${tool} already exist`);
135
+ log(`🌐 DNS ${tool}: already active`);
135
136
  return;
136
137
  }
137
138
 
@@ -139,43 +140,15 @@ async function addDNSEntry(tool, sudoPassword) {
139
140
 
140
141
  try {
141
142
  if (IS_WIN) {
142
- const hostsPath = HOSTS_FILE.replace(/'/g, "''");
143
-
144
- // Build PowerShell script with proper error handling
145
- const scriptLines = [];
146
- scriptLines.push(`$ErrorActionPreference = 'Stop'`);
147
- scriptLines.push(`$hostsPath = '${hostsPath}'`);
148
- scriptLines.push(`try {`);
149
- scriptLines.push(` $hostsContent = Get-Content -Path $hostsPath -Raw -ErrorAction SilentlyContinue`);
150
- scriptLines.push(` if (-not $hostsContent) { $hostsContent = '' }`);
151
-
152
- for (const host of entriesToAdd) {
153
- // Escape special regex chars in hostname
154
- const escapedHost = host.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
155
- scriptLines.push(` if ($hostsContent -notmatch '${escapedHost}') {`);
156
- scriptLines.push(` Add-Content -Path $hostsPath -Value '127.0.0.1 ${host}' -Encoding UTF8 -ErrorAction Stop`);
157
- scriptLines.push(` Write-Host "Added DNS entry: ${host}"`);
158
- scriptLines.push(` } else {`);
159
- scriptLines.push(` Write-Host "DNS entry already exists: ${host}"`);
160
- scriptLines.push(` }`);
161
- }
162
-
163
- scriptLines.push(` ipconfig /flushdns | Out-Null`);
164
- scriptLines.push(`} catch {`);
165
- scriptLines.push(` Write-Error "Failed to add DNS: $_"`);
166
- scriptLines.push(` exit 1`);
167
- scriptLines.push(`}`);
168
-
169
- const psScript = scriptLines.join("\n");
170
- const tmpPs1 = path.join(os.tmpdir(), `mitm_dns_add_${Date.now()}.ps1`);
171
- fs.writeFileSync(tmpPs1, psScript, "utf8");
172
-
173
- await executeElevatedPowerShell(tmpPs1, 30000);
143
+ // Process already has admin rights — edit hosts file directly
144
+ const toAppend = entriesToAdd.map(h => `127.0.0.1 ${h}`).join("\r\n") + "\r\n";
145
+ fs.appendFileSync(HOSTS_FILE, toAppend, "utf8");
146
+ require("child_process").execSync("ipconfig /flushdns", { windowsHide: true });
174
147
  } else {
175
148
  await execWithPassword(`echo "${entries}" >> ${HOSTS_FILE}`, sudoPassword);
176
149
  await flushDNS(sudoPassword);
177
150
  }
178
- console.log(`✅ Added DNS entries for ${tool}: ${entriesToAdd.join(", ")}`);
151
+ log(`🌐 DNS ${tool}: ✅ added ${entriesToAdd.join(", ")}`);
179
152
  } catch (error) {
180
153
  const msg = error.message?.includes("incorrect password") ? "Wrong sudo password" : "Failed to add DNS entry";
181
154
  throw new Error(msg);
@@ -191,43 +164,17 @@ async function removeDNSEntry(tool, sudoPassword) {
191
164
 
192
165
  const entriesToRemove = hosts.filter(h => checkDNSEntry(h));
193
166
  if (entriesToRemove.length === 0) {
194
- console.log(`DNS entries for ${tool} do not exist`);
167
+ log(`🌐 DNS ${tool}: already inactive`);
195
168
  return;
196
169
  }
197
170
 
198
171
  try {
199
172
  if (IS_WIN) {
173
+ // Process already has admin rights — edit hosts file directly
200
174
  const content = fs.readFileSync(HOSTS_FILE, "utf8");
201
175
  const filtered = content.split(/\r?\n/).filter(l => !entriesToRemove.some(h => l.includes(h))).join("\r\n");
202
- const tmpFile = path.join(os.tmpdir(), `hosts_filtered_${Date.now()}.tmp`);
203
- fs.writeFileSync(tmpFile, filtered, "utf8");
204
-
205
- const tmpEsc = tmpFile.replace(/'/g, "''");
206
- const hostsEsc = HOSTS_FILE.replace(/'/g, "''");
207
-
208
- // Build PowerShell script with proper error handling
209
- const scriptLines = [];
210
- scriptLines.push(`$ErrorActionPreference = 'Stop'`);
211
- scriptLines.push(`try {`);
212
- scriptLines.push(` Copy-Item -Path '${tmpEsc}' -Destination '${hostsEsc}' -Force -ErrorAction Stop`);
213
- scriptLines.push(` Write-Host "Hosts file updated successfully"`);
214
- scriptLines.push(` ipconfig /flushdns | Out-Null`);
215
- scriptLines.push(` Write-Host "DNS cache flushed"`);
216
- scriptLines.push(` Remove-Item '${tmpEsc}' -ErrorAction SilentlyContinue`);
217
- scriptLines.push(`} catch {`);
218
- scriptLines.push(` Write-Error "Failed to remove DNS: $_"`);
219
- scriptLines.push(` Remove-Item '${tmpEsc}' -ErrorAction SilentlyContinue`);
220
- scriptLines.push(` exit 1`);
221
- scriptLines.push(`}`);
222
-
223
- const psScript = scriptLines.join("\n");
224
- const tmpPs1 = path.join(os.tmpdir(), `mitm_dns_remove_${Date.now()}.ps1`);
225
- fs.writeFileSync(tmpPs1, psScript, "utf8");
226
-
227
- await executeElevatedPowerShell(tmpPs1, 30000);
228
-
229
- // Cleanup temp file if still exists
230
- try { fs.unlinkSync(tmpFile); } catch { /* ignore */ }
176
+ fs.writeFileSync(HOSTS_FILE, filtered, "utf8");
177
+ require("child_process").execSync("ipconfig /flushdns", { windowsHide: true });
231
178
  } else {
232
179
  for (const host of entriesToRemove) {
233
180
  const sedCmd = IS_MAC
@@ -237,7 +184,7 @@ async function removeDNSEntry(tool, sudoPassword) {
237
184
  }
238
185
  await flushDNS(sudoPassword);
239
186
  }
240
- console.log(`✅ Removed DNS entries for ${tool}: ${entriesToRemove.join(", ")}`);
187
+ log(`🌐 DNS ${tool}: ✅ removed ${entriesToRemove.join(", ")}`);
241
188
  } catch (error) {
242
189
  const msg = error.message?.includes("incorrect password") ? "Wrong sudo password" : "Failed to remove DNS entry";
243
190
  throw new Error(msg);
@@ -252,7 +199,7 @@ async function removeAllDNSEntries(sudoPassword) {
252
199
  try {
253
200
  await removeDNSEntry(tool, sudoPassword);
254
201
  } catch (e) {
255
- console.log(`[MITM] Warning: failed to remove DNS for ${tool}: ${e.message}`);
202
+ err(`DNS ${tool}: failed to remove ${e.message}`);
256
203
  }
257
204
  }
258
205
  }
@@ -0,0 +1,8 @@
1
+ function time() {
2
+ return new Date().toLocaleTimeString("en-US", { hour12: false });
3
+ }
4
+
5
+ const log = (msg) => console.log(`[${time()}] [MITM] ${msg}`);
6
+ const err = (msg) => console.error(`[${time()}] ❌ [MITM] ${msg}`);
7
+
8
+ module.exports = { log, err };
@@ -5,12 +5,14 @@ const os = require("os");
5
5
  const net = require("net");
6
6
  const https = require("https");
7
7
  const crypto = require("crypto");
8
- const { addDNSEntry, removeDNSEntry, removeAllDNSEntries, checkAllDNSStatus, executeElevatedPowerShell, TOOL_HOSTS } = require("./dns/dnsConfig");
8
+ const { addDNSEntry, removeDNSEntry, removeAllDNSEntries, checkAllDNSStatus, TOOL_HOSTS } = require("./dns/dnsConfig");
9
9
 
10
10
  const IS_WIN = process.platform === "win32";
11
11
  const { generateCert } = require("./cert/generate");
12
- const { installCert } = require("./cert/install");
12
+ const { installCert, uninstallCert } = require("./cert/install");
13
+ const { isCertExpired } = require("./cert/rootCA");
13
14
  const { MITM_DIR } = require("./paths");
15
+ const { log, err } = require("./logger");
14
16
 
15
17
  const MITM_PORT = 443;
16
18
  const MITM_WIN_NODE_PORT = 8443;
@@ -80,7 +82,7 @@ function isProcessAlive(pid) {
80
82
  function killProcess(pid, force = false, sudoPassword = null) {
81
83
  if (IS_WIN) {
82
84
  const flag = force ? "/F " : "";
83
- exec(`taskkill ${flag}/PID ${pid}`, () => { });
85
+ exec(`taskkill ${flag}/PID ${pid}`, { windowsHide: true }, () => { });
84
86
  } else {
85
87
  const sig = force ? "SIGKILL" : "SIGTERM";
86
88
  const cmd = `pkill -${sig} -P ${pid} 2>/dev/null; kill -${sig} ${pid} 2>/dev/null`;
@@ -140,7 +142,7 @@ async function saveMitmSettings(enabled, password) {
140
142
  if (password) updates.mitmSudoEncrypted = encryptPassword(password);
141
143
  await _updateSettings(updates);
142
144
  } catch (e) {
143
- console.log("[MITM] Failed to save settings:", e.message);
145
+ err(`Failed to save settings: ${e.message}`);
144
146
  }
145
147
  }
146
148
 
@@ -277,8 +279,10 @@ async function getMitmStatus() {
277
279
  const dnsStatus = checkAllDNSStatus();
278
280
  const rootCACertPath = path.join(MITM_DIR, "rootCA.crt");
279
281
  const certExists = fs.existsSync(rootCACertPath);
282
+ const { checkCertInstalled } = require("./cert/install");
283
+ const certTrusted = certExists ? await checkCertInstalled(rootCACertPath) : false;
280
284
 
281
- return { running, pid, certExists, dnsStatus };
285
+ return { running, pid, certExists, certTrusted, dnsStatus };
282
286
  }
283
287
 
284
288
  async function scheduleMitmRestart(apiKey) {
@@ -288,7 +292,7 @@ async function scheduleMitmRestart(apiKey) {
288
292
  if (aliveMs >= MITM_RESTART_RESET_MS) mitmRestartCount = 0;
289
293
 
290
294
  if (mitmRestartCount >= MITM_MAX_RESTARTS) {
291
- console.error("[MITM] Max restart attempts reached. Giving up.");
295
+ err("Max restart attempts reached. Giving up.");
292
296
  return;
293
297
  }
294
298
 
@@ -297,28 +301,28 @@ async function scheduleMitmRestart(apiKey) {
297
301
  mitmRestartCount++;
298
302
  mitmIsRestarting = true;
299
303
 
300
- console.log(`[MITM] Restarting in ${delay / 1000}s... (${mitmRestartCount}/${MITM_MAX_RESTARTS})`);
304
+ log(`Restarting in ${delay / 1000}s... (${mitmRestartCount}/${MITM_MAX_RESTARTS})`);
301
305
  await new Promise((r) => setTimeout(r, delay));
302
306
 
303
307
  try {
304
308
  const settings = _getSettings ? await _getSettings() : null;
305
309
  if (settings && !settings.mitmEnabled) {
306
- console.log("[MITM] MITM disabled, skipping restart");
310
+ log("MITM disabled, skipping restart");
307
311
  mitmIsRestarting = false;
308
312
  return;
309
313
  }
310
314
  const password = getCachedPassword() || await loadEncryptedPassword();
311
315
  if (!password && !IS_WIN) {
312
- console.error("[MITM] No cached password, cannot auto-restart");
316
+ err("No cached password, cannot auto-restart");
313
317
  mitmIsRestarting = false;
314
318
  return;
315
319
  }
316
320
  await startServer(apiKey, password);
317
- console.log("[MITM] Restarted successfully");
321
+ log("🔄 Restarted successfully");
318
322
  mitmRestartCount = 0;
319
323
  mitmIsRestarting = false;
320
- } catch (err) {
321
- console.error(`[MITM] Restart attempt ${mitmRestartCount}/${MITM_MAX_RESTARTS} failed:`, err.message);
324
+ } catch (e) {
325
+ err(`Restart attempt ${mitmRestartCount}/${MITM_MAX_RESTARTS} failed: ${e.message}`);
322
326
  mitmIsRestarting = false;
323
327
  // Schedule next retry
324
328
  scheduleMitmRestart(apiKey);
@@ -335,7 +339,7 @@ async function startServer(apiKey, sudoPassword) {
335
339
  const savedPid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
336
340
  if (savedPid && isProcessAlive(savedPid)) {
337
341
  serverPid = savedPid;
338
- console.log(`[MITM] Reusing existing process PID ${savedPid}`);
342
+ log(`♻️ Reusing existing process (PID: ${savedPid})`);
339
343
  await saveMitmSettings(true, sudoPassword);
340
344
  if (sudoPassword) setCachedPassword(sudoPassword);
341
345
  return { running: true, pid: savedPid };
@@ -357,7 +361,7 @@ async function startServer(apiKey, sudoPassword) {
357
361
  if (portStatus === "in-use" || portStatus === "no-permission") {
358
362
  const owner = await getPort443Owner(sudoPassword);
359
363
  if (owner && owner.name === "node") {
360
- console.log(`[MITM] Killing orphan node process on port 443 (PID ${owner.pid})...`);
364
+ log(`Killing orphan node process on port 443 (PID ${owner.pid})...`);
361
365
  try {
362
366
  const { execWithPassword } = require("./dns/dnsConfig");
363
367
  await execWithPassword(`kill -9 ${owner.pid}`, sudoPassword);
@@ -372,12 +376,19 @@ async function startServer(apiKey, sudoPassword) {
372
376
  }
373
377
  }
374
378
 
375
- // Step 1: Auto-migration - Generate Root CA if not exists
379
+ // Step 1: Generate Root CA if missing or expired
376
380
  const rootCACertPath = path.join(MITM_DIR, "rootCA.crt");
377
381
  const rootCAKeyPath = path.join(MITM_DIR, "rootCA.key");
378
-
379
- if (!fs.existsSync(rootCACertPath) || !fs.existsSync(rootCAKeyPath)) {
380
- console.log("[MITM] Generating Root CA certificate (first time or migration)...");
382
+ const certExists = fs.existsSync(rootCACertPath) && fs.existsSync(rootCAKeyPath);
383
+
384
+ if (!certExists || isCertExpired(rootCACertPath)) {
385
+ if (certExists) {
386
+ // Uninstall expired cert from system store before regenerating
387
+ log("🔐 Cert expired — uninstalling old cert...");
388
+ const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
389
+ try { await uninstallCert(password, rootCACertPath); } catch { /* best effort */ }
390
+ }
391
+ log("🔐 Generating Root CA...");
381
392
  await generateCert();
382
393
  }
383
394
 
@@ -385,35 +396,42 @@ async function startServer(apiKey, sudoPassword) {
385
396
  const { checkCertInstalled } = require("./cert/install");
386
397
  const rootCATrusted = await checkCertInstalled(rootCACertPath);
387
398
  if (!rootCATrusted) {
388
- console.log("[MITM] Installing Root CA to system trust store...");
389
- // Use provided password or cached/stored password
399
+ log("🔐 Cert: not trusted installing...");
390
400
  const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
391
401
  if (!password && !IS_WIN) {
392
402
  throw new Error("Sudo password required to install Root CA certificate");
393
403
  }
394
- await installCert(password, rootCACertPath);
395
- console.log("✅ Root CA installed successfully");
404
+ try {
405
+ await installCert(password, rootCACertPath);
406
+ log("🔐 Cert: ✅ trusted");
407
+ } catch (e) {
408
+ throw new Error(`Failed to trust certificate: ${e.message}`);
409
+ }
410
+ } else {
411
+ log("🔐 Cert: already trusted ✅");
396
412
  }
397
413
 
398
414
  // Step 2: Spawn server (Root CA already installed in Step 1.5)
415
+ log("🚀 Starting server...");
399
416
  if (IS_WIN) {
400
- const psSQ = (s) => s.replace(/'/g, "''");
401
- const nodePs = psSQ(process.execPath);
402
- const serverPs = psSQ(SERVER_PATH);
403
-
404
- const psScript = [
405
- `$ErrorActionPreference = 'Stop'`,
406
- `$conn = Get-NetTCPConnection -LocalPort 443 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1`,
407
- `if ($conn -and $conn.OwningProcess -gt 4) { Stop-Process -Id $conn.OwningProcess -Force -ErrorAction SilentlyContinue }`,
408
- `Start-Sleep -Milliseconds 500`,
409
- `$nodeCmd = 'set ROUTER_API_KEY=${psSQ(apiKey)}&& set NODE_ENV=production&& "${nodePs}" "${serverPs}"'`,
410
- `Start-Process cmd -ArgumentList '/c',$nodeCmd -WindowStyle Hidden`,
411
- `Start-Sleep -Milliseconds 500`,
412
- ].join("\n");
413
-
414
- const tmpPs1 = path.join(os.tmpdir(), `mitm_start_${Date.now()}.ps1`);
415
- fs.writeFileSync(tmpPs1, psScript, "utf8");
416
- await executeElevatedPowerShell(tmpPs1, 90000);
417
+ // Kill any process using port 443 before spawning
418
+ try {
419
+ const psKill = `$c = Get-NetTCPConnection -LocalPort 443 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1; if ($c -and $c.OwningProcess -gt 4) { Stop-Process -Id $c.OwningProcess -Force -ErrorAction SilentlyContinue }`;
420
+ execSync(`powershell -NonInteractive -WindowStyle Hidden -Command "${psKill}"`, { windowsHide: true });
421
+ await new Promise(r => setTimeout(r, 500));
422
+ } catch { /* best effort */ }
423
+
424
+ // Spawn directly process already has admin rights
425
+ serverProcess = spawn(
426
+ process.execPath,
427
+ [SERVER_PATH],
428
+ {
429
+ detached: false,
430
+ windowsHide: true,
431
+ stdio: ["ignore", "pipe", "pipe"],
432
+ env: { ...process.env, ROUTER_API_KEY: apiKey, NODE_ENV: "production" },
433
+ }
434
+ );
417
435
 
418
436
  if (_updateSettings) await _updateSettings({ mitmCertInstalled: true }).catch(() => { });
419
437
  } else {
@@ -427,26 +445,28 @@ async function startServer(apiKey, sudoPassword) {
427
445
  serverProcess.stdin.end();
428
446
  }
429
447
 
430
- if (!IS_WIN && serverProcess) {
448
+ if (serverProcess) {
431
449
  serverPid = serverProcess.pid;
432
450
  fs.writeFileSync(PID_FILE, String(serverPid));
433
451
  mitmLastStartTime = Date.now();
434
452
  }
435
453
 
436
454
  let startError = null;
437
- if (!IS_WIN) {
455
+ if (serverProcess) {
438
456
  serverProcess.stdout.on("data", (data) => {
439
- console.log(`[MITM Server] ${data.toString().trim()}`);
457
+ // server.js already formats its own logs — print as-is
458
+ process.stdout.write(data);
440
459
  });
441
460
  serverProcess.stderr.on("data", (data) => {
442
461
  const msg = data.toString().trim();
443
- if (msg && !msg.includes("Password:") && !msg.includes("password for")) {
444
- console.error(`[MITM Server Error] ${msg}`);
462
+ // Mac/Linux: filter sudo password prompt noise
463
+ if (msg && (IS_WIN || (!msg.includes("Password:") && !msg.includes("password for")))) {
464
+ err(msg);
445
465
  startError = msg;
446
466
  }
447
467
  });
448
468
  serverProcess.on("exit", (code) => {
449
- console.log(`MITM server exited with code ${code}`);
469
+ log(`Server exited (code: ${code})`);
450
470
  serverProcess = null;
451
471
  serverPid = null;
452
472
  try { fs.unlinkSync(PID_FILE); } catch { /* ignore */ }
@@ -455,19 +475,23 @@ async function startServer(apiKey, sudoPassword) {
455
475
  });
456
476
  }
457
477
 
458
- const health = await pollMitmHealth(IS_WIN ? 15000 : 8000, MITM_PORT);
478
+ const health = await pollMitmHealth(8000, MITM_PORT);
459
479
  if (!health) {
460
- if (IS_WIN) serverProcess = null;
480
+ if (serverProcess && !serverProcess.killed) { try { serverProcess.kill(); } catch { /* ignore */ } serverProcess = null; }
461
481
  const processUsing443 = getProcessUsingPort443();
462
482
  const portInfo = processUsing443 ? ` Port 443 already in use by ${processUsing443}.` : "";
463
483
  const reason = startError || `Check sudo password or port 443 access.${portInfo}`;
464
484
  throw new Error(`MITM server failed to start. ${reason}`);
465
485
  }
466
486
 
467
- if (IS_WIN && _updateSettings) await _updateSettings({ mitmCertInstalled: true }).catch(() => { });
468
- if (IS_WIN && health.pid) {
469
- serverPid = health.pid;
470
- fs.writeFileSync(PID_FILE, String(serverPid));
487
+ if (_updateSettings) await _updateSettings({ mitmCertInstalled: true }).catch(() => { });
488
+
489
+ log(`✅ Server healthy (PID: ${serverPid || health.pid})`);
490
+
491
+ // Log DNS status per tool
492
+ const dnsStatus = checkAllDNSStatus();
493
+ for (const [tool, active] of Object.entries(dnsStatus)) {
494
+ log(`🌐 DNS ${tool}: ${active ? "✅ active" : "❌ inactive"}`);
471
495
  }
472
496
 
473
497
  await saveMitmSettings(true, sudoPassword);
@@ -483,7 +507,7 @@ async function stopServer(sudoPassword) {
483
507
  // Prevent auto-restart from triggering on intentional stop
484
508
  mitmIsRestarting = true;
485
509
  mitmRestartCount = 0;
486
- console.log("[MITM] Stopping server...");
510
+ log(" Stopping server...");
487
511
 
488
512
  // Kill server process
489
513
  const proc = serverProcess;
@@ -492,7 +516,7 @@ async function stopServer(sudoPassword) {
492
516
  : (() => { try { return parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10); } catch { return null; } })();
493
517
 
494
518
  if (pidToKill && isProcessAlive(pidToKill)) {
495
- console.log(`Killing MITM server (PID: ${pidToKill})...`);
519
+ log(`Killing server (PID: ${pidToKill})...`);
496
520
  killProcess(pidToKill, false, sudoPassword);
497
521
  await new Promise(r => setTimeout(r, 1000));
498
522
  if (isProcessAlive(pidToKill)) killProcess(pidToKill, true, sudoPassword);
@@ -501,33 +525,15 @@ async function stopServer(sudoPassword) {
501
525
  serverPid = null;
502
526
 
503
527
  if (IS_WIN) {
504
- // Single elevated script: clean DNS + flush 1 UAC prompt only
528
+ // Process already has admin rightsedit hosts file directly
505
529
  const hostsFile = path.join(process.env.SystemRoot || "C:\\Windows", "System32", "drivers", "etc", "hosts");
506
- const psSQ = (s) => s.replace(/'/g, "''");
507
530
  const allHosts = Object.values(TOOL_HOSTS).flat();
508
-
509
- let hostsContent = "";
510
- try { hostsContent = fs.readFileSync(hostsFile, "utf8"); } catch { /* ignore */ }
511
- const filtered = hostsContent.split(/\r?\n/)
512
- .filter(l => !allHosts.some(h => l.includes(h)))
513
- .join("\r\n");
514
- const tmpHosts = path.join(os.tmpdir(), `mitm_hosts_clean_${Date.now()}.tmp`);
515
- fs.writeFileSync(tmpHosts, filtered, "utf8");
516
-
517
- const psScript = [
518
- `$ErrorActionPreference = 'Stop'`,
519
- `try {`,
520
- ` Copy-Item -Path '${psSQ(tmpHosts)}' -Destination '${psSQ(hostsFile)}' -Force -ErrorAction Stop`,
521
- ` ipconfig /flushdns | Out-Null`,
522
- ` Remove-Item '${psSQ(tmpHosts)}' -ErrorAction SilentlyContinue`,
523
- `} catch {`,
524
- ` Remove-Item '${psSQ(tmpHosts)}' -ErrorAction SilentlyContinue`,
525
- `}`,
526
- ].join("\n");
527
-
528
- const tmpPs1 = path.join(os.tmpdir(), `mitm_stop_${Date.now()}.ps1`);
529
- fs.writeFileSync(tmpPs1, psScript, "utf8");
530
- await executeElevatedPowerShell(tmpPs1, 30000);
531
+ try {
532
+ const hostsContent = fs.readFileSync(hostsFile, "utf8");
533
+ const filtered = hostsContent.split(/\r?\n/).filter(l => !allHosts.some(h => l.includes(h))).join("\r\n");
534
+ fs.writeFileSync(hostsFile, filtered, "utf8");
535
+ require("child_process").execSync("ipconfig /flushdns", { windowsHide: true });
536
+ } catch (e) { err(`Failed to clean hosts: ${e.message}`); }
531
537
  } else {
532
538
  await removeAllDNSEntries(sudoPassword);
533
539
  }
@@ -562,6 +568,19 @@ async function disableToolDNS(tool, sudoPassword) {
562
568
  return { success: true };
563
569
  }
564
570
 
571
+ /**
572
+ * Install Root CA to system trust store (standalone, no server start)
573
+ */
574
+ async function trustCert(sudoPassword) {
575
+ const rootCACertPath = path.join(MITM_DIR, "rootCA.crt");
576
+ if (!fs.existsSync(rootCACertPath)) throw new Error("Root CA not found. Start server first to generate it.");
577
+ const { installCert } = require("./cert/install");
578
+ const password = sudoPassword || getCachedPassword() || await loadEncryptedPassword();
579
+ if (!password && !IS_WIN) throw new Error("Sudo password required to trust certificate");
580
+ await installCert(password, rootCACertPath);
581
+ if (password) setCachedPassword(password);
582
+ }
583
+
565
584
  // Legacy aliases for backward compatibility
566
585
  const startMitm = startServer;
567
586
  const stopMitm = stopServer;
@@ -572,6 +591,7 @@ module.exports = {
572
591
  stopServer,
573
592
  enableToolDNS,
574
593
  disableToolDNS,
594
+ trustCert,
575
595
  // Legacy
576
596
  startMitm,
577
597
  stopMitm,
@@ -3,6 +3,7 @@ const fs = require("fs");
3
3
  const path = require("path");
4
4
  const dns = require("dns");
5
5
  const { promisify } = require("util");
6
+ const { log, err } = require("./logger");
6
7
 
7
8
  // Allow self-signed certs from MITM root CA when fetching external hosts
8
9
 
@@ -25,7 +26,7 @@ const DB_FILE = path.join(DATA_DIR, "db.json");
25
26
  const ENABLE_FILE_LOG = false;
26
27
 
27
28
  if (!API_KEY) {
28
- console.error("ROUTER_API_KEY required");
29
+ err("ROUTER_API_KEY required");
29
30
  process.exit(1);
30
31
  }
31
32
 
@@ -57,11 +58,11 @@ function sniCallback(servername, cb) {
57
58
 
58
59
  // Cache it
59
60
  certCache.set(servername, ctx);
60
- console.log(`✅ Generated cert for: ${servername}`);
61
+ log(`🔐 Cert generated: ${servername}`);
61
62
 
62
63
  cb(null, ctx);
63
64
  } catch (error) {
64
- console.error(`❌ SNI error for ${servername}:`, error.message);
65
+ err(`SNI error for ${servername}: ${error.message}`);
65
66
  cb(error);
66
67
  }
67
68
  }
@@ -79,7 +80,7 @@ try {
79
80
  SNICallback: sniCallback
80
81
  };
81
82
  } catch (e) {
82
- console.error(`❌ Root CA not found in ${certDir}: ${e.message}`);
83
+ err(`Root CA not found in ${certDir}: ${e.message}`);
83
84
  process.exit(1);
84
85
  }
85
86
 
@@ -134,7 +135,13 @@ function getMappedModel(tool, model) {
134
135
  try {
135
136
  if (!fs.existsSync(DB_FILE)) return null;
136
137
  const db = JSON.parse(fs.readFileSync(DB_FILE, "utf-8"));
137
- return db.mitmAlias?.[tool]?.[model] || null;
138
+ const aliases = db.mitmAlias?.[tool];
139
+ if (!aliases) return null;
140
+ // Exact match first
141
+ if (aliases[model]) return aliases[model];
142
+ // Prefix match fallback: find alias key that starts with model or model starts with key
143
+ const prefixKey = Object.keys(aliases).find(k => k && aliases[k] && (model.startsWith(k) || k.startsWith(model)));
144
+ return prefixKey ? aliases[prefixKey] : null;
138
145
  } catch {
139
146
  return null;
140
147
  }
@@ -167,8 +174,8 @@ async function passthrough(req, res, bodyBuffer) {
167
174
  forwardRes.pipe(res);
168
175
  });
169
176
 
170
- forwardReq.on("error", (err) => {
171
- console.error(`❌ Passthrough error: ${err.message}`);
177
+ forwardReq.on("error", (e) => {
178
+ err(`Passthrough error: ${e.message}`);
172
179
  if (!res.headersSent) res.writeHead(502);
173
180
  res.end("Bad Gateway");
174
181
  });
@@ -216,7 +223,7 @@ async function intercept(req, res, bodyBuffer, mappedModel) {
216
223
  res.write(decoder.decode(value, { stream: true }));
217
224
  }
218
225
  } catch (error) {
219
- console.error(`❌ ${error.message}`);
226
+ err(`Intercept error: ${error.message}`);
220
227
  if (!res.headersSent) res.writeHead(500, { "Content-Type": "application/json" });
221
228
  res.end(JSON.stringify({ error: { message: error.message, type: "mitm_error" } }));
222
229
  }
@@ -250,30 +257,34 @@ const server = https.createServer(sslOptions, async (req, res) => {
250
257
  if (!isChat) return passthrough(req, res, bodyBuffer);
251
258
 
252
259
  const model = extractModel(req.url, bodyBuffer);
253
- console.log("Extracted model:", model);
260
+ log(`🔍 model="${model}" url=${req.url}`);
254
261
  const mappedModel = getMappedModel(tool, model);
255
262
 
256
- if (!mappedModel) return passthrough(req, res, bodyBuffer);
263
+ if (!mappedModel) {
264
+ log(`⏩ passthrough | no mapping | ${tool} | ${model || "unknown"}`);
265
+ return passthrough(req, res, bodyBuffer);
266
+ }
257
267
 
268
+ log(`⚡ intercept | ${tool} | ${model} → ${mappedModel}`);
258
269
  return intercept(req, res, bodyBuffer, mappedModel);
259
- } catch (err) {
260
- console.error(`❌ Unhandled request error: ${err.message}`);
270
+ } catch (e) {
271
+ err(`Unhandled request error: ${e.message}`);
261
272
  if (!res.headersSent) res.writeHead(500, { "Content-Type": "application/json" });
262
- res.end(JSON.stringify({ error: { message: err.message, type: "mitm_error" } }));
273
+ res.end(JSON.stringify({ error: { message: e.message, type: "mitm_error" } }));
263
274
  }
264
275
  });
265
276
 
266
277
  server.listen(LOCAL_PORT, () => {
267
- console.log(`🚀 MITM ready on :${LOCAL_PORT}`);
278
+ log(`🚀 Server ready on :${LOCAL_PORT}`);
268
279
  });
269
280
 
270
281
  server.on("error", (error) => {
271
282
  if (error.code === "EADDRINUSE") {
272
- console.error(`❌ Port ${LOCAL_PORT} already in use`);
283
+ err(`Port ${LOCAL_PORT} already in use`);
273
284
  } else if (error.code === "EACCES") {
274
- console.error(`❌ Permission denied for port ${LOCAL_PORT}`);
285
+ err(`Permission denied for port ${LOCAL_PORT}`);
275
286
  } else {
276
- console.error(`❌ ${error.message}`);
287
+ err(error.message);
277
288
  }
278
289
  process.exit(1);
279
290
  });
package/cli.js CHANGED
@@ -121,22 +121,20 @@ function killAllAppProcesses() {
121
121
  let pids = [];
122
122
 
123
123
  if (platform === "win32") {
124
- // Windows: use tasklist + findstr (works on all Windows versions)
124
+ // Windows: use WMI to get full CommandLine (tasklist /V doesn't include it)
125
125
  try {
126
- const output = execSync('tasklist /FO CSV /V 2>nul | findstr /I "node"', {
127
- encoding: 'utf8',
128
- shell: true,
126
+ const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"node.exe\\"' | Select-Object ProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
127
+ const output = execSync(psCmd, {
128
+ encoding: "utf8",
129
129
  windowsHide: true,
130
130
  timeout: 5000
131
131
  });
132
- const lines = output.split('\n').filter(l => l.trim());
133
-
132
+ const lines = output.split("\n").slice(1).filter(l => l.trim());
134
133
  lines.forEach(line => {
135
134
  const isAppProcess = line.toLowerCase().includes("9router") ||
136
135
  line.toLowerCase().includes("next-server");
137
136
  if (isAppProcess) {
138
- // CSV format: "name","pid",...
139
- const match = line.match(/"node\.exe","(\d+)"/i);
137
+ const match = line.match(/^"(\d+)"/);
140
138
  if (match && match[1] && match[1] !== process.pid.toString()) {
141
139
  pids.push(match[1]);
142
140
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "9router",
3
- "version": "0.3.53",
3
+ "version": "0.3.55",
4
4
  "description": "9Router CLI - Start and manage 9Router server",
5
5
  "bin": {
6
6
  "9router": "./cli.js"