Files
ai_site/start-host.ps1
2026-07-31 10:19:22 +08:00

199 lines
8.1 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# native process mode (called by start.ps1 when Docker is unavailable)
param(
[switch]$Rebuild,
[switch]$NoBrowser,
[switch]$ShowConsole # show service windows (debug); default: hidden
)
$ErrorActionPreference = "Stop"
$Root = $PSScriptRoot
Set-Location -LiteralPath $Root
$LogDir = Join-Path $Root ".runtime\logs"
New-Item -ItemType Directory -Force -Path $LogDir | Out-Null
# Always wipe previous native/docker leftovers before binding ports
Write-Host "==> Pre-clean before native start" -ForegroundColor DarkGray
& (Join-Path $Root "scripts\Stop-Stack.ps1") -Quiet
Start-Sleep -Seconds 1
Write-Host "==> Native mode: need Go / Python / Node / PostgreSQL" -ForegroundColor Yellow
if (-not $ShowConsole) {
Write-Host " services run hidden; logs -> .runtime\logs\" -ForegroundColor DarkGray
}
function Clear-Port([int]$port) {
$conns = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
foreach ($c in $conns) {
$procId = $c.OwningProcess
if ($procId -gt 0) {
Write-Host " free port $port (pid=$procId)"
& taskkill.exe /F /T /PID $procId 2>$null | Out-Null
Stop-Process -Id $procId -Force -ErrorAction SilentlyContinue
}
}
}
Write-Host "==> Clearing ports 8888/8001/8180/5173"
foreach ($p in 8888, 8001, 8180, 5173) { Clear-Port $p }
Start-Sleep -Seconds 1
function Reset-LogFile([string]$path) {
try {
if (Test-Path -LiteralPath $path) {
# 句柄未释放时 Set-Content 会失败:先挪走旧文件
$prev = "$path.prev"
Remove-Item -LiteralPath $prev -Force -ErrorAction SilentlyContinue
Move-Item -LiteralPath $path -Destination $prev -Force -ErrorAction Stop
}
Set-Content -LiteralPath $path -Value "" -Encoding UTF8
return $path
} catch {
$alt = ($path -replace '\.log$', ".$(Get-Date -Format 'HHmmss').log")
Set-Content -LiteralPath $alt -Value "" -Encoding UTF8
return $alt
}
}
function Start-Svc($name, $workDir, $filePath, $argumentList) {
$outLog = Reset-LogFile (Join-Path $LogDir "$name.out.log")
$errLog = Reset-LogFile (Join-Path $LogDir "$name.err.log")
$pidFile = Join-Path $LogDir "$name.pid"
if ($ShowConsole) {
$argStr = ""
if ($argumentList) {
$parts = @()
foreach ($a in $argumentList) {
if ($a -match '\s') { $parts += ('"' + $a + '"') } else { $parts += $a }
}
$argStr = $parts -join ' '
}
$cmd = "Set-Location -LiteralPath '$workDir'; Write-Host '[$name]' -ForegroundColor Cyan; & '$filePath' $argStr"
$p = Start-Process -FilePath "powershell.exe" -ArgumentList @(
"-NoExit", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", $cmd
) -WorkingDirectory $workDir -PassThru
} else {
$p = Start-Process -FilePath $filePath `
-ArgumentList $argumentList `
-WorkingDirectory $workDir `
-WindowStyle Hidden `
-RedirectStandardOutput $outLog `
-RedirectStandardError $errLog `
-PassThru
}
if ($p) { Set-Content -LiteralPath $pidFile -Value $p.Id -Encoding ASCII }
Write-Host " started $name (pid=$($p.Id))" -ForegroundColor DarkGray
}
$plat = Join-Path $Root "platform\platform.exe"
$gw = Join-Path $Root "gateway\gateway.exe"
# 默认重编译,避免改 Go 源码后 restart 仍跑旧 exe
$needPlat = $Rebuild -or -not (Test-Path $plat)
$needGw = $Rebuild -or -not (Test-Path $gw)
if (-not $needPlat -and (Test-Path $plat)) {
$exeTime = (Get-Item $plat).LastWriteTime
$newer = Get-ChildItem -Path (Join-Path $Root "platform") -Recurse -Include *.go -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -gt $exeTime } |
Select-Object -First 1
if ($newer) { $needPlat = $true }
}
if (-not $needGw -and (Test-Path $gw)) {
$exeTime = (Get-Item $gw).LastWriteTime
$newer = Get-ChildItem -Path (Join-Path $Root "gateway") -Recurse -Include *.go -ErrorAction SilentlyContinue |
Where-Object { $_.LastWriteTime -gt $exeTime } |
Select-Object -First 1
if ($newer) { $needGw = $true }
}
if ($needPlat) {
Write-Host " building platform.exe ..." -ForegroundColor DarkGray
Push-Location (Join-Path $Root "platform")
go build -o platform.exe .
Pop-Location
}
if ($needGw) {
Write-Host " building gateway.exe ..." -ForegroundColor DarkGray
Push-Location (Join-Path $Root "gateway")
go build -o gateway.exe .
Pop-Location
}
Write-Host "==> Ensure web frontend (vite /#/preview)" -ForegroundColor DarkGray
& (Join-Path $Root "scripts\Ensure-Web.ps1")
# $? 判断 PS 脚本成败;勿单靠 $LASTEXITCODE会残留 docker/compose 等 native 失败码)
if (-not $?) { throw "Ensure-Web failed" }
$pyCmd = Get-Command python -ErrorAction SilentlyContinue
if (-not $pyCmd) { $pyCmd = Get-Command py -ErrorAction SilentlyContinue }
if (-not $pyCmd) { throw "python not found" }
$py = $pyCmd.Source
$npmCmd = Get-Command npm.cmd -ErrorAction SilentlyContinue
if (-not $npmCmd) { $npmCmd = Get-Command npm -ErrorAction SilentlyContinue }
if (-not $npmCmd) { throw "npm not found" }
# AI 截图直达本机 Vite
$env:WEB_BASE = "http://127.0.0.1:5173"
$env:PLATFORM_BASE = "http://127.0.0.1:8888"
$env:GATEWAY_BASE = "http://127.0.0.1:8180"
$env:GENERATE_LOG_DIR = Join-Path $Root ".runtime\logs\generate"
$env:FIDELITY_SHOT_DIR = Join-Path $Root ".runtime\fidelity_shots"
Start-Svc "platform" (Join-Path $Root "platform") $plat @("-f", "etc/platform.yaml")
Start-Sleep -Seconds 2
Start-Svc "ai-service" (Join-Path $Root "ai-service") $py @("-m", "uvicorn", "app:app", "--host", "127.0.0.1", "--port", "8001", "--reload")
Start-Sleep -Seconds 1
Start-Svc "gateway" (Join-Path $Root "gateway") $gw @("-f", "etc/gateway.yaml")
Start-Sleep -Seconds 1
Start-Svc "web" (Join-Path $Root "web") $npmCmd.Source @("run", "dev", "--", "--host", "127.0.0.1", "--port", "5173", "--strictPort")
Write-Host "==> Waiting for services..."
$deadline = (Get-Date).AddSeconds(45)
do {
$webOk = $false
$gwOk = $false
try {
$r = Invoke-WebRequest -Uri "http://127.0.0.1:5173/" -UseBasicParsing -TimeoutSec 2
if ($r.StatusCode -lt 500) { $webOk = $true }
} catch {}
try {
$r = Invoke-WebRequest -Uri "http://127.0.0.1:8180/gateway/health" -UseBasicParsing -TimeoutSec 2
if ($r.StatusCode -lt 500) { $gwOk = $true }
} catch {}
if ($webOk -and $gwOk) { break }
Start-Sleep -Seconds 1
} while ((Get-Date) -lt $deadline)
if ($webOk -and $gwOk) {
Write-Host "OK Web http://127.0.0.1:5173 Gateway http://127.0.0.1:8180 account demo/demo123" -ForegroundColor Green
Write-Host " logs $LogDir" -ForegroundColor DarkGray
} else {
Write-Host "WARN some services not ready yet. Check logs:" -ForegroundColor Yellow
Write-Host " $LogDir"
Write-Host " web=$webOk gateway=$gwOk"
Write-Host " (debug with visible windows: .\start-host.ps1 -ShowConsole)"
}
# 后台看门狗ai-service / gateway 挂掉自动拉起
$watchPidFile = Join-Path $LogDir "watchdog.pid"
if (Test-Path $watchPidFile) {
$oldWatch = Get-Content $watchPidFile -ErrorAction SilentlyContinue
if ($oldWatch) { Stop-Process -Id ([int]$oldWatch) -Force -ErrorAction SilentlyContinue }
}
$watchScript = Join-Path $Root "watch-services.ps1"
$watchOut = Join-Path $LogDir "watchdog.out.log"
$watchErr = Join-Path $LogDir "watchdog.err.log"
Set-Content -LiteralPath $watchOut -Value "" -Encoding UTF8
Set-Content -LiteralPath $watchErr -Value "" -Encoding UTF8
$wp = Start-Process -FilePath "powershell.exe" `
-ArgumentList @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $watchScript) `
-WorkingDirectory $Root `
-WindowStyle Hidden `
-RedirectStandardOutput $watchOut `
-RedirectStandardError $watchErr `
-PassThru
if ($wp) {
Set-Content -LiteralPath $watchPidFile -Value $wp.Id -Encoding ASCII
Write-Host " started watchdog (pid=$($wp.Id)) - auto-restarts ai-service if down" -ForegroundColor DarkGray
}
if (-not $NoBrowser) { Start-Process "http://127.0.0.1:5173" }