nox-openclaw-hunter 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +170 -10
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +529 -46
- package/dist/commands/export.js.map +1 -1
- package/dist/detector/cli-binary.d.ts.map +1 -1
- package/dist/detector/cli-binary.js +19 -0
- package/dist/detector/cli-binary.js.map +1 -1
- package/dist/detector/config.d.ts.map +1 -1
- package/dist/detector/config.js +135 -3
- package/dist/detector/config.js.map +1 -1
- package/dist/detector/process.d.ts.map +1 -1
- package/dist/detector/process.js +12 -1
- package/dist/detector/process.js.map +1 -1
- package/dist/enforcer/file-remover.d.ts +9 -0
- package/dist/enforcer/file-remover.d.ts.map +1 -1
- package/dist/enforcer/file-remover.js +76 -0
- package/dist/enforcer/file-remover.js.map +1 -1
- package/dist/enforcer/index.d.ts.map +1 -1
- package/dist/enforcer/index.js +19 -8
- package/dist/enforcer/index.js.map +1 -1
- package/dist/enforcer/service-stopper.d.ts +1 -0
- package/dist/enforcer/service-stopper.d.ts.map +1 -1
- package/dist/enforcer/service-stopper.js +7 -6
- package/dist/enforcer/service-stopper.js.map +1 -1
- package/dist/mdm/templates/detect.ps1.d.ts.map +1 -1
- package/dist/mdm/templates/detect.ps1.js +69 -38
- package/dist/mdm/templates/detect.ps1.js.map +1 -1
- package/dist/mdm/templates/enforce.ps1.d.ts.map +1 -1
- package/dist/mdm/templates/enforce.ps1.js +38 -25
- package/dist/mdm/templates/enforce.ps1.js.map +1 -1
- package/dist/platform/darwin.d.ts.map +1 -1
- package/dist/platform/darwin.js +117 -25
- package/dist/platform/darwin.js.map +1 -1
- package/dist/platform/index.d.ts +4 -0
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/windows.d.ts.map +1 -1
- package/dist/platform/windows.js +101 -0
- package/dist/platform/windows.js.map +1 -1
- package/docs/jumpcloud.jpeg +0 -0
- package/package.json +1 -1
package/dist/commands/export.js
CHANGED
|
@@ -432,26 +432,30 @@ $ErrorActionPreference = "SilentlyContinue"
|
|
|
432
432
|
$OpenClawFound = $false
|
|
433
433
|
$Details = @()
|
|
434
434
|
${webhookSection}
|
|
435
|
+
# All known variants: openclaw, moltbot, clawdbot, clawbot
|
|
436
|
+
$Variants = @("openclaw", "moltbot", "clawdbot", "clawbot")
|
|
437
|
+
|
|
435
438
|
# Check common installation paths
|
|
436
|
-
$CliPaths = @(
|
|
437
|
-
|
|
438
|
-
"$env:
|
|
439
|
-
"$env:ProgramFiles
|
|
440
|
-
)
|
|
439
|
+
$CliPaths = @()
|
|
440
|
+
foreach ($variant in $Variants) {
|
|
441
|
+
$CliPaths += "$env:LOCALAPPDATA\\Programs\\$variant\\$variant.exe"
|
|
442
|
+
$CliPaths += "$env:ProgramFiles\\$variant\\$variant.exe"
|
|
443
|
+
$CliPaths += "$env:ProgramFiles(x86)\\$variant\\$variant.exe"
|
|
444
|
+
}
|
|
441
445
|
|
|
442
446
|
foreach ($path in $CliPaths) {
|
|
443
447
|
if (Test-Path $path) {
|
|
444
448
|
$OpenClawFound = $true
|
|
445
449
|
$Details += "CLI found at $path"
|
|
446
|
-
break
|
|
447
450
|
}
|
|
448
451
|
}
|
|
449
452
|
|
|
450
|
-
# Check config
|
|
451
|
-
$ConfigPaths = @(
|
|
452
|
-
|
|
453
|
-
"$env:
|
|
454
|
-
|
|
453
|
+
# Check config directories (all variants)
|
|
454
|
+
$ConfigPaths = @()
|
|
455
|
+
foreach ($variant in $Variants) {
|
|
456
|
+
$ConfigPaths += "$env:USERPROFILE\\.$variant"
|
|
457
|
+
$ConfigPaths += "$env:APPDATA\\$variant"
|
|
458
|
+
}
|
|
455
459
|
|
|
456
460
|
foreach ($path in $ConfigPaths) {
|
|
457
461
|
if (Test-Path $path) {
|
|
@@ -460,11 +464,13 @@ foreach ($path in $ConfigPaths) {
|
|
|
460
464
|
}
|
|
461
465
|
}
|
|
462
466
|
|
|
463
|
-
# Check running processes
|
|
464
|
-
$
|
|
465
|
-
|
|
466
|
-
$
|
|
467
|
-
|
|
467
|
+
# Check running processes (all variants)
|
|
468
|
+
foreach ($variant in $Variants) {
|
|
469
|
+
$processes = Get-Process -Name "*$variant*" -ErrorAction SilentlyContinue
|
|
470
|
+
if ($processes) {
|
|
471
|
+
$OpenClawFound = $true
|
|
472
|
+
$Details += "Process running: $($processes.Name -join ', ')"
|
|
473
|
+
}
|
|
468
474
|
}
|
|
469
475
|
|
|
470
476
|
# Check gateway port
|
|
@@ -474,11 +480,163 @@ if ($portCheck.TcpTestSucceeded) {
|
|
|
474
480
|
$Details += "Gateway port 18789 listening"
|
|
475
481
|
}
|
|
476
482
|
|
|
477
|
-
# Check Windows
|
|
478
|
-
$
|
|
479
|
-
|
|
480
|
-
$
|
|
481
|
-
|
|
483
|
+
# Check Windows services (all variants)
|
|
484
|
+
foreach ($variant in $Variants) {
|
|
485
|
+
$service = Get-Service -Name "*$variant*" -ErrorAction SilentlyContinue
|
|
486
|
+
if ($service) {
|
|
487
|
+
$OpenClawFound = $true
|
|
488
|
+
$Details += "Service found: $($service.Name) ($($service.Status))"
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
# Check WSL2 installations
|
|
493
|
+
function Get-WslDistros {
|
|
494
|
+
$distroList = @()
|
|
495
|
+
|
|
496
|
+
# Method 1: Registry Lookup (Most Reliable)
|
|
497
|
+
$lxssRoot = "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss"
|
|
498
|
+
if (Test-Path $lxssRoot) {
|
|
499
|
+
Get-ChildItem -Path $lxssRoot -ErrorAction SilentlyContinue | ForEach-Object {
|
|
500
|
+
$distroName = (Get-ItemProperty -Path $_.PSPath -Name DistributionName -ErrorAction SilentlyContinue).DistributionName
|
|
501
|
+
if ($distroName) {
|
|
502
|
+
$distroList += $distroName
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
# Method 2: Fallback to wsl.exe CLI
|
|
508
|
+
if ($distroList.Count -eq 0) {
|
|
509
|
+
try {
|
|
510
|
+
$consoleEnc = [Console]::OutputEncoding
|
|
511
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
512
|
+
$output = wsl --list --quiet 2>$null
|
|
513
|
+
[Console]::OutputEncoding = $consoleEnc
|
|
514
|
+
|
|
515
|
+
if ($output) {
|
|
516
|
+
$cleaned = $output -replace '\\x00', ''
|
|
517
|
+
$lines = $cleaned -split '[\\r\\n]+' | Where-Object { $_.Trim() -and $_ -notmatch 'Windows Subsystem' }
|
|
518
|
+
foreach ($line in $lines) {
|
|
519
|
+
$d = $line.Trim()
|
|
520
|
+
if ($d) { $distroList += $d }
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
} catch {}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return $distroList | Select-Object -Unique
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function Get-Wsl2UserHomes {
|
|
530
|
+
param([string]$Distro)
|
|
531
|
+
$homes = @()
|
|
532
|
+
|
|
533
|
+
$basePaths = @(
|
|
534
|
+
"\\\\wsl.localhost\\$Distro",
|
|
535
|
+
"\\\\wsl\$\\$Distro"
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
foreach ($base in $basePaths) {
|
|
539
|
+
$homePath = "$base\\home"
|
|
540
|
+
if (Test-Path $homePath) {
|
|
541
|
+
Get-ChildItem -Path $homePath -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
|
542
|
+
$homes += $_.FullName
|
|
543
|
+
}
|
|
544
|
+
$rootPath = "$base\\root"
|
|
545
|
+
if (Test-Path $rootPath) {
|
|
546
|
+
$homes += $rootPath
|
|
547
|
+
}
|
|
548
|
+
break
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return $homes
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
# Scan all WSL2 distros
|
|
555
|
+
$WslDistros = Get-WslDistros
|
|
556
|
+
foreach ($distro in $WslDistros) {
|
|
557
|
+
$userHomes = Get-Wsl2UserHomes -Distro $distro
|
|
558
|
+
|
|
559
|
+
foreach ($home in $userHomes) {
|
|
560
|
+
# Check config directories (.openclaw, .clawdbot, etc.)
|
|
561
|
+
foreach ($variant in $Variants) {
|
|
562
|
+
$configDir = Join-Path $home ".$variant"
|
|
563
|
+
if (Test-Path $configDir) {
|
|
564
|
+
$OpenClawFound = $true
|
|
565
|
+
$Details += "WSL2 [$distro] config dir: $configDir"
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
# Check CLI binaries
|
|
570
|
+
foreach ($variant in $Variants) {
|
|
571
|
+
$binPaths = @(
|
|
572
|
+
(Join-Path $home ".local\\bin\\$variant"),
|
|
573
|
+
(Join-Path $home "bin\\$variant")
|
|
574
|
+
)
|
|
575
|
+
foreach ($binPath in $binPaths) {
|
|
576
|
+
if (Test-Path $binPath) {
|
|
577
|
+
$OpenClawFound = $true
|
|
578
|
+
$Details += "WSL2 [$distro] binary: $binPath"
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
# Check nvm node_modules
|
|
584
|
+
$nvmDir = Join-Path $home ".nvm\\versions\\node"
|
|
585
|
+
if (Test-Path $nvmDir) {
|
|
586
|
+
Get-ChildItem -Path $nvmDir -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
|
587
|
+
foreach ($variant in $Variants) {
|
|
588
|
+
$npmPkg = Join-Path $_.FullName "lib\\node_modules\\$variant"
|
|
589
|
+
if (Test-Path $npmPkg) {
|
|
590
|
+
$OpenClawFound = $true
|
|
591
|
+
$Details += "WSL2 [$distro] npm (nvm): $npmPkg"
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
# Check all npm/yarn/pnpm package locations
|
|
598
|
+
foreach ($variant in $Variants) {
|
|
599
|
+
$npmPaths = @(
|
|
600
|
+
(Join-Path $home ".local\\lib\\node_modules\\$variant"),
|
|
601
|
+
(Join-Path $home ".npm-global\\lib\\node_modules\\$variant"),
|
|
602
|
+
(Join-Path $home ".npm-packages\\lib\\node_modules\\$variant"),
|
|
603
|
+
(Join-Path $home ".npm\\node_modules\\$variant"),
|
|
604
|
+
(Join-Path $home "npm\\lib\\node_modules\\$variant"),
|
|
605
|
+
(Join-Path $home ".node_modules\\$variant"),
|
|
606
|
+
(Join-Path $home "node_modules\\$variant"),
|
|
607
|
+
(Join-Path $home ".yarn\\global\\node_modules\\$variant"),
|
|
608
|
+
(Join-Path $home ".config\\yarn\\global\\node_modules\\$variant"),
|
|
609
|
+
(Join-Path $home ".pnpm-global\\node_modules\\$variant")
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
foreach ($npmPath in $npmPaths) {
|
|
613
|
+
if (Test-Path $npmPath) {
|
|
614
|
+
$OpenClawFound = $true
|
|
615
|
+
$Details += "WSL2 [$distro] package: $npmPath"
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
# Check system-wide paths for this distro
|
|
622
|
+
$sysBase = "\\\\wsl.localhost\\$distro"
|
|
623
|
+
if (-not (Test-Path $sysBase)) { $sysBase = "\\\\wsl\$\\$distro" }
|
|
624
|
+
|
|
625
|
+
foreach ($variant in $Variants) {
|
|
626
|
+
$sysPaths = @(
|
|
627
|
+
"$sysBase\\usr\\local\\bin\\$variant",
|
|
628
|
+
"$sysBase\\usr\\bin\\$variant",
|
|
629
|
+
"$sysBase\\opt\\$variant\\$variant",
|
|
630
|
+
"$sysBase\\usr\\local\\lib\\node_modules\\$variant",
|
|
631
|
+
"$sysBase\\usr\\lib\\node_modules\\$variant"
|
|
632
|
+
)
|
|
633
|
+
foreach ($sysPath in $sysPaths) {
|
|
634
|
+
if (Test-Path $sysPath) {
|
|
635
|
+
$OpenClawFound = $true
|
|
636
|
+
$Details += "WSL2 [$distro] system: $sysPath"
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
482
640
|
}
|
|
483
641
|
|
|
484
642
|
$DetailsString = $Details -join "; "
|
|
@@ -969,6 +1127,66 @@ if command -v docker &>/dev/null; then
|
|
|
969
1127
|
log_action "Cleaned Docker artifacts"
|
|
970
1128
|
fi
|
|
971
1129
|
|
|
1130
|
+
# Remove npm global packages (all variants)
|
|
1131
|
+
log_action "Removing npm global packages..."
|
|
1132
|
+
NPM_REMOVED=0
|
|
1133
|
+
NPM_FAILED=0
|
|
1134
|
+
|
|
1135
|
+
# Get npm global directory
|
|
1136
|
+
if command -v npm &>/dev/null; then
|
|
1137
|
+
NPM_ROOT=$(npm root -g 2>/dev/null || echo "")
|
|
1138
|
+
if [[ -n "$NPM_ROOT" && -d "$NPM_ROOT" ]]; then
|
|
1139
|
+
for pkg_name in openclaw clawbot clawdbot moltbot; do
|
|
1140
|
+
pkg_path="$NPM_ROOT/$pkg_name"
|
|
1141
|
+
if [[ -d "$pkg_path" ]]; then
|
|
1142
|
+
rm -rf "$pkg_path" 2>/dev/null
|
|
1143
|
+
if [[ -d "$pkg_path" ]]; then
|
|
1144
|
+
log_action " FAILED to remove npm package: $pkg_path"
|
|
1145
|
+
NPM_FAILED=$((NPM_FAILED + 1))
|
|
1146
|
+
else
|
|
1147
|
+
log_action " Removed npm package: $pkg_path"
|
|
1148
|
+
NPM_REMOVED=$((NPM_REMOVED + 1))
|
|
1149
|
+
fi
|
|
1150
|
+
fi
|
|
1151
|
+
done
|
|
1152
|
+
fi
|
|
1153
|
+
fi
|
|
1154
|
+
|
|
1155
|
+
# Also check nvm directories for all users
|
|
1156
|
+
for user_home in $(get_all_user_homes); do
|
|
1157
|
+
nvm_dir="$user_home/.nvm/versions/node"
|
|
1158
|
+
if [[ -d "$nvm_dir" ]]; then
|
|
1159
|
+
for node_version in "$nvm_dir"/*; do
|
|
1160
|
+
if [[ -d "$node_version/lib/node_modules" ]]; then
|
|
1161
|
+
for pkg_name in openclaw clawbot clawdbot moltbot; do
|
|
1162
|
+
pkg_path="$node_version/lib/node_modules/$pkg_name"
|
|
1163
|
+
if [[ -d "$pkg_path" ]]; then
|
|
1164
|
+
rm -rf "$pkg_path" 2>/dev/null
|
|
1165
|
+
# Also remove the symlinked binary
|
|
1166
|
+
bin_path="$node_version/bin/$pkg_name"
|
|
1167
|
+
rm -f "$bin_path" 2>/dev/null
|
|
1168
|
+
if [[ -d "$pkg_path" ]]; then
|
|
1169
|
+
log_action " FAILED to remove npm package: $pkg_path"
|
|
1170
|
+
NPM_FAILED=$((NPM_FAILED + 1))
|
|
1171
|
+
else
|
|
1172
|
+
log_action " Removed npm package: $pkg_path"
|
|
1173
|
+
NPM_REMOVED=$((NPM_REMOVED + 1))
|
|
1174
|
+
fi
|
|
1175
|
+
fi
|
|
1176
|
+
done
|
|
1177
|
+
fi
|
|
1178
|
+
done
|
|
1179
|
+
fi
|
|
1180
|
+
done
|
|
1181
|
+
|
|
1182
|
+
if [[ $NPM_FAILED -gt 0 ]]; then
|
|
1183
|
+
log_action "npm removal: $NPM_REMOVED removed, $NPM_FAILED failed"
|
|
1184
|
+
elif [[ $NPM_REMOVED -gt 0 ]]; then
|
|
1185
|
+
log_action "npm removal completed ($NPM_REMOVED packages removed)"
|
|
1186
|
+
else
|
|
1187
|
+
log_action "npm removal completed (no npm packages found)"
|
|
1188
|
+
fi
|
|
1189
|
+
|
|
972
1190
|
# FINAL CLEANUP PASS - catch any respawned processes and recreated files
|
|
973
1191
|
log_action "Running final cleanup pass..."
|
|
974
1192
|
sleep 2
|
|
@@ -1089,31 +1307,39 @@ function Send-Webhook {
|
|
|
1089
1307
|
$ErrorActionPreference = "SilentlyContinue"
|
|
1090
1308
|
$PurgeResults = @()
|
|
1091
1309
|
${webhookSection}
|
|
1310
|
+
# All known variants: openclaw, moltbot, clawdbot, clawbot
|
|
1311
|
+
$Variants = @("openclaw", "moltbot", "clawdbot", "clawbot")
|
|
1312
|
+
|
|
1092
1313
|
function Log-Action {
|
|
1093
1314
|
param([string]$Message)
|
|
1094
1315
|
Write-Host "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $Message"
|
|
1095
1316
|
$script:PurgeResults += $Message
|
|
1096
1317
|
}
|
|
1097
1318
|
|
|
1098
|
-
# Kill running processes
|
|
1099
|
-
Log-Action "Killing
|
|
1100
|
-
|
|
1319
|
+
# Kill running processes (all variants)
|
|
1320
|
+
Log-Action "Killing processes (all variants)..."
|
|
1321
|
+
foreach ($variant in $Variants) {
|
|
1322
|
+
Get-Process -Name "*$variant*" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
|
|
1323
|
+
}
|
|
1101
1324
|
Log-Action "Processes terminated"
|
|
1102
1325
|
|
|
1103
|
-
# Stop and remove Windows
|
|
1104
|
-
$
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1326
|
+
# Stop and remove Windows services (all variants)
|
|
1327
|
+
foreach ($variant in $Variants) {
|
|
1328
|
+
$services = Get-Service -Name "*$variant*" -ErrorAction SilentlyContinue
|
|
1329
|
+
foreach ($service in $services) {
|
|
1330
|
+
Stop-Service -Name $service.Name -Force -ErrorAction SilentlyContinue
|
|
1331
|
+
sc.exe delete $service.Name 2>$null
|
|
1332
|
+
Log-Action "Stopped and removed service: $($service.Name)"
|
|
1333
|
+
}
|
|
1109
1334
|
}
|
|
1110
1335
|
|
|
1111
|
-
# Remove CLI binaries
|
|
1112
|
-
$CliPaths = @(
|
|
1113
|
-
|
|
1114
|
-
"$env:
|
|
1115
|
-
"$env:ProgramFiles
|
|
1116
|
-
)
|
|
1336
|
+
# Remove CLI binaries (all variants)
|
|
1337
|
+
$CliPaths = @()
|
|
1338
|
+
foreach ($variant in $Variants) {
|
|
1339
|
+
$CliPaths += "$env:LOCALAPPDATA\\Programs\\$variant"
|
|
1340
|
+
$CliPaths += "$env:ProgramFiles\\$variant"
|
|
1341
|
+
$CliPaths += "$env:ProgramFiles(x86)\\$variant"
|
|
1342
|
+
}
|
|
1117
1343
|
|
|
1118
1344
|
foreach ($path in $CliPaths) {
|
|
1119
1345
|
if (Test-Path $path) {
|
|
@@ -1122,11 +1348,12 @@ foreach ($path in $CliPaths) {
|
|
|
1122
1348
|
}
|
|
1123
1349
|
}
|
|
1124
1350
|
|
|
1125
|
-
# Remove config directories
|
|
1126
|
-
$ConfigPaths = @(
|
|
1127
|
-
|
|
1128
|
-
"$env:
|
|
1129
|
-
|
|
1351
|
+
# Remove config directories (all variants)
|
|
1352
|
+
$ConfigPaths = @()
|
|
1353
|
+
foreach ($variant in $Variants) {
|
|
1354
|
+
$ConfigPaths += "$env:USERPROFILE\\.$variant"
|
|
1355
|
+
$ConfigPaths += "$env:APPDATA\\$variant"
|
|
1356
|
+
}
|
|
1130
1357
|
|
|
1131
1358
|
foreach ($path in $ConfigPaths) {
|
|
1132
1359
|
if (Test-Path $path) {
|
|
@@ -1135,17 +1362,273 @@ foreach ($path in $ConfigPaths) {
|
|
|
1135
1362
|
}
|
|
1136
1363
|
}
|
|
1137
1364
|
|
|
1138
|
-
# Remove
|
|
1139
|
-
|
|
1365
|
+
# Remove npm global packages (all variants)
|
|
1366
|
+
Log-Action "Removing npm global packages..."
|
|
1367
|
+
if (Get-Command npm -ErrorAction SilentlyContinue) {
|
|
1368
|
+
$npmRoot = (npm root -g 2>$null)
|
|
1369
|
+
if ($npmRoot -and (Test-Path $npmRoot)) {
|
|
1370
|
+
foreach ($variant in $Variants) {
|
|
1371
|
+
$pkgPath = Join-Path $npmRoot $variant
|
|
1372
|
+
if (Test-Path $pkgPath) {
|
|
1373
|
+
Remove-Item -Path $pkgPath -Recurse -Force -ErrorAction SilentlyContinue
|
|
1374
|
+
Log-Action "Removed npm package: $pkgPath"
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
# Also check nvm directories for all users (Windows nvm-windows)
|
|
1381
|
+
$userProfiles = Get-ChildItem "C:\\Users" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notin @("Public", "Default", "Default User", "All Users") }
|
|
1382
|
+
foreach ($profile in $userProfiles) {
|
|
1383
|
+
$nvmDir = Join-Path $profile.FullName ".nvm"
|
|
1384
|
+
if (Test-Path $nvmDir) {
|
|
1385
|
+
Get-ChildItem $nvmDir -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
|
1386
|
+
$nodeModules = Join-Path $_.FullName "node_modules"
|
|
1387
|
+
if (Test-Path $nodeModules) {
|
|
1388
|
+
foreach ($variant in $Variants) {
|
|
1389
|
+
$pkgPath = Join-Path $nodeModules $variant
|
|
1390
|
+
if (Test-Path $pkgPath) {
|
|
1391
|
+
Remove-Item -Path $pkgPath -Recurse -Force -ErrorAction SilentlyContinue
|
|
1392
|
+
Log-Action "Removed npm package: $pkgPath"
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
# Also check AppData for nvm-windows
|
|
1399
|
+
$nvmWinDir = Join-Path $profile.FullName "AppData\\Roaming\\nvm"
|
|
1400
|
+
if (Test-Path $nvmWinDir) {
|
|
1401
|
+
Get-ChildItem $nvmWinDir -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -match "^v\\d" } | ForEach-Object {
|
|
1402
|
+
$nodeModules = Join-Path $_.FullName "node_modules"
|
|
1403
|
+
if (Test-Path $nodeModules) {
|
|
1404
|
+
foreach ($variant in $Variants) {
|
|
1405
|
+
$pkgPath = Join-Path $nodeModules $variant
|
|
1406
|
+
if (Test-Path $pkgPath) {
|
|
1407
|
+
Remove-Item -Path $pkgPath -Recurse -Force -ErrorAction SilentlyContinue
|
|
1408
|
+
Log-Action "Removed npm package: $pkgPath"
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
Log-Action "npm package removal completed"
|
|
1416
|
+
|
|
1417
|
+
# Remove scheduled tasks (all variants)
|
|
1418
|
+
foreach ($variant in $Variants) {
|
|
1419
|
+
Get-ScheduledTask -TaskName "*$variant*" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue
|
|
1420
|
+
}
|
|
1140
1421
|
Log-Action "Removed scheduled tasks"
|
|
1141
1422
|
|
|
1142
|
-
# Clean Docker (if installed)
|
|
1423
|
+
# Clean Docker (if installed) - all variants
|
|
1143
1424
|
if (Get-Command docker -ErrorAction SilentlyContinue) {
|
|
1144
|
-
|
|
1145
|
-
|
|
1425
|
+
foreach ($variant in $Variants) {
|
|
1426
|
+
docker ps -a --filter "name=$variant" --format "{{.ID}}" 2>$null | ForEach-Object { docker rm -f $_ 2>$null }
|
|
1427
|
+
docker images --filter "reference=*$variant*" --format "{{.ID}}" 2>$null | ForEach-Object { docker rmi -f $_ 2>$null }
|
|
1428
|
+
}
|
|
1146
1429
|
Log-Action "Cleaned Docker artifacts"
|
|
1147
1430
|
}
|
|
1148
1431
|
|
|
1432
|
+
# Remove WSL2 installations
|
|
1433
|
+
function Get-WslDistros {
|
|
1434
|
+
$distroList = @()
|
|
1435
|
+
|
|
1436
|
+
# Method 1: Registry Lookup (Most Reliable)
|
|
1437
|
+
$lxssRoot = "HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss"
|
|
1438
|
+
if (Test-Path $lxssRoot) {
|
|
1439
|
+
Get-ChildItem -Path $lxssRoot -ErrorAction SilentlyContinue | ForEach-Object {
|
|
1440
|
+
$distroName = (Get-ItemProperty -Path $_.PSPath -Name DistributionName -ErrorAction SilentlyContinue).DistributionName
|
|
1441
|
+
if ($distroName) {
|
|
1442
|
+
$distroList += $distroName
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
# Method 2: Fallback to wsl.exe CLI
|
|
1448
|
+
if ($distroList.Count -eq 0) {
|
|
1449
|
+
try {
|
|
1450
|
+
$consoleEnc = [Console]::OutputEncoding
|
|
1451
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
1452
|
+
$output = wsl --list --quiet 2>$null
|
|
1453
|
+
[Console]::OutputEncoding = $consoleEnc
|
|
1454
|
+
|
|
1455
|
+
if ($output) {
|
|
1456
|
+
$cleaned = $output -replace '\\x00', ''
|
|
1457
|
+
$lines = $cleaned -split '[\\r\\n]+' | Where-Object { $_.Trim() -and $_ -notmatch 'Windows Subsystem' }
|
|
1458
|
+
foreach ($line in $lines) {
|
|
1459
|
+
$d = $line.Trim()
|
|
1460
|
+
if ($d) { $distroList += $d }
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
} catch {}
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
return $distroList | Select-Object -Unique
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
function Get-Wsl2UserHomes {
|
|
1470
|
+
param([string]$Distro)
|
|
1471
|
+
$homes = @()
|
|
1472
|
+
|
|
1473
|
+
$basePaths = @(
|
|
1474
|
+
"\\\\wsl.localhost\\$Distro",
|
|
1475
|
+
"\\\\wsl\$\\$Distro"
|
|
1476
|
+
)
|
|
1477
|
+
|
|
1478
|
+
foreach ($base in $basePaths) {
|
|
1479
|
+
$homePath = "$base\\home"
|
|
1480
|
+
if (Test-Path $homePath) {
|
|
1481
|
+
Get-ChildItem -Path $homePath -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
|
1482
|
+
$homes += $_.FullName
|
|
1483
|
+
}
|
|
1484
|
+
$rootPath = "$base\\root"
|
|
1485
|
+
if (Test-Path $rootPath) {
|
|
1486
|
+
$homes += $rootPath
|
|
1487
|
+
}
|
|
1488
|
+
break
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
return $homes
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
function Remove-Wsl2Item {
|
|
1495
|
+
param([string]$Path, [string]$Description)
|
|
1496
|
+
if (-not (Test-Path $Path)) { return $false }
|
|
1497
|
+
|
|
1498
|
+
# Try PowerShell removal first
|
|
1499
|
+
Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue
|
|
1500
|
+
|
|
1501
|
+
if (-not (Test-Path $Path)) {
|
|
1502
|
+
Log-Action "Removed WSL2 $Description"
|
|
1503
|
+
return $true
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
# If failed, try via wsl command
|
|
1507
|
+
try {
|
|
1508
|
+
# Convert Windows path to WSL path (Handle both localhost and wsl$ formats)
|
|
1509
|
+
$wslPath = $Path -replace '^\\\\\\\\wsl\\.localhost\\\\[^\\\\]+\\\\', '/' -replace '^\\\\\\\\wsl\$\\\\[^\\\\]+\\\\', '/' -replace '\\\\', '/'
|
|
1510
|
+
|
|
1511
|
+
# Extract distro name
|
|
1512
|
+
$distro = if ($Path -match '\\\\wsl\\.localhost\\\\([^\\\\]+)\\\\') { $matches[1] }
|
|
1513
|
+
elseif ($Path -match '\\\\wsl\$\\\\([^\\\\]+)\\\\') { $matches[1] }
|
|
1514
|
+
else { $null }
|
|
1515
|
+
|
|
1516
|
+
if ($distro) {
|
|
1517
|
+
wsl -d $distro rm -rf "$wslPath" 2>$null
|
|
1518
|
+
if (-not (Test-Path $Path)) {
|
|
1519
|
+
Log-Action "Removed WSL2 $Description (via wsl)"
|
|
1520
|
+
return $true
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
} catch {}
|
|
1524
|
+
|
|
1525
|
+
Log-Action "WARNING: Failed to remove WSL2 $Description"
|
|
1526
|
+
return $false
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
Log-Action "Checking for WSL2 installations..."
|
|
1530
|
+
$WslDistros = Get-WslDistros
|
|
1531
|
+
$Wsl2Removed = 0
|
|
1532
|
+
|
|
1533
|
+
if ($WslDistros.Count -gt 0) {
|
|
1534
|
+
Log-Action "Found WSL2 distros: $($WslDistros -join ', ')"
|
|
1535
|
+
|
|
1536
|
+
foreach ($distro in $WslDistros) {
|
|
1537
|
+
# KILL SWITCH: Stop Linux processes first
|
|
1538
|
+
Log-Action "Killing WSL2 processes in [$distro]..."
|
|
1539
|
+
foreach ($variant in $Variants) {
|
|
1540
|
+
# Kill processes matching the variant name or node processes running it
|
|
1541
|
+
wsl -d $distro bash -c "pkill -f $variant 2>/dev/null; pkill -f 'node.*$variant' 2>/dev/null"
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
$userHomes = Get-Wsl2UserHomes -Distro $distro
|
|
1545
|
+
if ($userHomes.Count -gt 0) {
|
|
1546
|
+
Log-Action "Scanning WSL2 [$distro] users: $($userHomes.Count) found"
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
foreach ($home in $userHomes) {
|
|
1550
|
+
# Remove config directories (.openclaw, .clawdbot, etc.)
|
|
1551
|
+
foreach ($variant in $Variants) {
|
|
1552
|
+
$configDir = Join-Path $home ".$variant"
|
|
1553
|
+
if (Remove-Wsl2Item -Path $configDir -Description "[$distro] config: $configDir") {
|
|
1554
|
+
$Wsl2Removed++
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
# Remove CLI binaries
|
|
1559
|
+
foreach ($variant in $Variants) {
|
|
1560
|
+
$binPaths = @(
|
|
1561
|
+
(Join-Path $home ".local\\bin\\$variant"),
|
|
1562
|
+
(Join-Path $home "bin\\$variant")
|
|
1563
|
+
)
|
|
1564
|
+
foreach ($binPath in $binPaths) {
|
|
1565
|
+
if (Remove-Wsl2Item -Path $binPath -Description "[$distro] binary: $binPath") {
|
|
1566
|
+
$Wsl2Removed++
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
# Remove nvm node_modules
|
|
1572
|
+
$nvmDir = Join-Path $home ".nvm\\versions\\node"
|
|
1573
|
+
if (Test-Path $nvmDir) {
|
|
1574
|
+
Get-ChildItem -Path $nvmDir -Directory -ErrorAction SilentlyContinue | ForEach-Object {
|
|
1575
|
+
foreach ($variant in $Variants) {
|
|
1576
|
+
$npmPkg = Join-Path $_.FullName "lib\\node_modules\\$variant"
|
|
1577
|
+
if (Remove-Wsl2Item -Path $npmPkg -Description "[$distro] npm (nvm): $npmPkg") {
|
|
1578
|
+
$Wsl2Removed++
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
# Remove all npm/yarn/pnpm package locations
|
|
1585
|
+
foreach ($variant in $Variants) {
|
|
1586
|
+
$npmPaths = @(
|
|
1587
|
+
(Join-Path $home ".local\\lib\\node_modules\\$variant"),
|
|
1588
|
+
(Join-Path $home ".npm-global\\lib\\node_modules\\$variant"),
|
|
1589
|
+
(Join-Path $home ".npm-packages\\lib\\node_modules\\$variant"),
|
|
1590
|
+
(Join-Path $home ".npm\\node_modules\\$variant"),
|
|
1591
|
+
(Join-Path $home "npm\\lib\\node_modules\\$variant"),
|
|
1592
|
+
(Join-Path $home ".node_modules\\$variant"),
|
|
1593
|
+
(Join-Path $home "node_modules\\$variant"),
|
|
1594
|
+
(Join-Path $home ".yarn\\global\\node_modules\\$variant"),
|
|
1595
|
+
(Join-Path $home ".config\\yarn\\global\\node_modules\\$variant"),
|
|
1596
|
+
(Join-Path $home ".pnpm-global\\node_modules\\$variant")
|
|
1597
|
+
)
|
|
1598
|
+
|
|
1599
|
+
foreach ($npmPath in $npmPaths) {
|
|
1600
|
+
if (Remove-Wsl2Item -Path $npmPath -Description "[$distro] package: $npmPath") {
|
|
1601
|
+
$Wsl2Removed++
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
# Remove system-wide paths for this distro
|
|
1608
|
+
$sysBase = "\\\\wsl.localhost\\$distro"
|
|
1609
|
+
if (-not (Test-Path $sysBase)) { $sysBase = "\\\\wsl\$\\$distro" }
|
|
1610
|
+
|
|
1611
|
+
foreach ($variant in $Variants) {
|
|
1612
|
+
$sysPaths = @(
|
|
1613
|
+
"$sysBase\\usr\\local\\bin\\$variant",
|
|
1614
|
+
"$sysBase\\usr\\bin\\$variant",
|
|
1615
|
+
"$sysBase\\opt\\$variant",
|
|
1616
|
+
"$sysBase\\usr\\local\\lib\\node_modules\\$variant",
|
|
1617
|
+
"$sysBase\\usr\\lib\\node_modules\\$variant"
|
|
1618
|
+
)
|
|
1619
|
+
foreach ($sysPath in $sysPaths) {
|
|
1620
|
+
if (Remove-Wsl2Item -Path $sysPath -Description "[$distro] system: $sysPath") {
|
|
1621
|
+
$Wsl2Removed++
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
Log-Action "WSL2 cleanup completed ($Wsl2Removed items removed)"
|
|
1628
|
+
} else {
|
|
1629
|
+
Log-Action "No WSL2 distros found"
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1149
1632
|
${webhookUrl ? '$ResultsString = $PurgeResults -join "; "\nSend-Webhook -Status "purged" -Details $ResultsString\n' : ''}
|
|
1150
1633
|
Log-Action "Purge complete"
|
|
1151
1634
|
exit 0
|