Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| <# | |
| .SYNOPSIS | |
| CommunityOne Open Navigator - Windows installation script (PowerShell). | |
| .DESCRIPTION | |
| Windows-native equivalent of scripts/deployment/install.sh. Creates the | |
| Python virtual environment, installs the backend dependencies from | |
| requirements.txt (NOT `uv sync` — see the note below), seeds .env, and | |
| creates the logs directory. | |
| Why pip + requirements.txt and not `uv sync`: | |
| The root pyproject.toml is a *uv workspace* whose members are only | |
| packages/*. `uv sync` installs those workspace libraries but does NOT | |
| install the top-level requirements.txt — so the dev tooling | |
| (pytest/black/ruff) and runtime deps like yt-dlp are left out. The | |
| backend is installed from requirements.txt, which is the complete set. | |
| Run from the repository root (paths are relative to the CWD): | |
| powershell -ExecutionPolicy Bypass -File scripts\deployment\install.ps1 | |
| or via the thin root wrapper: | |
| .\install.ps1 | |
| #> | |
| $ErrorActionPreference = 'Stop' | |
| Write-Host "CommunityOne Open Navigator - Installation Script (Windows)" | |
| Write-Host "==================================================" | |
| Write-Host "" | |
| # --- Resolve a Python launcher ------------------------------------------------ | |
| # Prefer the `py` launcher (ships with python.org installers), fall back to | |
| # `python` on PATH. We need a real CPython, not the Windows Store stub. | |
| function Resolve-Python { | |
| foreach ($candidate in @( | |
| @{ Exe = 'py'; Args = @('-3') }, | |
| @{ Exe = 'python'; Args = @() } | |
| )) { | |
| $cmd = Get-Command $candidate.Exe -ErrorAction SilentlyContinue | |
| if ($null -eq $cmd) { continue } | |
| try { | |
| $ver = & $candidate.Exe @($candidate.Args + '--version') 2>&1 | |
| if ($ver -match 'Python\s+3\.\d+') { | |
| return [pscustomobject]@{ Exe = $candidate.Exe; Args = $candidate.Args; Version = "$ver".Trim() } | |
| } | |
| } catch { } | |
| } | |
| return $null | |
| } | |
| Write-Host "Checking Python version..." | |
| $py = Resolve-Python | |
| if ($null -eq $py) { | |
| Write-Host "[X] Error: Python 3 is not installed (or only the Windows Store stub is present)." -ForegroundColor Red | |
| Write-Host " Install Python 3.11-3.13 from https://www.python.org/downloads/windows/" | |
| Write-Host " (tick 'Add python.exe to PATH' in the installer), then re-run this script." | |
| exit 1 | |
| } | |
| # Parse MAJOR.MINOR from e.g. "Python 3.12.3" | |
| $pyVersion = ($py.Version -replace '^Python\s+', '') | |
| $verParts = $pyVersion.Split('.') | |
| $pyMajor = [int]$verParts[0] | |
| $pyMinor = [int]$verParts[1] | |
| Write-Host "[OK] Found Python $pyMajor.$pyMinor (via '$($py.Exe)')" | |
| # Python 3.14+ compatibility: some transitive deps (e.g. `whenever`) build a | |
| # Rust extension via PyO3, which currently supports up to Python 3.13. On 3.14+ | |
| # that build hard-fails. Tell those packages to skip the Rust extension and use | |
| # their (slower) pure-Python implementation so the install still succeeds. | |
| if ($pyMinor -ge 14) { | |
| Write-Host "[!] Python $pyMajor.$pyMinor detected - newer than PyO3's max supported (3.13)." -ForegroundColor Yellow | |
| Write-Host " Forcing pure-Python builds for Rust-backed deps (whenever) to avoid build failures." | |
| $env:WHENEVER_NO_BUILD_RUST_EXT = "1" | |
| $env:PYO3_USE_ABI3_FORWARD_COMPATIBILITY = "1" | |
| } | |
| # --- Optional system dependency: Tesseract OCR -------------------------------- | |
| # Unlike Linux, lxml ships Windows wheels, so no libxml2/libxslt headers are | |
| # needed. The only optional native tool is Tesseract (OCR fallback). Try winget, | |
| # then Chocolatey; otherwise tell the user how to get it. Never fatal. | |
| Write-Host "" | |
| Write-Host "Checking optional system dependency (Tesseract OCR)..." | |
| if (Get-Command tesseract -ErrorAction SilentlyContinue) { | |
| Write-Host "[OK] Tesseract available: $((tesseract --version 2>&1 | Select-Object -First 1))" | |
| } elseif (Get-Command winget -ErrorAction SilentlyContinue) { | |
| Write-Host "Installing Tesseract via winget..." | |
| try { | |
| winget install --id UB-Mannheim.TesseractOCR --accept-source-agreements --accept-package-agreements -e | |
| } catch { | |
| Write-Host "[!] winget could not install Tesseract; OCR fallback will stay disabled." -ForegroundColor Yellow | |
| } | |
| } elseif (Get-Command choco -ErrorAction SilentlyContinue) { | |
| Write-Host "Installing Tesseract via Chocolatey..." | |
| try { choco install -y tesseract } catch { | |
| Write-Host "[!] choco could not install Tesseract; OCR fallback will stay disabled." -ForegroundColor Yellow | |
| } | |
| } else { | |
| Write-Host "[!] Tesseract not found and no winget/choco available." -ForegroundColor Yellow | |
| Write-Host " OCR is optional. To enable it, install the UB-Mannheim Tesseract build:" | |
| Write-Host " https://github.com/UB-Mannheim/tesseract/wiki" | |
| } | |
| # --- Virtual environment ------------------------------------------------------ | |
| Write-Host "" | |
| Write-Host "Creating virtual environment..." | |
| if (Test-Path ".venv") { | |
| Write-Host "[!] Virtual environment already exists. Removing old one..." -ForegroundColor Yellow | |
| Remove-Item -Recurse -Force ".venv" | |
| } | |
| & $py.Exe @($py.Args + @('-m', 'venv', '.venv')) | |
| Write-Host "[OK] Virtual environment created" | |
| # Use the venv's interpreter directly (robust regardless of activation state / | |
| # ExecutionPolicy). All subsequent pip calls go through this python.exe. | |
| $venvPython = Join-Path (Get-Location) ".venv\Scripts\python.exe" | |
| if (-not (Test-Path $venvPython)) { | |
| Write-Host "[X] Expected venv interpreter not found at $venvPython" -ForegroundColor Red | |
| exit 1 | |
| } | |
| # --- pip + dependencies ------------------------------------------------------- | |
| Write-Host "" | |
| Write-Host "Upgrading pip..." | |
| & $venvPython -m pip install --upgrade pip | |
| Write-Host "[OK] pip upgraded" | |
| Write-Host "" | |
| Write-Host "Installing dependencies (this may take a few minutes)..." | |
| # Prefer CPU-only requirements (no GPU needed) when present, matching install.sh. | |
| if (Test-Path "requirements-cpu.txt") { | |
| Write-Host "Using CPU-only requirements (no GPU needed)..." | |
| & $venvPython -m pip install -r requirements-cpu.txt | |
| } else { | |
| & $venvPython -m pip install -r requirements.txt | |
| } | |
| Write-Host "[OK] Dependencies installed" | |
| # Install the local workspace libraries (packages/*) as editable, top-level | |
| # importable modules. requirements.txt only pins third-party deps; the API | |
| # entrypoint imports agents/ingestion/config/llm/etc. which now live under | |
| # packages/* (there is no top-level agents/ tree anymore), so without this step | |
| # `python main.py serve` fails with "ModuleNotFoundError: No module named | |
| # 'agents'". --no-deps keeps the dependency closure exactly as requirements.txt | |
| # pins it (these packages' own third-party deps are already installed above). | |
| # This is the full runtime set the Dockerfile installs (eager + lazy imports). | |
| Write-Host "" | |
| Write-Host "Installing local workspace packages (editable)..." | |
| & $venvPython -m pip install --no-deps ` | |
| -e packages/core -e packages/core-lib -e packages/datamodels ` | |
| -e packages/agents -e packages/scrapers -e packages/ingestion ` | |
| -e packages/llm -e packages/accessibility -e packages/hosting | |
| Write-Host "[OK] Workspace packages installed" | |
| # --- Optional: infrastructure CLIs (Azure CLI + Terraform) -------------------- | |
| # For the infra/azure subscriptions Terraform. Opt-in (most contributors don't | |
| # need it) — enable with: $env:INSTALL_INFRA_TOOLS = "1"; .\install.ps1 | |
| # Prefers winget/choco; falls back to a rootless install (azure-cli via pip, | |
| # terraform binary into .venv\Scripts) when neither is available. | |
| $TerraformVersion = if ($env:TERRAFORM_VERSION) { $env:TERRAFORM_VERSION } else { "1.9.8" } | |
| function Install-AzureCli { | |
| if (Get-Command az -ErrorAction SilentlyContinue) { Write-Host "[OK] Azure CLI already installed"; return } | |
| Write-Host "Installing Azure CLI..." | |
| if (Get-Command winget -ErrorAction SilentlyContinue) { | |
| try { winget install --id Microsoft.AzureCLI --accept-source-agreements --accept-package-agreements -e } catch {} | |
| } elseif (Get-Command choco -ErrorAction SilentlyContinue) { | |
| try { choco install -y azure-cli } catch {} | |
| } | |
| if (-not (Get-Command az -ErrorAction SilentlyContinue)) { | |
| Write-Host "[!] No system install path; installing azure-cli into .venv via pip (rootless)..." -ForegroundColor Yellow | |
| try { & $venvPython -m pip install --upgrade azure-cli } catch { | |
| Write-Host "[!] Could not install Azure CLI. Manual: https://learn.microsoft.com/cli/azure/install-azure-cli" -ForegroundColor Yellow | |
| } | |
| } | |
| } | |
| function Install-Terraform { | |
| if (Get-Command terraform -ErrorAction SilentlyContinue) { Write-Host "[OK] Terraform already installed"; return } | |
| Write-Host "Installing Terraform $TerraformVersion..." | |
| if (Get-Command winget -ErrorAction SilentlyContinue) { | |
| try { winget install --id Hashicorp.Terraform --accept-source-agreements --accept-package-agreements -e } catch {} | |
| } elseif (Get-Command choco -ErrorAction SilentlyContinue) { | |
| try { choco install -y terraform } catch {} | |
| } | |
| if (-not (Get-Command terraform -ErrorAction SilentlyContinue)) { | |
| # Rootless: drop the official binary into .venv\Scripts (on PATH once activated). | |
| $arch = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" } | |
| $url = "https://releases.hashicorp.com/terraform/$TerraformVersion/terraform_${TerraformVersion}_windows_$arch.zip" | |
| $zip = Join-Path $env:TEMP "terraform.zip" | |
| try { | |
| Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing | |
| Expand-Archive -Path $zip -DestinationPath ".venv\Scripts" -Force | |
| Remove-Item $zip -Force | |
| Write-Host "[OK] Terraform installed to .venv\Scripts" | |
| } catch { | |
| Write-Host "[!] Could not download Terraform. Manual: https://developer.hashicorp.com/terraform/install" -ForegroundColor Yellow | |
| } | |
| } | |
| } | |
| if ($env:INSTALL_INFRA_TOOLS -eq "1") { | |
| Write-Host "" | |
| Write-Host "Installing infrastructure CLIs (Azure CLI + Terraform) [INSTALL_INFRA_TOOLS=1]..." | |
| Install-AzureCli | |
| Install-Terraform | |
| # If a tool fell back to the rootless install it lives in .venv\Scripts, which is | |
| # only on PATH once the venv is activated. | |
| if (Test-Path ".venv\Scripts\terraform.exe") { | |
| Write-Host "[!] Rootless tools are in .venv\Scripts — activate the venv (.\.venv\Scripts\Activate.ps1) to use az/terraform." -ForegroundColor Yellow | |
| } | |
| } | |
| # --- .env --------------------------------------------------------------------- | |
| Write-Host "" | |
| if (-not (Test-Path ".env")) { | |
| Write-Host "Creating .env file from template..." | |
| Copy-Item ".env.example" ".env" | |
| Write-Host "[OK] .env file created" | |
| Write-Host "" | |
| Write-Host "[!] IMPORTANT: edit .env and set at least NEON_DATABASE_URL_DEV" -ForegroundColor Yellow | |
| Write-Host " (points the API at the local Postgres warehouse on localhost:5433)." | |
| } else { | |
| Write-Host "[OK] .env file already exists" | |
| } | |
| # --- logs --------------------------------------------------------------------- | |
| Write-Host "" | |
| Write-Host "Creating logs directory..." | |
| New-Item -ItemType Directory -Force -Path "logs" | Out-Null | |
| Write-Host "[OK] logs directory created" | |
| # --- Done --------------------------------------------------------------------- | |
| Write-Host "" | |
| Write-Host "==================================================" | |
| Write-Host "Installation Complete!" | |
| Write-Host "==================================================" | |
| Write-Host "" | |
| Write-Host "To activate the virtual environment, run:" | |
| Write-Host " .\.venv\Scripts\Activate.ps1" | |
| Write-Host "" | |
| Write-Host "Then you can use the CLI:" | |
| Write-Host " python main.py --help" | |
| Write-Host " python main.py serve" | |
| Write-Host "" | |
| Write-Host "Install the frontend, then launch all three services:" | |
| Write-Host " cd web_app; npm install; cd .." | |
| Write-Host " cd web_docs; npm install; cd .." | |
| Write-Host " .\start-all.ps1" | |
| Write-Host "" | |
| Write-Host "Don't forget to configure your .env file with API keys!" | |
| Write-Host "" | |
| if ($env:INSTALL_INFRA_TOOLS -ne "1") { | |
| Write-Host "Working on infra\azure (Azure subscriptions)? Re-run with the infra CLIs:" | |
| Write-Host ' $env:INSTALL_INFRA_TOOLS = "1"; .\install.ps1 # installs Azure CLI + Terraform' | |
| Write-Host "" | |
| } | |