Continued Work on Remote Script Execution

This commit is contained in:
2025-09-04 04:52:01 -06:00
parent c6047c41d9
commit 772a9c31d0
8 changed files with 485 additions and 1196 deletions

View File

@@ -1,19 +1,4 @@
#////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Launch-Borealis.ps1
<#
Borealis.ps1
----------------------
This script deploys the Borealis Workflow Automation Tool with three modules:
- Server (Web Dashboard)
- Agent (Client / Data Collector)
- Desktop App (Electron)
It begins by presenting a menu to the user. Based on the selection,
the corresponding module is launched or deployed.
Usage:
Set-ExecutionPolicy Unrestricted -Scope Process; .\Borealis.ps1
#>
#////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: <ProjectRoot>/Borealis.ps1
[CmdletBinding()]
param(
@@ -62,20 +47,6 @@ if ($Server) {
$host.UI.RawUI.WindowTitle = "Borealis"
Clear-Host
# ASCII Art Banner
@'
███████████ ████ ███
░░███░░░░░███ ░░███ ░░░
░███ ░███ ██████ ████████ ██████ ██████ ░███ ████ █████
░██████████ ███░░███░░███░░███ ███░░███ ░░░░░███ ░███ ░░███ ███░░
░███░░░░░███░███ ░███ ░███ ░░░ ░███████ ███████ ░███ ░███ ░░█████
░███ ░███░███ ░███ ░███ ░███░░░ ███░░███ ░███ ░███ ░░░░███
███████████ ░░██████ █████ ░░██████ ░░████████ █████ █████ ██████
░░░░░░░░░░░ ░░░░░░ ░░░░░ ░░░░░░ ░░░░░░░░ ░░░░░ ░░░░░ ░░░░░░
'@ | Write-Host -ForegroundColor DarkCyan
Write-Host "Automation Platform" -ForegroundColor DarkGray
Write-Host " "
## Note: Heavy dependency downloads are deferred until selecting Server (option 1)
# ---------------------- ASCII Art Terminal Required Changes ----------------------
# Set the .NET Console output encoding to UTF8
@@ -132,66 +103,8 @@ function Remove-BorealisServicesAndTasks {
function Repair-BorealisAgent {
$logName = 'Repair.log'
Write-AgentLog -FileName $logName -Message "=== Repair start ==="
$agentDir = Join-Path $scriptDir 'Agent'
$venvPython = Join-Path $agentDir 'Scripts\python.exe'
$deployScript = Join-Path $agentDir 'Borealis\agent_deployment.py'
# Aggressive cleanup first
Remove-BorealisServicesAndTasks -LogName $logName
Start-Sleep -Seconds 1
# Ensure venv and files exist by reusing the install block
Write-AgentLog -FileName $logName -Message "Ensuring agent venv and files"
$venvFolder = 'Agent'
$agentSourcePath = 'Data\Agent\borealis-agent.py'
$agentRequirements = 'Data\Agent\agent-requirements.txt'
$agentDestinationFolder = "$venvFolder\Borealis"
$venvPythonPath = Join-Path $scriptDir $venvFolder | Join-Path -ChildPath 'Scripts\python.exe'
if (-not (Test-Path "$venvFolder\Scripts\Activate")) {
$pythonForVenv = $pythonExe
if (-not (Test-Path $pythonForVenv)) {
$pyCmd = Get-Command py -ErrorAction SilentlyContinue
$pythonCmd = Get-Command python -ErrorAction SilentlyContinue
if ($pyCmd) { $pythonForVenv = $pyCmd.Source }
elseif ($pythonCmd) { $pythonForVenv = $pythonCmd.Source }
else { throw "Python not found. Please run Server setup (option 1) first." }
}
Write-AgentLog -FileName $logName -Message "Creating venv using: $pythonForVenv"
& $pythonForVenv -m venv $venvFolder | Out-Null
}
if (Test-Path $agentSourcePath) {
Write-AgentLog -FileName $logName -Message "Refreshing Agent/Borealis files"
Remove-Item $agentDestinationFolder -Recurse -Force -ErrorAction SilentlyContinue
New-Item -Path $agentDestinationFolder -ItemType Directory -Force | Out-Null
Copy-Item 'Data\Agent\borealis-agent.py' $agentDestinationFolder -Recurse
Copy-Item 'Data\Agent\agent_info.py' $agentDestinationFolder -Recurse
Copy-Item 'Data\Agent\agent_roles.py' $agentDestinationFolder -Recurse
Copy-Item 'Data\Agent\Python_API_Endpoints' $agentDestinationFolder -Recurse
Copy-Item 'Data\Agent\windows_script_service.py' $agentDestinationFolder -Force
Copy-Item 'Data\Agent\agent_deployment.py' $agentDestinationFolder -Force
Copy-Item 'Data\Agent\tray_launcher.py' $agentDestinationFolder -Force
if (Test-Path 'Data\Agent\Borealis.ico') { Copy-Item 'Data\Agent\Borealis.ico' $agentDestinationFolder -Force }
}
. "$venvFolder\Scripts\Activate"
if (Test-Path $agentRequirements) {
Write-AgentLog -FileName $logName -Message "Installing agent requirements"
& $venvPythonPath -m pip install --disable-pip-version-check -q -r $agentRequirements | Out-Null
}
# Install service via deployment helper (sets PythonHome/PythonPath)
Write-AgentLog -FileName $logName -Message "Running agent_deployment.py ensure-all"
$deployScript = Join-Path $agentDestinationFolder 'agent_deployment.py'
& $venvPythonPath -W ignore::SyntaxWarning $deployScript ensure-all *>&1 | Tee-Object -FilePath (Join-Path (Ensure-AgentLogDir) $logName) -Append | Out-Null
# Start the service explicitly
Write-AgentLog -FileName $logName -Message "Starting service BorealisAgent"
try { sc.exe start BorealisAgent 2>$null | Out-Null } catch {}
Start-Sleep -Seconds 2
Write-AgentLog -FileName $logName -Message "Query service state"
sc.exe query BorealisAgent *>> (Join-Path (Ensure-AgentLogDir) $logName)
InstallOrUpdate-BorealisAgent
Write-AgentLog -FileName $logName -Message "=== Repair end ==="
}
@@ -411,328 +324,121 @@ function Install_Agent_Dependencies {
}
}
#<# ---------------------- Agent Service Helper Functions (Windows) [Deprecated: superseded by Data/Agent/agent_deployment.py] ----------------------
function Ensure-BorealisAgent-Service {
function Ensure-AgentTasks {
# Registers SYSTEM Supervisor + 5-min Watchdog via UAC-elevated stub
param(
[string]$VenvPython,
[string]$ServiceScript
[string]$ScriptRoot
)
if (-not (Test-IsWindows)) {
Write-Host "Agent service setup skipped (non-Windows)." -ForegroundColor DarkGray
return
}
$supName = 'Borealis Agent - Supervisor'
$py = Join-Path $ScriptRoot 'Agent\Scripts\python.exe'
$supScript= Join-Path $ScriptRoot 'Data\Agent\agent_supervisor.py'
$wdName = 'Borealis Agent - Watchdog'
$serviceName = 'BorealisAgent'
$svc = Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'" -ErrorAction SilentlyContinue
$needsInstall = $false
if (-not $svc) { $needsInstall = $true }
else {
if ($svc.StartMode -notin @('Auto','Automatic')) { $needsInstall = $true }
if ($svc.StartName -ne 'LocalSystem') { $needsInstall = $true }
# Verify the service points to the current project venv (folder may have moved)
try {
$venvRoot = Split-Path $VenvPython -Parent
$pathName = $svc.PathName
if ($pathName -and $venvRoot) {
if ($pathName -notlike ("*" + $venvRoot + "*")) { $needsInstall = $true }
$taskStub = @"
$ErrorActionPreference='Continue'
$sup = '$supName'
$py = "$py"
$supScr = "$supScript"
$wd = '$wdName'
try { Unregister-ScheduledTask -TaskName $sup -Confirm:$false -ErrorAction SilentlyContinue } catch {}
$a = New-ScheduledTaskAction -Execute $py -Argument ('-W ignore::SyntaxWarning "' + $supScr + '"')
$t = New-ScheduledTaskTrigger -AtStartup
$s = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Hidden -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
$p = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName $sup -Action $a -Trigger $t -Settings $s -Principal $p -Force | Out-Null
$wdScript = @"
$ErrorActionPreference='SilentlyContinue'
if (-not (Get-ScheduledTask -TaskName "$sup" -ErrorAction SilentlyContinue)) { exit }
$st = (Get-ScheduledTask -TaskName "$sup").State
if ($st -eq 'Disabled') { Enable-ScheduledTask -TaskName "$sup" | Out-Null }
if ($st -ne 'Running') { Start-ScheduledTask -TaskName "$sup" | Out-Null }
"@
$wdFile = Join-Path $env:ProgramData 'Borealis\watchdog.ps1'
New-Item -ItemType Directory -Force -Path (Split-Path $wdFile -Parent) | Out-Null
Set-Content -Path $wdFile -Value $wdScript -Encoding UTF8
try { Unregister-ScheduledTask -TaskName $wd -Confirm:$false -ErrorAction SilentlyContinue } catch {}
$wa = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ('-NoProfile -ExecutionPolicy Bypass -File "' + $wdFile + '"')
$wt = New-ScheduledTaskTrigger -Once -At ([datetime]::Now.AddMinutes(1)) -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Days 365)
$ws = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Hidden
Register-ScheduledTask -TaskName $wd -Action $wa -Trigger $wt -Settings $ws -Principal $p -Force | Out-Null
Start-ScheduledTask -TaskName $sup | Out-Null
@"
$tmpElev = New-TemporaryFile
Set-Content -Path $tmpElev.FullName -Value $taskStub -Encoding UTF8
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = 'powershell.exe'
$psi.Verb = 'runas'
$psi.ArgumentList = @('-NoProfile','-ExecutionPolicy','Bypass','-File', $tmpElev.FullName)
$psi.UseShellExecute = $true
try { $proc = [System.Diagnostics.Process]::Start($psi); $proc.WaitForExit() } catch {}
Remove-Item $tmpElev.FullName -Force -ErrorAction SilentlyContinue
"@
}
function InstallOrUpdate-BorealisAgent {
Write-Host "Ensuring Agent Dependencies Exist..." -ForegroundColor DarkCyan
Install_Shared_Dependencies
Install_Agent_Dependencies
if (-not (Test-Path $pythonExe)) {
Write-Host "`r$($symbols.Fail) Bundled Python not found at '$pythonExe'." -ForegroundColor Red
exit 1
}
$env:PATH = '{0};{1}' -f (Split-Path $pythonExe), $env:PATH
Write-Host "Deploying Borealis Agent..." -ForegroundColor Blue
$venvFolder = "Agent"
$agentSourcePath = "Data\Agent\borealis-agent.py"
$agentRequirements = "Data\Agent\agent-requirements.txt"
$agentDestinationFolder = "$venvFolder\Borealis"
$agentDestinationFile = "$venvFolder\Borealis\borealis-agent.py"
$venvPython = Join-Path $scriptDir $venvFolder | Join-Path -ChildPath 'Scripts\python.exe'
Run-Step "Create Virtual Python Environment" {
if (-not (Test-Path "$venvFolder\Scripts\Activate")) {
$pythonForVenv = $pythonExe
if (-not (Test-Path $pythonForVenv)) {
$pyCmd = Get-Command py -ErrorAction SilentlyContinue
$pythonCmd = Get-Command python -ErrorAction SilentlyContinue
if ($pyCmd) { $pythonForVenv = $pyCmd.Source }
elseif ($pythonCmd) { $pythonForVenv = $pythonCmd.Source }
else {
Write-Host "Python not found. Install Python or run Server setup (option 1)." -ForegroundColor Red
exit 1
}
}
} catch {}
& $pythonForVenv -m venv $venvFolder
}
if (Test-Path $agentSourcePath) {
Remove-Item $agentDestinationFolder -Recurse -Force -ErrorAction SilentlyContinue
New-Item -Path $agentDestinationFolder -ItemType Directory -Force | Out-Null
Copy-Item "Data\Agent\borealis-agent.py" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\agent_info.py" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\agent_roles.py" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\Python_API_Endpoints" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\agent_deployment.py" $agentDestinationFolder -Force
Copy-Item "Data\Agent\tray_launcher.py" $agentDestinationFolder -Force
if (Test-Path "Data\Agent\Borealis.ico") { Copy-Item "Data\Agent\Borealis.ico" $agentDestinationFolder -Force }
}
. "$venvFolder\Scripts\Activate"
}
if ($needsInstall) {
if (-not (Test-IsAdmin)) {
Write-Host "Admin rights required to install/update the agent service. Prompting UAC..." -ForegroundColor Yellow
$tmp = New-TemporaryFile
$logDir = Join-Path $scriptDir 'Logs'
if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }
$log = Join-Path $logDir 'Borealis_AgentService_Install.log'
$vEsc = $VenvPython.Replace('"','""')
$sEsc = $ServiceScript.Replace('"','""')
$content = @"
$ErrorActionPreference = 'Continue'
$venv = "$vEsc"
$srv = "$sEsc"
$logPath = "$log"
try {
try { New-Item -ItemType Directory -Force -Path (Split-Path $logPath -Parent) | Out-Null } catch {}
# Ensure pywin32 postinstall is applied in this venv (required for services)
try {
& $venv -m pywin32_postinstall -install *>&1 | Tee-Object -FilePath $logPath -Append
} catch { }
"[INFO] Installing service via: $venv $srv --startup auto install" | Out-File -FilePath $logPath -Encoding UTF8
& $venv $srv --startup auto install *>&1 | Tee-Object -FilePath $logPath -Append
try { sc.exe config BorealisAgent obj= LocalSystem | Tee-Object -FilePath $logPath -Append } catch {}
$code = $LASTEXITCODE
if ($code -eq $null) { $code = 0 }
"[INFO] Exit code: $code" | Tee-Object -FilePath $logPath -Append | Out-Host
} catch {
"[ERROR] $_" | Tee-Object -FilePath $logPath -Append | Out-Host
$code = 1
} finally {
if ($code -ne 0 -or $env:BOREALIS_DEBUG_UAC -eq '1') {
Read-Host 'Press Enter to close this elevated window...'
}
exit $code
}
"@
# pass key vars via env so the elevated scope can see them
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = 'powershell.exe'
$psi.Verb = 'runas'
$psi.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$($tmp.FullName)`""
$psi.UseShellExecute = $true
$psi.WindowStyle = 'Normal'
Set-Content -Path $tmp.FullName -Value $content -Force -Encoding UTF8
$proc = [System.Diagnostics.Process]::Start($psi)
$proc.WaitForExit()
Remove-Item $tmp.FullName -Force -ErrorAction SilentlyContinue
if (Test-Path $log) {
Write-Host "--- Elevated install log: $log ---" -ForegroundColor DarkCyan
Get-Content $log | Write-Host
}
} else {
try { & $VenvPython $ServiceScript remove } catch {}
& $VenvPython $ServiceScript --startup auto install
try { sc.exe config BorealisAgent obj= LocalSystem } catch {}
}
# Refresh service object
$svc = Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'" -ErrorAction SilentlyContinue
if (-not $svc) {
Write-Host "Failed to install Borealis Agent service." -ForegroundColor Red
return
Run-Step "Install Python Dependencies" {
if (Test-Path $agentRequirements) {
& $venvPython -m pip install --disable-pip-version-check -q -r $agentRequirements | Out-Null
}
}
if ($svc.State -ne 'Running') {
if (-not (Test-IsAdmin)) {
Write-Host "Admin rights required to start the agent service. Prompting UAC..." -ForegroundColor Yellow
$tmp2 = New-TemporaryFile
$log2 = Join-Path $scriptDir 'Logs\Borealis_AgentService_Start.log'
$content2 = @"
$ErrorActionPreference = 'Continue'
try {
Start-Service -Name '$serviceName'
"[INFO] Started Borealis Agent service." | Out-File -FilePath "$log2" -Encoding UTF8
$code = 0
} catch {
"[ERROR] $_" | Out-File -FilePath "$log2" -Encoding UTF8
$code = 1
} finally {
if ($code -ne 0 -or $env:BOREALIS_DEBUG_UAC -eq '1') { Read-Host 'Press Enter to close this elevated window...' }
exit $code
}
"@
Set-Content -Path $tmp2.FullName -Value $content2 -Force -Encoding UTF8
$psi2 = New-Object System.Diagnostics.ProcessStartInfo
$psi2.FileName = 'powershell.exe'
$psi2.Verb = 'runas'
$psi2.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$($tmp2.FullName)`""
$psi2.UseShellExecute = $true
$psi2.WindowStyle = 'Normal'
$proc2 = [System.Diagnostics.Process]::Start($psi2)
$proc2.WaitForExit()
Remove-Item $tmp2.FullName -Force -ErrorAction SilentlyContinue
if (Test-Path $log2) {
Write-Host "--- Elevated start log: $log2 ---" -ForegroundColor DarkCyan
Get-Content $log2 | Write-Host
}
} else {
Start-Service -Name $serviceName
}
}
Write-Host "`nConfiguring Borealis Agent (tasks)..." -ForegroundColor Blue
Write-Host "===================================================================================="
Ensure-AgentTasks -ScriptRoot $scriptDir
Write-Host "Borealis Agent service is installed and running as LocalSystem (Automatic)." -ForegroundColor Green
# Ensure per-user logon task for helper
$deployScript = Join-Path (Join-Path $scriptDir 'Agent\Borealis') 'agent_deployment.py'
try { & (Join-Path $scriptDir 'Agent\Scripts\python.exe') -W ignore::SyntaxWarning $deployScript task-ensure | Out-Null } catch {}
}
# Ensure Script Agent (LocalSystem Windows Service)
function Ensure-BorealisScriptAgent-Service {
param(
[string]$VenvPython,
[string]$ServiceScript
)
if (-not (Test-IsWindows)) { return }
$serviceName = 'BorealisAgent'
$svc = Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'" -ErrorAction SilentlyContinue
$needsInstall = $false
if (-not $svc) { $needsInstall = $true }
else {
if ($svc.StartMode -notin @('Auto','Automatic')) { $needsInstall = $true }
if ($svc.StartName -ne 'LocalSystem') { $needsInstall = $true }
try {
$venvRoot = Split-Path $VenvPython -Parent
if ($svc.PathName -and $venvRoot -and ($svc.PathName -notlike ("*" + $venvRoot + "*"))) { $needsInstall = $true }
} catch {}
}
$logs = Join-Path $scriptDir 'Logs'
$tempDir = Join-Path $scriptDir 'Temp'; if (-not (Test-Path $tempDir)) { New-Item -ItemType Directory -Path $tempDir -Force | Out-Null }
if (-not (Test-Path $logs)) { New-Item -ItemType Directory -Path $logs -Force | Out-Null }
$preflight = Join-Path $logs 'Borealis_ScriptAgent_Preflight.log'
"$(Get-Date -Format s) Preflight: Ensure-BorealisScriptAgent-Service (needsInstall=$needsInstall)" | Out-File -FilePath $preflight -Append -Encoding UTF8
if ($needsInstall) {
if (-not (Test-IsAdmin)) {
Write-Host "Admin rights required to install/update the script agent service. Prompting UAC..." -ForegroundColor Yellow
$log = Join-Path $logs 'Borealis_ScriptAgent_Install.log'
$vEsc = $VenvPython.Replace('"','""')
$sEsc = $ServiceScript.Replace('"','""')
$content = @"
$ErrorActionPreference = 'Continue'
$venv = "$vEsc"
$srv = "$sEsc"
$logPath = "$log"
try {
try { New-Item -ItemType Directory -Force -Path (Split-Path $logPath -Parent) | Out-Null } catch {}
& $venv -m pywin32_postinstall -install *>&1 | Tee-Object -FilePath $logPath -Append
try { & $venv $srv remove *>&1 | Tee-Object -FilePath $logPath -Append } catch {}
& $venv $srv --startup auto install *>&1 | Tee-Object -FilePath $logPath -Append
sc.exe config $serviceName obj= LocalSystem | Tee-Object -FilePath $logPath -Append
$code = $LASTEXITCODE; if ($code -eq $null) { $code = 0 }
} catch {
"[ERROR] $_" | Tee-Object -FilePath $logPath -Append | Out-Host
$code = 1
} finally {
if ($code -ne 0 -or $env:BOREALIS_DEBUG_UAC -eq '1') { Read-Host 'Press Enter to close this elevated window...' }
exit $code
}
"@
$elevateScript = Join-Path $tempDir 'Elevated-Install-ScriptAgent.ps1'
Set-Content -Path $elevateScript -Value $content -Force -Encoding UTF8
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = 'powershell.exe'
$psi.Verb = 'runas'
$psi.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$elevateScript`""
$psi.UseShellExecute = $true
$psi.WindowStyle = 'Normal'
$psi.WorkingDirectory = $scriptDir
$proc = [System.Diagnostics.Process]::Start($psi)
$proc.WaitForExit()
if ($proc.ExitCode -eq 0) { Remove-Item $elevateScript -Force -ErrorAction SilentlyContinue } else { Write-Host "Keeping stub for troubleshooting: $elevateScript" -ForegroundColor Yellow }
if (Test-Path $log) { Write-Host "--- Elevated install log: $log ---" -ForegroundColor DarkCyan; Get-Content $log | Write-Host }
else { Write-Host "Install log not found at: $log" -ForegroundColor Yellow }
if ($proc.ExitCode -ne 0) { Write-Host "Elevated install returned code $($proc.ExitCode)" -ForegroundColor Red; return }
} else {
try { & $VenvPython $ServiceScript remove } catch {}
& $VenvPython $ServiceScript --startup auto install
try { sc.exe config $serviceName obj= LocalSystem } catch {}
}
}
$svc = Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'" -ErrorAction SilentlyContinue
if (-not $svc) { Write-Host "ScriptAgent service not found after install." -ForegroundColor Red; return $false }
if ($svc.State -ne 'Running') {
if (-not (Test-IsAdmin)) {
Write-Host "Admin rights required to start the script agent service. Prompting UAC..." -ForegroundColor Yellow
$log2 = Join-Path $logs 'Borealis_ScriptAgent_Start.log'
$content2 = @"
$ErrorActionPreference = 'Continue'
try { Start-Service -Name '$serviceName'; "[INFO] Started." | Out-File -FilePath "$log2" -Encoding UTF8; $code = 0 } catch { "[ERROR] $_" | Out-File -FilePath "$log2" -Encoding UTF8; $code = 1 } finally { if ($code -ne 0 -or $env:BOREALIS_DEBUG_UAC -eq '1') { Read-Host 'Press Enter to close this elevated window...' }; exit $code }
"@
$elevateStart = Join-Path $tempDir 'Elevated-Start-ScriptAgent.ps1'
Set-Content -Path $elevateStart -Value $content2 -Force -Encoding UTF8
$psi2 = New-Object System.Diagnostics.ProcessStartInfo
$psi2.FileName = 'powershell.exe'
$psi2.Verb = 'runas'
$psi2.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$elevateStart`""
$psi2.UseShellExecute = $true
$psi2.WindowStyle = 'Normal'
$psi2.WorkingDirectory = $scriptDir
$proc2 = [System.Diagnostics.Process]::Start($psi2)
$proc2.WaitForExit()
if ($proc2.ExitCode -eq 0) { Remove-Item $elevateStart -Force -ErrorAction SilentlyContinue } else { Write-Host "Keeping stub for troubleshooting: $elevateStart" -ForegroundColor Yellow }
if (Test-Path $log2) { Write-Host "--- Elevated start log: $log2 ---" -ForegroundColor DarkCyan; Get-Content $log2 | Write-Host }
else { Write-Host "Start log not found at: $log2" -ForegroundColor Yellow }
if ($proc2.ExitCode -ne 0) { Write-Host "Elevated start returned code $($proc2.ExitCode)" -ForegroundColor Red; return }
} else {
Start-Service -Name $serviceName
}
Start-Sleep -Seconds 2
$svc = Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'" -ErrorAction SilentlyContinue
if ($svc.State -ne 'Running') { Write-Host "ScriptAgent service failed to start." -ForegroundColor Red; return $false }
}
return $true
}
# Ensure Collector Agent (per-user scheduled task)
function Ensure-BorealisCollector-Task {
param(
[string]$VenvPython,
[string]$CollectorScript
)
$logs = Join-Path $scriptDir 'Logs'
if (-not (Test-Path $logs)) { New-Item -ItemType Directory -Path $logs -Force | Out-Null }
"$(Get-Date -Format s) Preflight: Ensure-BorealisCollector-Task" | Out-File -FilePath (Join-Path $logs 'Borealis_Collector_Preflight.log') -Append -Encoding UTF8
$tempDir = Join-Path $scriptDir 'Temp'
if (-not (Test-Path $tempDir)) { New-Item -ItemType Directory -Path $tempDir -Force | Out-Null }
$logC = Join-Path $logs 'Borealis_CollectorTask_Install.log'
$taskName = 'BorealisCollectorAgent'
$taskExists = $false
try {
$null = schtasks.exe /Query /TN $taskName 2>$null
if ($LASTEXITCODE -eq 0) { $taskExists = $true }
} catch {}
$quoted = '"' + $VenvPython + '" -W ignore::SyntaxWarning "' + $CollectorScript + '"'
if ($taskExists) {
# Replace to ensure it points to current project
# Attempt delete in current user context first
try {
schtasks.exe /Delete /TN $taskName /F 2>&1 | Tee-Object -FilePath $logC -Append | Out-Host
} catch {}
if ($LASTEXITCODE -ne 0) {
# If deletion failed (likely created under elevated/Admin previously), delete via elevated stub
$stubDel = Join-Path $tempDir 'Elevated-Delete-CollectorTask.ps1'
$tnEsc = $taskName.Replace('"','""')
$lgEsc = $logC.Replace('"','""')
$contentDel = @"
$ErrorActionPreference = 'Continue'
try {
schtasks.exe /Delete /TN "$tnEsc" /F *>&1 | Tee-Object -FilePath "$lgEsc" -Append
$code = $LASTEXITCODE; if ($code -eq $null) { $code = 0 }
} catch { "[ERROR] $_" | Tee-Object -FilePath "$lgEsc" -Append; $code = 1 } finally {
if ($code -ne 0 -or $env:BOREALIS_DEBUG_UAC -eq '1') { Read-Host 'Press Enter to close this elevated window...' }
exit $code
}
"@
Set-Content -Path $stubDel -Value $contentDel -Force -Encoding UTF8
$psiD = New-Object System.Diagnostics.ProcessStartInfo
$psiD.FileName = 'powershell.exe'
$psiD.Verb = 'runas'
$psiD.Arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$stubDel`""
$psiD.UseShellExecute = $true
$psiD.WindowStyle = 'Normal'
try { $psiD.WorkingDirectory = $scriptDir; $pd = [System.Diagnostics.Process]::Start($psiD); $pd.WaitForExit() } catch {}
Remove-Item $stubDel -Force -ErrorAction SilentlyContinue
}
# Re-evaluate existence; if still present, abort
try { $null = schtasks.exe /Query /TN $taskName 2>$null } catch {}
if ($LASTEXITCODE -eq 0) {
Write-Host "Failed to remove existing Collector task (permissions)." -ForegroundColor Red
if (Test-Path $logC) { Write-Host "--- Collector task log: $logC ---" -ForegroundColor DarkCyan; Get-Content $logC | Write-Host }
return $false
}
}
# Create per-user task in the current (non-elevated) user context
# Do NOT elevate creation to avoid creating task under Administrator by mistake
schtasks.exe /Create /SC ONLOGON /TN $taskName /TR $quoted /F /RL LIMITED 2>&1 | Tee-Object -FilePath $logC -Append | Out-Host
if ($LASTEXITCODE -ne 0) {
Write-Host "Failed to create Collector task." -ForegroundColor Red
if (Test-Path $logC) { Write-Host "--- Collector task log: $logC ---" -ForegroundColor DarkCyan; Get-Content $logC | Write-Host }
return $false
}
# If currently logged in, start now
try { schtasks.exe /Run /TN $taskName 2>&1 | Tee-Object -FilePath $logC -Append | Out-Host } catch {}
# Validate task exists
try { $null = schtasks.exe /Query /TN $taskName 2>$null } catch {}
if ($LASTEXITCODE -ne 0) { Write-Host "Collector task missing after create." -ForegroundColor Red; return $false }
return $true
}
#>
# ---------------------- Common Initialization & Visuals ----------------------
# ---------------------- Main ----------------------
Clear-Host
# ASCII Art Banner
@@ -749,9 +455,6 @@ Clear-Host
'@ | Write-Host -ForegroundColor DarkCyan
Write-Host "Automation Platform" -ForegroundColor DarkGray
## Defer PATH updates and tool presence checks until after a selection is made
# ---------------------- Menu Prompt & User Input ----------------------
if (-not $choice) {
Write-Host " "
Write-Host "Please choose which function you want to launch:"
@@ -769,48 +472,35 @@ if (-not $choice) {
Write-Host "<ENTER>" -ForegroundColor DarkCyan
$choice = Read-Host
}
switch ($choice) {
switch ($choice) {
"1" {
$host.UI.RawUI.WindowTitle = "Borealis Server"
Write-Host "Ensuring Server Dependencies Exist..." -ForegroundColor DarkCyan
# ---------------------- Ensure users.json is Present ----------------------
Run-Step "First-Run: Generating users.json" {
$usersJsonPath = Join-Path $scriptDir "users.json"
if (-not (Test-Path $usersJsonPath)) {
$defaultUsers = @{ users = @(@{ username = "admin"; password = "e6c83b282aeb2e022844595721cc00bbda47cb24537c1779f9bb84f04039e1676e6ba8573e588da1052510e3aa0a32a9e55879ae22b0c2d62136fc0a3e85f8bb" }) } |
ConvertTo-Json -Depth 4
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($usersJsonPath, $defaultUsers, $utf8NoBom)
$defaultUsers = @{ users = @(@{ username = "admin"; password = "e6c83b282aeb2e022844595721cc00bbda47cb24537c1779f9bb84f04039e1676e6ba8573e588da1052510e3aa0a32a9e55879ae22b0c2d62136fc0a3e85f8bb" }) } | ConvertTo-Json -Depth 4
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($usersJsonPath, $defaultUsers, $utf8NoBom)
}
}
Install_Shared_Dependencies
Install_Server_Dependencies
# After ensuring dependencies, verify key tools and update PATH
foreach ($tool in @($pythonExe, $nodeExe, $npmCmd, $npxCmd)) {
if (-not (Test-Path $tool)) {
Write-Host "`r$($symbols.Fail) Bundled executable not found at '$tool'." -ForegroundColor Red
exit 1
}
if (-not (Test-Path $tool)) { Write-Host "`r$($symbols.Fail) Bundled executable not found at '$tool'." -ForegroundColor Red; exit 1 }
}
$env:PATH = '{0};{1};{2}' -f (Split-Path $pythonExe), (Split-Path $nodeExe), $env:PATH
if (-not $modeChoice) {
Write-Host " "
Write-Host "Configure Borealis Server Mode:" -ForegroundColor DarkYellow
Write-Host " 1) Build & Launch > " -NoNewLine -ForegroundColor DarkGray
Write-Host "Production Flask Server @ " -NoNewLine
Write-Host "http://localhost:5000" -ForegroundColor DarkCyan
Write-Host " 2) [Skip Build] & Immediately Launch > " -NoNewLine -ForegroundColor DarkGray
Write-Host "Production Flask Server @ " -NoNewLine
Write-Host "http://localhost:5000" -ForegroundColor DarkCyan
Write-Host " 3) Launch > " -NoNewLine -ForegroundColor DarkGray
Write-Host "[Hotload-Ready] " -NoNewLine -ForegroundColor Green
Write-Host "Vite Dev Server @ " -NoNewLine
Write-Host "http://localhost:5173" -ForegroundColor DarkCyan
Write-Host " 1) Build & Launch > Production Flask Server @ http://localhost:5000" -ForegroundColor DarkCyan
Write-Host " 2) [Skip Build] & Immediately Launch > Production Flask Server @ http://localhost:5000" -ForegroundColor DarkCyan
Write-Host " 3) Launch > [Hotload-Ready] Vite Dev Server @ http://localhost:5173" -ForegroundColor DarkCyan
$modeChoice = Read-Host "Enter choice [1/2/3]"
}
@@ -822,16 +512,12 @@ switch ($choice) {
& (Join-Path $scriptDir "Server\Scripts\python.exe") (Join-Path $scriptDir "Server\Borealis\server.py")
Pop-Location
}
Exit 0
}
"3" { $borealis_operation_mode = "developer" }
default {
Write-Host "Invalid mode choice: $modeChoice" -ForegroundColor Red
Exit 1
break
}
"3" { $borealis_operation_mode = "developer" }
default { Write-Host "Invalid mode choice: $modeChoice" -ForegroundColor Red; break }
}
# ───── Now run your deploy logic ─────
Write-Host "Deploying Borealis Server in '$borealis_operation_mode' mode" -ForegroundColor Blue
$venvFolder = "Server"
@@ -841,9 +527,7 @@ switch ($choice) {
$webUIDestination = "$venvFolder\web-interface"
$venvPython = Join-Path $venvFolder 'Scripts\python.exe'
# Create Virtual Environment & Copy Server Assets
Run-Step "Create Borealis Virtual Python Environment" {
# Leverage Bundled Python Dependency to Construct Virtual Python Environment
if (-not (Test-Path "$venvFolder\Scripts\Activate")) { & $pythonExe -m venv $venvFolder | Out-Null }
if (Test-Path $dataSource) {
Remove-Item $dataDestination -Recurse -Force -ErrorAction SilentlyContinue
@@ -855,14 +539,10 @@ switch ($choice) {
. "$venvFolder\Scripts\Activate"
}
# Install Python Dependencies
Run-Step "Install Python Dependencies into Virtual Python Environment" {
if (Test-Path "$dataSource\Server\server-requirements.txt") {
& $venvPython -m pip install --disable-pip-version-check -q -r "$dataSource\Server\server-requirements.txt" | Out-Null
}
if (Test-Path "$dataSource\Server\server-requirements.txt") { & $venvPython -m pip install --disable-pip-version-check -q -r "$dataSource\Server\server-requirements.txt" | Out-Null }
}
# Copy Vite WebUI Assets
Run-Step "Copy Borealis WebUI Files into: $webUIDestination" {
if (Test-Path $webUIDestination) {
Remove-Item "$webUIDestination\public\*" -Recurse -Force -ErrorAction SilentlyContinue
@@ -873,7 +553,6 @@ switch ($choice) {
Copy-Item "$customUIPath\*" $webUIDestination -Recurse -Force
}
# NPM Install for WebUI
Run-Step "Vite Web Frontend: Install NPM Packages" {
Push-Location $webUIDestination
$env:npm_config_loglevel = "silent"
@@ -881,7 +560,6 @@ switch ($choice) {
Pop-Location
}
# Vite Operation Mode Control (build vs dev)
Run-Step "Vite Web Frontend: Start ($borealis_operation_mode)" {
Push-Location $webUIDestination
if ($borealis_operation_mode -eq "developer") { $viteSubCommand = "dev" } else { $viteSubCommand = "build" }
@@ -889,16 +567,13 @@ switch ($choice) {
Pop-Location
}
# Launch Flask Server
Run-Step "Borealis: Launch Flask Server" {
Push-Location (Join-Path $scriptDir "Server")
$py = Join-Path $scriptDir "Server\Scripts\python.exe"
$server_py = Join-Path $scriptDir "Server\Borealis\server.py"
Write-Host "`nLaunching Borealis..." -ForegroundColor Green
Write-Host "===================================================================================="
Write-Host "$($symbols.Running) Python Flask API Server Started..."
& $py $server_py
Pop-Location
}
@@ -917,16 +592,10 @@ switch ($choice) {
if (-not $agentSubChoice) { $agentSubChoice = Read-Host "Select an option" }
switch ($agentSubChoice) {
'2' {
Repair-BorealisAgent
break
}
'3' {
Remove-BorealisAgent
break
}
'1' { InstallOrUpdate-BorealisAgent; break }
'2' { Repair-BorealisAgent; break }
'3' { Remove-BorealisAgent; break }
'4' {
# Manually launch helper for the current session (optional)
$venvPythonw = Join-Path $scriptDir 'Agent\Scripts\pythonw.exe'
$helper = Join-Path $scriptDir 'Agent\Borealis\borealis-agent.py'
if (-not (Test-Path $venvPythonw)) { Write-Host "pythonw.exe not found under Agent\Scripts" -ForegroundColor Yellow }
@@ -937,115 +606,33 @@ switch ($choice) {
}
break
}
'5' { break }
Default {
# 1) Install/Update Agent (original behavior)
Write-Host "Ensuring Agent Dependencies Exist..." -ForegroundColor DarkCyan
Install_Shared_Dependencies
Install_Agent_Dependencies
if (-not (Test-Path $pythonExe)) {
Write-Host "`r$($symbols.Fail) Bundled Python not found at '$pythonExe'." -ForegroundColor Red
exit 1
}
$env:PATH = '{0};{1}' -f (Split-Path $pythonExe), $env:PATH
Write-Host "Deploying Borealis Agent..." -ForegroundColor Blue
$venvFolder = "Agent"
$agentSourcePath = "Data\Agent\borealis-agent.py"
$agentRequirements = "Data\Agent\agent-requirements.txt"
$agentDestinationFolder = "$venvFolder\Borealis"
$agentDestinationFile = "$venvFolder\Borealis\borealis-agent.py"
$venvPython = Join-Path $scriptDir $venvFolder | Join-Path -ChildPath 'Scripts\python.exe'
Run-Step "Create Virtual Python Environment" {
if (-not (Test-Path "$venvFolder\Scripts\Activate")) {
$pythonForVenv = $pythonExe
if (-not (Test-Path $pythonForVenv)) {
$pyCmd = Get-Command py -ErrorAction SilentlyContinue
$pythonCmd = Get-Command python -ErrorAction SilentlyContinue
if ($pyCmd) { $pythonForVenv = $pyCmd.Source }
elseif ($pythonCmd) { $pythonForVenv = $pythonCmd.Source }
else {
Write-Host "Python not found. Install Python or run Server setup (option 1)." -ForegroundColor Red
exit 1
}
}
& $pythonForVenv -m venv $venvFolder
}
if (Test-Path $agentSourcePath) {
Remove-Item $agentDestinationFolder -Recurse -Force -ErrorAction SilentlyContinue
New-Item -Path $agentDestinationFolder -ItemType Directory -Force | Out-Null
Copy-Item "Data\Agent\borealis-agent.py" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\agent_info.py" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\agent_roles.py" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\Python_API_Endpoints" $agentDestinationFolder -Recurse
Copy-Item "Data\Agent\windows_script_service.py" $agentDestinationFolder -Force
Copy-Item "Data\Agent\agent_deployment.py" $agentDestinationFolder -Force
Copy-Item "Data\Agent\tray_launcher.py" $agentDestinationFolder -Force
if (Test-Path "Data\Agent\Borealis.ico") { Copy-Item "Data\Agent\Borealis.ico" $agentDestinationFolder -Force }
}
. "$venvFolder\Scripts\Activate"
}
Run-Step "Install Python Dependencies" {
if (Test-Path $agentRequirements) {
& $venvPython -m pip install --disable-pip-version-check -q -r $agentRequirements | Out-Null
}
}
Write-Host "`nConfiguring Borealis Agent (service)..." -ForegroundColor Blue
Write-Host "===================================================================================="
$deployScript = Join-Path $agentDestinationFolder 'agent_deployment.py'
& $venvPython -W ignore::SyntaxWarning $deployScript ensure-all
if ($LASTEXITCODE -ne 0) {
Write-Host "Agent setup FAILED." -ForegroundColor Red
Write-Host " - See logs under: $(Join-Path $scriptDir 'Logs')" -ForegroundColor Red
exit 1
} else {
Write-Host "Agent setup complete. Service ensured." -ForegroundColor DarkGreen
}
}
default { break }
}
}
"3" {
$host.UI.RawUI.WindowTitle = "Borealis Electron"
# Desktop App Deployment (Electron)
Clear-Host
Write-Host "Deploying Borealis Desktop App..." -ForegroundColor Cyan
Write-Host "===================================================================================="
$electronSource = "Data\Electron"
$electronDestination = "ElectronApp"
$scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent
# 1) Prepare ElectronApp folder
Run-Step "Prepare ElectronApp folder" {
if (Test-Path $electronDestination) {
Remove-Item $electronDestination -Recurse -Force
}
if (Test-Path $electronDestination) { Remove-Item $electronDestination -Recurse -Force }
New-Item -Path $electronDestination -ItemType Directory | Out-Null
# Copy deployed Flask server
$deployedServer = Join-Path $scriptDir 'Server\Borealis'
if (-not (Test-Path $deployedServer)) {
throw "Server\Borealis not found - please run choice 1 first."
}
if (-not (Test-Path $deployedServer)) { throw "Server\Borealis not found - please run choice 1 first." }
Copy-Item $deployedServer "$electronDestination\Server" -Recurse
# Copy Electron scaffold files
Copy-Item "$electronSource\package.json" "$electronDestination" -Force
Copy-Item "$electronSource\main.js" "$electronDestination" -Force
# Copy built WebUI into renderer
$staticBuild = Join-Path $scriptDir 'Server\web-interface\build'
if (-not (Test-Path $staticBuild)) {
throw "WebUI build not found - run choice 1 to build WebUI first."
}
if (-not (Test-Path $staticBuild)) { throw "WebUI build not found - run choice 1 to build WebUI first." }
Copy-Item "$staticBuild\*" "$electronDestination\renderer" -Recurse -Force
}
# 2) Install Electron & Builder
Run-Step "ElectronApp: Install Node dependencies" {
Push-Location $electronDestination
$env:NODE_ENV = ''
@@ -1054,14 +641,12 @@ switch ($choice) {
Pop-Location
}
# 3) Package desktop app
Run-Step "ElectronApp: Package with electron-builder" {
Push-Location $electronDestination
& $npmCmd run dist
Pop-Location
}
# 4) Launch in dev mode
Run-Step "ElectronApp: Launch in dev mode" {
Push-Location $electronDestination
& $npmCmd run dev
@@ -1071,43 +656,29 @@ switch ($choice) {
"4" {
$host.UI.RawUI.WindowTitle = "Borealis Packager"
# Prompt the User for Which System to Package using Pyinstaller
Write-Host "Choose which module to package into a self-contained EXE file:" -ForegroundColor DarkYellow
Write-Host " 1) Server" -ForegroundColor DarkGray
Write-Host " 2) Agent" -ForegroundColor DarkGray
$exePackageChoice = Read-Host "Enter choice [1/2]"
switch ($exePackageChoice) {
"1" {
"1" {
$serverScriptDir = Join-Path -Path $PSScriptRoot -ChildPath "Data\Server"
Set-Location -Path $serverScriptDir
& (Join-Path -Path $serverScriptDir -ChildPath "Package-Borealis-Server.ps1")
& (Join-Path -Path $serverScriptDir -ChildPath "Package-Borealis-Server.ps1")
}
"2" {
"2" {
$agentScriptDir = Join-Path -Path $PSScriptRoot -ChildPath "Data\Agent"
Set-Location -Path $agentScriptDir
& (Join-Path -Path $agentScriptDir -ChildPath "Package_Borealis-Agent.ps1")
& (Join-Path -Path $agentScriptDir -ChildPath "Package_Borealis-Agent.ps1")
}
default {
Write-Host "Invalid Choice. Exiting..." -ForegroundColor Red
exit 1
}
}
}
default {
Write-Host "Invalid selection. Exiting..." -ForegroundColor Red
exit 1
default { Write-Host "Invalid Choice. Exiting..." -ForegroundColor Red; exit 1 }
}
}
"5" {
$host.UI.RawUI.WindowTitle = "Borealis Updater"
Write-Host " "
Write-Host "Updating Borealis..." -ForegroundColor Green
# Prepare paths
$updateZip = Join-Path $scriptDir "Update_Staging\main.zip"
$updateDir = Join-Path $scriptDir "Update_Staging\Borealis-main"
$preservePath = Join-Path $scriptDir "Data\Server\Python_API_Endpoints\Tesseract-OCR"
@@ -1115,62 +686,41 @@ switch ($choice) {
Run-Step "Updating: Move Tesseract-OCR Folder Somewhere Safe to Restore Later" {
if (Test-Path $preservePath) {
# Ensure staging folder exists
$stagingPath = Join-Path $scriptDir "Update_Staging"
if (-not (Test-Path $stagingPath)) {
New-Item -ItemType Directory -Force -Path $stagingPath | Out-Null
}
if (-not (Test-Path $stagingPath)) { New-Item -ItemType Directory -Force -Path $stagingPath | Out-Null }
Move-Item -Path $preservePath -Destination $preserveBackupPath -Force
}
}
Run-Step "Updating: Clean Up Folders to Prepare for Update" {
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue `
(Join-Path $scriptDir "Data"), `
(Join-Path $scriptDir "Server\web-interface\src"), `
(Join-Path $scriptDir "Server\web-interface\build"), `
(Join-Path $scriptDir "Server\web-interface\public"), `
(Join-Path $scriptDir "Server\Borealis")
(Join-Path $scriptDir "Data"), `
(Join-Path $scriptDir "Server\web-interface\src"), `
(Join-Path $scriptDir "Server\web-interface\build"), `
(Join-Path $scriptDir "Server\web-interface\public"), `
(Join-Path $scriptDir "Server\Borealis")
}
Run-Step "Updating: Create Update Staging Folder" {
$stagingPath = Join-Path $scriptDir "Update_Staging"
if (-not (Test-Path $stagingPath)) {
New-Item -ItemType Directory -Force -Path $stagingPath | Out-Null
}
if (-not (Test-Path $stagingPath)) { New-Item -ItemType Directory -Force -Path $stagingPath | Out-Null }
$updateZip = Join-Path $stagingPath "main.zip"
$updateDir = Join-Path $stagingPath "Borealis-main"
}
Run-Step "Updating: Download Update from https://github.com/bunny-lab-io/Borealis/archive/refs/heads/main.zip" {
Invoke-WebRequest -Uri "https://github.com/bunny-lab-io/Borealis/archive/refs/heads/main.zip" -OutFile $updateZip
}
Run-Step "Updating: Extract Update Files" {
Expand-Archive -Path $updateZip -DestinationPath (Join-Path $scriptDir "Update_Staging") -Force
}
Run-Step "Updating: Copy Update Files into Production Borealis Root Folder" {
Copy-Item "$updateDir\*" $scriptDir -Recurse -Force
}
Run-Step "Updating: Download Update" { Invoke-WebRequest -Uri "https://github.com/bunny-lab-io/Borealis/archive/refs/heads/main.zip" -OutFile $updateZip }
Run-Step "Updating: Extract Update Files" { Expand-Archive -Path $updateZip -DestinationPath (Join-Path $scriptDir "Update_Staging") -Force }
Run-Step "Updating: Copy Update Files into Production Borealis Root Folder" { Copy-Item "$updateDir\*" $scriptDir -Recurse -Force }
Run-Step "Updating: Restore Tesseract-OCR Folder" {
$restorePath = Join-Path $scriptDir "Data\Server\Python_API_Endpoints"
if (Test-Path $preserveBackupPath) {
# Ensure destination path exists
if (-not (Test-Path $restorePath)) {
New-Item -ItemType Directory -Force -Path $restorePath | Out-Null
}
if (-not (Test-Path $restorePath)) { New-Item -ItemType Directory -Force -Path $restorePath | Out-Null }
Move-Item -Path $preserveBackupPath -Destination $restorePath -Force
}
}
Run-Step "Updating: Clean Up Update Staging Folder" {
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue (Join-Path $scriptDir "Update_Staging")
}
Run-Step "Updating: Clean Up Update Staging Folder" { Remove-Item -Recurse -Force -ErrorAction SilentlyContinue (Join-Path $scriptDir "Update_Staging") }
Write-Host "`nUpdate Complete! Please Re-Launch the Borealis Script." -ForegroundColor Green
Read-Host "Press any key to re-launch Borealis..."
@@ -1182,12 +732,11 @@ switch ($choice) {
$host.UI.RawUI.WindowTitle = "AutoHotKey Automation Testing"
Write-Host " "
Write-Host "Lauching AutoHotKey Testing Script..." -ForegroundColor Blue
$venvFolder = "Macro_Testing"
$scriptSourcePath = "Data\Experimental\Macros\Macro_Script.py"
$scriptRequirements = "Data\Experimental\Macros\macro-requirements.txt"
$scriptDestinationFolder = "$venvFolder\Borealis"
$scriptDestinationFile = "$venvFolder\Borealis\Macro_Script.py"
$scriptSourcePath = "Data\Experimental\Macros\Macro_Script.py"
$scriptRequirements = "Data\Experimental\Macros\macro-requirements.txt"
$scriptDestinationFolder= "$venvFolder\Borealis"
$scriptDestinationFile = "$venvFolder\Borealis\Macro_Script.py"
$venvPython = Join-Path $scriptDir $venvFolder | Join-Path -ChildPath 'Scripts\python.exe'
Run-Step "Create Virtual Python Environment" {
@@ -1198,10 +747,7 @@ switch ($choice) {
$pythonCmd = Get-Command python -ErrorAction SilentlyContinue
if ($pyCmd) { $pythonForVenv = $pyCmd.Source }
elseif ($pythonCmd) { $pythonForVenv = $pythonCmd.Source }
else {
Write-Host "Python not found. Install Python or run Server setup (option 1)." -ForegroundColor Red
exit 1
}
else { Write-Host "Python not found. Install Python or run Server setup (option 1)." -ForegroundColor Red; exit 1 }
}
& $pythonForVenv -m venv $venvFolder
}
@@ -1214,14 +760,11 @@ switch ($choice) {
. "$venvFolder\Scripts\Activate"
}
Run-Step "Install Python Dependencies" {
if (Test-Path $scriptRequirements) {
& $venvPython -m pip install --disable-pip-version-check -q -r $scriptRequirements | Out-Null
}
}
Run-Step "Install Python Dependencies" { if (Test-Path $scriptRequirements) { & $venvPython -m pip install --disable-pip-version-check -q -r $scriptRequirements | Out-Null } }
Write-Host "`nLaunching Macro Testing Script..." -ForegroundColor Blue
Write-Host "===================================================================================="
& $venvPython -W ignore::SyntaxWarning $scriptDestinationFile
}
default { Write-Host "Invalid selection. Exiting..." -ForegroundColor Red; exit 1 }
}