$ErrorActionPreference = "Stop" function Test-PortFree { param([int]$Port) # Use netstat because it reliably shows listeners from Session 0 services too. $pattern = ":$Port\\s" $hit = netstat -ano -p tcp | Select-String -Pattern "LISTENING" | Select-String -Pattern $pattern return (-not $hit) } function Test-ApApi { param([int]$Port) try { $res = Invoke-WebRequest -UseBasicParsing -TimeoutSec 1 -Uri "http://127.0.0.1:$Port/api/health" if ($res.StatusCode -ne 200) { return $false } # Only reuse the correct backend. Old/other uvicorn apps may also return {"ok":true}. # Our backend1 includes service/build fields. return (($res.Content -match '"service"\s*:\s*"backend1"') -and ($res.Content -match '"build"\s*:\s*"backend1-')) } catch { return $false } } function Ensure-Venv { if (-not (Test-Path ".venv\\Scripts\\python.exe")) { Write-Host "Creating venv at .venv ..." python -m venv .venv } } $projectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path Set-Location $projectRoot Ensure-Venv Write-Host "Installing Python deps..." & ".\\.venv\\Scripts\\python.exe" -m pip install -r requirements.txt | Out-Host $candidatePorts = @(8000, 8010, 8020, 8030, 8040) $port = $null $startBackend = $true # Prefer reusing an already-running AP backend if found. foreach ($p in $candidatePorts) { if (Test-ApApi -Port $p) { $port = $p; $startBackend = $false; break } } foreach ($p in $candidatePorts) { if ($port) { break } if (Test-PortFree -Port $p) { $port = $p; break } } if (-not $port) { throw "No free port found. Tried: $($candidatePorts -join ', ')" } $apiBase = "http://127.0.0.1:$port" Write-Host "" if ($startBackend) { Write-Host "Starting backend on $apiBase ..." Start-Process powershell -WorkingDirectory $projectRoot -ArgumentList @( "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "& '.\\.venv\\Scripts\\python.exe' -m uvicorn backend1.main:app --reload --host 127.0.0.1 --port $port" ) | Out-Null } else { Write-Host "Backend already running on $apiBase (reusing it)" } if (Test-PortFree -Port 5173) { Write-Host "Starting frontend dev server (Vite) on http://localhost:5173 ..." Start-Process powershell -WorkingDirectory (Join-Path $projectRoot "frontend") -ArgumentList @( "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "`$env:VITE_API_PROXY_TARGET='$apiBase'; npm run dev" ) | Out-Null } else { Write-Host "Frontend dev server already running on http://localhost:5173 (not starting another)" } Write-Host "" Write-Host "Open:" Write-Host " Frontend UI: http://localhost:5173" Write-Host " Backend UI: $apiBase" Write-Host " API health: $apiBase/api/health" Write-Host "" Write-Host "If port 8000 is in use, this script automatically uses 8010/8020/etc."