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.
- package/dist/cli.cjs +6 -6
- package/dist/extension/background.js +120 -17
- package/dist/extension/manifest.json +2 -2
- package/dist/extension/popup.html +7 -0
- package/dist/extension/popup.js +6 -0
- package/dist/ptyDaemon.cjs +5 -5
- package/dist/server.cjs +248 -241
- package/dist/ui/assets/index-BefL072o.js +8 -0
- package/dist/ui/assets/index-DvsANh5-.css +1 -0
- package/dist/ui/index.html +2 -2
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +2 -2
- package/dist/web/__next._full.txt +26 -20
- package/dist/web/__next._head.txt +1 -1
- package/dist/web/__next._index.txt +12 -7
- package/dist/web/__next._tree.txt +2 -2
- package/dist/web/_next/static/chunks/1772-2df6c72aa1bdf99d.js +1 -0
- package/dist/web/_next/static/chunks/1920-64e4610715fd991d.js +1 -0
- package/dist/web/_next/static/chunks/1968-90d80a8543ed4f21.js +32 -0
- package/dist/web/_next/static/chunks/556-1dec70a3f28ddbe8.js +1 -0
- package/dist/web/_next/static/chunks/5587-b8f18d331fdde617.js +1 -0
- package/dist/web/_next/static/chunks/6153.189180c190f90b2f.js +1 -0
- package/dist/web/_next/static/chunks/6221-2be9b41ee97fc1e6.js +11 -0
- package/dist/web/_next/static/chunks/7489.c1e8656da3738df7.js +1 -0
- package/dist/web/_next/static/chunks/8126-c11d39a1ae6ac126.js +1 -0
- package/dist/web/_next/static/chunks/820-c1bd7547f2433453.js +1 -0
- package/dist/web/_next/static/chunks/8534.189180c190f90b2f.js +1 -0
- package/dist/web/_next/static/chunks/9121-cf1e65bb26b0908b.js +1 -0
- package/dist/web/_next/static/chunks/{9491-6dc334192080d071.js → 9491-970597f510e71615.js} +1 -1
- package/dist/web/_next/static/chunks/app/_global-error/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/_not-found/page-bfa58c699e86fa7c.js +1 -0
- package/dist/web/_next/static/chunks/app/admin/access/page-79e70c584b6e2150.js +5 -0
- package/dist/web/_next/static/chunks/app/admin/login/page-4a768b6df8ed5259.js +1 -0
- package/dist/web/_next/static/chunks/app/admin/ota/page-e4d26a8db9968a98.js +5 -0
- package/dist/web/_next/static/chunks/app/admin/page-1c13a4c1567ed18e.js +5 -0
- package/dist/web/_next/static/chunks/app/admin/turn/page-dbd8be78d0941005.js +5 -0
- package/dist/web/_next/static/chunks/app/download/page-e27de0a4170f4b73.js +1 -0
- package/dist/web/_next/static/chunks/app/layout-fc9671123388edff.js +1 -0
- package/dist/web/_next/static/chunks/app/login/page-8216ac4904ee3551.js +1 -0
- package/dist/web/_next/static/chunks/app/{page-1e67d8a5f3775276.js → page-fde2c88f21078fca.js} +2 -2
- package/dist/web/_next/static/chunks/app/workspace/browse/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/editor/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/files/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/git/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/layout-0d349197dc482ccd.js +23 -0
- package/dist/web/_next/static/chunks/app/workspace/mobile/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/pair/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/remote/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/settings/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/terminal/[sessionId]/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/welcome/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/app/workspace/workspaces/page-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/main-72206f0a3cb91ecb.js +5 -0
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/app-error-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/forbidden-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/not-found-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/unauthorized-e60883b219ccba1a.js +1 -0
- package/dist/web/_next/static/chunks/{webpack-dd1f7a5ae02e5d84.js → webpack-31691f9bc04b8076.js} +1 -1
- package/dist/web/_next/static/css/{adc0ee53b89bee3c.css → 4da4daf9f2bf1755.css} +1 -1
- package/dist/web/_next/static/css/577dbf61f141a630.css +1 -0
- package/dist/web/_next/static/{55Oo1FQxj9HIxB7QE1XWG → u29HK3zWfDC3mM40skU_h}/_buildManifest.js +1 -1
- package/dist/web/_not-found/__next._full.txt +20 -18
- package/dist/web/_not-found/__next._head.txt +1 -1
- package/dist/web/_not-found/__next._index.txt +7 -7
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +1 -1
- package/dist/web/_not-found/__next._not-found.txt +1 -1
- package/dist/web/_not-found/__next._tree.txt +2 -2
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +20 -18
- package/dist/web/admin/__next._full.txt +29 -22
- package/dist/web/admin/__next._head.txt +1 -1
- package/dist/web/admin/__next._index.txt +12 -7
- package/dist/web/admin/__next._tree.txt +2 -2
- package/dist/web/admin/__next.admin.__PAGE__.txt +2 -2
- package/dist/web/admin/__next.admin.txt +1 -1
- package/dist/web/admin/access/__next._full.txt +30 -22
- package/dist/web/admin/access/__next._head.txt +1 -1
- package/dist/web/admin/access/__next._index.txt +12 -7
- package/dist/web/admin/access/__next._tree.txt +2 -2
- package/dist/web/admin/access/__next.admin.access.__PAGE__.txt +2 -2
- package/dist/web/admin/access/__next.admin.access.txt +1 -1
- package/dist/web/admin/access/__next.admin.txt +1 -1
- package/dist/web/admin/access.html +1 -1
- package/dist/web/admin/access.txt +30 -22
- package/dist/web/admin/login/__next._full.txt +30 -22
- package/dist/web/admin/login/__next._head.txt +1 -1
- package/dist/web/admin/login/__next._index.txt +12 -7
- package/dist/web/admin/login/__next._tree.txt +2 -2
- package/dist/web/admin/login/__next.admin.login.__PAGE__.txt +2 -2
- package/dist/web/admin/login/__next.admin.login.txt +1 -1
- package/dist/web/admin/login/__next.admin.txt +1 -1
- package/dist/web/admin/login.html +1 -1
- package/dist/web/admin/login.txt +30 -22
- package/dist/web/admin/ota/__next._full.txt +30 -22
- package/dist/web/admin/ota/__next._head.txt +1 -1
- package/dist/web/admin/ota/__next._index.txt +12 -7
- package/dist/web/admin/ota/__next._tree.txt +2 -2
- package/dist/web/admin/ota/__next.admin.ota.__PAGE__.txt +2 -2
- package/dist/web/admin/ota/__next.admin.ota.txt +1 -1
- package/dist/web/admin/ota/__next.admin.txt +1 -1
- package/dist/web/admin/ota.html +1 -1
- package/dist/web/admin/ota.txt +30 -22
- package/dist/web/admin/turn/__next._full.txt +30 -22
- package/dist/web/admin/turn/__next._head.txt +1 -1
- package/dist/web/admin/turn/__next._index.txt +12 -7
- package/dist/web/admin/turn/__next._tree.txt +2 -2
- package/dist/web/admin/turn/__next.admin.turn.__PAGE__.txt +2 -2
- package/dist/web/admin/turn/__next.admin.turn.txt +1 -1
- package/dist/web/admin/turn/__next.admin.txt +1 -1
- package/dist/web/admin/turn.html +1 -1
- package/dist/web/admin/turn.txt +30 -22
- package/dist/web/admin.html +1 -1
- package/dist/web/admin.txt +29 -22
- package/dist/web/download/__next._full.txt +26 -19
- package/dist/web/download/__next._head.txt +1 -1
- package/dist/web/download/__next._index.txt +12 -7
- package/dist/web/download/__next._tree.txt +2 -2
- package/dist/web/download/__next.download.__PAGE__.txt +2 -2
- package/dist/web/download/__next.download.txt +1 -1
- package/dist/web/download.html +1 -1
- package/dist/web/download.txt +26 -19
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +26 -20
- package/dist/web/login/__next._full.txt +29 -22
- package/dist/web/login/__next._head.txt +1 -1
- package/dist/web/login/__next._index.txt +12 -7
- package/dist/web/login/__next._tree.txt +2 -2
- package/dist/web/login/__next.login.__PAGE__.txt +2 -2
- package/dist/web/login/__next.login.txt +1 -1
- package/dist/web/login.html +1 -1
- package/dist/web/login.txt +29 -22
- package/dist/web/workspace/__next._full.txt +27 -20
- package/dist/web/workspace/__next._head.txt +1 -1
- package/dist/web/workspace/__next._index.txt +12 -7
- package/dist/web/workspace/__next._tree.txt +3 -3
- package/dist/web/workspace/__next.workspace.__PAGE__.txt +1 -1
- package/dist/web/workspace/__next.workspace.txt +3 -3
- package/dist/web/workspace/browse/__next._full.txt +30 -22
- package/dist/web/workspace/browse/__next._head.txt +1 -1
- package/dist/web/workspace/browse/__next._index.txt +12 -7
- package/dist/web/workspace/browse/__next._tree.txt +3 -3
- package/dist/web/workspace/browse/__next.workspace.browse.__PAGE__.txt +1 -1
- package/dist/web/workspace/browse/__next.workspace.browse.txt +1 -1
- package/dist/web/workspace/browse/__next.workspace.txt +3 -3
- package/dist/web/workspace/browse.html +1 -1
- package/dist/web/workspace/browse.txt +30 -22
- package/dist/web/workspace/editor/__next._full.txt +30 -22
- package/dist/web/workspace/editor/__next._head.txt +1 -1
- package/dist/web/workspace/editor/__next._index.txt +12 -7
- package/dist/web/workspace/editor/__next._tree.txt +3 -3
- package/dist/web/workspace/editor/__next.workspace.editor.__PAGE__.txt +1 -1
- package/dist/web/workspace/editor/__next.workspace.editor.txt +1 -1
- package/dist/web/workspace/editor/__next.workspace.txt +3 -3
- package/dist/web/workspace/editor.html +1 -1
- package/dist/web/workspace/editor.txt +30 -22
- package/dist/web/workspace/files/__next._full.txt +30 -22
- package/dist/web/workspace/files/__next._head.txt +1 -1
- package/dist/web/workspace/files/__next._index.txt +12 -7
- package/dist/web/workspace/files/__next._tree.txt +3 -3
- package/dist/web/workspace/files/__next.workspace.files.__PAGE__.txt +1 -1
- package/dist/web/workspace/files/__next.workspace.files.txt +1 -1
- package/dist/web/workspace/files/__next.workspace.txt +3 -3
- package/dist/web/workspace/files.html +1 -1
- package/dist/web/workspace/files.txt +30 -22
- package/dist/web/workspace/git/__next._full.txt +30 -22
- package/dist/web/workspace/git/__next._head.txt +1 -1
- package/dist/web/workspace/git/__next._index.txt +12 -7
- package/dist/web/workspace/git/__next._tree.txt +3 -3
- package/dist/web/workspace/git/__next.workspace.git.__PAGE__.txt +1 -1
- package/dist/web/workspace/git/__next.workspace.git.txt +1 -1
- package/dist/web/workspace/git/__next.workspace.txt +3 -3
- package/dist/web/workspace/git.html +1 -1
- package/dist/web/workspace/git.txt +30 -22
- package/dist/web/workspace/mobile/__next._full.txt +30 -22
- package/dist/web/workspace/mobile/__next._head.txt +1 -1
- package/dist/web/workspace/mobile/__next._index.txt +12 -7
- package/dist/web/workspace/mobile/__next._tree.txt +3 -3
- package/dist/web/workspace/mobile/__next.workspace.mobile.__PAGE__.txt +1 -1
- package/dist/web/workspace/mobile/__next.workspace.mobile.txt +1 -1
- package/dist/web/workspace/mobile/__next.workspace.txt +3 -3
- package/dist/web/workspace/mobile.html +1 -1
- package/dist/web/workspace/mobile.txt +30 -22
- package/dist/web/workspace/pair/__next._full.txt +30 -22
- package/dist/web/workspace/pair/__next._head.txt +1 -1
- package/dist/web/workspace/pair/__next._index.txt +12 -7
- package/dist/web/workspace/pair/__next._tree.txt +3 -3
- package/dist/web/workspace/pair/__next.workspace.pair.__PAGE__.txt +1 -1
- package/dist/web/workspace/pair/__next.workspace.pair.txt +1 -1
- package/dist/web/workspace/pair/__next.workspace.txt +3 -3
- package/dist/web/workspace/pair.html +1 -1
- package/dist/web/workspace/pair.txt +30 -22
- package/dist/web/workspace/remote/__next._full.txt +30 -22
- package/dist/web/workspace/remote/__next._head.txt +1 -1
- package/dist/web/workspace/remote/__next._index.txt +12 -7
- package/dist/web/workspace/remote/__next._tree.txt +3 -3
- package/dist/web/workspace/remote/__next.workspace.remote.__PAGE__.txt +1 -1
- package/dist/web/workspace/remote/__next.workspace.remote.txt +1 -1
- package/dist/web/workspace/remote/__next.workspace.txt +3 -3
- package/dist/web/workspace/remote.html +1 -1
- package/dist/web/workspace/remote.txt +30 -22
- package/dist/web/workspace/settings/__next._full.txt +37 -0
- package/dist/web/{dev/question → workspace/settings}/__next._head.txt +1 -1
- package/dist/web/workspace/settings/__next._index.txt +17 -0
- package/dist/web/{dev/question → workspace/settings}/__next._tree.txt +3 -2
- package/dist/web/workspace/settings/__next.workspace.settings.__PAGE__.txt +5 -0
- package/dist/web/{dev/question/__next.dev.question.txt → workspace/settings/__next.workspace.settings.txt} +1 -1
- package/dist/web/workspace/settings/__next.workspace.txt +8 -0
- package/dist/web/workspace/settings.html +1 -0
- package/dist/web/workspace/settings.txt +37 -0
- package/dist/web/workspace/terminal/default/__next._full.txt +30 -24
- package/dist/web/workspace/terminal/default/__next._head.txt +1 -1
- package/dist/web/workspace/terminal/default/__next._index.txt +12 -7
- package/dist/web/workspace/terminal/default/__next._tree.txt +3 -3
- package/dist/web/workspace/terminal/default/__next.workspace.terminal.$d$sessionId.__PAGE__.txt +1 -1
- package/dist/web/workspace/terminal/default/__next.workspace.terminal.$d$sessionId.txt +1 -1
- package/dist/web/workspace/terminal/default/__next.workspace.terminal.txt +1 -1
- package/dist/web/workspace/terminal/default/__next.workspace.txt +3 -3
- package/dist/web/workspace/terminal/default.html +1 -1
- package/dist/web/workspace/terminal/default.txt +30 -24
- package/dist/web/workspace/welcome/__next._full.txt +30 -22
- package/dist/web/workspace/welcome/__next._head.txt +1 -1
- package/dist/web/workspace/welcome/__next._index.txt +12 -7
- package/dist/web/workspace/welcome/__next._tree.txt +3 -3
- package/dist/web/workspace/welcome/__next.workspace.txt +3 -3
- package/dist/web/workspace/welcome/__next.workspace.welcome.__PAGE__.txt +1 -1
- package/dist/web/workspace/welcome/__next.workspace.welcome.txt +1 -1
- package/dist/web/workspace/welcome.html +1 -1
- package/dist/web/workspace/welcome.txt +30 -22
- package/dist/web/workspace/workspaces/__next._full.txt +30 -22
- package/dist/web/workspace/workspaces/__next._head.txt +1 -1
- package/dist/web/workspace/workspaces/__next._index.txt +12 -7
- package/dist/web/workspace/workspaces/__next._tree.txt +3 -3
- package/dist/web/workspace/workspaces/__next.workspace.txt +3 -3
- package/dist/web/workspace/workspaces/__next.workspace.workspaces.__PAGE__.txt +1 -1
- package/dist/web/workspace/workspaces/__next.workspace.workspaces.txt +1 -1
- package/dist/web/workspace/workspaces.html +1 -1
- package/dist/web/workspace/workspaces.txt +30 -22
- package/dist/web/workspace.html +1 -1
- package/dist/web/workspace.txt +27 -20
- package/package.json +5 -5
- package/dist/ui/assets/index-D_C1NTm1.js +0 -8
- package/dist/ui/assets/index-SHlsPzjb.css +0 -1
- package/dist/web/_next/static/chunks/1772-ef73c166e83f5eff.js +0 -1
- package/dist/web/_next/static/chunks/1920-5ead25286846df83.js +0 -1
- package/dist/web/_next/static/chunks/1968-4d2969f0b7112e0b.js +0 -32
- package/dist/web/_next/static/chunks/329-15d3e36af1b2827f.js +0 -1
- package/dist/web/_next/static/chunks/556-a8f04c41c5663ee8.js +0 -1
- package/dist/web/_next/static/chunks/5587-fc5af8c76df14222.js +0 -1
- package/dist/web/_next/static/chunks/6153.8c6b8930e22ceea0.js +0 -1
- package/dist/web/_next/static/chunks/6221-cf883148bf8a4c1e.js +0 -11
- package/dist/web/_next/static/chunks/7489.24938d89538cd03e.js +0 -1
- package/dist/web/_next/static/chunks/8126-0279fc9e17c08aff.js +0 -1
- package/dist/web/_next/static/chunks/820-99036fb63c5462c8.js +0 -1
- package/dist/web/_next/static/chunks/8534.8c6b8930e22ceea0.js +0 -1
- package/dist/web/_next/static/chunks/9121-3d281debd0f3e659.js +0 -1
- package/dist/web/_next/static/chunks/app/_global-error/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/_not-found/page-9f829d2c4beb1840.js +0 -1
- package/dist/web/_next/static/chunks/app/admin/access/page-45f45ad529e5b691.js +0 -5
- package/dist/web/_next/static/chunks/app/admin/login/page-382072b5b43d3c29.js +0 -1
- package/dist/web/_next/static/chunks/app/admin/ota/page-293c0743bd60f454.js +0 -5
- package/dist/web/_next/static/chunks/app/admin/page-fc676dae451dd646.js +0 -5
- package/dist/web/_next/static/chunks/app/admin/turn/page-2ab33033fc7f0919.js +0 -5
- package/dist/web/_next/static/chunks/app/dev/question/page-bafce0c9fd4e8488.js +0 -1
- package/dist/web/_next/static/chunks/app/download/page-a65d1c7fcf6397af.js +0 -1
- package/dist/web/_next/static/chunks/app/layout-f1429d22e935695f.js +0 -1
- package/dist/web/_next/static/chunks/app/login/page-a5dd37d1cbbb394e.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/browse/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/editor/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/files/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/git/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/layout-d8bb677fa1caa5a7.js +0 -20
- package/dist/web/_next/static/chunks/app/workspace/mobile/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/pair/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/remote/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/terminal/[sessionId]/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/welcome/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/app/workspace/workspaces/page-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/main-e10b0dbebb4de0a8.js +0 -5
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/app-error-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/forbidden-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/not-found-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/chunks/next/dist/client/components/builtin/unauthorized-2ece09c883187d82.js +0 -1
- package/dist/web/_next/static/css/1c2cca827fa36d54.css +0 -1
- package/dist/web/dev/question/__next._full.txt +0 -29
- package/dist/web/dev/question/__next._index.txt +0 -12
- package/dist/web/dev/question/__next.dev.question.__PAGE__.txt +0 -9
- package/dist/web/dev/question/__next.dev.txt +0 -5
- package/dist/web/dev/question.html +0 -1
- package/dist/web/dev/question.txt +0 -29
- /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=
|
|
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.
|
|
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.
|
|
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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}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.
|
|
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(
|
|
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,
|
|
5
|
-
//
|
|
6
|
-
//
|
|
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 —
|
|
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
|
-
//
|
|
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
|
|
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
|
-
//
|
|
202
|
-
// (a debugger session
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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 & 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>
|
package/dist/extension/popup.js
CHANGED
|
@@ -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();
|