Role-Specific Dependencies Now Only Download When Agent or Server is Chosen

This commit is contained in:
2025-09-02 23:13:33 -06:00
parent 4fdcd2e3c5
commit 9442412aea

View File

@@ -66,7 +66,7 @@ Clear-Host
'@ | Write-Host -ForegroundColor DarkCyan '@ | Write-Host -ForegroundColor DarkCyan
Write-Host "Automation Platform" -ForegroundColor DarkGray Write-Host "Automation Platform" -ForegroundColor DarkGray
Write-Host " " Write-Host " "
Write-Host "Ensuring Dependencies Exist..." -ForegroundColor DarkCyan ## Note: Heavy dependency downloads are deferred until selecting Server (option 1)
# ---------------------- ASCII Art Terminal Required Changes ---------------------- # ---------------------- ASCII Art Terminal Required Changes ----------------------
# Set the .NET Console output encoding to UTF8 # Set the .NET Console output encoding to UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
@@ -125,160 +125,163 @@ $node7zUrl = "https://nodejs.org/dist/v23.11.0/node-v23.11.0-win-x64.7z"
$nodeInstallDir = Join-Path $depsRoot "NodeJS" $nodeInstallDir = Join-Path $depsRoot "NodeJS"
$node7zPath = Join-Path $depsRoot "node-v23.11.0-win-x64.7z" $node7zPath = Join-Path $depsRoot "node-v23.11.0-win-x64.7z"
# ---------------------- Ensure NodeJS is Present (Bundled via 7-Zip) ---------------------- # ---------------------- Dependency Installation Functions ----------------------
Run-Step "Dependency: NodeJS" { function Install_Shared_Dependencies {
if (-not (Test-Path $nodeExe)) { # Python (shared by Server and Agent)
# Download archive if not present Run-Step "Dependency: Python" {
if (-not (Test-Path $node7zPath)) { $pythonInstallDir = Join-Path $scriptDir "Dependencies\Python"
Invoke-WebRequest -Uri $node7zUrl -OutFile $node7zPath $localPythonExe = Join-Path $pythonInstallDir "python.exe"
}
# Extract using bundled 7z $pythonMsiBaseUrl = "https://www.python.org/ftp/python/3.13.3/amd64/"
if (-not (Test-Path $sevenZipExe)) { $pythonMsiFiles = @(
throw "7-Zip CLI not found at: $sevenZipExe" "core.msi",
} "exe.msi",
"lib.msi",
"pip.msi",
"dev.msi"
)
& $sevenZipExe x $node7zPath "-o$nodeInstallDir" -y | Out-Null if (-not (Test-Path $localPythonExe)) {
if (-not (Test-Path $pythonInstallDir)) {
# The extracted contents might live under a subfolder; flatten if needed New-Item -ItemType Directory -Path $pythonInstallDir | Out-Null
$extracted = Get-ChildItem $nodeInstallDir | Where-Object { $_.PSIsContainer } | Select-Object -First 1
if ($extracted) {
Get-ChildItem $extracted.FullName | Move-Item -Destination $nodeInstallDir -Force
Remove-Item $extracted.FullName -Recurse -Force
}
# Clean Up 7z File After Extraction
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $node7zPath
}
}
# ---------------------- Ensure Python is Present (via Installer Extraction) ----------------------
Run-Step "Dependency: Python" {
$pythonInstallDir = Join-Path $scriptDir "Dependencies\Python"
$pythonExe = Join-Path $pythonInstallDir "python.exe"
$pythonMsiBaseUrl = "https://www.python.org/ftp/python/3.13.3/amd64/"
$pythonMsiFiles = @(
"core.msi",
"exe.msi",
"lib.msi",
"pip.msi",
"dev.msi"
)
if (-not (Test-Path $pythonExe)) {
if (-not (Test-Path $pythonInstallDir)) {
New-Item -ItemType Directory -Path $pythonInstallDir | Out-Null
}
foreach ($file in $pythonMsiFiles) {
$url = "$pythonMsiBaseUrl$file"
$localPath = Join-Path $scriptDir "Dependencies\$file"
# Download if missing
if (-not (Test-Path $localPath)) {
Invoke-WebRequest -Uri $url -OutFile $localPath
} }
# Extract MSI into install directory foreach ($file in $pythonMsiFiles) {
Start-Process -Wait -NoNewWindow -FilePath "msiexec.exe" ` $url = "$pythonMsiBaseUrl$file"
-ArgumentList "/a `"$localPath`" /qn TARGETDIR=`"$pythonInstallDir`"" $localPath = Join-Path $scriptDir "Dependencies\$file"
}
# Clean up downloaded MSIs # Download if missing
foreach ($file in $pythonMsiFiles) { if (-not (Test-Path $localPath)) {
$localPath = Join-Path $scriptDir "Dependencies\$file" Invoke-WebRequest -Uri $url -OutFile $localPath
Remove-Item $localPath -Force -ErrorAction SilentlyContinue }
}
# Validate success # Extract MSI into install directory
if (-not (Test-Path $pythonExe)) { Start-Process -Wait -NoNewWindow -FilePath "msiexec.exe" `
throw "Python executable not found after MSI extraction." -ArgumentList "/a `"$localPath`" /qn TARGETDIR=`"$pythonInstallDir`""
}
# Clean up downloaded MSIs
foreach ($file in $pythonMsiFiles) {
$localPath = Join-Path $scriptDir "Dependencies\$file"
Remove-Item $localPath -Force -ErrorAction SilentlyContinue
}
# Validate success
if (-not (Test-Path $localPythonExe)) {
throw "Python executable not found after MSI extraction."
}
} }
} else {
} }
} }
# ---------------------- Ensure Tesseract OCR is Present (Extract from SFX EXE) ---------------------- function Install_Server_Dependencies {
Run-Step "Dependency: Tesseract-OCR" { # NodeJS (required for Vite / Web UI)
$tessExeUrl = "https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe" Run-Step "Dependency: NodeJS" {
$tessExePath = Join-Path $depsRoot "tesseract-installer.exe" if (-not (Test-Path $nodeExe)) {
$tessInstallDir = Join-Path $scriptDir "Data\Server\Python_API_Endpoints\Tesseract-OCR" # Download archive if not present
if (-not (Test-Path $node7zPath)) {
Invoke-WebRequest -Uri $node7zUrl -OutFile $node7zPath
}
if (-not (Test-Path (Join-Path $tessInstallDir "tesseract.exe"))) { # Extract using bundled 7z
# Download the installer if it doesn't exist if (-not (Test-Path $sevenZipExe)) {
if (-not (Test-Path $tessExePath)) { throw "7-Zip CLI not found at: $sevenZipExe"
Invoke-WebRequest -Uri $tessExeUrl -OutFile $tessExePath }
& $sevenZipExe x $node7zPath "-o$nodeInstallDir" -y | Out-Null
# The extracted contents might live under a subfolder; flatten if needed
$extracted = Get-ChildItem $nodeInstallDir | Where-Object { $_.PSIsContainer } | Select-Object -First 1
if ($extracted) {
Get-ChildItem $extracted.FullName | Move-Item -Destination $nodeInstallDir -Force
Remove-Item $extracted.FullName -Recurse -Force
}
# Clean Up 7z File After Extraction
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $node7zPath
} }
# Extract using 7-Zip
if (-not (Test-Path $sevenZipExe)) {
throw "7-Zip CLI not found at: $sevenZipExe"
}
if (Test-Path $tessInstallDir) {
Remove-Item $tessInstallDir -Recurse -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Path $tessInstallDir | Out-Null
& $sevenZipExe x $tessExePath "-o$tessInstallDir" -y | Out-Null
# Optional cleanup
Remove-Item $tessExePath -Force -ErrorAction SilentlyContinue
} }
} }
# ---------------------- Download Tesseract English Language Trained Data ---------------------- function Install_Agent_Dependencies {
Run-Step "Dependency: Tesseract-OCR - Trained Model Data" { # Tesseract OCR Engine
$langDataDir = Join-Path $scriptDir "Data\Server\Python_API_Endpoints\Tesseract-OCR\tessdata" Run-Step "Dependency: Tesseract-OCR" {
$engPath = Join-Path $langDataDir "eng.traineddata" $tessExeUrl = "https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe"
$osdPath = Join-Path $langDataDir "osd.traineddata" $tessExePath = Join-Path $depsRoot "tesseract-installer.exe"
$tessInstallDir = Join-Path $scriptDir "Data\Server\Python_API_Endpoints\Tesseract-OCR"
if (-not (Test-Path $engPath)) { if (-not (Test-Path (Join-Path $tessInstallDir "tesseract.exe"))) {
Invoke-WebRequest -Uri "https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata" -OutFile $engPath # Download the installer if it doesn't exist
if (-not (Test-Path $tessExePath)) {
Invoke-WebRequest -Uri $tessExeUrl -OutFile $tessExePath
}
# Extract using 7-Zip
if (-not (Test-Path $sevenZipExe)) {
throw "7-Zip CLI not found at: $sevenZipExe"
}
if (Test-Path $tessInstallDir) {
Remove-Item $tessInstallDir -Recurse -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Path $tessInstallDir | Out-Null
& $sevenZipExe x $tessExePath "-o$tessInstallDir" -y | Out-Null
# Optional cleanup
Remove-Item $tessExePath -Force -ErrorAction SilentlyContinue
}
} }
if (-not (Test-Path $osdPath)) { # Tesseract language data
Invoke-WebRequest -Uri "https://github.com/tesseract-ocr/tessdata/raw/main/osd.traineddata" -OutFile $osdPath Run-Step "Dependency: Tesseract-OCR - Trained Model Data" {
$langDataDir = Join-Path $scriptDir "Data\Server\Python_API_Endpoints\Tesseract-OCR\tessdata"
$engPath = Join-Path $langDataDir "eng.traineddata"
$osdPath = Join-Path $langDataDir "osd.traineddata"
if (-not (Test-Path $engPath)) {
Invoke-WebRequest -Uri "https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata" -OutFile $engPath
}
if (-not (Test-Path $osdPath)) {
Invoke-WebRequest -Uri "https://github.com/tesseract-ocr/tessdata/raw/main/osd.traineddata" -OutFile $osdPath
}
} }
}
# ---------------------- Ensure AutoHotKey is Present (Bundled Portable ZIP) ---------------------- # AutoHotKey portable
Run-Step "Dependency: AutoHotKey" { Run-Step "Dependency: AutoHotKey" {
$ahkVersion = "2.0.19" # Update this field for new AHK releases (without the 'v' prefix) $ahkVersion = "2.0.19"
$ahkVersionTag = "v$ahkVersion" $ahkVersionTag = "v$ahkVersion"
$ahkZipName = "AutoHotkey_$ahkVersion.zip" $ahkZipName = "AutoHotkey_$ahkVersion.zip"
$ahkZipUrl = "https://github.com/AutoHotkey/AutoHotkey/releases/download/$ahkVersionTag/$ahkZipName" $ahkZipUrl = "https://github.com/AutoHotkey/AutoHotkey/releases/download/$ahkVersionTag/$ahkZipName"
$ahkZipPath = Join-Path $depsRoot $ahkZipName $ahkZipPath = Join-Path $depsRoot $ahkZipName
$ahkInstallDir = Join-Path $depsRoot "AutoHotKey" $ahkInstallDir = Join-Path $depsRoot "AutoHotKey"
$ahkExePath = Join-Path $ahkInstallDir "AutoHotkey64.exe" # Adjust if needed $ahkExePath = Join-Path $ahkInstallDir "AutoHotkey64.exe"
if (-not (Test-Path $ahkExePath)) {
# SECTION: Download Step
if (-not (Test-Path $ahkZipPath)) {
Invoke-WebRequest -Uri $ahkZipUrl -OutFile $ahkZipPath
}
# SECTION: Extraction Step
if (-not (Test-Path $sevenZipExe)) {
throw "7-Zip CLI not found at: $sevenZipExe"
}
if (Test-Path $ahkInstallDir) {
Remove-Item $ahkInstallDir -Recurse -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Path $ahkInstallDir | Out-Null
& $sevenZipExe x $ahkZipPath "-o$ahkInstallDir" -y | Out-Null
# SECTION: Post-Processing / Cleanup
Remove-Item $ahkZipPath -Force -ErrorAction SilentlyContinue
# SECTION: Validation
if (-not (Test-Path $ahkExePath)) { if (-not (Test-Path $ahkExePath)) {
throw "AutoHotKey executable not found after extraction." if (-not (Test-Path $ahkZipPath)) {
Invoke-WebRequest -Uri $ahkZipUrl -OutFile $ahkZipPath
}
if (-not (Test-Path $sevenZipExe)) {
throw "7-Zip CLI not found at: $sevenZipExe"
}
if (Test-Path $ahkInstallDir) {
Remove-Item $ahkInstallDir -Recurse -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Path $ahkInstallDir | Out-Null
& $sevenZipExe x $ahkZipPath "-o$ahkInstallDir" -y | Out-Null
Remove-Item $ahkZipPath -Force -ErrorAction SilentlyContinue
if (-not (Test-Path $ahkExePath)) {
throw "AutoHotKey executable not found after extraction."
}
} }
} }
} }
### Heavy dependency bootstrap moved into Server menu (choice 1)
# ---------------------- Common Initialization & Visuals ---------------------- # ---------------------- Common Initialization & Visuals ----------------------
Clear-Host Clear-Host
@@ -297,14 +300,7 @@ Clear-Host
'@ | Write-Host -ForegroundColor DarkCyan '@ | Write-Host -ForegroundColor DarkCyan
Write-Host "Automation Platform" -ForegroundColor DarkGray Write-Host "Automation Platform" -ForegroundColor DarkGray
foreach ($tool in @($pythonExe, $nodeExe, $npmCmd, $npxCmd)) { ## Defer PATH updates and tool presence checks until after a selection is made
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
# ---------------------- Menu Prompt & User Input ---------------------- # ---------------------- Menu Prompt & User Input ----------------------
if (-not $choice) { if (-not $choice) {
@@ -328,6 +324,19 @@ switch ($choice) {
"1" { "1" {
$host.UI.RawUI.WindowTitle = "Borealis Server" $host.UI.RawUI.WindowTitle = "Borealis Server"
Write-Host "Ensuring Server Dependencies Exist..." -ForegroundColor DarkCyan
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
}
}
$env:PATH = '{0};{1};{2}' -f (Split-Path $pythonExe), (Split-Path $nodeExe), $env:PATH
if (-not $modeChoice) { if (-not $modeChoice) {
Write-Host " " Write-Host " "
Write-Host "Configure Borealis Server Mode:" -ForegroundColor DarkYellow Write-Host "Configure Borealis Server Mode:" -ForegroundColor DarkYellow
@@ -439,6 +448,15 @@ switch ($choice) {
$host.UI.RawUI.WindowTitle = "Borealis Agent" $host.UI.RawUI.WindowTitle = "Borealis Agent"
# Agent Deployment (Client / Data Collector) # Agent Deployment (Client / Data Collector)
Write-Host " " Write-Host " "
Write-Host "Ensuring Agent Dependencies Exist..." -ForegroundColor DarkCyan
Install_Shared_Dependencies
Install_Agent_Dependencies
# Confirm Python presence and update PATH
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 Write-Host "Deploying Borealis Agent..." -ForegroundColor Blue
$venvFolder = "Agent" $venvFolder = "Agent"
@@ -450,7 +468,18 @@ switch ($choice) {
Run-Step "Create Virtual Python Environment" { Run-Step "Create Virtual Python Environment" {
if (-not (Test-Path "$venvFolder\Scripts\Activate")) { if (-not (Test-Path "$venvFolder\Scripts\Activate")) {
& $pythonExe -m venv $venvFolder $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) { if (Test-Path $agentSourcePath) {
# Remove Existing "Agent/Borealis" folder. # Remove Existing "Agent/Borealis" folder.
@@ -663,7 +692,18 @@ switch ($choice) {
Run-Step "Create Virtual Python Environment" { Run-Step "Create Virtual Python Environment" {
if (-not (Test-Path "$venvFolder\Scripts\Activate")) { if (-not (Test-Path "$venvFolder\Scripts\Activate")) {
& $pythonExe -m venv $venvFolder $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 $scriptSourcePath) { if (Test-Path $scriptSourcePath) {
Remove-Item $scriptDestinationFolder -Recurse -Force -ErrorAction SilentlyContinue Remove-Item $scriptDestinationFolder -Recurse -Force -ErrorAction SilentlyContinue