@geekbeer/minion 2.43.1 → 2.44.0
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/package.json +1 -1
- package/win/minion-cli.ps1 +114 -19
package/package.json
CHANGED
package/win/minion-cli.ps1
CHANGED
|
@@ -218,8 +218,8 @@ function Restart-MinionProcess {
|
|
|
218
218
|
# ============================================================
|
|
219
219
|
|
|
220
220
|
function Invoke-Setup {
|
|
221
|
-
$totalSteps =
|
|
222
|
-
if ($SetupTunnel) { $totalSteps =
|
|
221
|
+
$totalSteps = 10
|
|
222
|
+
if ($SetupTunnel) { $totalSteps = 11 }
|
|
223
223
|
|
|
224
224
|
# Minionization warning
|
|
225
225
|
Write-Host ""
|
|
@@ -308,8 +308,64 @@ function Invoke-Setup {
|
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
# Step 2: Install Claude Code
|
|
312
|
-
Write-Step 2 $totalSteps "
|
|
311
|
+
# Step 2: Install Git (required by Claude Code for git-bash)
|
|
312
|
+
Write-Step 2 $totalSteps "Checking Git (git-bash)..."
|
|
313
|
+
$gitBashPath = $null
|
|
314
|
+
if (Test-CommandExists 'git') {
|
|
315
|
+
$gitVersion = & git --version 2>$null
|
|
316
|
+
Write-Detail "Git already installed ($gitVersion)"
|
|
317
|
+
# Detect bash.exe path from git installation
|
|
318
|
+
$gitExe = (Get-Command git).Source
|
|
319
|
+
$gitDir = Split-Path (Split-Path $gitExe)
|
|
320
|
+
$candidateBash = Join-Path $gitDir 'bin\bash.exe'
|
|
321
|
+
if (Test-Path $candidateBash) { $gitBashPath = $candidateBash }
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
Write-Host " Installing Git via winget..."
|
|
325
|
+
try {
|
|
326
|
+
& winget install --id Git.Git --accept-package-agreements --accept-source-agreements
|
|
327
|
+
# Refresh PATH
|
|
328
|
+
$env:PATH = [System.Environment]::GetEnvironmentVariable('PATH', 'Machine') + ';' + [System.Environment]::GetEnvironmentVariable('PATH', 'User')
|
|
329
|
+
if (Test-CommandExists 'git') {
|
|
330
|
+
Write-Detail "Git installed successfully"
|
|
331
|
+
$gitExe = (Get-Command git).Source
|
|
332
|
+
$gitDir = Split-Path (Split-Path $gitExe)
|
|
333
|
+
$candidateBash = Join-Path $gitDir 'bin\bash.exe'
|
|
334
|
+
if (Test-Path $candidateBash) { $gitBashPath = $candidateBash }
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
Write-Warn "Git installed but not in PATH. Please restart this terminal."
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
Write-Warn "Failed to install Git. Please install manually from https://git-scm.com/downloads/win"
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
# Fallback: search common install paths
|
|
345
|
+
if (-not $gitBashPath) {
|
|
346
|
+
$commonPaths = @(
|
|
347
|
+
'C:\Program Files\Git\bin\bash.exe',
|
|
348
|
+
'C:\Program Files (x86)\Git\bin\bash.exe',
|
|
349
|
+
(Join-Path $env:LOCALAPPDATA 'Programs\Git\bin\bash.exe')
|
|
350
|
+
)
|
|
351
|
+
foreach ($p in $commonPaths) {
|
|
352
|
+
if (Test-Path $p) { $gitBashPath = $p; break }
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if ($gitBashPath) {
|
|
356
|
+
Write-Detail "git-bash found: $gitBashPath"
|
|
357
|
+
# Set CLAUDE_CODE_GIT_BASH_PATH for the current user (persists across sessions)
|
|
358
|
+
[Environment]::SetEnvironmentVariable('CLAUDE_CODE_GIT_BASH_PATH', $gitBashPath, 'User')
|
|
359
|
+
$env:CLAUDE_CODE_GIT_BASH_PATH = $gitBashPath
|
|
360
|
+
Write-Detail "CLAUDE_CODE_GIT_BASH_PATH set for current user"
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
Write-Warn "git-bash not found. Claude Code may not work."
|
|
364
|
+
Write-Host " Install Git from https://git-scm.com/downloads/win and re-run setup." -ForegroundColor Gray
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
# Step 3: Install Claude Code CLI
|
|
368
|
+
Write-Step 3 $totalSteps "Installing Claude Code..."
|
|
313
369
|
if (Test-CommandExists 'claude') {
|
|
314
370
|
$claudeVersion = & claude --version 2>$null
|
|
315
371
|
Write-Detail "Claude Code already installed ($claudeVersion)"
|
|
@@ -330,8 +386,8 @@ function Invoke-Setup {
|
|
|
330
386
|
Write-Host " Please run 'claude' in a terminal to complete the authentication process." -ForegroundColor Yellow
|
|
331
387
|
Write-Host ""
|
|
332
388
|
|
|
333
|
-
# Step
|
|
334
|
-
Write-Step
|
|
389
|
+
# Step 4: Create config directory and .env
|
|
390
|
+
Write-Step 4 $totalSteps "Creating config directory and .env..."
|
|
335
391
|
New-Item -Path $DataDir -ItemType Directory -Force | Out-Null
|
|
336
392
|
New-Item -Path $LogDir -ItemType Directory -Force | Out-Null
|
|
337
393
|
$envValues = @{
|
|
@@ -344,8 +400,8 @@ function Invoke-Setup {
|
|
|
344
400
|
Write-EnvFile $EnvFile $envValues
|
|
345
401
|
Write-Detail "$EnvFile generated"
|
|
346
402
|
|
|
347
|
-
# Step
|
|
348
|
-
Write-Step
|
|
403
|
+
# Step 5: Install node-pty (required for Windows terminal management)
|
|
404
|
+
Write-Step 5 $totalSteps "Installing terminal support (node-pty)..."
|
|
349
405
|
$npmRoot = & npm root -g 2>$null
|
|
350
406
|
$minionPkgDir = Join-Path $npmRoot '@geekbeer\minion'
|
|
351
407
|
if (Test-Path $minionPkgDir) {
|
|
@@ -383,8 +439,8 @@ function Invoke-Setup {
|
|
|
383
439
|
Write-Host " Please run: npm install -g @geekbeer/minion"
|
|
384
440
|
}
|
|
385
441
|
|
|
386
|
-
# Step
|
|
387
|
-
Write-Step
|
|
442
|
+
# Step 6: Generate start-agent.ps1 and register auto-start
|
|
443
|
+
Write-Step 6 $totalSteps "Registering auto-start..."
|
|
388
444
|
$serverJs = Join-Path $minionPkgDir 'win\server.js'
|
|
389
445
|
if (-not (Test-Path $serverJs)) {
|
|
390
446
|
$serverJs = Join-Path $minionPkgDir 'win' 'server.js'
|
|
@@ -421,23 +477,45 @@ if (Test-Path `$EnvFile) {
|
|
|
421
477
|
|
|
422
478
|
New-Item -Path `$LogDir -ItemType Directory -Force | Out-Null
|
|
423
479
|
|
|
480
|
+
# Startup log for debugging VNC/websockify/cloudflared launch
|
|
481
|
+
`$StartupLog = Join-Path `$LogDir 'startup.log'
|
|
482
|
+
function Write-StartupLog {
|
|
483
|
+
param([string]`$Message)
|
|
484
|
+
`$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
|
485
|
+
Add-Content -Path `$StartupLog -Value "[`$ts] `$Message"
|
|
486
|
+
}
|
|
487
|
+
Write-StartupLog "=== start-agent.ps1 starting (PID: `$PID) ==="
|
|
488
|
+
Write-StartupLog "DataDir: `$DataDir"
|
|
489
|
+
Write-StartupLog "ServerJs: `$ServerJs"
|
|
490
|
+
|
|
424
491
|
# Write PID of this watchdog process
|
|
425
492
|
Set-Content -Path `$PidFile -Value `$PID
|
|
426
493
|
|
|
427
494
|
# Helper: find websockify executable
|
|
428
495
|
function Get-WebsockifyCommand {
|
|
429
496
|
if (Get-Command websockify -ErrorAction SilentlyContinue) {
|
|
430
|
-
|
|
497
|
+
`$found = (Get-Command websockify).Source
|
|
498
|
+
Write-StartupLog "websockify found on PATH: `$found"
|
|
499
|
+
return @(`$found)
|
|
431
500
|
}
|
|
501
|
+
Write-StartupLog "websockify not on PATH, checking Python..."
|
|
432
502
|
if (Get-Command python -ErrorAction SilentlyContinue) {
|
|
503
|
+
`$pyPath = (Get-Command python).Source
|
|
504
|
+
Write-StartupLog "Python found: `$pyPath"
|
|
433
505
|
`$scriptsDir = & python -c "import sysconfig; print(sysconfig.get_path('scripts'))" 2>`$null
|
|
506
|
+
Write-StartupLog "Python Scripts dir: `$scriptsDir"
|
|
434
507
|
if (`$scriptsDir) {
|
|
435
508
|
`$wsExe = Join-Path `$scriptsDir 'websockify.exe'
|
|
509
|
+
Write-StartupLog "Checking `$wsExe : exists=$(Test-Path `$wsExe)"
|
|
436
510
|
if (Test-Path `$wsExe) { return @(`$wsExe) }
|
|
437
511
|
}
|
|
438
512
|
`$check = & python -c "import websockify" 2>&1
|
|
513
|
+
Write-StartupLog "python -c 'import websockify' exit code: `$LASTEXITCODE"
|
|
439
514
|
if (`$LASTEXITCODE -eq 0) { return @('python', '-m', 'websockify') }
|
|
515
|
+
} else {
|
|
516
|
+
Write-StartupLog "Python not found"
|
|
440
517
|
}
|
|
518
|
+
Write-StartupLog "websockify not found by any method"
|
|
441
519
|
return `$null
|
|
442
520
|
}
|
|
443
521
|
|
|
@@ -448,29 +526,43 @@ if (Test-Path 'C:\Program Files\TightVNC\tvnserver.exe') {
|
|
|
448
526
|
} elseif (Test-Path (Join-Path `$DataDir 'tightvnc\PFiles\TightVNC\tvnserver.exe')) {
|
|
449
527
|
`$vncExe = Join-Path `$DataDir 'tightvnc\PFiles\TightVNC\tvnserver.exe'
|
|
450
528
|
}
|
|
529
|
+
Write-StartupLog "VNC exe: `$vncExe"
|
|
451
530
|
if (`$vncExe) {
|
|
452
531
|
# Start VNC server in application mode (no admin, no service registration)
|
|
453
532
|
`$vncProc = Get-Process -Name tvnserver -ErrorAction SilentlyContinue
|
|
454
533
|
if (-not `$vncProc) {
|
|
534
|
+
Write-StartupLog "Starting TightVNC server..."
|
|
455
535
|
Start-Process -FilePath `$vncExe -ArgumentList '-run' -WindowStyle Hidden
|
|
456
536
|
# Wait for VNC server to bind port 5900 before starting websockify
|
|
457
537
|
Start-Sleep -Seconds 3
|
|
538
|
+
} else {
|
|
539
|
+
Write-StartupLog "TightVNC already running (PID: `$(`$vncProc.Id))"
|
|
458
540
|
}
|
|
459
541
|
# Reload registry config (ensures no-auth settings are applied)
|
|
460
542
|
& `$vncExe -controlapp -reload 2>`$null
|
|
461
|
-
`$wsCmd = Get-WebsockifyCommand
|
|
543
|
+
[array]`$wsCmd = Get-WebsockifyCommand
|
|
544
|
+
Write-StartupLog "websockify command result (count=`$(`$wsCmd.Count)): `$(`$wsCmd -join ' ')"
|
|
462
545
|
if (`$wsCmd) {
|
|
463
546
|
`$wsProc = Get-Process -Name websockify -ErrorAction SilentlyContinue
|
|
464
547
|
if (-not `$wsProc) {
|
|
548
|
+
Write-StartupLog "Starting websockify (count=`$(`$wsCmd.Count))..."
|
|
465
549
|
if (`$wsCmd.Count -eq 1) {
|
|
466
550
|
Start-Process -FilePath `$wsCmd[0] -ArgumentList '6080', 'localhost:5900' -WindowStyle Hidden
|
|
551
|
+
Write-StartupLog "websockify started: `$(`$wsCmd[0]) 6080 localhost:5900"
|
|
467
552
|
} else {
|
|
468
553
|
# python -m websockify 6080 localhost:5900
|
|
469
554
|
`$wsArgs = (`$wsCmd[1..(`$wsCmd.Count-1)] + @('6080', 'localhost:5900')) -join ' '
|
|
470
555
|
Start-Process -FilePath `$wsCmd[0] -ArgumentList `$wsArgs -WindowStyle Hidden
|
|
556
|
+
Write-StartupLog "websockify started: `$(`$wsCmd[0]) `$wsArgs"
|
|
471
557
|
}
|
|
558
|
+
} else {
|
|
559
|
+
Write-StartupLog "websockify already running (PID: `$(`$wsProc.Id))"
|
|
472
560
|
}
|
|
561
|
+
} else {
|
|
562
|
+
Write-StartupLog "ERROR: websockify command not found, skipping"
|
|
473
563
|
}
|
|
564
|
+
} else {
|
|
565
|
+
Write-StartupLog "VNC server not found, skipping VNC+websockify setup"
|
|
474
566
|
}
|
|
475
567
|
|
|
476
568
|
# Start cloudflared tunnel if configured
|
|
@@ -484,9 +576,12 @@ if (Test-Path `$cfConfig) {
|
|
|
484
576
|
}
|
|
485
577
|
if (`$cfExe) {
|
|
486
578
|
Start-Process -FilePath `$cfExe -ArgumentList 'tunnel', 'run' -WindowStyle Hidden
|
|
579
|
+
Write-StartupLog "cloudflared started: `$cfExe"
|
|
487
580
|
}
|
|
488
581
|
}
|
|
489
582
|
|
|
583
|
+
Write-StartupLog "=== Startup sequence complete, entering watchdog loop ==="
|
|
584
|
+
|
|
490
585
|
# Watchdog loop: restart node if it crashes
|
|
491
586
|
`$nodePath = (Get-Command node).Source
|
|
492
587
|
while (`$true) {
|
|
@@ -521,8 +616,8 @@ Remove-Item `$PidFile -Force -ErrorAction SilentlyContinue
|
|
|
521
616
|
$shortcut.Save()
|
|
522
617
|
Write-Detail "Startup shortcut created: $shortcutPath"
|
|
523
618
|
|
|
524
|
-
# Step
|
|
525
|
-
Write-Step
|
|
619
|
+
# Step 7: Disable screensaver, lock screen, and sleep
|
|
620
|
+
Write-Step 7 $totalSteps "Disabling screensaver, lock screen, and sleep..."
|
|
526
621
|
# Screensaver off
|
|
527
622
|
Set-ItemProperty -Path 'HKCU:\Control Panel\Desktop' -Name ScreenSaveActive -Value '0'
|
|
528
623
|
Set-ItemProperty -Path 'HKCU:\Control Panel\Desktop' -Name ScreenSaveTimeOut -Value '0'
|
|
@@ -538,8 +633,8 @@ Remove-Item `$PidFile -Force -ErrorAction SilentlyContinue
|
|
|
538
633
|
& powercfg -change -monitor-timeout-dc 0 2>$null
|
|
539
634
|
Write-Detail "Sleep and monitor timeout disabled"
|
|
540
635
|
|
|
541
|
-
# Step
|
|
542
|
-
Write-Step
|
|
636
|
+
# Step 8: Install TightVNC Server
|
|
637
|
+
Write-Step 8 $totalSteps "Setting up TightVNC Server..."
|
|
543
638
|
$vncSystemPath = 'C:\Program Files\TightVNC\tvnserver.exe'
|
|
544
639
|
$vncPortableDir = Join-Path $DataDir 'tightvnc'
|
|
545
640
|
$vncPortablePath = Join-Path $vncPortableDir 'PFiles\TightVNC\tvnserver.exe'
|
|
@@ -598,8 +693,8 @@ Remove-Item `$PidFile -Force -ErrorAction SilentlyContinue
|
|
|
598
693
|
Write-Detail "TightVNC configured: localhost-only, no VNC password (auth via HQ proxy)"
|
|
599
694
|
}
|
|
600
695
|
|
|
601
|
-
# Step
|
|
602
|
-
Write-Step
|
|
696
|
+
# Step 9: Setup websockify (WebSocket proxy for VNC)
|
|
697
|
+
Write-Step 9 $totalSteps "Setting up websockify..."
|
|
603
698
|
if (Get-WebsockifyCommand) {
|
|
604
699
|
Write-Detail "websockify already installed"
|
|
605
700
|
}
|
|
@@ -655,7 +750,7 @@ Remove-Item `$PidFile -Force -ErrorAction SilentlyContinue
|
|
|
655
750
|
}
|
|
656
751
|
}
|
|
657
752
|
|
|
658
|
-
# Step
|
|
753
|
+
# Step 10 (optional): Cloudflare Tunnel
|
|
659
754
|
if ($SetupTunnel) {
|
|
660
755
|
$currentStep = $totalSteps - 1
|
|
661
756
|
Write-Step $currentStep $totalSteps "Setting up Cloudflare Tunnel..."
|