param (
[string]$NodeId = "",
[string]$AuthToken = "",
[string]$HubUrl = "",
[string]$GrpcUrl = "",
[switch]$RegisterService = $false,
[switch]$ForceFirewall = $false,
[switch]$AutoRun = $true
)
$ErrorActionPreference = "Stop"
Write-Host "==========================================" -ForegroundColor Cyan
Write-Host " CORTEX AGENT WINDOWS BOOTSTRAP " -ForegroundColor Cyan
Write-Host "==========================================" -ForegroundColor Cyan
# 1. Check Python installation (defensively avoid Microsoft Store alias)
$pythonValid = $false
try {
# Check if python is in path and not the 0-byte executable from store
$out = python --version 2>&1
if ($out -like "*Python *") { $pythonValid = $true }
} catch { }
if (!$pythonValid) {
Write-Host "[!] Python not found or invalid. Installing via winget..." -ForegroundColor Yellow
winget install -e --id Python.Python.3.12 --accept-package-agreements --accept-source-agreements
# Refresh PATH for the current session
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
}
# 2. Verify Python version
$pyVer = python --version
Write-Host "[*] Found $pyVer"
# 3. Create working directory
$workDir = "C:\CortexAgent"
if (!(Test-Path $workDir)) {
New-Item -ItemType Directory -Path $workDir
}
Set-Location $workDir
# 4. Download agent code from Hub
if ((-not $HubUrl) -or (-not $AuthToken)) {
Write-Host "[!] Hub details missing. Will prompt for them later after basic setup." -ForegroundColor Yellow
} else {
Write-Host "[*] Fetching agent source from Hub..." -ForegroundColor Cyan
$downloadUrl = "$HubUrl/api/v1/agent/download"
$tarPath = Join-Path $workDir "agent.tar.gz"
$headers = @{"X-Agent-Token" = $AuthToken}
try {
if (Get-Command curl.exe -ErrorAction SilentlyContinue) {
Write-Host "[*] Using curl.exe for robust download..." -ForegroundColor Gray
curl.exe -L -H "X-Agent-Token: $AuthToken" "$downloadUrl" -o "$tarPath"
} else {
Invoke-WebRequest -Uri $downloadUrl -Headers $headers -OutFile $tarPath
}
Write-Host "[+] Download complete. Extracting..." -ForegroundColor Green
# Windows 10+ has tar.exe built-in.
if (Get-Command tar -ErrorAction SilentlyContinue) {
# M7: Use a temporary directory for extraction to avoid locking issues on existing files
$extractTmp = Join-Path $workDir "extract_tmp"
if (!(Test-Path $extractTmp)) { New-Item -ItemType Directory -Path $extractTmp | Out-Null }
tar -xzf $tarPath -C $extractTmp --strip-components=1
Move-Item -Path "$extractTmp\*" -Destination $workDir -Force -ErrorAction SilentlyContinue
Remove-Item $extractTmp -Recurse -Force
} else {
Write-Warning "tar.exe not found. Attempting Expand-Archive (may only support .zip)."
}
Remove-Item $tarPath -ErrorAction SilentlyContinue
} catch {
Write-Warning "Failed to download code: $_"
Write-Host "[!] Please ensure agent-node source is manually placed at $workDir" -ForegroundColor Yellow
}
}
# 5. Setup Virtual Environment
Write-Host "[*] Creating Virtual Environment..."
if (!(Test-Path "venv")) {
python -m venv venv
}
$pythonExe = Join-Path $workDir "venv\Scripts\python.exe"
# 6. Install Dependencies
Write-Host "[*] Installing Dependencies..." -ForegroundColor Cyan
& $pythonExe -m pip install --upgrade pip
& $pythonExe -m pip install -r requirements.txt
# Explicitly ensure critical mesh/windows dependencies are installed
& $pythonExe -m pip install watchdog pywinpty pypiwin32 --no-warn-script-location
# 7. Environment Setup
Write-Host "------------------------------------------"
Write-Host " Enter Agent Configuration Details:"
if (-not $NodeId) { $NodeId = Read-Host " AGENT_NODE_ID (e.g. pc-node-1)" }
if (-not $AuthToken) { $AuthToken = Read-Host " AGENT_AUTH_TOKEN" }
if (-not $HubUrl) { $HubUrl = Read-Host " HUB_URL (e.g. http://192.168.68.140:8002)" }
if (-not $GrpcUrl) { $GrpcUrl = Read-Host " GRPC_ENDPOINT (e.g. 192.168.68.140:50051)" }
$envFile = @"
AGENT_NODE_ID=$NodeId
AGENT_AUTH_TOKEN=$AuthToken
AGENT_HUB_URL=$HubUrl
GRPC_ENDPOINT=$GrpcUrl
AGENT_TLS_ENABLED=false
PYTHONUTF8=1
"@
$envFile | Out-File -FilePath ".env" -Encoding ascii
# 8. Test Execution
Write-Host "[*] Bootstrap complete." -ForegroundColor Green
if ($AutoRun) {
Write-Host "[⚡] Auto-starting Agent..." -ForegroundColor Cyan
Start-Process -FilePath $pythonExe -ArgumentList "src\agent_node\main.py" -WorkingDirectory $workDir
} else {
Write-Host " To run manually: .\venv\Scripts\python.exe src\agent_node\main.py" -ForegroundColor Yellow
}
# 9. Optional Service Registration
if ($RegisterService) {
Write-Host "[*] Registering Scheduled Task..."
& $pythonExe install_service.py --name "CortexAgent" --run
} elseif ($NodeId -eq "" -or !$NodeId) {
# Only ask if we are in interactive mode (no NodeId provided early)
$ans = Read-Host "Would you like to register this as a startup task? (y/n)"
if ($ans -eq "y") {
& $pythonExe install_service.py --name "CortexAgent" --run
}
}
# 10. Security & Firewall Check
Write-Host "------------------------------------------"
Write-Host "[*] Checking Windows Firewall status..." -ForegroundColor Cyan
$profiles = Get-NetFirewallProfile
$disabled = $profiles | Where-Object { $_.Enabled -eq "False" }
if ($disabled) {
if ($ForceFirewall) {
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
Write-Host "[+] Windows Firewall enabled." -ForegroundColor Green
} elseif ($NodeId -eq "" -or !$NodeId) {
$ans = Read-Host "[!] Warning: Firewall disabled. Enable it now? (y/n)"
if ($ans -eq "y") {
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
}
}
}
# Add rule for Python communication
Write-Host "[*] Adding firewall exception for agent communication..."
if ($pythonExe -and (Test-Path $pythonExe)) {
New-NetFirewallRule -DisplayName "Cortex Agent Communication" -Direction Outbound -Program $pythonExe -Action Allow -Description "Allows Cortex Agent to reach the Hub" -ErrorAction SilentlyContinue
New-NetFirewallRule -DisplayName "Cortex Agent Communication" -Direction Inbound -Program $pythonExe -Action Allow -Description "Allows Cortex Agent Mesh Communication" -Profile Any -ErrorAction SilentlyContinue
}
Write-Host "=========================================="
Write-Host " DONE! Check the Hub for node status. " -ForegroundColor Cyan
Write-Host "=========================================="