9remote 3.0.40 → 3.0.46

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 (292) hide show
  1. package/dist/cli.cjs +6 -6
  2. package/dist/extension/background.js +120 -17
  3. package/dist/extension/manifest.json +2 -2
  4. package/dist/extension/popup.html +7 -0
  5. package/dist/extension/popup.js +6 -0
  6. package/dist/ptyDaemon.cjs +5 -5
  7. package/dist/server.cjs +248 -241
  8. package/dist/ui/assets/index-BefL072o.js +8 -0
  9. package/dist/ui/assets/index-DvsANh5-.css +1 -0
  10. package/dist/ui/index.html +2 -2
  11. package/dist/web/404.html +1 -1
  12. package/dist/web/__next.__PAGE__.txt +2 -2
  13. package/dist/web/__next._full.txt +26 -20
  14. package/dist/web/__next._head.txt +1 -1
  15. package/dist/web/__next._index.txt +12 -7
  16. package/dist/web/__next._tree.txt +2 -2
  17. package/dist/web/_next/static/chunks/1772-2df6c72aa1bdf99d.js +1 -0
  18. package/dist/web/_next/static/chunks/1920-64e4610715fd991d.js +1 -0
  19. package/dist/web/_next/static/chunks/1968-90d80a8543ed4f21.js +32 -0
  20. package/dist/web/_next/static/chunks/556-1dec70a3f28ddbe8.js +1 -0
  21. package/dist/web/_next/static/chunks/5587-b8f18d331fdde617.js +1 -0
  22. package/dist/web/_next/static/chunks/6153.189180c190f90b2f.js +1 -0
  23. package/dist/web/_next/static/chunks/6221-2be9b41ee97fc1e6.js +11 -0
  24. package/dist/web/_next/static/chunks/7489.c1e8656da3738df7.js +1 -0
  25. package/dist/web/_next/static/chunks/8126-c11d39a1ae6ac126.js +1 -0
  26. package/dist/web/_next/static/chunks/820-c1bd7547f2433453.js +1 -0
  27. package/dist/web/_next/static/chunks/8534.189180c190f90b2f.js +1 -0
  28. package/dist/web/_next/static/chunks/9121-cf1e65bb26b0908b.js +1 -0
  29. package/dist/web/_next/static/chunks/{9491-6dc334192080d071.js → 9491-970597f510e71615.js} +1 -1
  30. package/dist/web/_next/static/chunks/app/_global-error/page-e60883b219ccba1a.js +1 -0
  31. package/dist/web/_next/static/chunks/app/_not-found/page-bfa58c699e86fa7c.js +1 -0
  32. package/dist/web/_next/static/chunks/app/admin/access/page-79e70c584b6e2150.js +5 -0
  33. package/dist/web/_next/static/chunks/app/admin/login/page-4a768b6df8ed5259.js +1 -0
  34. package/dist/web/_next/static/chunks/app/admin/ota/page-e4d26a8db9968a98.js +5 -0
  35. package/dist/web/_next/static/chunks/app/admin/page-1c13a4c1567ed18e.js +5 -0
  36. package/dist/web/_next/static/chunks/app/admin/turn/page-dbd8be78d0941005.js +5 -0
  37. package/dist/web/_next/static/chunks/app/download/page-e27de0a4170f4b73.js +1 -0
  38. package/dist/web/_next/static/chunks/app/layout-fc9671123388edff.js +1 -0
  39. package/dist/web/_next/static/chunks/app/login/page-8216ac4904ee3551.js +1 -0
  40. package/dist/web/_next/static/chunks/app/{page-1e67d8a5f3775276.js → page-fde2c88f21078fca.js} +2 -2
  41. package/dist/web/_next/static/chunks/app/workspace/browse/page-e60883b219ccba1a.js +1 -0
  42. package/dist/web/_next/static/chunks/app/workspace/editor/page-e60883b219ccba1a.js +1 -0
  43. package/dist/web/_next/static/chunks/app/workspace/files/page-e60883b219ccba1a.js +1 -0
  44. package/dist/web/_next/static/chunks/app/workspace/git/page-e60883b219ccba1a.js +1 -0
  45. package/dist/web/_next/static/chunks/app/workspace/layout-0d349197dc482ccd.js +23 -0
  46. package/dist/web/_next/static/chunks/app/workspace/mobile/page-e60883b219ccba1a.js +1 -0
  47. package/dist/web/_next/static/chunks/app/workspace/page-e60883b219ccba1a.js +1 -0
  48. package/dist/web/_next/static/chunks/app/workspace/pair/page-e60883b219ccba1a.js +1 -0
  49. package/dist/web/_next/static/chunks/app/workspace/remote/page-e60883b219ccba1a.js +1 -0
  50. package/dist/web/_next/static/chunks/app/workspace/settings/page-e60883b219ccba1a.js +1 -0
  51. package/dist/web/_next/static/chunks/app/workspace/terminal/[sessionId]/page-e60883b219ccba1a.js +1 -0
  52. package/dist/web/_next/static/chunks/app/workspace/welcome/page-e60883b219ccba1a.js +1 -0
  53. package/dist/web/_next/static/chunks/app/workspace/workspaces/page-e60883b219ccba1a.js +1 -0
  54. package/dist/web/_next/static/chunks/main-72206f0a3cb91ecb.js +5 -0
  55. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/app-error-e60883b219ccba1a.js +1 -0
  56. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/forbidden-e60883b219ccba1a.js +1 -0
  57. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/not-found-e60883b219ccba1a.js +1 -0
  58. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/unauthorized-e60883b219ccba1a.js +1 -0
  59. package/dist/web/_next/static/chunks/{webpack-dd1f7a5ae02e5d84.js → webpack-31691f9bc04b8076.js} +1 -1
  60. package/dist/web/_next/static/css/{adc0ee53b89bee3c.css → 4da4daf9f2bf1755.css} +1 -1
  61. package/dist/web/_next/static/css/577dbf61f141a630.css +1 -0
  62. package/dist/web/_next/static/{55Oo1FQxj9HIxB7QE1XWG → u29HK3zWfDC3mM40skU_h}/_buildManifest.js +1 -1
  63. package/dist/web/_not-found/__next._full.txt +20 -18
  64. package/dist/web/_not-found/__next._head.txt +1 -1
  65. package/dist/web/_not-found/__next._index.txt +7 -7
  66. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +1 -1
  67. package/dist/web/_not-found/__next._not-found.txt +1 -1
  68. package/dist/web/_not-found/__next._tree.txt +2 -2
  69. package/dist/web/_not-found.html +1 -1
  70. package/dist/web/_not-found.txt +20 -18
  71. package/dist/web/admin/__next._full.txt +29 -22
  72. package/dist/web/admin/__next._head.txt +1 -1
  73. package/dist/web/admin/__next._index.txt +12 -7
  74. package/dist/web/admin/__next._tree.txt +2 -2
  75. package/dist/web/admin/__next.admin.__PAGE__.txt +2 -2
  76. package/dist/web/admin/__next.admin.txt +1 -1
  77. package/dist/web/admin/access/__next._full.txt +30 -22
  78. package/dist/web/admin/access/__next._head.txt +1 -1
  79. package/dist/web/admin/access/__next._index.txt +12 -7
  80. package/dist/web/admin/access/__next._tree.txt +2 -2
  81. package/dist/web/admin/access/__next.admin.access.__PAGE__.txt +2 -2
  82. package/dist/web/admin/access/__next.admin.access.txt +1 -1
  83. package/dist/web/admin/access/__next.admin.txt +1 -1
  84. package/dist/web/admin/access.html +1 -1
  85. package/dist/web/admin/access.txt +30 -22
  86. package/dist/web/admin/login/__next._full.txt +30 -22
  87. package/dist/web/admin/login/__next._head.txt +1 -1
  88. package/dist/web/admin/login/__next._index.txt +12 -7
  89. package/dist/web/admin/login/__next._tree.txt +2 -2
  90. package/dist/web/admin/login/__next.admin.login.__PAGE__.txt +2 -2
  91. package/dist/web/admin/login/__next.admin.login.txt +1 -1
  92. package/dist/web/admin/login/__next.admin.txt +1 -1
  93. package/dist/web/admin/login.html +1 -1
  94. package/dist/web/admin/login.txt +30 -22
  95. package/dist/web/admin/ota/__next._full.txt +30 -22
  96. package/dist/web/admin/ota/__next._head.txt +1 -1
  97. package/dist/web/admin/ota/__next._index.txt +12 -7
  98. package/dist/web/admin/ota/__next._tree.txt +2 -2
  99. package/dist/web/admin/ota/__next.admin.ota.__PAGE__.txt +2 -2
  100. package/dist/web/admin/ota/__next.admin.ota.txt +1 -1
  101. package/dist/web/admin/ota/__next.admin.txt +1 -1
  102. package/dist/web/admin/ota.html +1 -1
  103. package/dist/web/admin/ota.txt +30 -22
  104. package/dist/web/admin/turn/__next._full.txt +30 -22
  105. package/dist/web/admin/turn/__next._head.txt +1 -1
  106. package/dist/web/admin/turn/__next._index.txt +12 -7
  107. package/dist/web/admin/turn/__next._tree.txt +2 -2
  108. package/dist/web/admin/turn/__next.admin.turn.__PAGE__.txt +2 -2
  109. package/dist/web/admin/turn/__next.admin.turn.txt +1 -1
  110. package/dist/web/admin/turn/__next.admin.txt +1 -1
  111. package/dist/web/admin/turn.html +1 -1
  112. package/dist/web/admin/turn.txt +30 -22
  113. package/dist/web/admin.html +1 -1
  114. package/dist/web/admin.txt +29 -22
  115. package/dist/web/download/__next._full.txt +26 -19
  116. package/dist/web/download/__next._head.txt +1 -1
  117. package/dist/web/download/__next._index.txt +12 -7
  118. package/dist/web/download/__next._tree.txt +2 -2
  119. package/dist/web/download/__next.download.__PAGE__.txt +2 -2
  120. package/dist/web/download/__next.download.txt +1 -1
  121. package/dist/web/download.html +1 -1
  122. package/dist/web/download.txt +26 -19
  123. package/dist/web/index.html +1 -1
  124. package/dist/web/index.txt +26 -20
  125. package/dist/web/login/__next._full.txt +29 -22
  126. package/dist/web/login/__next._head.txt +1 -1
  127. package/dist/web/login/__next._index.txt +12 -7
  128. package/dist/web/login/__next._tree.txt +2 -2
  129. package/dist/web/login/__next.login.__PAGE__.txt +2 -2
  130. package/dist/web/login/__next.login.txt +1 -1
  131. package/dist/web/login.html +1 -1
  132. package/dist/web/login.txt +29 -22
  133. package/dist/web/workspace/__next._full.txt +27 -20
  134. package/dist/web/workspace/__next._head.txt +1 -1
  135. package/dist/web/workspace/__next._index.txt +12 -7
  136. package/dist/web/workspace/__next._tree.txt +3 -3
  137. package/dist/web/workspace/__next.workspace.__PAGE__.txt +1 -1
  138. package/dist/web/workspace/__next.workspace.txt +3 -3
  139. package/dist/web/workspace/browse/__next._full.txt +30 -22
  140. package/dist/web/workspace/browse/__next._head.txt +1 -1
  141. package/dist/web/workspace/browse/__next._index.txt +12 -7
  142. package/dist/web/workspace/browse/__next._tree.txt +3 -3
  143. package/dist/web/workspace/browse/__next.workspace.browse.__PAGE__.txt +1 -1
  144. package/dist/web/workspace/browse/__next.workspace.browse.txt +1 -1
  145. package/dist/web/workspace/browse/__next.workspace.txt +3 -3
  146. package/dist/web/workspace/browse.html +1 -1
  147. package/dist/web/workspace/browse.txt +30 -22
  148. package/dist/web/workspace/editor/__next._full.txt +30 -22
  149. package/dist/web/workspace/editor/__next._head.txt +1 -1
  150. package/dist/web/workspace/editor/__next._index.txt +12 -7
  151. package/dist/web/workspace/editor/__next._tree.txt +3 -3
  152. package/dist/web/workspace/editor/__next.workspace.editor.__PAGE__.txt +1 -1
  153. package/dist/web/workspace/editor/__next.workspace.editor.txt +1 -1
  154. package/dist/web/workspace/editor/__next.workspace.txt +3 -3
  155. package/dist/web/workspace/editor.html +1 -1
  156. package/dist/web/workspace/editor.txt +30 -22
  157. package/dist/web/workspace/files/__next._full.txt +30 -22
  158. package/dist/web/workspace/files/__next._head.txt +1 -1
  159. package/dist/web/workspace/files/__next._index.txt +12 -7
  160. package/dist/web/workspace/files/__next._tree.txt +3 -3
  161. package/dist/web/workspace/files/__next.workspace.files.__PAGE__.txt +1 -1
  162. package/dist/web/workspace/files/__next.workspace.files.txt +1 -1
  163. package/dist/web/workspace/files/__next.workspace.txt +3 -3
  164. package/dist/web/workspace/files.html +1 -1
  165. package/dist/web/workspace/files.txt +30 -22
  166. package/dist/web/workspace/git/__next._full.txt +30 -22
  167. package/dist/web/workspace/git/__next._head.txt +1 -1
  168. package/dist/web/workspace/git/__next._index.txt +12 -7
  169. package/dist/web/workspace/git/__next._tree.txt +3 -3
  170. package/dist/web/workspace/git/__next.workspace.git.__PAGE__.txt +1 -1
  171. package/dist/web/workspace/git/__next.workspace.git.txt +1 -1
  172. package/dist/web/workspace/git/__next.workspace.txt +3 -3
  173. package/dist/web/workspace/git.html +1 -1
  174. package/dist/web/workspace/git.txt +30 -22
  175. package/dist/web/workspace/mobile/__next._full.txt +30 -22
  176. package/dist/web/workspace/mobile/__next._head.txt +1 -1
  177. package/dist/web/workspace/mobile/__next._index.txt +12 -7
  178. package/dist/web/workspace/mobile/__next._tree.txt +3 -3
  179. package/dist/web/workspace/mobile/__next.workspace.mobile.__PAGE__.txt +1 -1
  180. package/dist/web/workspace/mobile/__next.workspace.mobile.txt +1 -1
  181. package/dist/web/workspace/mobile/__next.workspace.txt +3 -3
  182. package/dist/web/workspace/mobile.html +1 -1
  183. package/dist/web/workspace/mobile.txt +30 -22
  184. package/dist/web/workspace/pair/__next._full.txt +30 -22
  185. package/dist/web/workspace/pair/__next._head.txt +1 -1
  186. package/dist/web/workspace/pair/__next._index.txt +12 -7
  187. package/dist/web/workspace/pair/__next._tree.txt +3 -3
  188. package/dist/web/workspace/pair/__next.workspace.pair.__PAGE__.txt +1 -1
  189. package/dist/web/workspace/pair/__next.workspace.pair.txt +1 -1
  190. package/dist/web/workspace/pair/__next.workspace.txt +3 -3
  191. package/dist/web/workspace/pair.html +1 -1
  192. package/dist/web/workspace/pair.txt +30 -22
  193. package/dist/web/workspace/remote/__next._full.txt +30 -22
  194. package/dist/web/workspace/remote/__next._head.txt +1 -1
  195. package/dist/web/workspace/remote/__next._index.txt +12 -7
  196. package/dist/web/workspace/remote/__next._tree.txt +3 -3
  197. package/dist/web/workspace/remote/__next.workspace.remote.__PAGE__.txt +1 -1
  198. package/dist/web/workspace/remote/__next.workspace.remote.txt +1 -1
  199. package/dist/web/workspace/remote/__next.workspace.txt +3 -3
  200. package/dist/web/workspace/remote.html +1 -1
  201. package/dist/web/workspace/remote.txt +30 -22
  202. package/dist/web/workspace/settings/__next._full.txt +37 -0
  203. package/dist/web/{dev/question → workspace/settings}/__next._head.txt +1 -1
  204. package/dist/web/workspace/settings/__next._index.txt +17 -0
  205. package/dist/web/{dev/question → workspace/settings}/__next._tree.txt +3 -2
  206. package/dist/web/workspace/settings/__next.workspace.settings.__PAGE__.txt +5 -0
  207. package/dist/web/{dev/question/__next.dev.question.txt → workspace/settings/__next.workspace.settings.txt} +1 -1
  208. package/dist/web/workspace/settings/__next.workspace.txt +8 -0
  209. package/dist/web/workspace/settings.html +1 -0
  210. package/dist/web/workspace/settings.txt +37 -0
  211. package/dist/web/workspace/terminal/default/__next._full.txt +30 -24
  212. package/dist/web/workspace/terminal/default/__next._head.txt +1 -1
  213. package/dist/web/workspace/terminal/default/__next._index.txt +12 -7
  214. package/dist/web/workspace/terminal/default/__next._tree.txt +3 -3
  215. package/dist/web/workspace/terminal/default/__next.workspace.terminal.$d$sessionId.__PAGE__.txt +1 -1
  216. package/dist/web/workspace/terminal/default/__next.workspace.terminal.$d$sessionId.txt +1 -1
  217. package/dist/web/workspace/terminal/default/__next.workspace.terminal.txt +1 -1
  218. package/dist/web/workspace/terminal/default/__next.workspace.txt +3 -3
  219. package/dist/web/workspace/terminal/default.html +1 -1
  220. package/dist/web/workspace/terminal/default.txt +30 -24
  221. package/dist/web/workspace/welcome/__next._full.txt +30 -22
  222. package/dist/web/workspace/welcome/__next._head.txt +1 -1
  223. package/dist/web/workspace/welcome/__next._index.txt +12 -7
  224. package/dist/web/workspace/welcome/__next._tree.txt +3 -3
  225. package/dist/web/workspace/welcome/__next.workspace.txt +3 -3
  226. package/dist/web/workspace/welcome/__next.workspace.welcome.__PAGE__.txt +1 -1
  227. package/dist/web/workspace/welcome/__next.workspace.welcome.txt +1 -1
  228. package/dist/web/workspace/welcome.html +1 -1
  229. package/dist/web/workspace/welcome.txt +30 -22
  230. package/dist/web/workspace/workspaces/__next._full.txt +30 -22
  231. package/dist/web/workspace/workspaces/__next._head.txt +1 -1
  232. package/dist/web/workspace/workspaces/__next._index.txt +12 -7
  233. package/dist/web/workspace/workspaces/__next._tree.txt +3 -3
  234. package/dist/web/workspace/workspaces/__next.workspace.txt +3 -3
  235. package/dist/web/workspace/workspaces/__next.workspace.workspaces.__PAGE__.txt +1 -1
  236. package/dist/web/workspace/workspaces/__next.workspace.workspaces.txt +1 -1
  237. package/dist/web/workspace/workspaces.html +1 -1
  238. package/dist/web/workspace/workspaces.txt +30 -22
  239. package/dist/web/workspace.html +1 -1
  240. package/dist/web/workspace.txt +27 -20
  241. package/package.json +5 -5
  242. package/dist/ui/assets/index-D_C1NTm1.js +0 -8
  243. package/dist/ui/assets/index-SHlsPzjb.css +0 -1
  244. package/dist/web/_next/static/chunks/1772-ef73c166e83f5eff.js +0 -1
  245. package/dist/web/_next/static/chunks/1920-5ead25286846df83.js +0 -1
  246. package/dist/web/_next/static/chunks/1968-4d2969f0b7112e0b.js +0 -32
  247. package/dist/web/_next/static/chunks/329-15d3e36af1b2827f.js +0 -1
  248. package/dist/web/_next/static/chunks/556-a8f04c41c5663ee8.js +0 -1
  249. package/dist/web/_next/static/chunks/5587-fc5af8c76df14222.js +0 -1
  250. package/dist/web/_next/static/chunks/6153.8c6b8930e22ceea0.js +0 -1
  251. package/dist/web/_next/static/chunks/6221-cf883148bf8a4c1e.js +0 -11
  252. package/dist/web/_next/static/chunks/7489.24938d89538cd03e.js +0 -1
  253. package/dist/web/_next/static/chunks/8126-0279fc9e17c08aff.js +0 -1
  254. package/dist/web/_next/static/chunks/820-99036fb63c5462c8.js +0 -1
  255. package/dist/web/_next/static/chunks/8534.8c6b8930e22ceea0.js +0 -1
  256. package/dist/web/_next/static/chunks/9121-3d281debd0f3e659.js +0 -1
  257. package/dist/web/_next/static/chunks/app/_global-error/page-2ece09c883187d82.js +0 -1
  258. package/dist/web/_next/static/chunks/app/_not-found/page-9f829d2c4beb1840.js +0 -1
  259. package/dist/web/_next/static/chunks/app/admin/access/page-45f45ad529e5b691.js +0 -5
  260. package/dist/web/_next/static/chunks/app/admin/login/page-382072b5b43d3c29.js +0 -1
  261. package/dist/web/_next/static/chunks/app/admin/ota/page-293c0743bd60f454.js +0 -5
  262. package/dist/web/_next/static/chunks/app/admin/page-fc676dae451dd646.js +0 -5
  263. package/dist/web/_next/static/chunks/app/admin/turn/page-2ab33033fc7f0919.js +0 -5
  264. package/dist/web/_next/static/chunks/app/dev/question/page-bafce0c9fd4e8488.js +0 -1
  265. package/dist/web/_next/static/chunks/app/download/page-a65d1c7fcf6397af.js +0 -1
  266. package/dist/web/_next/static/chunks/app/layout-f1429d22e935695f.js +0 -1
  267. package/dist/web/_next/static/chunks/app/login/page-a5dd37d1cbbb394e.js +0 -1
  268. package/dist/web/_next/static/chunks/app/workspace/browse/page-2ece09c883187d82.js +0 -1
  269. package/dist/web/_next/static/chunks/app/workspace/editor/page-2ece09c883187d82.js +0 -1
  270. package/dist/web/_next/static/chunks/app/workspace/files/page-2ece09c883187d82.js +0 -1
  271. package/dist/web/_next/static/chunks/app/workspace/git/page-2ece09c883187d82.js +0 -1
  272. package/dist/web/_next/static/chunks/app/workspace/layout-d8bb677fa1caa5a7.js +0 -20
  273. package/dist/web/_next/static/chunks/app/workspace/mobile/page-2ece09c883187d82.js +0 -1
  274. package/dist/web/_next/static/chunks/app/workspace/page-2ece09c883187d82.js +0 -1
  275. package/dist/web/_next/static/chunks/app/workspace/pair/page-2ece09c883187d82.js +0 -1
  276. package/dist/web/_next/static/chunks/app/workspace/remote/page-2ece09c883187d82.js +0 -1
  277. package/dist/web/_next/static/chunks/app/workspace/terminal/[sessionId]/page-2ece09c883187d82.js +0 -1
  278. package/dist/web/_next/static/chunks/app/workspace/welcome/page-2ece09c883187d82.js +0 -1
  279. package/dist/web/_next/static/chunks/app/workspace/workspaces/page-2ece09c883187d82.js +0 -1
  280. package/dist/web/_next/static/chunks/main-e10b0dbebb4de0a8.js +0 -5
  281. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/app-error-2ece09c883187d82.js +0 -1
  282. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/forbidden-2ece09c883187d82.js +0 -1
  283. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/not-found-2ece09c883187d82.js +0 -1
  284. package/dist/web/_next/static/chunks/next/dist/client/components/builtin/unauthorized-2ece09c883187d82.js +0 -1
  285. package/dist/web/_next/static/css/1c2cca827fa36d54.css +0 -1
  286. package/dist/web/dev/question/__next._full.txt +0 -29
  287. package/dist/web/dev/question/__next._index.txt +0 -12
  288. package/dist/web/dev/question/__next.dev.question.__PAGE__.txt +0 -9
  289. package/dist/web/dev/question/__next.dev.txt +0 -5
  290. package/dist/web/dev/question.html +0 -1
  291. package/dist/web/dev/question.txt +0 -29
  292. /package/dist/web/_next/static/{55Oo1FQxj9HIxB7QE1XWG → u29HK3zWfDC3mM40skU_h}/_ssgManifest.js +0 -0
package/dist/cli.cjs CHANGED
@@ -8,11 +8,11 @@ Right-click to open / quit`}function wa(){let{port:e,tunnelUrl:n}=Tn,r=process.p
8
8
  `;for(var d=0;d<a;d+=2){t+=f.WHITE_ALL;for(var m=0;m<a;m++)c[d][m]===s&&c[d+1][m]===s?t+=f.WHITE_ALL:c[d][m]===s&&c[d+1][m]===i?t+=f.WHITE_BLACK:c[d][m]===i&&c[d+1][m]===s?t+=f.BLACK_WHITE:t+=f.BLACK_ALL;t+=f.WHITE_ALL+`
9
9
  `}l||(t+=p)}else{var w=ei(qr).times(o.getModuleCount()+3);t+=w+`
10
10
  `,o.modules.forEach(function(v){t+=qr,t+=v.map(Su).join(""),t+=qr+`
11
- `}),t+=w}r?r(t):console.log(t)},setErrorLevel:function(e){this.error=qa[e]||this.error}}});for(let e of[process.stdout,process.stderr])e?.on?.("error",n=>{if(n?.code!=="EPIPE")throw n});var yr=require("fs"),Nn=require("path"),wi=require("url"),vi=A(require("os"),1);var gr=A(require("dns"),1),Ae=A(require("path"),1),fi=A(require("os"),1),ee="9remote",to=process.env.NREMOTE_REGISTRY||`https://registry.npmjs.org/${ee}/latest`,ke=`${ee}@latest`,Le=process.env.NREMOTE_HOME||Ae.default.join(fi.default.homedir(),".9remote"),V={ROOT:Le,LOGS:Ae.default.join(Le,"logs"),STATE:Ae.default.join(Le,"state"),CONFIG:Ae.default.join(Le,"config"),BIN:Ae.default.join(Le,"bin"),PIDS:Ae.default.join(Le,"pids"),BUFFERS:Ae.default.join(Le,"buffers"),DAEMON:Ae.default.join(Le,"daemon"),AI_SESSIONS:Ae.default.join(Le,"ai-sessions"),BACKGROUNDS:Ae.default.join(Le,"backgrounds")},Mn=new gr.default.promises.Resolver;Mn.setServers(["1.1.1.1","1.0.0.1","8.8.8.8"]);var eo=gr.default.lookup,Ac=/^(\d{1,3}\.){3}\d{1,3}$|^::1$|^[0-9a-f:]+$/i;gr.default.lookup=(e,n,r)=>{if(typeof n=="function"&&(r=n,n={}),e==="localhost"||Ac.test(e))return eo(e,n,r);(async()=>{if(n.family===6)return{addrs:await Mn.resolve6(e),family:6};if(n.family===4)return{addrs:await Mn.resolve4(e),family:4};let[t,i]=await Promise.allSettled([Mn.resolve4(e),Mn.resolve6(e)]);return t.status==="fulfilled"&&t.value?.length?{addrs:t.value,family:4}:i.status==="fulfilled"&&i.value?.length?{addrs:i.value,family:6}:null})().then(t=>{if(!t?.addrs?.length)return eo(e,n,r);n.all?r(null,t.addrs.map(i=>({address:i,family:t.family}))):r(null,t.addrs[0],t.family)}).catch(()=>eo(e,n,r))};var $=2208,pi=process.execPath,di=(e=process.env)=>process.versions.electron?{...e,ELECTRON_RUN_AS_NODE:"1"}:{...e};var li=5173,ui=3e3;var tf=[`http://localhost:${$}`,`http://127.0.0.1:${$}`,`http://localhost:${li}`,`http://127.0.0.1:${li}`,`http://localhost:${ui}`,`http://127.0.0.1:${ui}`],Cn={fileName:"agent.log",rotatedName:"agent.log.1",maxBytes:2*1024*1024,cleanupAfterDays:7},mi=60,O={STOPPED:0,PREPARING:1,CONNECTING:2,TUNNELING:3,VERIFYING:4,READY:5},hi={showTunnelUrlInMenu:!1};var gi={CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN:"1"};var yi={checkIntervalMs:3e4,requestTimeoutMs:5e3},ge={server:{strategy:"exp",baseMs:1e3,maxMs:6e4},tunnelRestart:{strategy:"exp",baseMs:2e3,maxMs:3e5},tunnelSpawn:{strategy:"linear",baseMs:5e3,maxMs:6e4},tunnelRateLimit:{strategy:"exp",baseMs:6e4,maxMs:9e5},internet:{strategy:"linear",baseMs:3e3,maxMs:6e4},sse:{strategy:"linear",baseMs:2e3,maxMs:2e3},urlSync:{strategy:"linear",baseMs:5e3,maxMs:6e4}},kc={Accept:"application/json, text/plain, */*","Accept-Language":"en-US,en;q=0.9","Cache-Control":"no-cache",Pragma:"no-cache","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"};function W(e,n={}){return fetch(e,{...n,headers:{...kc,...n.headers}})}var Rc=(0,Nn.dirname)((0,wi.fileURLToPath)(__importMetaUrl)),Pc=[(0,Nn.join)(vi.default.homedir(),".9remote",".env"),(0,Nn.join)(Rc,"..",".env")];function $c(e){for(let n of e.split(`
11
+ `}),t+=w}r?r(t):console.log(t)},setErrorLevel:function(e){this.error=qa[e]||this.error}}});for(let e of[process.stdout,process.stderr])e?.on?.("error",n=>{if(n?.code!=="EPIPE")throw n});var yr=require("fs"),Nn=require("path"),wi=require("url"),vi=A(require("os"),1);var gr=A(require("dns"),1),Ae=A(require("path"),1),fi=A(require("os"),1),ee="9remote",to=process.env.NREMOTE_REGISTRY||`https://registry.npmjs.org/${ee}/latest`,ke=`${ee}@latest`,Le=process.env.NREMOTE_HOME||Ae.default.join(fi.default.homedir(),".9remote"),V={ROOT:Le,LOGS:Ae.default.join(Le,"logs"),STATE:Ae.default.join(Le,"state"),CONFIG:Ae.default.join(Le,"config"),BIN:Ae.default.join(Le,"bin"),PIDS:Ae.default.join(Le,"pids"),BUFFERS:Ae.default.join(Le,"buffers"),DAEMON:Ae.default.join(Le,"daemon"),AI_SESSIONS:Ae.default.join(Le,"ai-sessions"),BACKGROUNDS:Ae.default.join(Le,"backgrounds")},Mn=new gr.default.promises.Resolver;Mn.setServers(["1.1.1.1","1.0.0.1","8.8.8.8"]);var eo=gr.default.lookup,Ac=/^(\d{1,3}\.){3}\d{1,3}$|^::1$|^[0-9a-f:]+$/i;gr.default.lookup=(e,n,r)=>{if(typeof n=="function"&&(r=n,n={}),e==="localhost"||Ac.test(e))return eo(e,n,r);(async()=>{if(n.family===6)return{addrs:await Mn.resolve6(e),family:6};if(n.family===4)return{addrs:await Mn.resolve4(e),family:4};let[t,i]=await Promise.allSettled([Mn.resolve4(e),Mn.resolve6(e)]);return t.status==="fulfilled"&&t.value?.length?{addrs:t.value,family:4}:i.status==="fulfilled"&&i.value?.length?{addrs:i.value,family:6}:null})().then(t=>{if(!t?.addrs?.length)return eo(e,n,r);n.all?r(null,t.addrs.map(i=>({address:i,family:t.family}))):r(null,t.addrs[0],t.family)}).catch(()=>eo(e,n,r))};var $=2208,pi=process.execPath,di=(e=process.env)=>process.versions.electron?{...e,ELECTRON_RUN_AS_NODE:"1"}:{...e};var li=5173,ui=2200;var tf=[`http://localhost:${$}`,`http://127.0.0.1:${$}`,`http://localhost:${li}`,`http://127.0.0.1:${li}`,`http://localhost:${ui}`,`http://127.0.0.1:${ui}`],Cn={fileName:"agent.log",rotatedName:"agent.log.1",maxBytes:2*1024*1024,cleanupAfterDays:7},mi=60,O={STOPPED:0,PREPARING:1,CONNECTING:2,TUNNELING:3,VERIFYING:4,READY:5},hi={showTunnelUrlInMenu:!1};var gi={CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN:"1"};var yi={checkIntervalMs:3e4,requestTimeoutMs:5e3},ge={server:{strategy:"exp",baseMs:1e3,maxMs:6e4},tunnelRestart:{strategy:"exp",baseMs:2e3,maxMs:3e5},tunnelSpawn:{strategy:"linear",baseMs:5e3,maxMs:6e4},tunnelRateLimit:{strategy:"exp",baseMs:6e4,maxMs:9e5},internet:{strategy:"linear",baseMs:3e3,maxMs:6e4},sse:{strategy:"linear",baseMs:2e3,maxMs:2e3},urlSync:{strategy:"linear",baseMs:5e3,maxMs:6e4}},kc={Accept:"application/json, text/plain, */*","Accept-Language":"en-US,en;q=0.9","Cache-Control":"no-cache",Pragma:"no-cache","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"};function W(e,n={}){return fetch(e,{...n,headers:{...kc,...n.headers}})}var Rc=(0,Nn.dirname)((0,wi.fileURLToPath)(__importMetaUrl)),Pc=[(0,Nn.join)(vi.default.homedir(),".9remote",".env"),(0,Nn.join)(Rc,"..",".env")];function $c(e){for(let n of e.split(`
12
12
  `)){let r=n.trim();if(!r||r.startsWith("#"))continue;let o=r.match(/^([A-Z_][A-Z0-9_]*)\s*=\s*"?(.*?)"?$/);o&&!process.env[o[1]]&&(process.env[o[1]]=o[2])}}for(let e of Pc)if((0,yr.existsSync)(e))try{$c((0,yr.readFileSync)(e,"utf8"))}catch{}for(let[e,n]of Object.entries(gi))process.env[e]||(process.env[e]=n);var xo=A(require("path"),1),Ts=A(require("fs"),1),xs=require("url");var Ei=A(bi(),1),ro=A(require("crypto"),1),{machineIdSync:Oc}=Ei.default;async function Xt(e=null){let n=e||process.env.MACHINE_ID_SALT||"9remote-salt";try{let r=Oc();return ro.default.createHash("sha256").update(r+n).digest("hex").substring(0,16)}catch(r){return console.error("Error getting machine ID:",r),ro.default.randomUUID().replace(/-/g,"").substring(0,16)}}var xi=A(require("crypto"),1),Si="abcdefghijklmnpqrstuvwxyz123456789",Ic=8;function Ti(){let e="";for(let n=0;n<Ic;n++)e+=Si[xi.default.randomInt(Si.length)];return e}function kt(e){return`sk-${(e||"").slice(0,8).toLowerCase()}-${Ti()}-${Ti()}`}function oo(e){return/^sk-[a-z0-9]{8}-[a-np-z1-9]{8}-[a-np-z1-9]{8}$/.test(e||"")}function Q(e){if(!oo(e))return e||null;let n=e.split("-");return`${n[0]}-${n[1]}-${n[2]}`}function Ai(e){return typeof e!="string"||!e?!1:/^sk-[a-z0-9]{8}-[a-z0-9]{4}-[0-9a-f]{6}$/.test(e.trim().toLowerCase())}function wr(e){return!e||e.length<8?"sk-***":`${e.slice(0,3)}***${e.slice(-4)}`}var de=A(require("fs"),1),Un=A(require("path"),1);var ye=require("fs"),ki=require("path"),_c=0;function je(e,n,r={}){let{mode:o=384,spaces:t=2}=r;(0,ye.mkdirSync)((0,ki.dirname)(e),{recursive:!0});let i=`${e}.${process.pid}.${++_c}.tmp`;try{(0,ye.writeFileSync)(i,JSON.stringify(n,null,t),{mode:o}),(0,ye.renameSync)(i,e)}catch(s){try{(0,ye.existsSync)(i)&&(0,ye.unlinkSync)(i)}catch{}throw s}}function Ri(e,n=null){try{return(0,ye.existsSync)(e)?JSON.parse((0,ye.readFileSync)(e,"utf8")):n}catch{return n}}var uf=V.STATE,Bn=Un.default.join(V.STATE,"state.json"),io=Un.default.join(V.ROOT,"keys.json"),vr=Un.default.join(V.STATE,"cmd.json"),Pi=Un.default.join(V.STATE,"settings.json");function Jt(){for(let e of[V.ROOT,V.STATE])de.default.existsSync(e)||de.default.mkdirSync(e,{recursive:!0})}function $i(){try{return Jt(),de.default.existsSync(Bn)?JSON.parse(de.default.readFileSync(Bn,"utf8")):null}catch{return null}}function Fn(e){try{Jt(),je(Bn,e)}catch(n){console.error("Error saving state:",n)}}function Oi(){try{de.default.existsSync(Bn)&&de.default.unlinkSync(Bn)}catch{}}function Y(){try{return Jt(),de.default.existsSync(Pi)?JSON.parse(de.default.readFileSync(Pi,"utf8"))||{}:{}}catch{return{}}}function Kn(){try{return Jt(),de.default.existsSync(io)?JSON.parse(de.default.readFileSync(io,"utf8")):{machineId:null,key:null,name:"Default",createdAt:null}}catch{return{machineId:null,key:null,name:"Default",createdAt:null}}}function Qt(e){try{Jt(),je(vr,{cmd:e,ts:Date.now()},{spaces:0})}catch{}}function Ii(){try{if(!de.default.existsSync(vr))return null;let e=JSON.parse(de.default.readFileSync(vr,"utf8"));return de.default.unlinkSync(vr),e.cmd}catch{return null}}function We(e,n,r="Default"){try{Jt();let o={machineId:e,key:n,name:r,createdAt:new Date().toISOString()};return je(io,o),o}catch(o){return console.error("Error saving key:",o),null}}var Me=A(require("fs"),1),so=A(require("path"),1);var Er=V.LOGS,Hn=so.default.join(Er,Cn.fileName),Sr=so.default.join(Er,Cn.rotatedName),_i=!1,Li=null;function Lc(){Me.default.existsSync(Er)||Me.default.mkdirSync(Er,{recursive:!0})}function Mc(){try{if(Me.default.statSync(Hn).size<Cn.maxBytes)return;try{Me.default.rmSync(Sr,{force:!0})}catch{}Me.default.renameSync(Hn,Sr)}catch{}}function Cc(){try{let e=Me.default.statSync(Sr);Date.now()-e.mtimeMs>Cn.cleanupAfterDays*864e5&&Me.default.rmSync(Sr,{force:!0})}catch{}}function ao(e){try{Mc(),Me.default.appendFileSync(Hn,e+`
13
13
  `)}catch{}}function br(e){return e.map(n=>{if(n instanceof Error)return n.stack||n.message;if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}).join(" ")}var Nc=/\x1b\[[0-9;]*m/g,Dc=/https?:\/\/[^\s]+/g;function Bc(e){return String(e).replace(Nc,"").replace(Dc,"").replace(/\s+$/g,"")}function zt(e,n,r){let o=Bc(r);if(!o)return;let t=`${new Date().toISOString()} ${n.toUpperCase()} [${e}] ${o}`;if(ao(t),Li)try{Li(t)}catch{}}function Uc(){process.on("uncaughtException",e=>zt("crash","error",`uncaughtException: ${e?.stack||e?.message||e}`)),process.on("unhandledRejection",e=>{let n=e instanceof Error?e.stack||e.message:String(e);zt("crash","error",`unhandledRejection: ${n}`)}),process.on("exit",e=>ao(`${new Date().toISOString()} INFO [exit] code=${e} pid=${process.pid}`))}function Mi(){_i||(_i=!0,Lc(),Cc(),ao(`
14
14
  === SESSION ${new Date().toISOString()} pid=${process.pid} argv=${process.argv.slice(2).join(" ")} ===`),Uc())}function Ci(e=60){try{return Me.default.readFileSync(Hn,"utf8").split(`
15
- `).filter(Boolean).slice(-e)}catch{return[]}}var Fc=process.env.NODE_ENV==="development"||process.env.AGENT_DEBUG==="1";function F(e){return{debug:(...n)=>{Fc&&zt(e,"debug",br(n))},info:(...n)=>zt(e,"info",br(n)),warn:(...n)=>zt(e,"warn",br(n)),error:(...n)=>zt(e,"error",br(n))}}var jn=Hn;var ct=A(require("crypto"),1),en=require("fs");var Ni=require("path");var mf=Buffer.from("302a300506032b656e","hex");var Tr=(0,Ni.join)(V.CONFIG,"hostKey.json"),bf=Buffer.from("302a300506032b6570032100","hex"),Zt=null;function co(){if(Zt)return Zt;try{if((0,en.existsSync)(Tr)){let s=JSON.parse((0,en.readFileSync)(Tr,"utf8")),a=Buffer.from(s.publicKey,"base64");if(!s.x25519PrivateKey){let l=ct.default.generateKeyPairSync("x25519");s.x25519PrivateKey=l.privateKey.export({type:"pkcs8",format:"der"}).toString("base64"),s.x25519PublicKey=l.publicKey.export({type:"spki",format:"der"}).toString("base64"),je(Tr,s)}let c=Buffer.from(s.x25519PublicKey,"base64");return Zt={privateKey:ct.default.createPrivateKey({key:Buffer.from(s.privateKey,"base64"),format:"der",type:"pkcs8"}),publicKey:ct.default.createPublicKey({key:a,format:"der",type:"spki"}),publicKeyB64:a.subarray(-32).toString("base64"),x25519PrivateKey:ct.default.createPrivateKey({key:Buffer.from(s.x25519PrivateKey,"base64"),format:"der",type:"pkcs8"}),x25519PublicKeyB64:c.subarray(-32).toString("base64")},Zt}}catch{}(0,en.mkdirSync)(V.CONFIG,{recursive:!0});let{privateKey:e,publicKey:n}=ct.default.generateKeyPairSync("ed25519"),r=n.export({type:"spki",format:"der"}).toString("base64"),o=e.export({type:"pkcs8",format:"der"}).toString("base64"),t=ct.default.generateKeyPairSync("x25519"),i=t.publicKey.export({type:"spki",format:"der"}).toString("base64");return je(Tr,{privateKey:o,publicKey:r,x25519PrivateKey:t.privateKey.export({type:"pkcs8",format:"der"}).toString("base64"),x25519PublicKey:i}),Zt={privateKey:e,publicKey:n,publicKeyB64:Buffer.from(r,"base64").subarray(-32).toString("base64"),x25519PrivateKey:t.privateKey,x25519PublicKeyB64:Buffer.from(i,"base64").subarray(-32).toString("base64")},Zt}function lt(){return co().publicKeyB64}function ut(){return co().x25519PublicKeyB64}var Kc="9remote-session-v1";function Hc({apiKey:e,tunnelUrl:n,localIp:r,expiryMinutes:o,ts:t}){let i=a=>{let c=a==null?"":String(a);return`${c.length}:${c}`},s=`${Kc}|${i(e)}${i(n)}${i(r)}${i(o)}${i(t)}`;return ct.default.sign(null,Buffer.from(s,"utf8"),co().privateKey).toString("base64")}function Rt(e){let n=Date.now();return{ts:n,sig:Hc({...e,ts:n})}}var Bi=A(require("crypto"),1),Ui=require("path");var jc=F("pairing"),Fi=(0,Ui.join)(V.STATE,"pairing.json"),Di="ABCDEFGHIJKLMNPQRSTUVWXYZ123456789",Wc=2;function Ki(){let e="";for(let n=0;n<Wc;n++)e+=Di[Bi.default.randomInt(Di.length)];return e}function Gc(){let e=Ri(Fi,null);return!e||Date.now()>e.expiresAt?null:e}function Vc(e){try{je(Fi,e)}catch(n){jc.error(`persist pairing state: ${n.message}`)}}function Hi(e,n,r,o=null){Vc({tempKey:e,tail:n,expiresAt:r,workerUrl:o})}function ji(){let e=Gc();return e?{tempKey:e.tempKey,tail:e.tail,expiresAt:e.expiresAt}:null}var lo=F("session"),Yc=10;async function Wn(e,n){let r=async()=>{let o=await W(`${n}/api/temp-key/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify((()=>{let t={apiKey:Q(e),expiryMinutes:Yc};return{...t,...Rt(t)}})())});if(!o.ok){let t=await o.json().catch(()=>null);throw new Error(t?.error||`HTTP ${o.status}`)}return o.json()};try{let o;try{o=await r()}catch(i){if(lo.warn(`Temp key creation failed (${i.message}) \u2014 re-registering session`),!await Pt(e,n))throw i;o=await r()}let t=Ki();return Hi(o.tempKey,t,o.expiresAt,n),{...o,oneTimeKey:`${o.tempKey}${t}`}}catch(o){return lo.error(`Temp key creation failed: ${o?.message||o}`),null}}function Gn(e,n){return n?.tempKey?`${e}/login?k=${n.tempKey}#${n.oneTimeKey}`:`${e}/login`}async function Pt(e,n,r,o){try{let t=await W(`${n}/api/session/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(e),hostPublicKey:lt(),hostX25519Key:ut(),tempKey:ji()?.tempKey||void 0})});if(!t.ok)throw new Error(`HTTP ${t.status}`);return r&&await W(`${n}/api/session/update`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(e),tunnelUrl:r,...Rt({apiKey:Q(e),tunnelUrl:r})})}).catch(()=>{}),o&&Q(o)!==Q(e)&&await W(`${n}/api/session/delete`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(o),...Rt({apiKey:Q(o)})})}).catch(()=>{}),!0}catch(t){return lo.error(`Session registration failed: ${t?.message||t}`),!1}}var ns=A(require("os"),1);var Rr=A(require("readline"),1),Gi=A(require("http"),1);var uo=require("child_process"),qc={screenRecording:"x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",accessibility:"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"};function xr(e){let n=qc[e];n&&process.platform==="darwin"&&(0,uo.exec)(`open "${n}"`,()=>{})}function Re({strategy:e,baseMs:n,maxMs:r},o){let t=Math.max(1,o),i=e==="exp"?n*Math.pow(2,t-1):n*t;return Math.min(i,r)}async function Ar({config:e,task:n,label:r="task",log:o=()=>{},ctx:t={}}){let i=0;for(;!t.cancelled;){i++;try{if(await n(i))return!0}catch(a){o(`\u274C ${r} attempt ${i} error: ${a?.message||a}`)}if(t.cancelled)return!1;let s=Re(e,i);o(`\u{1F504} ${r} retry in ${s}ms (attempt ${i})`),await new Promise(a=>setTimeout(a,s))}return!1}var S={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",orange:"\x1B[38;2;230;138;110m",green:"\x1B[32m",red:"\x1B[31m",yellow:"\x1B[33m",cyan:"\x1B[36m",white:"\x1B[37m"},Vi=()=>Math.min(44,process.stdout.columns||44);function po(e,n=null){let o=Vi()-2,t=(a="")=>{let c=a.replace(/\x1b\[[0-9;]*m/g,""),l=Math.max(0,o-c.length);return S.orange+"\u2551"+S.reset+a+" ".repeat(l)+S.orange+"\u2551"+S.reset},i=(a,c=l=>l)=>{let l=a.replace(/\x1b\[[0-9;]*m/g,""),f=Math.floor((o-l.length)/2),u=o-l.length-f;return S.orange+"\u2551"+S.reset+" ".repeat(f)+c(a)+" ".repeat(u)+S.orange+"\u2551"+S.reset},s=["",S.orange+"\u2554"+"\u2550".repeat(o)+"\u2557"+S.reset,t(),i(`\u{1F680} 9Remote v${e}`,a=>S.bold+S.orange+a+S.reset),i("Remote terminal access from anywhere",a=>S.dim+a+S.reset),t()];return n&&(s.push(i(`\u2B06 New version v${n} available!`,a=>S.yellow+S.bold+a+S.reset)),s.push(i(`Run: npm i -g ${ke}`,a=>S.dim+a+S.reset)),s.push(t())),s.push(S.orange+"\u255A"+"\u2550".repeat(o)+"\u255D"+S.reset),s.push(""),s.join(`
15
+ `).filter(Boolean).slice(-e)}catch{return[]}}var Fc=process.env.NREMOTE_ENV==="development"||process.env.AGENT_DEBUG==="1";function F(e){return{debug:(...n)=>{Fc&&zt(e,"debug",br(n))},info:(...n)=>zt(e,"info",br(n)),warn:(...n)=>zt(e,"warn",br(n)),error:(...n)=>zt(e,"error",br(n))}}var jn=Hn;var ct=A(require("crypto"),1),en=require("fs");var Ni=require("path");var mf=Buffer.from("302a300506032b656e","hex");var Tr=(0,Ni.join)(V.CONFIG,"hostKey.json"),bf=Buffer.from("302a300506032b6570032100","hex"),Zt=null;function co(){if(Zt)return Zt;try{if((0,en.existsSync)(Tr)){let s=JSON.parse((0,en.readFileSync)(Tr,"utf8")),a=Buffer.from(s.publicKey,"base64");if(!s.x25519PrivateKey){let l=ct.default.generateKeyPairSync("x25519");s.x25519PrivateKey=l.privateKey.export({type:"pkcs8",format:"der"}).toString("base64"),s.x25519PublicKey=l.publicKey.export({type:"spki",format:"der"}).toString("base64"),je(Tr,s)}let c=Buffer.from(s.x25519PublicKey,"base64");return Zt={privateKey:ct.default.createPrivateKey({key:Buffer.from(s.privateKey,"base64"),format:"der",type:"pkcs8"}),publicKey:ct.default.createPublicKey({key:a,format:"der",type:"spki"}),publicKeyB64:a.subarray(-32).toString("base64"),x25519PrivateKey:ct.default.createPrivateKey({key:Buffer.from(s.x25519PrivateKey,"base64"),format:"der",type:"pkcs8"}),x25519PublicKeyB64:c.subarray(-32).toString("base64")},Zt}}catch{}(0,en.mkdirSync)(V.CONFIG,{recursive:!0});let{privateKey:e,publicKey:n}=ct.default.generateKeyPairSync("ed25519"),r=n.export({type:"spki",format:"der"}).toString("base64"),o=e.export({type:"pkcs8",format:"der"}).toString("base64"),t=ct.default.generateKeyPairSync("x25519"),i=t.publicKey.export({type:"spki",format:"der"}).toString("base64");return je(Tr,{privateKey:o,publicKey:r,x25519PrivateKey:t.privateKey.export({type:"pkcs8",format:"der"}).toString("base64"),x25519PublicKey:i}),Zt={privateKey:e,publicKey:n,publicKeyB64:Buffer.from(r,"base64").subarray(-32).toString("base64"),x25519PrivateKey:t.privateKey,x25519PublicKeyB64:Buffer.from(i,"base64").subarray(-32).toString("base64")},Zt}function lt(){return co().publicKeyB64}function ut(){return co().x25519PublicKeyB64}var Kc="9remote-session-v1";function Hc({apiKey:e,tunnelUrl:n,localIp:r,expiryMinutes:o,ts:t}){let i=a=>{let c=a==null?"":String(a);return`${c.length}:${c}`},s=`${Kc}|${i(e)}${i(n)}${i(r)}${i(o)}${i(t)}`;return ct.default.sign(null,Buffer.from(s,"utf8"),co().privateKey).toString("base64")}function Rt(e){let n=Date.now();return{ts:n,sig:Hc({...e,ts:n})}}var Bi=A(require("crypto"),1),Ui=require("path");var jc=F("pairing"),Fi=(0,Ui.join)(V.STATE,"pairing.json"),Di="ABCDEFGHIJKLMNPQRSTUVWXYZ123456789",Wc=2;function Ki(){let e="";for(let n=0;n<Wc;n++)e+=Di[Bi.default.randomInt(Di.length)];return e}function Gc(){let e=Ri(Fi,null);return!e||Date.now()>e.expiresAt?null:e}function Vc(e){try{je(Fi,e)}catch(n){jc.error(`persist pairing state: ${n.message}`)}}function Hi(e,n,r,o=null){Vc({tempKey:e,tail:n,expiresAt:r,workerUrl:o})}function ji(){let e=Gc();return e?{tempKey:e.tempKey,tail:e.tail,expiresAt:e.expiresAt}:null}var lo=F("session"),Yc=10;async function Wn(e,n){let r=async()=>{let o=await W(`${n}/api/temp-key/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify((()=>{let t={apiKey:Q(e),expiryMinutes:Yc};return{...t,...Rt(t)}})())});if(!o.ok){let t=await o.json().catch(()=>null);throw new Error(t?.error||`HTTP ${o.status}`)}return o.json()};try{let o;try{o=await r()}catch(i){if(lo.warn(`Temp key creation failed (${i.message}) \u2014 re-registering session`),!await Pt(e,n))throw i;o=await r()}let t=Ki();return Hi(o.tempKey,t,o.expiresAt,n),{...o,oneTimeKey:`${o.tempKey}${t}`}}catch(o){return lo.error(`Temp key creation failed: ${o?.message||o}`),null}}function Gn(e,n){return n?.tempKey?`${e}/login?k=${n.tempKey}#${n.oneTimeKey}`:`${e}/login`}async function Pt(e,n,r,o){try{let t=await W(`${n}/api/session/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(e),hostPublicKey:lt(),hostX25519Key:ut(),tempKey:ji()?.tempKey||void 0})});if(!t.ok)throw new Error(`HTTP ${t.status}`);return r&&await W(`${n}/api/session/update`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(e),tunnelUrl:r,...Rt({apiKey:Q(e),tunnelUrl:r})})}).catch(()=>{}),o&&Q(o)!==Q(e)&&await W(`${n}/api/session/delete`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(o),...Rt({apiKey:Q(o)})})}).catch(()=>{}),!0}catch(t){return lo.error(`Session registration failed: ${t?.message||t}`),!1}}var ns=A(require("os"),1);var Rr=A(require("readline"),1),Gi=A(require("http"),1);var uo=require("child_process"),qc={screenRecording:"x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture",accessibility:"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"};function xr(e){let n=qc[e];n&&process.platform==="darwin"&&(0,uo.exec)(`open "${n}"`,()=>{})}function Re({strategy:e,baseMs:n,maxMs:r},o){let t=Math.max(1,o),i=e==="exp"?n*Math.pow(2,t-1):n*t;return Math.min(i,r)}async function Ar({config:e,task:n,label:r="task",log:o=()=>{},ctx:t={}}){let i=0;for(;!t.cancelled;){i++;try{if(await n(i))return!0}catch(a){o(`\u274C ${r} attempt ${i} error: ${a?.message||a}`)}if(t.cancelled)return!1;let s=Re(e,i);o(`\u{1F504} ${r} retry in ${s}ms (attempt ${i})`),await new Promise(a=>setTimeout(a,s))}return!1}var S={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",orange:"\x1B[38;2;230;138;110m",green:"\x1B[32m",red:"\x1B[31m",yellow:"\x1B[33m",cyan:"\x1B[36m",white:"\x1B[37m"},Vi=()=>Math.min(44,process.stdout.columns||44);function po(e,n=null){let o=Vi()-2,t=(a="")=>{let c=a.replace(/\x1b\[[0-9;]*m/g,""),l=Math.max(0,o-c.length);return S.orange+"\u2551"+S.reset+a+" ".repeat(l)+S.orange+"\u2551"+S.reset},i=(a,c=l=>l)=>{let l=a.replace(/\x1b\[[0-9;]*m/g,""),f=Math.floor((o-l.length)/2),u=o-l.length-f;return S.orange+"\u2551"+S.reset+" ".repeat(f)+c(a)+" ".repeat(u)+S.orange+"\u2551"+S.reset},s=["",S.orange+"\u2554"+"\u2550".repeat(o)+"\u2557"+S.reset,t(),i(`\u{1F680} 9Remote v${e}`,a=>S.bold+S.orange+a+S.reset),i("Remote terminal access from anywhere",a=>S.dim+a+S.reset),t()];return n&&(s.push(i(`\u2B06 New version v${n} available!`,a=>S.yellow+S.bold+a+S.reset)),s.push(i(`Run: npm i -g ${ke}`,a=>S.dim+a+S.reset)),s.push(t())),s.push(S.orange+"\u255A"+"\u2550".repeat(o)+"\u255D"+S.reset),s.push(""),s.join(`
16
16
  `)}function rn(e,n=null){console.log(po(e,n))}var Wi=["\u28FE","\u28FD","\u28FB","\u28BF","\u287F","\u28DF","\u28EF","\u28F7"],fo=[{label:"Preparing",desc:"Checking dependencies"},{label:"Connecting",desc:"Creating session"},{label:"Starting tunnel",desc:"Spawning tunnel"},{label:"Verifying tunnel",desc:"Health check"},{label:"Ready",desc:"Tunnel is live"}],Xc=process.platform==="win32",Jc=Xc?120:80;process.on("exit",()=>{nn&&process.stdout.isTTY&&process.stdout.write("\x1B[?25h")});var Yi=(e,n)=>{nn&&process.stdout.isTTY&&process.stdout.write("\x1B[?25h"),process.listenerCount(e)<=1&&process.exit(n)};process.on("SIGINT",()=>Yi("SIGINT",130));process.on("SIGTERM",()=>Yi("SIGTERM",143));var Ge=0,$t=null,kr=0,Ce=-1,Vn=null,tn=null,nn=!1;function qi(){let e=[],n=Ce===fo.length-1;return fo.forEach((r,o)=>{let t=o===Ce&&Vn?Vn:r.desc;if(o<Ce||n&&o===Ce)e.push(` ${S.green}\u2713${S.reset} ${S.dim}${r.label}${S.reset}`),tn&&o===tn.afterIdx&&e.push(` ${S.green}\u2713${S.reset} ${S.cyan}${tn.text}${S.reset}`);else if(o===Ce){let i=Wi[kr%Wi.length];e.push(` ${S.orange}${i}${S.reset} ${S.bold}${r.label}${S.reset} ${S.dim}${t}${S.reset}`)}else e.push(` ${S.dim}\u25CB ${r.label}${S.reset}`)}),e}function Xi(){let e=qi();Ge>0&&process.stdout.write(`\x1B[${Ge}A\x1B[0J`),process.stdout.write(e.join(`
17
17
  `)+`
18
18
  `),Ge=e.length}function Ji(){if(Ge===0||Ce<0)return;let e=qi();if(e.length!==Ge){Xi();return}let n=Ce+(tn&&tn.afterIdx<Ce?1:0),r=Ge-n;process.stdout.write(`\x1B[${r}A\r\x1B[2K${e[n]}\x1B[${r}B\r`)}function Qc(){nn||(process.stdout.write("\x1B[?25l"),nn=!0)}function Qi(){nn&&(process.stdout.write("\x1B[?25h"),nn=!1)}function zi(e,n=!1,r=null){$t&&(clearInterval($t),$t=null),Ce=e,Vn=r,kr=0,n||(Ge=0),Xi(),e>=0&&e<fo.length-1?(Qc(),$t=setInterval(()=>{kr++,Ji()},Jc)):Qi()}function on(e){Vn=e,Ge>0&&Ji()}function Zi(){$t&&(clearInterval($t),$t=null),Qi(),Ge=0,Ce=-1,Vn=null,tn=null,kr=0}function Ne(e,n,r=0,o="",t=null,i=null){return new Promise(s=>{let a=r,c=!0,l=!0,f=process.platform==="win32",u=()=>{if(!c)return;process.stdout.write(l?"\x1B[2J\x1B[H":"\x1B[H"),l=!1;let w=typeof o=="function"?o():o;if(w)for(let v of w.split(`
@@ -41,7 +41,7 @@ ${s}
41
41
  `:`
42
42
  `)+r,t=o+1,o=e.indexOf(`
43
43
  `,t)}while(o!==-1);return i+=e.slice(t),i}var{stdout:ms,stderr:hs}=fs,vo=Symbol("GENERATOR"),an=Symbol("STYLER"),qn=Symbol("IS_EMPTY"),gs=["ansi","ansi","ansi256","ansi16m"],cn=Object.create(null),sl=(e,n={})=>{if(n.level&&!(Number.isInteger(n.level)&&n.level>=0&&n.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let r=ms?ms.level:0;e.level=n.level===void 0?r:n.level};var al=e=>{let n=(...r)=>r.join(" ");return sl(n,e),Object.setPrototypeOf(n,Xn.prototype),n};function Xn(e){return al(e)}Object.setPrototypeOf(Xn.prototype,Function.prototype);for(let[e,n]of Object.entries(Pe))cn[e]={get(){let r=Ir(this,Eo(n.open,n.close,this[an]),this[qn]);return Object.defineProperty(this,e,{value:r}),r}};cn.visible={get(){let e=Ir(this,this[an],!0);return Object.defineProperty(this,"visible",{value:e}),e}};var bo=(e,n,r,...o)=>e==="rgb"?n==="ansi16m"?Pe[r].ansi16m(...o):n==="ansi256"?Pe[r].ansi256(Pe.rgbToAnsi256(...o)):Pe[r].ansi(Pe.rgbToAnsi(...o)):e==="hex"?bo("rgb",n,r,...Pe.hexToRgb(...o)):Pe[r][e](...o),cl=["rgb","hex","ansi256"];for(let e of cl){cn[e]={get(){let{level:r}=this;return function(...o){let t=Eo(bo(e,gs[r],"color",...o),Pe.color.close,this[an]);return Ir(this,t,this[qn])}}};let n="bg"+e[0].toUpperCase()+e.slice(1);cn[n]={get(){let{level:r}=this;return function(...o){let t=Eo(bo(e,gs[r],"bgColor",...o),Pe.bgColor.close,this[an]);return Ir(this,t,this[qn])}}}}var ll=Object.defineProperties(()=>{},{...cn,level:{enumerable:!0,get(){return this[vo].level},set(e){this[vo].level=e}}}),Eo=(e,n,r)=>{let o,t;return r===void 0?(o=e,t=n):(o=r.openAll+e,t=n+r.closeAll),{open:e,close:n,openAll:o,closeAll:t,parent:r}},Ir=(e,n,r)=>{let o=(...t)=>ul(o,t.length===1?""+t[0]:t.join(" "));return Object.setPrototypeOf(o,ll),o[vo]=e,o[an]=n,o[qn]=r,o},ul=(e,n)=>{if(e.level<=0||!n)return e[qn]?"":n;let r=e[an];if(r===void 0)return n;let{openAll:o,closeAll:t}=r;if(n.includes("\x1B"))for(;r!==void 0;)n=ps(n,r.close,r.open),r=r.parent;let i=n.indexOf(`
44
- `);return i!==-1&&(n=ds(n,t,o,i)),o+n+t};Object.defineProperties(Xn.prototype,cn);var fl=Xn(),Qf=Xn({level:hs?hs.level:0});var h=fl;var ep=process.env.NODE_ENV==="development";var I=process.env.NREMOTE_WORKER_URL||"https://9remote.cc",ys=3e4,ws=500,So=300,$e={cmdMs:1e3,pendingApprovalMs:3e3,statsMs:5e3,serverReadyIntervalMs:200,serverReadyTimeoutMs:5e3,bgServerReadyTimeoutMs:15e3,bgServerReadyIntervalMs:300},ft={intervalMs:2e3,timeoutMs:12e4,fetchTimeoutMs:5e3,dnsTimeoutMs:2e3,maxLogEntries:80,postReadyHoldMs:2e3},ie={killCloudflaredMs:500,killCloudflaredTuiMs:300,serverBootMs:2e3,guestRecheckMs:3e3,trayReadyMs:1e3,postReadyHoldMs:2e3,bgSpawnFlushMs:400};var Ve={maxLogLines:200,headerWidth:44},Ye={checkIntervalMs:36e5,connectCheckDebounceMs:9e5,maxRetry:3,retryDelayMs:3e3,verifyTimeoutMs:15e3,lockTtlMs:3e5,lockFile:"update.lock",gateTimeoutMs:6e4},vs=5e3,To=12e4;var _r=1500,bs=2,Es=3e4,me={orange:h.rgb(230,138,110),orangeDim:h.rgb(200,120,95)};function Ss(){return process.env.CODESPACES==="true"}var pl=xo.default.dirname((0,xs.fileURLToPath)(__importMetaUrl));async function pt(){let e=await Xt();if(Ss()&&process.env.NREMOTE_API_KEY)return We(e,process.env.NREMOTE_API_KEY,"Codespace");let n=Kn();if(n.key)Ai(n.key)&&(n=await dl(e,n));else{let r=kt(e);n=We(e,r,"Default")}return n}async function dl(e,n){if(await X())return n;let r=kt(e);if(Y().remoteEnabled===!1)return We(e,r,n.name||"Default");await Pt(r,I,null,n.key);let o=Kn();return oo(o.key)?o:We(e,r,n.name||"Default")}function De(){return"3.0.40"}var z=require("fs"),Cs=require("url"),un=require("child_process"),Ee=A(require("path"),1),dt=A(require("os"),1);var ln=A(require("fs"),1),Ao=A(require("path"),1),As=A(require("os"),1),ks=require("child_process"),Lr=Ao.default.join(As.default.homedir(),".9remote","pids");function ml(){try{ln.default.existsSync(Lr)||ln.default.mkdirSync(Lr,{recursive:!0})}catch{}}function ko(e){return Ao.default.join(Lr,`${e}.pid`)}function Be(e,n){if(n)try{ml(),ln.default.writeFileSync(ko(e),String(n))}catch{}}function Jn(e){try{let n=ln.default.readFileSync(ko(e),"utf8").trim(),r=parseInt(n,10);return Number.isFinite(r)&&r>0?r:null}catch{return null}}function qe(e){try{ln.default.unlinkSync(ko(e))}catch{}}function Ro(e){if(!e)return!1;try{return process.kill(e,0),!0}catch{return!1}}function hl(e){let n=Jn(e);if(qe(e),!n)return!1;try{process.platform==="win32"?(0,ks.execSync)(`taskkill /F /T /PID ${n}`,{stdio:"ignore",windowsHide:!0}):process.kill(n,"SIGKILL")}catch{}return!0}var gl=["cloudflared","agent"];function Rs(){for(let e of gl)hl(e)}function Ps(){return Lr}var _t=require("child_process"),B=require("fs"),Ot=require("path"),$o=A(require("os"),1),It=A(require("path"),1),Os=require("url");var Cr=(0,Ot.join)(V.LOGS,"autostart.log"),Mr="cc.9remote.agent",Nr="9Remote",Dr=["--tray","--skip-update","--start"],Qn=$o.default.homedir(),$s=It.default.dirname((0,Os.fileURLToPath)(__importMetaUrl)),se={darwin:(0,Ot.join)(Qn,"Library","LaunchAgents",`${Mr}.plist`),linux:(0,Ot.join)(Qn,".config","autostart",`${Mr}.desktop`),linuxSystemd:(0,Ot.join)(Qn,".config","systemd","user",`${Mr}.service`),win:(0,Ot.join)(process.env.APPDATA||"","Microsoft","Windows","Start Menu","Programs","Startup",`${Nr}.vbs`)};function Xe(){for(let e=$s,n=null;e!==n;n=e,e=It.default.dirname(e)){let r=It.default.join(e,"package.json");if((0,B.existsSync)(r)){try{let o=JSON.parse((0,B.readFileSync)(r,"utf8"));if(o.name!==ee)continue;let t=typeof o.bin=="string"?o.bin:o.bin?.[ee];if(t){let i=It.default.resolve(e,t);if((0,B.existsSync)(i))return i}}catch{}break}}return process.argv[1]||It.default.resolve($s,"..","index.js")}function Oe(){return process.execPath}function Oo(){return process.versions.electron?"env ELECTRON_RUN_AS_NODE=1 ":""}function Is(e){let n=Oe(),r=Xe();if(process.platform==="win32"){let t=e.join(" "),i=(0,Ot.join)($o.default.tmpdir(),`${ee}-launch.vbs`);return(0,B.writeFileSync)(i,`CreateObject("WScript.Shell").Run """${n}"" ""${r}"" ${t}", 0, False
44
+ `);return i!==-1&&(n=ds(n,t,o,i)),o+n+t};Object.defineProperties(Xn.prototype,cn);var fl=Xn(),Qf=Xn({level:hs?hs.level:0});var h=fl;var ep=process.env.NREMOTE_ENV==="development";var I=process.env.NREMOTE_WORKER_URL||"https://9remote.cc",ys=3e4,ws=500,So=300,$e={cmdMs:1e3,pendingApprovalMs:3e3,statsMs:5e3,serverReadyIntervalMs:200,serverReadyTimeoutMs:5e3,bgServerReadyTimeoutMs:15e3,bgServerReadyIntervalMs:300},ft={intervalMs:2e3,timeoutMs:12e4,fetchTimeoutMs:5e3,dnsTimeoutMs:2e3,maxLogEntries:80,postReadyHoldMs:2e3},ie={killCloudflaredMs:500,killCloudflaredTuiMs:300,serverBootMs:2e3,guestRecheckMs:3e3,trayReadyMs:1e3,postReadyHoldMs:2e3,bgSpawnFlushMs:400};var Ve={maxLogLines:200,headerWidth:44},Ye={checkIntervalMs:36e5,connectCheckDebounceMs:9e5,maxRetry:3,retryDelayMs:3e3,verifyTimeoutMs:15e3,lockTtlMs:3e5,lockFile:"update.lock",gateTimeoutMs:6e4},vs=5e3,To=12e4,_r=1500,bs=2,Es=3e4,me={orange:h.rgb(230,138,110),orangeDim:h.rgb(200,120,95)};function Ss(){return process.env.CODESPACES==="true"}var pl=xo.default.dirname((0,xs.fileURLToPath)(__importMetaUrl));async function pt(){let e=await Xt();if(Ss()&&process.env.NREMOTE_API_KEY)return We(e,process.env.NREMOTE_API_KEY,"Codespace");let n=Kn();if(n.key)Ai(n.key)&&(n=await dl(e,n));else{let r=kt(e);n=We(e,r,"Default")}return n}async function dl(e,n){if(await X())return n;let r=kt(e);if(Y().remoteEnabled===!1)return We(e,r,n.name||"Default");await Pt(r,I,null,n.key);let o=Kn();return oo(o.key)?o:We(e,r,n.name||"Default")}function De(){return"3.0.46"}var z=require("fs"),Cs=require("url"),un=require("child_process"),Ee=A(require("path"),1),dt=A(require("os"),1);var ln=A(require("fs"),1),Ao=A(require("path"),1),As=A(require("os"),1),ks=require("child_process"),Lr=Ao.default.join(As.default.homedir(),".9remote","pids");function ml(){try{ln.default.existsSync(Lr)||ln.default.mkdirSync(Lr,{recursive:!0})}catch{}}function ko(e){return Ao.default.join(Lr,`${e}.pid`)}function Be(e,n){if(n)try{ml(),ln.default.writeFileSync(ko(e),String(n))}catch{}}function Jn(e){try{let n=ln.default.readFileSync(ko(e),"utf8").trim(),r=parseInt(n,10);return Number.isFinite(r)&&r>0?r:null}catch{return null}}function qe(e){try{ln.default.unlinkSync(ko(e))}catch{}}function Ro(e){if(!e)return!1;try{return process.kill(e,0),!0}catch{return!1}}function hl(e){let n=Jn(e);if(qe(e),!n)return!1;try{process.platform==="win32"?(0,ks.execSync)(`taskkill /F /T /PID ${n}`,{stdio:"ignore",windowsHide:!0}):process.kill(n,"SIGKILL")}catch{}return!0}var gl=["cloudflared","agent"];function Rs(){for(let e of gl)hl(e)}function Ps(){return Lr}var _t=require("child_process"),B=require("fs"),Ot=require("path"),$o=A(require("os"),1),It=A(require("path"),1),Os=require("url");var Cr=(0,Ot.join)(V.LOGS,"autostart.log"),Mr="cc.9remote.agent",Nr="9Remote",Dr=["--tray","--skip-update","--start"],Qn=$o.default.homedir(),$s=It.default.dirname((0,Os.fileURLToPath)(__importMetaUrl)),se={darwin:(0,Ot.join)(Qn,"Library","LaunchAgents",`${Mr}.plist`),linux:(0,Ot.join)(Qn,".config","autostart",`${Mr}.desktop`),linuxSystemd:(0,Ot.join)(Qn,".config","systemd","user",`${Mr}.service`),win:(0,Ot.join)(process.env.APPDATA||"","Microsoft","Windows","Start Menu","Programs","Startup",`${Nr}.vbs`)};function Xe(){for(let e=$s,n=null;e!==n;n=e,e=It.default.dirname(e)){let r=It.default.join(e,"package.json");if((0,B.existsSync)(r)){try{let o=JSON.parse((0,B.readFileSync)(r,"utf8"));if(o.name!==ee)continue;let t=typeof o.bin=="string"?o.bin:o.bin?.[ee];if(t){let i=It.default.resolve(e,t);if((0,B.existsSync)(i))return i}}catch{}break}}return process.argv[1]||It.default.resolve($s,"..","index.js")}function Oe(){return process.execPath}function Oo(){return process.versions.electron?"env ELECTRON_RUN_AS_NODE=1 ":""}function Is(e){let n=Oe(),r=Xe();if(process.platform==="win32"){let t=e.join(" "),i=(0,Ot.join)($o.default.tmpdir(),`${ee}-launch.vbs`);return(0,B.writeFileSync)(i,`CreateObject("WScript.Shell").Run """${n}"" ""${r}"" ${t}", 0, False
45
45
  `),(0,_t.execFile)("wscript.exe",[i],{windowsHide:!0}).unref?.(),null}let o=(0,_t.spawn)(n,[r,...e],{detached:!0,stdio:"ignore"});return o.unref(),o.pid||null}function _s(){let e=It.default.dirname(Oe()),n=["/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin","/opt/homebrew/bin"];return n.includes(e)||n.unshift(e),n.join(":")}function Po(e){return String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function yl(e,n){let r=[e,n,...Dr].map(o=>` <string>${Po(o)}</string>`).join(`
46
46
  `);return`<?xml version="1.0" encoding="UTF-8"?>
47
47
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -96,7 +96,7 @@ StandardError=append:${Cr}
96
96
 
97
97
  [Install]
98
98
  WantedBy=default.target
99
- `}function xl(e){try{return(0,_t.execFileSync)("systemctl",["--user",...e],{stdio:"ignore"}),!0}catch{return!1}}function Al(){return(0,B.existsSync)(se.linux)||(0,B.existsSync)(se.linuxSystemd)}async function kl(){try{if(process.platform==="darwin")return wl();if(process.platform==="win32")return await El();if(process.platform==="linux")return Al()}catch{}return!1}async function Ls(){try{if(process.platform==="win32"&&bl(),!await kl())return!1;if(process.platform==="darwin"){let e=yl(Oe(),Xe());return((0,B.existsSync)(se.darwin)?(0,B.readFileSync)(se.darwin,"utf8"):"")===e?!1:((0,B.writeFileSync)(se.darwin,e),!0)}if(process.platform==="win32"){let e=vl();return((0,B.existsSync)(se.win)?(0,B.readFileSync)(se.win,"utf8"):"")===e?!1:((0,B.writeFileSync)(se.win,e),!0)}if(process.platform==="linux"){if((0,B.existsSync)(se.linuxSystemd)){let e=Tl();return(0,B.readFileSync)(se.linuxSystemd,"utf8")===e?!1:((0,B.writeFileSync)(se.linuxSystemd,e),xl(["daemon-reload"]),!0)}if((0,B.existsSync)(se.linux)){let e=Sl();return(0,B.readFileSync)(se.linux,"utf8")===e?!1:((0,B.writeFileSync)(se.linux,e),!0)}}}catch{}return!1}var Mt=F("update"),Rl=Ee.default.dirname((0,Cs.fileURLToPath)(__importMetaUrl)),Ns=(0,z.existsSync)("/.dockerenv"),Ds=8e3;var Lt=2208,Io=Ee.default.join(dt.default.homedir(),".9remote","cloudflared.pid");function Pl(){try{Rs()}catch{}try{if((0,z.existsSync)(Io)){let e=parseInt((0,z.readFileSync)(Io,"utf8"));if(Number.isFinite(e))try{process.kill(e)}catch{}try{(0,z.unlinkSync)(Io)}catch{}}}catch{}try{process.platform==="win32"?(0,un.execSync)(`for /f "tokens=5" %a in ('netstat -aon ^| findstr :${Lt}') do taskkill /F /PID %a`,{stdio:"ignore",windowsHide:!0}):(0,un.execSync)(`lsof -ti:${Lt} | xargs kill -9 2>/dev/null || true`,{stdio:"ignore"})}catch{}if(process.platform==="win32"){let e=Date.now()+1500;for(;Date.now()<e;);}}function Bs(){return"3.0.40"}function Us(e,n){let r=e.split(".").map(Number),o=n.split(".").map(Number);for(let t=0;t<3;t++){if(o[t]>r[t])return!0;if(o[t]<r[t])return!1}return!1}function $l(){return process.env.CODESPACES==="true"||process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN?"GitHub Codespaces":Ns?"Docker":null}function Br(){Pl()}async function Fs(){try{let e=Bs();if(!e)return null;let n=await W(to,{signal:AbortSignal.timeout(Ds)});if(!n.ok)return null;let{version:r}=await n.json();return r&&Us(e,r)?{current:e,latest:r}:null}catch{return null}}var Ct=Ee.default.join(V.STATE,Ye.lockFile);function Ol(){try{if((0,z.existsSync)(Ct)){let{pid:e,ts:n}=JSON.parse((0,z.readFileSync)(Ct,"utf8")),r=Date.now()-n<Ye.lockTtlMs,o=!1;try{process.kill(e,0),o=!0}catch{}if(r&&o)return!1}}catch{}try{(0,z.writeFileSync)(Ct,JSON.stringify({pid:process.pid,ts:Date.now()}))}catch{}return!0}async function Il(){try{let e=await W(to,{signal:AbortSignal.timeout(Ds)});if(!e.ok)return null;let{version:n}=await e.json();return n||null}catch{return null}}function Ks(){try{if(process.env.NREMOTE_REGISTRY)return`--registry ${new URL(process.env.NREMOTE_REGISTRY).origin}`}catch{}return""}function Hs(){let e=Xe(),n=Ee.default.sep,r=`${n}lib${n}node_modules${n}`,o=e.indexOf(r);return o>0?{global:"-g",prefix:`--prefix "${e.slice(0,o)}"`}:(o=e.indexOf(`${n}node_modules${n}`),o>0?{global:"",prefix:`--prefix "${e.slice(0,o)}"`}:{global:"-g",prefix:""})}function Ms(){let e=process.argv.slice(2).filter(t=>t!=="--skip-update"),r=e.includes("ui")||e.includes("start")||e.some(t=>["--tray","--auto","--start"].includes(t))?e.join(" "):"--tray";return`${r.includes("--start")||r.includes("start")?r:`${r} --start`} --skip-update`}function js(){let e=process.env.NREMOTE_NPM_CLI;return e&&(0,z.existsSync)(e)?process.platform==="win32"?`"${Oe()}" "${e}"`:`env ELECTRON_RUN_AS_NODE=1 "${Oe()}" "${e}"`:"npm"}function _l(e,n){let r=Ee.default.join(dt.default.tmpdir(),`${ee}-gate.cjs`),o=`const http = require("http");
99
+ `}function xl(e){try{return(0,_t.execFileSync)("systemctl",["--user",...e],{stdio:"ignore"}),!0}catch{return!1}}function Al(){return(0,B.existsSync)(se.linux)||(0,B.existsSync)(se.linuxSystemd)}async function kl(){try{if(process.platform==="darwin")return wl();if(process.platform==="win32")return await El();if(process.platform==="linux")return Al()}catch{}return!1}async function Ls(){try{if(process.platform==="win32"&&bl(),!await kl())return!1;if(process.platform==="darwin"){let e=yl(Oe(),Xe());return((0,B.existsSync)(se.darwin)?(0,B.readFileSync)(se.darwin,"utf8"):"")===e?!1:((0,B.writeFileSync)(se.darwin,e),!0)}if(process.platform==="win32"){let e=vl();return((0,B.existsSync)(se.win)?(0,B.readFileSync)(se.win,"utf8"):"")===e?!1:((0,B.writeFileSync)(se.win,e),!0)}if(process.platform==="linux"){if((0,B.existsSync)(se.linuxSystemd)){let e=Tl();return(0,B.readFileSync)(se.linuxSystemd,"utf8")===e?!1:((0,B.writeFileSync)(se.linuxSystemd,e),xl(["daemon-reload"]),!0)}if((0,B.existsSync)(se.linux)){let e=Sl();return(0,B.readFileSync)(se.linux,"utf8")===e?!1:((0,B.writeFileSync)(se.linux,e),!0)}}}catch{}return!1}var Mt=F("update"),Rl=Ee.default.dirname((0,Cs.fileURLToPath)(__importMetaUrl)),Ns=(0,z.existsSync)("/.dockerenv"),Ds=8e3;var Lt=2208,Io=Ee.default.join(dt.default.homedir(),".9remote","cloudflared.pid");function Pl(){try{Rs()}catch{}try{if((0,z.existsSync)(Io)){let e=parseInt((0,z.readFileSync)(Io,"utf8"));if(Number.isFinite(e))try{process.kill(e)}catch{}try{(0,z.unlinkSync)(Io)}catch{}}}catch{}try{process.platform==="win32"?(0,un.execSync)(`for /f "tokens=5" %a in ('netstat -aon ^| findstr :${Lt}') do taskkill /F /PID %a`,{stdio:"ignore",windowsHide:!0}):(0,un.execSync)(`lsof -ti:${Lt} | xargs kill -9 2>/dev/null || true`,{stdio:"ignore"})}catch{}if(process.platform==="win32"){let e=Date.now()+1500;for(;Date.now()<e;);}}function Bs(){return"3.0.46"}function Us(e,n){let r=e.split(".").map(Number),o=n.split(".").map(Number);for(let t=0;t<3;t++){if(o[t]>r[t])return!0;if(o[t]<r[t])return!1}return!1}function $l(){return process.env.CODESPACES==="true"||process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN?"GitHub Codespaces":Ns?"Docker":null}function Br(){Pl()}async function Fs(){try{let e=Bs();if(!e)return null;let n=await W(to,{signal:AbortSignal.timeout(Ds)});if(!n.ok)return null;let{version:r}=await n.json();return r&&Us(e,r)?{current:e,latest:r}:null}catch{return null}}var Ct=Ee.default.join(V.STATE,Ye.lockFile);function Ol(){try{if((0,z.existsSync)(Ct)){let{pid:e,ts:n}=JSON.parse((0,z.readFileSync)(Ct,"utf8")),r=Date.now()-n<Ye.lockTtlMs,o=!1;try{process.kill(e,0),o=!0}catch{}if(r&&o)return!1}}catch{}try{(0,z.writeFileSync)(Ct,JSON.stringify({pid:process.pid,ts:Date.now()}))}catch{}return!0}async function Il(){try{let e=await W(to,{signal:AbortSignal.timeout(Ds)});if(!e.ok)return null;let{version:n}=await e.json();return n||null}catch{return null}}function Ks(){try{if(process.env.NREMOTE_REGISTRY)return`--registry ${new URL(process.env.NREMOTE_REGISTRY).origin}`}catch{}return""}function Hs(){let e=Xe(),n=Ee.default.sep,r=`${n}lib${n}node_modules${n}`,o=e.indexOf(r);return o>0?{global:"-g",prefix:`--prefix "${e.slice(0,o)}"`}:(o=e.indexOf(`${n}node_modules${n}`),o>0?{global:"",prefix:`--prefix "${e.slice(0,o)}"`}:{global:"-g",prefix:""})}function Ms(){let e=process.argv.slice(2).filter(t=>t!=="--skip-update"),r=e.includes("ui")||e.includes("start")||e.some(t=>["--tray","--auto","--start"].includes(t))?e.join(" "):"--tray";return`${r.includes("--start")||r.includes("start")?r:`${r} --start`} --skip-update`}function js(){let e=process.env.NREMOTE_NPM_CLI;return e&&(0,z.existsSync)(e)?process.platform==="win32"?`"${Oe()}" "${e}"`:`env ELECTRON_RUN_AS_NODE=1 "${Oe()}" "${e}"`:"npm"}function _l(e,n){let r=Ee.default.join(dt.default.tmpdir(),`${ee}-gate.cjs`),o=`const http = require("http");
100
100
  const PORT = ${e};
101
101
  const EXIT_MS = ${n};
102
102
  const HTML = '<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>9Remote</title><style>body{margin:0;height:100vh;display:flex;align-items:center;justify-content:center;background:#101218;color:#c9ced6;font-family:system-ui,-apple-system,sans-serif}.spin{width:26px;height:26px;border:3px solid #2a2f3a;border-top-color:#e68a6e;border-radius:50%;animation:r 1s linear infinite;margin:0 auto 14px}@keyframes r{to{transform:rotate(360deg)}}</style></head><body><div><div class="spin"></div><div>9Remote is updating\u2026</div></div><script>setInterval(function(){fetch("/api/health",{cache:"no-store"}).then(function(r){if(r.ok)location.reload()}).catch(function(){})},1500)</script></body></html>';
@@ -252,7 +252,7 @@ kill -9 ${r} 2>/dev/null
252
252
  `,"utf8");let s=!1,a=()=>{if(!s){s=!0;try{G.default.rmSync(t,{recursive:!0,force:!0})}catch{}}},c=(0,ze.spawn)(o,["tunnel","--url",`http://localhost:${e}`,"--config",i,"--no-autoupdate","--protocol","http2"],{detached:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"]});return Be("cloudflared",c.pid),gn=c.pid,or=!1,new Promise((l,f)=>{let u=!1,p=null,d="",m=setTimeout(()=>{if(!u){u=!0,a(),gn===c.pid&&(gn=null);try{c.kill("SIGKILL")}catch{}qe("cloudflared"),f(new Error("Quick tunnel timed out after 90s"))}},9e4),w=v=>{let P=v.toString();d+=P,d.length>4096&&(d=d.slice(-4096));let E=Zl(P);if(E){if(!u){u=!0,p=E,Se=E,bn=Date.now(),Qe=0,ar=0,yn=null,clearTimeout(m),a(),su(),ne.info(`tunnel ready: ${E}`),l({child:c,tunnelUrl:E});return}E!==p&&(ne.info(`URL rotated: ${E}`),p=E,Se=E,bn=Date.now(),Qe=0,ar=0,n?.(E))}};c.stdout.on("data",w),c.stderr.on("data",w),c.on("error",v=>{u||(u=!0,clearTimeout(m),a(),f(v))}),c.on("exit",(v,P)=>{a();let E=gn!==c.pid,x=or||E;if(ne.info(`cloudflared exited (intentional=${or} superseded=${E})`),x||Dt("unreachable"),!u){u=!0,clearTimeout(m);let R=d.trim().split(`
253
253
  `).slice(-5).join(" | ");gn=null,f(new Error(`cloudflared exited (code=${v}, signal=${P}) output: ${R||"(empty)"}`));return}x||ir(e,`quick tunnel exit code ${v}`)})})}function Fr(e){if(En)try{(0,ze.execSync)(`taskkill /PID ${e} /T /F`,{windowsHide:!0,stdio:"ignore"})}catch{}else try{process.kill(e,"SIGKILL")}catch{}}function eu(e){return e?e.split(`
254
254
  `).flatMap(n=>{let r=n.match(/^\s*(\d+)\s+(.+)$/);return r?[{pid:Number(r[1]),args:r[2].trim()}]:[]}):[]}function tu(e,n){return Array.isArray(e)?e.filter(r=>{if(!r?.args||typeof r.pid!="number")return!1;let o=r.args.split(/\s+/);return o.includes(n)&&o.includes("tunnel")}).map(r=>r.pid):[]}function nu(e){try{let n=En?(0,ze.execSync)(`powershell -NoProfile -Command "Get-CimInstance Win32_Process -Filter 'Name=\\'cloudflared.exe\\'' | ForEach-Object { \\"$($_.ProcessId) $($_.CommandLine)\\"" }"`,{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}):(0,ze.execSync)("ps -eo pid=,args=",{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return tu(eu(n),e)}catch{return[]}}function ru(e){let n=nu(e);for(let r of n)r!==process.pid&&(ne.info(`killing leftover cloudflared pid=${r}`),Fr(r));return n}function ou(e){try{let n=[];if(En){let r=`Get-NetTCPConnection -LocalPort ${e} -State Established -ErrorAction SilentlyContinue | Where-Object { (Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue).Name -eq 'cloudflared' } | Select-Object -ExpandProperty OwningProcess -Unique`;n=(0,ze.execSync)(`powershell -NoProfile -Command "${r}"`,{encoding:"utf8",windowsHide:!0,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).map(t=>+t.trim()).filter(Boolean)}else n=(0,ze.execSync)(`lsof -nP -iTCP:${e} -sTCP:ESTABLISHED 2>/dev/null | awk '/cloudflar/ {print $2}' | sort -u`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).split(`
255
- `).map(o=>+o.trim()).filter(Boolean);for(let r of new Set(n))Fr(r)}catch{}}function ce(){if(!Uo){Uo=!0;try{try{if(G.default.existsSync(Fo)){let n=parseInt(G.default.readFileSync(Fo,"utf8"));Number.isFinite(n)&&(or=!0,Fr(n)),G.default.unlinkSync(Fo)}}catch{}let e=Jn("cloudflared");or=!0,gn=null,e&&(Fr(e),qe("cloudflared")),ou($)}finally{setTimeout(()=>{Uo=!1},2e3)}}}function ca(){if(!Se)return!1;let e=Jn("cloudflared");return!!e&&Ro(e)}function la(){tr=0,vn=!1,sr=null,wn=null,Se=null,Qe=0,ar=0,yn=null,au()}var iu=/^(utun|awdl|llw|anpi|bridge|gif|stf|ipsec|ap|tun|tap|vmnet|veth|docker)/i;function na(){let e=gt.default.networkInterfaces(),n=[];for(let[r,o]of Object.entries(e))if(o&&!iu.test(r))for(let t of o)!t.internal&&t.family==="IPv4"&&n.push(`${r}:${t.address}`);return n.sort().join("|")}function su(){rr||(Ur=na(),Do=Date.now(),rr=setInterval(async()=>{try{let e=Date.now(),n=e-Do;if(Do=e,Ko||vn||!sr||wn==null)return;if(n>Wl){if(ne.info(`Sleep/wake detected (gap=${n}ms)`),Se){let s=!1;for(let a=0;a<3;a++){if((await pn(Se)).ok){s=!0;break}a<2&&await new Promise(l=>setTimeout(l,3e3))}if(s)return;ne.info("tunnel unresponsive after sleep \u2192 restarting")}Dt("unreachable"),ce(),ir(wn,"woke from sleep");return}let r=na(),o=r!==Ur;Ur=r;let t=Jn("cloudflared"),i=!t||!Ro(t);if(!o&&!i){if(Se&&bn&&Date.now()-bn>ea&&e-ar>=Je.edgeProbeIntervalMs){ar=e;let s=await pn(Se);if(s.ok)Qe=0;else if(++Qe>=Je.edgeProbeFailureThreshold){let a=await Hl(Je.readyTimeoutMs);if(a>0){ne.info(`edge probe failing but cloudflared holds ${a} connection(s) \u2014 not restarting`),Qe=0;return}ne.warn(`tunnel unreachable but cloudflared alive \u2014 edge lost after ${Qe} probes (ready=${a??"unknown"}), restarting`),Qe=0,Dt("unreachable"),ce(),ir(wn,"tunnel unreachable (edge lost)")}else ne.debug(`edge probe failed (${Qe}/${Je.edgeProbeFailureThreshold}) \u2014 ${s.dnsCode??s.httpStatus??"no response"}`)}return}if(o&&!i&&bn&&Date.now()-bn<ea||(o&&ne.info("Network change detected"),i&&ne.warn("cloudflared not alive \u2014 watchdog"),Dt("unreachable"),await new Promise(s=>setTimeout(s,Je.networkRestoreDelayMs)),!await ia()))return;if(o&&!i&&Se){let s=!1;for(let a=0;a<2;a++){if((await pn(Se)).ok){s=!0;break}a===0&&await new Promise(l=>setTimeout(l,2e3))}if(s){ne.info("Tunnel survived network change, skip restart");return}}o&&!i&&ce(),ir(wn,o?"network change":"liveness watchdog")}catch(e){ne.error(`network monitor tick failed: ${e?.message||e}`)}},Je.networkCheckIntervalMs))}function au(){rr&&(clearInterval(rr),rr=null),Ur=null}Ft();async function yt(e,n={}){let r=n.intervalMs??ft.intervalMs,o=n.timeoutMs??ft.timeoutMs,t=`${e}/api/health`,i=(()=>{try{return new URL(e).hostname}catch{return null}})(),s=Date.now(),a=0,c=[];await j({healthCheck:{running:!0,timeoutMs:o,startedAt:s,logs:[]}});let l=f=>{c.push(f);let u=c.length>ft.maxLogEntries?c.slice(-ft.maxLogEntries):c;j({healthCheck:{running:!0,timeoutMs:o,startedAt:s,logs:u}})};for(;Date.now()-s<o;){if(a++,fn(),i){let u=await Lo(i,ft.dnsTimeoutMs);if(!u.ok){let p=u.code==="ENOTFOUND"||u.code==="ETIMEOUT"||u.code==="ESERVFAIL",d=p?"connecting...":u.code;on(`#${a} \u2192 ${d}`),l({attempt:a,status:d,elapsedMs:u.elapsedMs,ok:!1,waiting:p,time:Date.now()}),await new Promise(m=>setTimeout(m,r));continue}}let f=Date.now();try{let u=await W(t,{signal:AbortSignal.timeout(ft.fetchTimeoutMs)}),p=Date.now()-f;if(on(`#${a} \u2192 ${u.status}`),l({attempt:a,status:String(u.status),elapsedMs:p,ok:u.ok,time:Date.now()}),u.ok)return await j({healthCheck:{running:!1,timeoutMs:0,startedAt:null,logs:[]}}),await new Promise(d=>setTimeout(d,ft.postReadyHoldMs)),!0}catch(u){let p=Date.now()-f,d=u.cause?.code||u.code||u.message,m=d==="ENOTFOUND",w=m?"connecting...":d;on(`#${a} \u2192 ${w}`),l({attempt:a,status:w,elapsedMs:p,ok:!1,waiting:m,time:Date.now()})}await new Promise(u=>setTimeout(u,r))}return await j({healthCheck:{running:!1,timeoutMs:o,startedAt:s,logs:c}}),!1}var tt=F("tunnel"),Wo=null,ba=null,Ea=0;async function Kt(e,n){if(tt.debug(`updateTunnelUrl: key=${e?.slice(0,8)} url=${n}`),Y().remoteEnabled===!1)return;if(Ht(e),n&&n===ba&&Date.now()-Ea<vs){tt.debug("updateTunnelUrl: skipped (debounce, same URL)");return}Wo&&(Wo.cancelled=!0);let r={cancelled:!1};Wo=r;let o=is();Ar({config:ge.urlSync,label:`urlSync ${n}`,log:t=>tt.warn(t),ctx:r,task:async()=>{let t=await W(`${I}/api/session/update`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify((()=>{let s={apiKey:Q(e),tunnelUrl:n,localIp:o?`${o}:${$}`:null};return{...s,...Rt(s)}})())});if(r.cancelled)return!0;if(t.ok)return ba=n,Ea=Date.now(),tt.debug(`urlSync OK: pushed ${n} to server`),du(n),!0;let i=await t.text().catch(()=>"");return tt.warn(`urlSync HTTP ${t.status}: ${i.slice(0,200)}`),!1}}),n&&Js(n)}var An=null,kn=null,Go=!1,Yo=0;async function qo(e,n){let r={apiKey:e,online:n},o=await W(`${I}/api/session/heartbeat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...r,...Rt(r)})});return o.ok||tt.warn(`heartbeat online=${n} HTTP ${o.status}`),o.ok}async function Vo(){if(!(Go||!kn)){Go=!0;try{await qo(kn,!0),Yo=Date.now()}catch(e){tt.debug(`heartbeat failed: ${e?.message||e}`)}finally{Go=!1}}}function Ht(e){let n=Q(e);if(n&&Y().remoteEnabled!==!1){if(An&&kn===n){Date.now()-Yo>=To&&Vo();return}Hr(),kn=n,Vo(),An=setInterval(Vo,To),An.unref?.()}}function Hr({offline:e=!1}={}){An&&(clearInterval(An),An=null);let n=kn;return kn=null,Yo=0,!e||!n?null:qo(n,!1).catch(r=>tt.debug(`goodbye failed: ${r?.message||r}`))}function wt(e){let n=Q(e);if(!n)return Promise.resolve(!1);Hr();let r=qo(n,!1).catch(o=>(tt.debug(`offline mark failed: ${o?.message||o}`),!1));return Promise.race([r,new Promise(o=>setTimeout(()=>o(!1),_r))])}var ur=null;async function du(e){if(ur?.url===e)return;let n={url:e};ur=n,Qs();try{let r=await yt(e,{timeoutMs:Es});if(ur!==n)return;r&&Dt("healthy")}catch{}finally{ur===n&&(ur=null),zs()}}var nt=F("server"),Aa=jr.default.dirname((0,xa.fileURLToPath)(__importMetaUrl)),mu=jr.default.resolve(Aa,"./server.cjs"),Sa=jr.default.resolve(Aa,"../../index.js");function Wr(e){try{process.platform==="win32"?(0,fr.execSync)(`for /f "tokens=5" %a in ('netstat -aon ^| findstr :${e}') do taskkill /F /PID %a`,{stdio:"ignore",windowsHide:!0}):(0,fr.execSync)(`lsof -ti:${e} | xargs kill -9 2>/dev/null || true`,{stdio:"ignore"})}catch{}}function vt(e,n,r){let o=null,t=!1,i=!1,s=!0,a=0,c=null,l=()=>{s&&(Wr($),s=!1);let f=process.env.NODE_ENV==="development"&&Xo.default.existsSync(Sa),u=f?Sa:mu;Xo.default.existsSync(u)||(nt.error(`Server not found: ${u}`),process.exit(1));let p={...process.env,PORT:String($)};f||delete p.NODE_ENV,o=(0,fr.spawn)(pi,[u],{cwd:V.ROOT,stdio:["ignore","inherit","inherit"],detached:!1,windowsHide:!0,env:di(p)}),c&&clearTimeout(c),c=setTimeout(()=>{a=0},ys),o.on("exit",(d,m)=>{if(c&&(clearTimeout(c),c=null),t)return;if(i){i=!1,nt.info("Restarting server (requested)..."),setTimeout(()=>{l(),r?.()},500);return}nt.error(`Server exited unexpectedly (code: ${d}, signal: ${m})`),a++;let w=Re(ge.server,a);nt.warn(`Restarting server in ${w}ms (fail#${a})`),n&&n(),setTimeout(()=>{l(),r?.()},w)}),o.on("error",d=>{nt.error(`Server error: ${d.message}`)}),e?.(o)};return l(),{getProcess:()=>o,shutdown:()=>{if(t=!0,!!o){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{try{o&&o.kill("SIGKILL")}catch{}},2e3)}},restart:()=>{if(!o)return!1;i=!0;try{o.kill("SIGTERM")}catch{}return setTimeout(()=>{try{o&&i&&o.kill("SIGKILL")}catch{}},2e3),!0}}}function ka(e){return e?.restart?e.restart():!1}function rt({serverManager:e,tunnelProcess:n,exit:r=!0,code:o=0}={}){try{er()}catch{}try{e?.shutdown?.()}catch{}try{n?.kill?.()}catch{}try{ce()}catch{}try{Bt()}catch{}try{Wr($)}catch{}try{la()}catch{}try{Oi()}catch{}try{qe("agent")}catch{}try{qe("cloudflared")}catch{}let t=Hr({offline:!0});if(r){let i=new Promise(a=>setTimeout(a,ws)),s=t?Promise.race([t,new Promise(a=>setTimeout(a,_r))]):null;Promise.all([i,s]).finally(()=>process.exit(o))}}var Ta=!1;function bt(e,n){if(Ta)return;Ta=!0;let r=!1,o=t=>{r||(r=!0,nt.info(`Stopping 9Remote (${t})...`),rt({serverManager:e,tunnelProcess:n}),nt.info("Server stopped"))};if(process.on("SIGINT",()=>o("SIGINT")),process.on("SIGTERM",()=>o("SIGTERM")),process.on("SIGHUP",()=>o("SIGHUP")),process.platform==="win32"){process.on("SIGBREAK",()=>o("SIGBREAK"));try{import("readline").then(({createInterface:t})=>{t({input:process.stdin,output:process.stdout}).on("SIGINT",()=>o("SIGINT")),process.stdin.isTTY&&process.stdin.unref?.()}).catch(()=>{})}catch{}}process.on("uncaughtException",t=>{nt.error(`Uncaught exception: ${t?.stack||t?.message||t}`),o("uncaughtException"),setTimeout(()=>process.exit(1),So)}),process.on("unhandledRejection",t=>{nt.error(`Unhandled rejection: ${t?.stack||t?.message||t}`),o("unhandledRejection"),setTimeout(()=>process.exit(1),So)})}Ft();var jt=F("tunnel");async function hu(e,n,r,o){let t=0;for(;;){t++;try{return await Ze(e,n,r)}catch(i){let s=Re(ge.tunnelSpawn,t);jt.warn(`spawn attempt ${t} failed: ${i?.message||i} \u2014 retry in ${s}ms`),o?.({attempt:t,delay:s}),await new Promise(a=>setTimeout(a,s))}}}function ot({onUrlUpdate:e,setTunnel:n,onRetry:r}){return async o=>{try{let t=await hu(o,e,null,r);it(),n(t.child),await e(t.tunnelUrl),jt.info(`Tunnel restarted: ${t.tunnelUrl}`)}catch(t){jt.error(`Tunnel restart failed: ${t?.message||t}`)}}}var Gr=null;function it(){Gr&&(Gr.cancelled=!0,Gr=null)}function Rn(e,{onUrlUpdate:n,onRestart:r,setActiveTunnel:o,onReady:t}){it();let i={cancelled:!1};return Gr=i,Ar({config:ge.tunnelRateLimit,task:async()=>{if(i.cancelled)return!0;if(ca())return jt.info("bg-tunnel: a tunnel is already live \u2014 standing down"),!0;let s=await Ze(e,n,r);if(i.cancelled){try{ce()}catch{}return!0}try{o?.(s.child),await n?.(s.tunnelUrl),await t?.(s),jt.info(`bg tunnel up: ${s.tunnelUrl}`)}catch(a){jt.error(`bg tunnel post-spawn failed: ${a?.message||a}`)}return!0},label:"bg-tunnel",log:s=>jt.info(s),ctx:i}),i}var ti=A(Ja(),1);var xu=F("session");function Au(e,n="\u{1F4F1} Scan QR to connect:"){console.log(me.orange(`
255
+ `).map(o=>+o.trim()).filter(Boolean);for(let r of new Set(n))Fr(r)}catch{}}function ce(){if(!Uo){Uo=!0;try{try{if(G.default.existsSync(Fo)){let n=parseInt(G.default.readFileSync(Fo,"utf8"));Number.isFinite(n)&&(or=!0,Fr(n)),G.default.unlinkSync(Fo)}}catch{}let e=Jn("cloudflared");or=!0,gn=null,e&&(Fr(e),qe("cloudflared")),ou($)}finally{setTimeout(()=>{Uo=!1},2e3)}}}function ca(){if(!Se)return!1;let e=Jn("cloudflared");return!!e&&Ro(e)}function la(){tr=0,vn=!1,sr=null,wn=null,Se=null,Qe=0,ar=0,yn=null,au()}var iu=/^(utun|awdl|llw|anpi|bridge|gif|stf|ipsec|ap|tun|tap|vmnet|veth|docker)/i;function na(){let e=gt.default.networkInterfaces(),n=[];for(let[r,o]of Object.entries(e))if(o&&!iu.test(r))for(let t of o)!t.internal&&t.family==="IPv4"&&n.push(`${r}:${t.address}`);return n.sort().join("|")}function su(){rr||(Ur=na(),Do=Date.now(),rr=setInterval(async()=>{try{let e=Date.now(),n=e-Do;if(Do=e,Ko||vn||!sr||wn==null)return;if(n>Wl){if(ne.info(`Sleep/wake detected (gap=${n}ms)`),Se){let s=!1;for(let a=0;a<3;a++){if((await pn(Se)).ok){s=!0;break}a<2&&await new Promise(l=>setTimeout(l,3e3))}if(s)return;ne.info("tunnel unresponsive after sleep \u2192 restarting")}Dt("unreachable"),ce(),ir(wn,"woke from sleep");return}let r=na(),o=r!==Ur;Ur=r;let t=Jn("cloudflared"),i=!t||!Ro(t);if(!o&&!i){if(Se&&bn&&Date.now()-bn>ea&&e-ar>=Je.edgeProbeIntervalMs){ar=e;let s=await pn(Se);if(s.ok)Qe=0;else if(++Qe>=Je.edgeProbeFailureThreshold){let a=await Hl(Je.readyTimeoutMs);if(a>0){ne.info(`edge probe failing but cloudflared holds ${a} connection(s) \u2014 not restarting`),Qe=0;return}ne.warn(`tunnel unreachable but cloudflared alive \u2014 edge lost after ${Qe} probes (ready=${a??"unknown"}), restarting`),Qe=0,Dt("unreachable"),ce(),ir(wn,"tunnel unreachable (edge lost)")}else ne.debug(`edge probe failed (${Qe}/${Je.edgeProbeFailureThreshold}) \u2014 ${s.dnsCode??s.httpStatus??"no response"}`)}return}if(o&&!i&&bn&&Date.now()-bn<ea||(o&&ne.info("Network change detected"),i&&ne.warn("cloudflared not alive \u2014 watchdog"),Dt("unreachable"),await new Promise(s=>setTimeout(s,Je.networkRestoreDelayMs)),!await ia()))return;if(o&&!i&&Se){let s=!1;for(let a=0;a<2;a++){if((await pn(Se)).ok){s=!0;break}a===0&&await new Promise(l=>setTimeout(l,2e3))}if(s){ne.info("Tunnel survived network change, skip restart");return}}o&&!i&&ce(),ir(wn,o?"network change":"liveness watchdog")}catch(e){ne.error(`network monitor tick failed: ${e?.message||e}`)}},Je.networkCheckIntervalMs))}function au(){rr&&(clearInterval(rr),rr=null),Ur=null}Ft();async function yt(e,n={}){let r=n.intervalMs??ft.intervalMs,o=n.timeoutMs??ft.timeoutMs,t=`${e}/api/health`,i=(()=>{try{return new URL(e).hostname}catch{return null}})(),s=Date.now(),a=0,c=[];await j({healthCheck:{running:!0,timeoutMs:o,startedAt:s,logs:[]}});let l=f=>{c.push(f);let u=c.length>ft.maxLogEntries?c.slice(-ft.maxLogEntries):c;j({healthCheck:{running:!0,timeoutMs:o,startedAt:s,logs:u}})};for(;Date.now()-s<o;){if(a++,fn(),i){let u=await Lo(i,ft.dnsTimeoutMs);if(!u.ok){let p=u.code==="ENOTFOUND"||u.code==="ETIMEOUT"||u.code==="ESERVFAIL",d=p?"connecting...":u.code;on(`#${a} \u2192 ${d}`),l({attempt:a,status:d,elapsedMs:u.elapsedMs,ok:!1,waiting:p,time:Date.now()}),await new Promise(m=>setTimeout(m,r));continue}}let f=Date.now();try{let u=await W(t,{signal:AbortSignal.timeout(ft.fetchTimeoutMs)}),p=Date.now()-f;if(on(`#${a} \u2192 ${u.status}`),l({attempt:a,status:String(u.status),elapsedMs:p,ok:u.ok,time:Date.now()}),u.ok)return await j({healthCheck:{running:!1,timeoutMs:0,startedAt:null,logs:[]}}),await new Promise(d=>setTimeout(d,ft.postReadyHoldMs)),!0}catch(u){let p=Date.now()-f,d=u.cause?.code||u.code||u.message,m=d==="ENOTFOUND",w=m?"connecting...":d;on(`#${a} \u2192 ${w}`),l({attempt:a,status:w,elapsedMs:p,ok:!1,waiting:m,time:Date.now()})}await new Promise(u=>setTimeout(u,r))}return await j({healthCheck:{running:!1,timeoutMs:o,startedAt:s,logs:c}}),!1}var tt=F("tunnel"),Wo=null,ba=null,Ea=0;async function Kt(e,n){if(tt.debug(`updateTunnelUrl: key=${e?.slice(0,8)} url=${n}`),Y().remoteEnabled===!1)return;if(Ht(e),n&&n===ba&&Date.now()-Ea<vs){tt.debug("updateTunnelUrl: skipped (debounce, same URL)");return}Wo&&(Wo.cancelled=!0);let r={cancelled:!1};Wo=r;let o=is();Ar({config:ge.urlSync,label:`urlSync ${n}`,log:t=>tt.warn(t),ctx:r,task:async()=>{let t=await W(`${I}/api/session/update`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify((()=>{let s={apiKey:Q(e),tunnelUrl:n,localIp:o?`${o}:${$}`:null};return{...s,...Rt(s)}})())});if(r.cancelled)return!0;if(t.ok)return ba=n,Ea=Date.now(),tt.debug(`urlSync OK: pushed ${n} to server`),du(n),!0;let i=await t.text().catch(()=>"");return tt.warn(`urlSync HTTP ${t.status}: ${i.slice(0,200)}`),!1}}),n&&Js(n)}var An=null,kn=null,Go=!1,Yo=0;async function qo(e,n){let r={apiKey:e,online:n},o=await W(`${I}/api/session/heartbeat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...r,...Rt(r)})});return o.ok||tt.warn(`heartbeat online=${n} HTTP ${o.status}`),o.ok}async function Vo(){if(!(Go||!kn)){Go=!0;try{await qo(kn,!0),Yo=Date.now()}catch(e){tt.debug(`heartbeat failed: ${e?.message||e}`)}finally{Go=!1}}}function Ht(e){let n=Q(e);if(n&&Y().remoteEnabled!==!1){if(An&&kn===n){Date.now()-Yo>=To&&Vo();return}Hr(),kn=n,Vo(),An=setInterval(Vo,To),An.unref?.()}}function Hr({offline:e=!1}={}){An&&(clearInterval(An),An=null);let n=kn;return kn=null,Yo=0,!e||!n?null:qo(n,!1).catch(r=>tt.debug(`goodbye failed: ${r?.message||r}`))}function wt(e){let n=Q(e);if(!n)return Promise.resolve(!1);Hr();let r=qo(n,!1).catch(o=>(tt.debug(`offline mark failed: ${o?.message||o}`),!1));return Promise.race([r,new Promise(o=>setTimeout(()=>o(!1),_r))])}var ur=null;async function du(e){if(ur?.url===e)return;let n={url:e};ur=n,Qs();try{let r=await yt(e,{timeoutMs:Es});if(ur!==n)return;r&&Dt("healthy")}catch{}finally{ur===n&&(ur=null),zs()}}var nt=F("server"),Aa=jr.default.dirname((0,xa.fileURLToPath)(__importMetaUrl)),mu=jr.default.resolve(Aa,"./server.cjs"),Sa=jr.default.resolve(Aa,"../../index.js");function Wr(e){try{process.platform==="win32"?(0,fr.execSync)(`for /f "tokens=5" %a in ('netstat -aon ^| findstr :${e}') do taskkill /F /PID %a`,{stdio:"ignore",windowsHide:!0}):(0,fr.execSync)(`lsof -ti:${e} | xargs kill -9 2>/dev/null || true`,{stdio:"ignore"})}catch{}}function vt(e,n,r){let o=null,t=!1,i=!1,s=!0,a=0,c=null,l=()=>{s&&(Wr($),s=!1);let f=process.env.NREMOTE_ENV==="development"&&Xo.default.existsSync(Sa),u=f?Sa:mu;Xo.default.existsSync(u)||(nt.error(`Server not found: ${u}`),process.exit(1));let p={...process.env,PORT:String($)};f||delete p.NREMOTE_ENV,o=(0,fr.spawn)(pi,[u],{cwd:V.ROOT,stdio:["ignore","inherit","inherit"],detached:!1,windowsHide:!0,env:di(p)}),c&&clearTimeout(c),c=setTimeout(()=>{a=0},ys),o.on("exit",(d,m)=>{if(c&&(clearTimeout(c),c=null),t)return;if(i){i=!1,nt.info("Restarting server (requested)..."),setTimeout(()=>{l(),r?.()},500);return}nt.error(`Server exited unexpectedly (code: ${d}, signal: ${m})`),a++;let w=Re(ge.server,a);nt.warn(`Restarting server in ${w}ms (fail#${a})`),n&&n(),setTimeout(()=>{l(),r?.()},w)}),o.on("error",d=>{nt.error(`Server error: ${d.message}`)}),e?.(o)};return l(),{getProcess:()=>o,shutdown:()=>{if(t=!0,!!o){try{o.kill("SIGTERM")}catch{}setTimeout(()=>{try{o&&o.kill("SIGKILL")}catch{}},2e3)}},restart:()=>{if(!o)return!1;i=!0;try{o.kill("SIGTERM")}catch{}return setTimeout(()=>{try{o&&i&&o.kill("SIGKILL")}catch{}},2e3),!0}}}function ka(e){return e?.restart?e.restart():!1}function rt({serverManager:e,tunnelProcess:n,exit:r=!0,code:o=0}={}){try{er()}catch{}try{e?.shutdown?.()}catch{}try{n?.kill?.()}catch{}try{ce()}catch{}try{Bt()}catch{}try{Wr($)}catch{}try{la()}catch{}try{Oi()}catch{}try{qe("agent")}catch{}try{qe("cloudflared")}catch{}let t=Hr({offline:!0});if(r){let i=new Promise(a=>setTimeout(a,ws)),s=t?Promise.race([t,new Promise(a=>setTimeout(a,_r))]):null;Promise.all([i,s]).finally(()=>process.exit(o))}}var Ta=!1;function bt(e,n){if(Ta)return;Ta=!0;let r=!1,o=t=>{r||(r=!0,nt.info(`Stopping 9Remote (${t})...`),rt({serverManager:e,tunnelProcess:n}),nt.info("Server stopped"))};if(process.on("SIGINT",()=>o("SIGINT")),process.on("SIGTERM",()=>o("SIGTERM")),process.on("SIGHUP",()=>o("SIGHUP")),process.platform==="win32"){process.on("SIGBREAK",()=>o("SIGBREAK"));try{import("readline").then(({createInterface:t})=>{t({input:process.stdin,output:process.stdout}).on("SIGINT",()=>o("SIGINT")),process.stdin.isTTY&&process.stdin.unref?.()}).catch(()=>{})}catch{}}process.on("uncaughtException",t=>{nt.error(`Uncaught exception: ${t?.stack||t?.message||t}`),o("uncaughtException"),setTimeout(()=>process.exit(1),So)}),process.on("unhandledRejection",t=>{nt.error(`Unhandled rejection: ${t?.stack||t?.message||t}`),o("unhandledRejection"),setTimeout(()=>process.exit(1),So)})}Ft();var jt=F("tunnel");async function hu(e,n,r,o){let t=0;for(;;){t++;try{return await Ze(e,n,r)}catch(i){let s=Re(ge.tunnelSpawn,t);jt.warn(`spawn attempt ${t} failed: ${i?.message||i} \u2014 retry in ${s}ms`),o?.({attempt:t,delay:s}),await new Promise(a=>setTimeout(a,s))}}}function ot({onUrlUpdate:e,setTunnel:n,onRetry:r}){return async o=>{try{let t=await hu(o,e,null,r);it(),n(t.child),await e(t.tunnelUrl),jt.info(`Tunnel restarted: ${t.tunnelUrl}`)}catch(t){jt.error(`Tunnel restart failed: ${t?.message||t}`)}}}var Gr=null;function it(){Gr&&(Gr.cancelled=!0,Gr=null)}function Rn(e,{onUrlUpdate:n,onRestart:r,setActiveTunnel:o,onReady:t}){it();let i={cancelled:!1};return Gr=i,Ar({config:ge.tunnelRateLimit,task:async()=>{if(i.cancelled)return!0;if(ca())return jt.info("bg-tunnel: a tunnel is already live \u2014 standing down"),!0;let s=await Ze(e,n,r);if(i.cancelled){try{ce()}catch{}return!0}try{o?.(s.child),await n?.(s.tunnelUrl),await t?.(s),jt.info(`bg tunnel up: ${s.tunnelUrl}`)}catch(a){jt.error(`bg tunnel post-spawn failed: ${a?.message||a}`)}return!0},label:"bg-tunnel",log:s=>jt.info(s),ctx:i}),i}var ti=A(Ja(),1);var xu=F("session");function Au(e,n="\u{1F4F1} Scan QR to connect:"){console.log(me.orange(`
256
256
  ${n}`)),ti.default.generate(e,{small:!0,type:"terminal",margin:0},r=>{console.log(r.trim())})}function ku(e){return new Promise(n=>{ti.default.generate(e,{small:!0,type:"terminal",margin:0},r=>{n(me.orangeDim("\u{1F4F1} Scan QR to connect:")+`
257
257
  `+r.trim())})})}async function Xr(e,n){let r=await Wn(e,I),o=Math.min(Ve.headerWidth,process.stdout.columns||55);if(!r){xu.warn("Temp key creation failed \u2014 showing UI without a QR"),await L(O.READY,{tunnelUrl:n,permanentKey:e,workerUrl:I}),console.log(h.red(`
258
258
  \u274C Failed to create one-time key \u2014 generate a new one from the menu`)),console.log(me.orange("\u2550".repeat(o))),console.log(h.white("App URL".padEnd(14))+h.gray(`${I}/login`)),console.log(h.white("Key".padEnd(14))+h.gray(e)),console.log(me.orange("\u2550".repeat(o)));return}let t=Gn(I,r);await L(O.READY,{tunnelUrl:n,oneTimeKey:r.oneTimeKey,oneTimeKeyExpiresAt:r.expiresAt,permanentKey:e,qrUrl:t,workerUrl:I}),Au(t),console.log(h.gray(`
@@ -262,7 +262,7 @@ QR expires in 30 minutes (one-time use)
262
262
  `))):i.push(h.gray(`
263
263
  (One-time key used \u2014 generate a new one from menu)
264
264
  `)),i.push(me.orange("\u2550".repeat(t)),h.white("App URL".padEnd(14))+h.gray(`${I}/login`)),hi.showTunnelUrlInMenu&&i.push(h.white("Tunnel".padEnd(14))+(o?h.cyan(o):h.gray("\u2014"))),i.push(h.white("One-Time Key".padEnd(14))+(e?me.orange.bold(e)+h.dim(" (expires in 30m)"):h.gray("\u2014")),h.white("Key".padEnd(14))+h.dim(n),me.orange("\u2550".repeat(t))),i.join(`
265
- `)}var we=F("cmd");function Tt(e,n,r,o){let t=!1;setInterval(async()=>{if(t)return;let i=Ii();if(i){t=!0;try{if(i==="stop-tunnel")await Qa(e,n,r);else if(i==="restart-tunnel")await Qa(e,n,r),await za(e,n,r);else if(i==="start-tunnel"){if(await za(e,n,r)==="alreadyRunning"){t=!1;return}}else if(i==="regenerate-key")await Ru();else if(i==="shutdown")Pu(e,n);else if(i==="update"){let s=await Gs();we.info(`cmd update -> ${s?"started":"SKIPPED (see reasons above)"}`)}else i==="restart"&&ka(o?.())}catch(s){we.error(`cmd "${i}" failed: ${s?.message||s}`)}finally{t=!1}}},$e.cmdMs)}async function Qa(e,n,r){it(),er();let o=e();o&&(o.kill(),n(null),we.info("Tunnel stopped")),r&&await wt(r),await L(O.STOPPED,{tunnelUrl:"",oneTimeKey:"",oneTimeKeyExpiresAt:null,qrUrl:""}),xn({tunnelUrl:"",running:!0})}async function za(e,n,r){if(Y().remoteEnabled===!1){we.info("Start skipped \u2014 remote is disabled");return}let o=e();if(o)if(o.killed||o.exitCode!=null)n(null);else{let t=await te("/api/ui/state");return await L(O.READY,{tunnelUrl:t?.tunnelUrl||""}),"alreadyRunning"}it(),we.info("Starting...");try{await L(O.PREPARING),await cr(Pr),await L(O.CONNECTING);let t=await W(`${I}/api/session/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(r),hostPublicKey:lt(),hostX25519Key:ut()})});if(!t.ok)throw new Error(`Session create failed: ${t.status}`);await q("/api/signaling/retry",{}),Ht(r),await L(O.TUNNELING);let i=async l=>{await Kt(r,l),await j({tunnelUrl:l}),mn(l),xn({tunnelUrl:l,running:!0})},s=({attempt:l,delay:f})=>{j({tunnelRetry:{attempt:l,delay:f,at:Date.now()}})},a=null;try{a=await Ze($,i,ot({onUrlUpdate:i,setTunnel:l=>n(l),onRetry:s}))}catch(l){we.error(`Tunnel spawn failed: ${l?.message||l} \u2014 QR RTC-only, bg retry`)}j({tunnelRetry:null});let c="";a&&(n(a.child),c=a.tunnelUrl,await L(O.VERIFYING),await yt(c)||(we.warn("Tunnel health check timed out \u2014 bg reconnect"),c="",n(null),a=null)),await Xr(r,c),await L(O.READY,{tunnelUrl:c}),a||Rn($,{onUrlUpdate:i,onRestart:ot({onUrlUpdate:i,setTunnel:l=>n(l),onRetry:s}),setActiveTunnel:n,onReady:async l=>{await L(O.READY,{tunnelUrl:l.tunnelUrl})}})}catch(t){we.error(`Failed to start: ${t.message}`),await L(O.STOPPED)}}async function Ru(){if(Y().remoteEnabled===!1){we.info("Key regeneration skipped \u2014 remote is disabled");return}let e=await Xt(),n=kt(e),r=Kn();if(!await Pt(n,I,$i()?.tunnelUrl,r?.key)){we.error("Key regeneration aborted \u2014 could not register the new key");return}We(e,n,r?.name||"Default"),await j({permanentKey:n,oneTimeKey:"",oneTimeKeyExpiresAt:null,qrUrl:"",pairingUsed:!0}),we.info(`Key regenerated: ${wr(n)}`)}function Pu(e,n){it(),we.info("Shutting down 9Remote completely...");let r=e();n(null),rt({tunnelProcess:r}),we.info("9Remote stopped")}Ft();async function Za(){if(await X()&&(await new Promise(a=>setTimeout(a,ie.guestRecheckMs)),await X())){console.log(h.green(`
265
+ `)}var we=F("cmd");function Tt(e,n,r,o){let t=!1;setInterval(async()=>{if(t)return;let i=Ii();if(i){t=!0;try{if(i==="stop-tunnel")await Qa(e,n,r);else if(i==="restart-tunnel")await Qa(e,n,r),await za(e,n,r);else if(i==="start-tunnel"){if(await za(e,n,r)==="alreadyRunning"){t=!1;return}}else if(i==="regenerate-key")await Ru();else if(i==="shutdown")Pu(e,n);else if(i==="update"){let s=await Gs();we.info(`cmd update -> ${s?"started":"SKIPPED (see reasons above)"}`)}else i==="restart"&&ka(o?.())}catch(s){we.error(`cmd "${i}" failed: ${s?.message||s}`)}finally{t=!1}}},$e.cmdMs)}async function Qa(e,n,r){it(),er();let o=e();o&&(o.kill(),n(null),we.info("Tunnel stopped")),r&&await wt(r),await L(O.STOPPED,{tunnelUrl:"",oneTimeKey:"",oneTimeKeyExpiresAt:null,qrUrl:""}),xn({tunnelUrl:"",running:!0})}async function za(e,n,r){if(Y().remoteEnabled===!1){we.info("Start skipped \u2014 remote is disabled");return}let o=async i=>{await Kt(r,i),await j({tunnelUrl:i}),mn(i),xn({tunnelUrl:i,running:!0})},t=e();if(t)if(t.killed||t.exitCode!=null)n(null);else{let i=await te("/api/ui/state");return await L(O.READY,{tunnelUrl:i?.tunnelUrl||""}),i?.tunnelUrl&&await o(i.tunnelUrl),"alreadyRunning"}it(),we.info("Starting...");try{await L(O.PREPARING),await cr(Pr),await L(O.CONNECTING);let i=await W(`${I}/api/session/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(r),hostPublicKey:lt(),hostX25519Key:ut()})});if(!i.ok)throw new Error(`Session create failed: ${i.status}`);await q("/api/signaling/retry",{}),Ht(r),await L(O.TUNNELING);let s=({attempt:l,delay:f})=>{j({tunnelRetry:{attempt:l,delay:f,at:Date.now()}})},a=null;try{a=await Ze($,o,ot({onUrlUpdate:o,setTunnel:l=>n(l),onRetry:s}))}catch(l){we.error(`Tunnel spawn failed: ${l?.message||l} \u2014 QR RTC-only, bg retry`)}j({tunnelRetry:null});let c="";a&&(n(a.child),c=a.tunnelUrl,await L(O.VERIFYING),await yt(c)?await o(c):(we.warn("Tunnel health check timed out \u2014 bg reconnect"),c="",n(null),a=null)),await Xr(r,c),await L(O.READY,{tunnelUrl:c}),a||Rn($,{onUrlUpdate:o,onRestart:ot({onUrlUpdate:o,setTunnel:l=>n(l),onRetry:s}),setActiveTunnel:n,onReady:async l=>{await L(O.READY,{tunnelUrl:l.tunnelUrl})}})}catch(i){we.error(`Failed to start: ${i.message}`),await L(O.STOPPED)}}async function Ru(){if(Y().remoteEnabled===!1){we.info("Key regeneration skipped \u2014 remote is disabled");return}let e=await Xt(),n=kt(e),r=Kn();if(!await Pt(n,I,$i()?.tunnelUrl,r?.key)){we.error("Key regeneration aborted \u2014 could not register the new key");return}We(e,n,r?.name||"Default"),await j({permanentKey:n,oneTimeKey:"",oneTimeKeyExpiresAt:null,qrUrl:"",pairingUsed:!0}),we.info(`Key regenerated: ${wr(n)}`)}function Pu(e,n){it(),we.info("Shutting down 9Remote completely...");let r=e();n(null),rt({tunnelProcess:r}),we.info("9Remote stopped")}Ft();async function Za(){if(await X()&&(await new Promise(a=>setTimeout(a,ie.guestRecheckMs)),await X())){console.log(h.green(`
266
266
  \u{1F310} UI already served at http://localhost:${$}`));return}Be("agent",process.pid),rn(De());let e=await pt(),n=process.argv.find(a=>a.startsWith("--theme=")),r=n?n.split("=")[1]:null;try{ce(),await new Promise(a=>setTimeout(a,ie.killCloudflaredMs))}catch{}let o=vt(null,null);await new Promise(a=>setTimeout(a,ie.serverBootMs));let t=`http://localhost:${$}`;console.log(h.green(`
267
267
  \u{1F310} UI ready at ${t}`));let i=null;Y().remoteEnabled===!1&&await wt(e.key),await j({permanentKey:e.key,step:O.STOPPED,theme:r}),bt(o,null),Tt(()=>i,a=>{i=a},e.key,()=>o),await lr({port:$,onQuit:()=>{let a=i;i=null,rt({serverManager:o,tunnelProcess:a,exit:!1}),Bt(),setTimeout(()=>process.exit(0),500)},onOpenUI:()=>Ut(t)}),xn({tunnelUrl:"",running:!0}),(process.argv.includes("--start")||process.argv.includes("--skip-update"))&&Y().remoteEnabled!==!1&&Qt("start-tunnel"),await new Promise(()=>{})}Ft();async function ec(){if(await X()&&(await new Promise(l=>setTimeout(l,ie.guestRecheckMs)),await X())){console.log(`
268
268
  \u{1F310} 9Remote already running at http://localhost:${$}`);return}Be("agent",process.pid),Ls().catch(()=>{});let e=await pt(),n=process.argv.find(l=>l.startsWith("--theme=")),r=n?n.split("=")[1]:null;try{ce(),await new Promise(l=>setTimeout(l,ie.killCloudflaredMs))}catch{}let o=vt(null,null);await new Promise(l=>setTimeout(l,ie.serverBootMs));let t=`http://localhost:${$}`,i=null;await j({permanentKey:e.key,step:O.STOPPED,theme:r});let s=()=>{let l=i;i=null,rt({serverManager:o,tunnelProcess:l,exit:!1})};bt(o,null),Tt(()=>i,l=>{i=l},e.key,()=>o);try{qe("cloudflared")}catch{}(process.argv.includes("--start")||process.argv.includes("--skip-update"))&&Y().remoteEnabled!==!1&&Qt("start-tunnel"),await lr({port:$,onQuit:s,onOpenUI:()=>Ut(t)})&&jo({title:"9Remote is running",message:`Open ${t} or use the tray icon to manage.`}),await new Promise(()=>{})}var Gt=F("mode");async function $u(e){Gt.info("Starting server..."),await L(O.PREPARING);try{ce(),await new Promise(l=>setTimeout(l,ie.killCloudflaredMs))}catch{}let n=Y().remoteEnabled===!1,r=!n;if(n&&await wt(e),r)try{let l=await W(`${I}/api/session/create`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:Q(e),hostPublicKey:lt(),hostX25519Key:ut()})});if(!l.ok)throw new Error(`Session create failed: ${l.status}`);Ht(e)}catch(l){Gt.error(`Session create failed: ${l.message} \u2014 local-only, retry from Web UI`),r=!1}let o=await X(),t=o?{getProcess:()=>null,shutdown:()=>{}}:vt(null,null);o||await new Promise(l=>setTimeout(l,ie.serverBootMs)),Gt.info("Starting tunnel..."),await L(O.CONNECTING);let i={current:null},s="",a=async l=>{Gt.info(`Tunnel URL rotated: ${l}`),await Kt(e,l),j({tunnelUrl:l}),mn(l)},c=null;if(r)try{c=await Ze($,a,ot({onUrlUpdate:a,setTunnel:l=>{i.current=l}}))}catch(l){Gt.error(`Tunnel spawn failed: ${l.message} \u2014 RTC-only, bg retry`)}return c&&(i.current=c.child,s=c.tunnelUrl,await yt(s)||(Gt.warn("Tunnel health check timed out \u2014 bg reconnect"),i.current=null,s="",c=null)),!c&&r&&Rn($,{onUrlUpdate:a,onRestart:ot({onUrlUpdate:a,setTunnel:l=>{i.current=l}}),setActiveTunnel:l=>{i.current=l},onReady:async l=>{await L(O.READY,{tunnelUrl:l.tunnelUrl})}}),s&&await Kt(e,s),r?await L(O.READY,{tunnelUrl:s}):await L(O.STOPPED,{tunnelUrl:""}),Fn({apiKey:e,tunnelUrl:s,serverPid:t.getProcess()?.pid,tunnelPid:i.current?.pid}),{serverManager:t,tunnelRef:i,tunnelUrl:s,remoteOnline:r}}async function tc(){rn(De());let e=await pt();Gt.info(`Using key: ${wr(e.key)} (${e.name})`);let{serverManager:n,tunnelRef:r,tunnelUrl:o,remoteOnline:t}=await $u(e.key);t?await Xr(e.key,o):console.log(`\u26A0 ${Y().remoteEnabled===!1?"Remote is disabled \u2014 enable it in Web UI settings":'Remote not connected \u2014 tap "remote \xB7 offline" in the Web UI to retry'}. Local mode.`),bt(n,r.current),Tt(()=>r.current,s=>{r.current=s},e.key);let i=Date.now();setInterval(()=>{let s=Math.floor((Date.now()-i)/1e3),a=Math.floor(s/3600),c=Math.floor(s%3600/60),l=s%60;j({uptime:`${a}:${String(c).padStart(2,"0")}:${String(l).padStart(2,"0")}`})},$e.statsMs),await new Promise(()=>{})}var nc=A(require("path"),1),rc=A(require("fs"),1);Ft();async function oc(){let e=`http://localhost:${$}`;await X()&&(Wr($),await new Promise(c=>setTimeout(c,500)));let n=["--tray"],r=process.argv.find(c=>c.startsWith("--theme="));r&&n.push(r);let o=jn;try{rc.default.mkdirSync(nc.default.dirname(o),{recursive:!0})}catch{}let t=null;try{t=Is(n),t&&Be("agent",t)}catch(c){console.log(h.red(`
@@ -1,17 +1,25 @@
1
1
  // 9remote browser bridge — a dumb pipe. All business logic (snapshot,
2
2
  // click gates, tab discipline, settle waits) lives in the host engine; this
3
3
  // worker drives pages with a static content-script runner + synthetic DOM
4
- // events, so Chrome never shows a debugging banner. It should almost never
5
- // change. Deliberately NOT an ES module (no import): the host bakes the relay
6
- // URL into this placeholder at install time, so no "type": "module" /
7
- // SW-cache class of bugs.
4
+ // events (no debugging banner), or — when the user turns Debug mode on — with
5
+ // chrome.debugger for trusted input. It should almost never change.
6
+ // Deliberately NOT an ES module (no import): the host bakes the relay URL into
7
+ // this placeholder at install time, so no "type": "module" / SW-cache class of bugs.
8
8
  const RELAY_URL = "__RELAY_URL__";
9
9
 
10
10
  let ws = null;
11
11
  let paused = false; // user's kill switch (popup) — survives Chrome restarts
12
+ let debugMode = false; // popup toggle, off by default: chrome.debugger instead of the runner
13
+ const attached = new Set(); // tab ids (strings) with a live chrome.debugger attach
12
14
  const agentTabs = new Set(); // tabs the bridge opened or drives — never "the user's focus"
13
15
  let activeTabId = null; // tab Chrome currently shows
14
16
  let prevActiveTabId = null; // tab shown before the current one — the focus restore target
17
+ // Idle soft-detach: Chrome closes the "started debugging" banner ~5s after the
18
+ // debugger detaches, so an idle agent gets out of the user's face. The next
19
+ // command re-attaches transparently — the engine never notices.
20
+ let lastCallAt = 0;
21
+ const IDLE_DETACH_MS = 10000;
22
+ const IDLE_SWEEP_MS = 3000;
15
23
  const GROUP_TITLE = "9remote"; // agent tabs share one named tab group
16
24
  const GROUP_COLOR = "orange"; // matches the 9remote brand
17
25
 
@@ -39,7 +47,7 @@ function normErr(tid, e) {
39
47
  const msg = e?.message || String(e);
40
48
  if (/no tab|tab not found|cannot access|chrome:\/\/|chrome web store/i.test(msg)) return `No target with given id: ${tid}`;
41
49
  if (/refused to evaluate|content security policy/i.test(msg)) {
42
- return `page CSP blocks script injection — this site cannot be driven via the extension`;
50
+ return `page CSP blocks script injection — turn on Debug mode in the extension popup for this site`;
43
51
  }
44
52
  return msg; // anything else reads as "document navigating" to the engine
45
53
  }
@@ -114,15 +122,25 @@ const SHIM = {
114
122
  return {};
115
123
  },
116
124
  "Target.attachToTarget": async ({ targetId }) => {
117
- // No debugger session exists — the session id IS the tab id.
125
+ // The session id IS the tab id in both modes.
118
126
  const tid = String(targetId);
127
+ if (debugMode && attached.has(tid)) return { sessionId: tid }; // session heal re-attaches its own target
119
128
  agentTabs.add(tid);
129
+ if (debugMode) {
130
+ // One attached page at a time — mirrors engine usage, avoids stacked infobars.
131
+ for (const prev of [...attached]) if (prev !== tid) detachQuiet(prev);
132
+ await attachDebugger(tid);
133
+ attached.add(tid);
134
+ }
120
135
  // A popup our click spawned takes the focus Chrome gives it — hand it back
121
136
  // to the tab the user was actually reading. The agent drives in background.
122
137
  snapBackFocus(tid);
123
138
  return { sessionId: tid };
124
139
  },
125
- "Target.detachFromTarget": async () => ({}),
140
+ "Target.detachFromTarget": async ({ sessionId }) => {
141
+ if (debugMode) await detachQuiet(String(sessionId));
142
+ return {};
143
+ },
126
144
  "Target.getTargetInfo": async ({ targetId }) => {
127
145
  const t = await chrome.tabs.get(Number(targetId));
128
146
  return { targetInfo: { targetId: String(t.id), type: "page", title: t.title, url: t.url } };
@@ -139,7 +157,65 @@ const SHIM = {
139
157
 
140
158
  let inputAt = 0; // last Input.* dispatch — gates popup adoption below
141
159
 
160
+ async function detachQuiet(tid) {
161
+ attached.delete(tid);
162
+ try { await chrome.debugger.detach({ tabId: Number(tid) }); } catch { /* already gone */ }
163
+ }
164
+
165
+ // The debugger target registers a beat after tabs.create — a cold attach can
166
+ // fail with "No target with given id" even though the tab exists. Retry while
167
+ // the tab is alive per chrome.tabs (source of truth), and surface the full
168
+ // picture when Chrome still refuses.
169
+ async function attachDebugger(tid) {
170
+ for (let i = 0; i < 10; i++) {
171
+ try {
172
+ await chrome.debugger.attach({ tabId: Number(tid) }, "1.3");
173
+ return;
174
+ } catch (e) {
175
+ const tabs = await chrome.tabs.query({}).catch(() => []);
176
+ if (!tabs.some((t) => String(t.id) === tid)) {
177
+ throw new Error(`attach tid=${tid}: tab not in chrome.tabs (closed?) — ${e.message}`);
178
+ }
179
+ if (i === 9) throw new Error(`attach tid=${tid}: tab alive but Chrome refuses — ${e.message}`);
180
+ await new Promise((r) => setTimeout(r, 100));
181
+ }
182
+ }
183
+ }
184
+
185
+ async function dispatchDebug(method, params, targetId) {
186
+ if (SHIM[method]) return SHIM[method](params, targetId);
187
+ if (targetId == null) throw new Error(`${method} is not available via the extension`);
188
+ if (method.startsWith("Input.")) inputAt = Date.now();
189
+ const tid = String(targetId);
190
+ // Not attached (idle soft-detach, or this worker restarted and lost its set):
191
+ // try to (re)attach first. Other failures (e.g. DevTools open on the tab)
192
+ // must surface as themselves.
193
+ if (!attached.has(tid)) {
194
+ await attachDebugger(tid);
195
+ attached.add(tid);
196
+ }
197
+ try {
198
+ return await chrome.debugger.sendCommand({ tabId: Number(tid) }, method, params);
199
+ } catch (e) {
200
+ if (!/no target|closed|detached|not found/i.test(e?.message || "")) throw e;
201
+ // The idle soft-detach timer can fire between our attach check and the
202
+ // send — re-attach ONCE and retry before declaring the target dead.
203
+ try {
204
+ await attachDebugger(tid);
205
+ attached.add(tid);
206
+ return await chrome.debugger.sendCommand({ tabId: Number(tid) }, method, params);
207
+ } catch {
208
+ detachQuiet(tid);
209
+ throw new Error(`No target with given id: ${targetId}`);
210
+ }
211
+ }
212
+ }
213
+
142
214
  async function dispatch(method, params, targetId) {
215
+ return debugMode ? dispatchDebug(method, params || {}, targetId) : dispatchRunner(method, params || {}, targetId);
216
+ }
217
+
218
+ async function dispatchRunner(method, params, targetId) {
143
219
  if (LIGHT_NOOP.has(method)) return {};
144
220
  if (method === "Runtime.evaluate") {
145
221
  if (targetId == null) throw new Error("Runtime.evaluate needs a target");
@@ -173,7 +249,7 @@ async function dispatch(method, params, targetId) {
173
249
  }
174
250
  if (SHIM[method]) return SHIM[method](params, targetId);
175
251
  if (LIGHT_UNSUPPORTED.has(method)) {
176
- throw new Error(`${method} is not available via the extension`);
252
+ throw new Error(`${method} is not available — turn on Debug mode in the extension popup`);
177
253
  }
178
254
  throw new Error(`${method} is not available via the extension`);
179
255
  }
@@ -182,6 +258,21 @@ function send(frame) {
182
258
  try { ws?.send(JSON.stringify(frame)); } catch { /* relay down — close handler reconnects */ }
183
259
  }
184
260
 
261
+ chrome.debugger.onEvent.addListener((source, method, params) => {
262
+ send({ t: "event", method, params, sessionId: String(source.tabId ?? source.targetId) });
263
+ });
264
+ // "Cancel" on the debug infobar, DevTools open, or tab close — surface it the
265
+ // way CDP would so the engine drops and rebuilds the session instead of wedging.
266
+ chrome.debugger.onDetach.addListener((source) => {
267
+ const tid = String(source.tabId ?? source.targetId);
268
+ attached.delete(tid);
269
+ send({ t: "event", method: "Target.detachedFromTarget", params: { sessionId: tid, targetId: tid } });
270
+ });
271
+ // The idle sweep behind the soft-detach (see lastCallAt above).
272
+ setInterval(() => {
273
+ if (!attached.size || Date.now() - lastCallAt < IDLE_DETACH_MS) return;
274
+ for (const tid of [...attached]) detachQuiet(tid);
275
+ }, IDLE_SWEEP_MS);
185
276
  // Synthesize Target.targetCreated the engine's popup adoption listens for —
186
277
  // chrome.tabs never surfaces browser-level target events.
187
278
  const POPUP_WINDOW_MS = 1500; // born within this after our Input dispatch = the agent's click
@@ -198,15 +289,15 @@ chrome.tabs.onCreated.addListener((tab) => {
198
289
  ...((tab.openerTabId != null && agentPopup) ? { openerId: String(tab.openerTabId) } : {})
199
290
  } } });
200
291
  });
201
- // Synthesize the main-frame navigation events settle() keys its nav tail on
202
- // (a debugger session would get them from CDP for free).
292
+ // Runner mode: synthesize the main-frame navigation events settle() keys its
293
+ // nav tail on (a debugger session gets them from CDP for free).
203
294
  chrome.webNavigation.onBeforeNavigate.addListener((d) => {
204
- if (d.frameId !== 0) return;
295
+ if (debugMode || d.frameId !== 0) return;
205
296
  send({ t: "event", method: "Page.frameRequestedNavigation",
206
297
  params: { frame: {}, disposition: "currentTab" }, sessionId: String(d.tabId) });
207
298
  });
208
299
  chrome.webNavigation.onCommitted.addListener((d) => {
209
- if (d.frameId !== 0) return;
300
+ if (debugMode || d.frameId !== 0) return;
210
301
  send({ t: "event", method: "Page.frameNavigated",
211
302
  params: { frame: { id: "0", url: d.url } }, sessionId: String(d.tabId) });
212
303
  });
@@ -216,17 +307,19 @@ chrome.webNavigation.onCommitted.addListener((d) => {
216
307
  chrome.tabs.onActivated.addListener(({ tabId }) => {
217
308
  if (activeTabId !== tabId) { prevActiveTabId = activeTabId; activeTabId = tabId; }
218
309
  });
219
- // A closed tab is gone for good — never adopt onto its id again.
310
+ // A closed tab is gone for good — never re-attach or adopt onto its id.
220
311
  chrome.tabs.onRemoved.addListener((tabId) => {
312
+ attached.delete(String(tabId));
221
313
  runnerTabs.delete(tabId);
222
314
  });
223
315
 
224
- // The user's kill switch: pause = drop the relay, hard. Nothing rides
316
+ // The user's kill switch: pause = drop debugger + relay, hard. Nothing rides
225
317
  // through; the host simply sees the extension go offline.
226
318
  async function setPaused(next) {
227
319
  paused = next;
228
320
  try { await chrome.storage.local.set({ paused: next }); } catch { /* non-fatal */ }
229
321
  if (next) {
322
+ for (const tid of [...attached]) detachQuiet(tid);
230
323
  try { ws?.close(); } catch { /* already closed */ }
231
324
  ws = null;
232
325
  } else if (!ws) {
@@ -234,14 +327,14 @@ async function setPaused(next) {
234
327
  }
235
328
  }
236
329
 
237
- // Popup surface — status + the pause toggle.
330
+ // Popup surface — status + the pause and Debug mode toggles.
238
331
  chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
239
332
  if (msg?.t === "status") {
240
333
  let host = "";
241
334
  try { host = new URL(RELAY_URL).host; } catch { /* keep empty */ }
242
335
  sendResponse({
243
336
  connected: ws?.readyState === WebSocket.OPEN, host,
244
- version: chrome.runtime.getManifest().version, paused
337
+ version: chrome.runtime.getManifest().version, paused, debug: debugMode
245
338
  });
246
339
  return false;
247
340
  }
@@ -249,6 +342,14 @@ chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
249
342
  setPaused(Boolean(msg.paused)).then(() => sendResponse({ ok: true }));
250
343
  return true;
251
344
  }
345
+ if (msg?.t === "setDebug") {
346
+ debugMode = Boolean(msg.debug);
347
+ try { chrome.storage.local.set({ debug: debugMode }); } catch { /* non-fatal */ }
348
+ // Leaving Debug mode: drop every attach so the banner clears in seconds.
349
+ if (!debugMode) for (const tid of [...attached]) detachQuiet(tid);
350
+ sendResponse({ ok: true, debug: debugMode });
351
+ return false;
352
+ }
252
353
  });
253
354
 
254
355
  function connect() {
@@ -260,6 +361,7 @@ function connect() {
260
361
  try { m = JSON.parse(ev.data); } catch { return; }
261
362
  if (m.t === "ping") return send({ t: "pong" });
262
363
  if (m.t !== "call") return;
364
+ lastCallAt = Date.now();
263
365
  try { send({ t: "result", id: m.id, result: await dispatch(m.method, m.params, m.targetId) }); }
264
366
  catch (e) { send({ t: "result", id: m.id, error: e?.message || String(e) }); }
265
367
  };
@@ -268,7 +370,8 @@ function connect() {
268
370
  ws.onerror = () => { try { ws?.close(); } catch { /* retry via onclose */ } };
269
371
  }
270
372
  // Boot: honor a persisted pause before the first connection attempt.
271
- chrome.storage.local.get(["paused"]).then((saved) => {
373
+ chrome.storage.local.get(["paused", "debug"]).then((saved) => {
272
374
  paused = Boolean(saved?.paused);
375
+ debugMode = Boolean(saved?.debug); // off unless the user turned it on
273
376
  if (!paused) connect();
274
377
  }).catch(() => connect());
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "9remote Bridge",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "description": "Lets the 9remote host drive this browser. All logic lives on the host — this is only a pipe.",
6
- "permissions": ["tabs", "tabGroups", "storage", "webNavigation", "scripting"],
6
+ "permissions": ["tabs", "tabGroups", "storage", "webNavigation", "scripting", "debugger"],
7
7
  "host_permissions": ["<all_urls>"],
8
8
  "background": { "service_worker": "background.js" },
9
9
  "action": { "default_popup": "popup.html" },
@@ -53,6 +53,13 @@
53
53
  </div>
54
54
  <label class="switch"><input type="checkbox" id="bridge" checked><span class="slider"></span></label>
55
55
  </div>
56
+ <div class="section row" style="border-top: none; padding-top: 0;">
57
+ <div>
58
+ <div class="what">Debug mode</div>
59
+ <div class="hint">Real clicks &amp; typing; works on sites that block scripts</div>
60
+ </div>
61
+ <label class="switch"><input type="checkbox" id="debug"><span class="slider"></span></label>
62
+ </div>
56
63
  <script src="popup.js"></script>
57
64
  </body>
58
65
  </html>
@@ -13,6 +13,7 @@ async function render() {
13
13
  $("label").textContent = paused ? "Bridge paused" : s.connected ? "Connected" : "Reconnecting…";
14
14
  $("pauseHint").textContent = paused ? "Blocked until you turn it back on" : "Host may drive this browser";
15
15
  $("bridge").checked = !paused;
16
+ $("debug").checked = Boolean(s.debug);
16
17
  }
17
18
 
18
19
  $("bridge").addEventListener("change", async (e) => {
@@ -20,4 +21,9 @@ $("bridge").addEventListener("change", async (e) => {
20
21
  render();
21
22
  });
22
23
 
24
+ $("debug").addEventListener("change", async (e) => {
25
+ await ask({ t: "setDebug", debug: e.target.checked });
26
+ render();
27
+ });
28
+
23
29
  render();