Files
zclaw_openfang/start-all.ps1
iven f79560a911 refactor(desktop): split kernel_commands/pipeline_commands into modules, add SaaS client libs and gateway modules
Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines)
into focused sub-modules under kernel_commands/ and pipeline_commands/ directories.
Add gateway module (commands, config, io, runtime), health_check, and 15 new
TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel
sub-systems (a2a, agent, chat, hands, skills, triggers).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 11:12:47 +08:00

374 lines
12 KiB
PowerShell

# ZCLAW Full Stack Start Script
# Starts: PostgreSQL (Docker) -> SaaS Backend -> Admin V2 (Vite) -> ChromeDriver (optional) -> Tauri Desktop
#
# NOTE: ZCLAW now uses internal Kernel (zclaw-kernel) for all operations.
# No external ZCLAW runtime is required.
param(
[switch]$NoBrowser,
[switch]$Dev,
[switch]$Help,
[switch]$Stop,
[switch]$DesktopOnly,
[switch]$NoSaas
)
$ErrorActionPreference = "Continue"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
# Colors
function info { param($msg) Write-Host "[INFO] $msg" -ForegroundColor Cyan }
function ok { param($msg) Write-Host "[OK] $msg" -ForegroundColor Green }
function warn { param($msg) Write-Host "[WARN] $msg" -ForegroundColor Yellow }
function err { param($msg) Write-Host "[ERROR] $msg" -ForegroundColor Red }
if ($Help) {
Write-Host @"
ZCLAW Full Stack Start Script
==============================
Usage: .\start-all.ps1 [options]
Options:
-DesktopOnly Start desktop only (skip ChromeDriver + SaaS + PostgreSQL)
-NoBrowser Skip ChromeDriver startup
-NoSaas Skip PostgreSQL + SaaS backend + Admin dashboard startup
-Dev Development mode (hot reload)
-Stop Stop all services
-Help Show this help
Note:
ZCLAW uses an internal Rust-based Kernel for all operations.
No external runtime is required.
Quick Commands:
pnpm start # Start all services
pnpm start:dev # Start in dev mode
pnpm start:desktop # Start desktop only (no browser, no SaaS)
"@
exit 0
}
# Stop all services
if ($Stop) {
info "Stopping all ZCLAW services..."
# Stop ChromeDriver
Get-Process -Name "chromedriver" -ErrorAction SilentlyContinue | Stop-Process -Force
ok "ChromeDriver stopped"
# Stop SaaS backend (kill process tree)
Get-Process -Name "zclaw-saas" -ErrorAction SilentlyContinue | ForEach-Object {
& taskkill /T /F /PID $_.Id 2>$null
ok "Stopped SaaS backend process tree (PID: $($_.Id))"
}
$port8080 = netstat -ano | Select-String ":8080.*LISTENING"
if ($port8080) {
$pid8080 = ($port8080 -split '\s+')[-1]
if ($pid8080 -match '^\d+$') {
& taskkill /T /F /PID $pid8080 2>$null
ok "Stopped SaaS backend on port 8080 (PID: $pid8080)"
}
}
# Stop Admin V2 dev server (Vite on port 5173)
$port5173 = netstat -ano | Select-String ":5173.*LISTENING"
if ($port5173) {
$pid5173 = ($port5173 -split '\s+')[-1]
if ($pid5173 -match '^\d+$') {
& taskkill /T /F /PID $pid5173 2>$null
ok "Stopped Admin V2 process on port 5173 (PID: $pid5173)"
}
}
# Stop any legacy Next.js admin on ports 3000-3002
foreach ($adminPort in @(3000, 3001, 3002)) {
$portMatch = netstat -ano | Select-String ":${adminPort}.*LISTENING"
if ($portMatch) {
$adminPid = ($portMatch -split '\s+')[-1]
if ($adminPid -match '^\d+$') {
& taskkill /T /F /PID $adminPid 2>$null
ok "Stopped legacy Admin process on port $adminPort (PID: $adminPid)"
}
}
}
# Stop any process on port 4200 (legacy, may still be in use)
$port4200 = netstat -ano | Select-String ":4200.*LISTENING"
if ($port4200) {
$pid4200 = ($port4200 -split '\s+')[-1]
if ($pid4200 -match '^\d+$') {
& taskkill /T /F /PID $pid4200 2>$null
ok "Stopped process on port 4200 (PID: $pid4200)"
}
}
# Stop Tauri/ZClaw
Get-Process -Name "ZClaw" -ErrorAction SilentlyContinue | Stop-Process -Force
Get-Process -Name "desktop" -ErrorAction SilentlyContinue | Stop-Process -Force
ok "ZCLAW Desktop stopped"
# Kill any process on port 1420 (Vite dev server)
$port1420 = netstat -ano | Select-String ":1420.*LISTENING"
if ($port1420) {
$pid1420 = ($port1420 -split '\s+')[-1]
if ($pid1420 -match '^\d+$') {
& taskkill /T /F /PID $pid1420 2>$null
ok "Killed process on port 1420 (PID: $pid1420)"
}
}
ok "All services stopped"
exit 0
}
Write-Host ""
Write-Host "===============================================" -ForegroundColor Magenta
Write-Host " ZCLAW - AI Agent Desktop Client" -ForegroundColor Magenta
Write-Host "===============================================" -ForegroundColor Magenta
Write-Host ""
# Track processes for cleanup
$Jobs = @()
$CleanupCalled = $false
function Cleanup {
if ($CleanupCalled) { return }
$CleanupCalled = $true
info "Cleaning up child services..."
# Kill tracked process trees (parent + all children)
foreach ($job in $Jobs) {
if ($job -and !$job.HasExited) {
info "Stopping $($job.ProcessName) (PID: $($job.Id)) and child processes"
try {
& taskkill /T /F /PID $job.Id 2>$null
if (!$job.HasExited) { $job.Kill() }
} catch {
try { $job.Kill() } catch {}
}
}
}
# Fallback: kill ALL processes on service ports (5173 = Admin V2 Vite)
foreach ($port in @(8080, 5173)) {
$listening = netstat -ano | Select-String ":${port}.*LISTENING"
if ($listening) {
$pid = ($listening -split '\s+')[-1]
if ($pid -match '^\d+$') {
info "Killing process on port $port (PID: $pid)"
& taskkill /T /F /PID $pid 2>$null
}
}
}
ok "Cleanup complete"
}
# Ctrl+C handler: ensures Cleanup runs even on interrupt
try {
$null = [Console]::CancelKeyPress.Add_Invocation({
param($sender, $e)
$e.Cancel = $true # Prevent immediate termination
Cleanup
})
} catch {
# Not running in an interactive console (e.g. launched via pnpm) - rely on try/finally instead
}
trap { Cleanup; break }
# Skip SaaS and ChromeDriver if DesktopOnly
if ($DesktopOnly) {
$NoBrowser = $true
$NoSaas = $true
}
# 1. PostgreSQL (Windows native) - required for SaaS backend
if (-not $NoSaas) {
info "Checking PostgreSQL..."
$port5432 = netstat -ano | Select-String ":5432.*LISTENING"
if ($port5432) {
ok "PostgreSQL is running on port 5432"
} else {
# Try to start the Windows PostgreSQL service
$pgService = Get-Service -Name "postgresql*" -ErrorAction SilentlyContinue | Select-Object -First 1
if ($pgService) {
if ($pgService.Status -ne "Running") {
info "Starting PostgreSQL service: $($pgService.Name)..."
Start-Service -Name $pgService.Name -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
ok "PostgreSQL service started"
} else {
ok "PostgreSQL service is running"
}
} else {
warn "PostgreSQL not found on port 5432 and no Windows service detected."
warn "SaaS backend requires PostgreSQL. Please start it manually."
$NoSaas = $true
}
}
} else {
info "Skipping PostgreSQL"
}
Write-Host ""
# 2. SaaS Backend (for cloud features: account, relay, config sync)
if (-not $NoSaas) {
info "Checking SaaS backend..."
# Check if port 8080 is already in use
$port8080 = netstat -ano | Select-String ":8080.*LISTENING"
if ($port8080) {
$pid8080 = ($port8080 -split '\s+')[-1]
if ($pid8080 -match '^\d+$') {
ok "SaaS backend already running on port 8080 (PID: $pid8080)"
}
} else {
# Check if zclaw-saas binary exists
$saasBin = "$ScriptDir\target\debug\zclaw-saas.exe"
$saasBinRelease = "$ScriptDir\target\release\zclaw-saas.exe"
# Dev mode: prefer debug binary (allows JWT fallback); Release mode: prefer release binary
$saasExe = if ($Dev -and (Test-Path $saasBin)) { $saasBin } elseif (Test-Path $saasBinRelease) { $saasBinRelease } elseif (Test-Path $saasBin) { $saasBin } else { $null }
if ($saasExe) {
ok "SaaS backend binary found: $saasExe"
info "Starting SaaS backend on port 8080..."
if ($Dev) {
$env:ZCLAW_SAAS_DEV = "true"
if (-not $env:DB_PASSWORD) {
$env:DB_PASSWORD = "123123"
}
if (-not $env:ZCLAW_SAAS_JWT_SECRET) {
$env:ZCLAW_SAAS_JWT_SECRET = "dev-only-insecure-jwt-secret-32ch"
}
}
$proc = Start-Process -FilePath $saasExe -PassThru -WindowStyle Minimized
$Jobs += $proc
Start-Sleep -Seconds 3
if ($proc.HasExited) {
err "SaaS backend exited unexpectedly. Run manually: cd $ScriptDir && ZCLAW_SAAS_DEV=true cargo run -p zclaw-saas"
} else {
ok "SaaS backend started (PID: $($proc.Id))"
}
} else {
warn "SaaS backend binary not found. Building..."
info "Run: cargo build -p zclaw-saas"
warn "SaaS cloud features will be unavailable until built."
}
}
} else {
info "Skipping SaaS backend"
}
Write-Host ""
# 3. Admin V2 (Vite + Ant Design Pro on port 5173)
if (-not $NoSaas) {
info "Checking Admin V2 dashboard..."
$port5173 = netstat -ano | Select-String ":5173.*LISTENING"
if ($port5173) {
$pid5173 = ($port5173 -split '\s+')[-1]
if ($pid5173 -match '^\d+$') {
ok "Admin V2 already running on port 5173 (PID: $pid5173)"
}
} else {
if (Test-Path "$ScriptDir\admin-v2\package.json") {
info "Starting Admin V2 on port 5173..."
$proc = Start-Process -FilePath "cmd.exe" -ArgumentList "/c cd /d `"$ScriptDir\admin-v2`" && pnpm dev" -PassThru -WindowStyle Minimized
$Jobs += $proc
Start-Sleep -Seconds 5
$port5173Check = netstat -ano | Select-String ":5173.*LISTENING"
if ($port5173Check) {
ok "Admin V2 started on port 5173 (PID: $($proc.Id))"
} else {
warn "Admin V2 may still be starting. Check http://localhost:5173"
}
} else {
warn "admin-v2 directory not found. Skipping."
}
}
} else {
info "Skipping Admin V2 dashboard"
}
Write-Host ""
# 4. ChromeDriver (optional - for Browser Hand automation)
if (-not $NoBrowser) {
info "Checking ChromeDriver..."
$existing = Get-Process -Name "chromedriver" -ErrorAction SilentlyContinue
if ($existing) {
ok "ChromeDriver already running (PID: $($existing.Id))"
} else {
$chromedriver = Get-Command chromedriver -ErrorAction SilentlyContinue
if ($chromedriver) {
ok "ChromeDriver found: $($chromedriver.Source)"
info "Starting ChromeDriver on port 4444..."
$proc = Start-Process -FilePath "chromedriver" -ArgumentList "--port=4444" -PassThru -WindowStyle Hidden
$Jobs += $proc
Start-Sleep -Milliseconds 500
if ($proc.HasExited) {
warn "ChromeDriver exited. Check if port 4444 is in use."
} else {
ok "ChromeDriver started (PID: $($proc.Id))"
}
} else {
warn "ChromeDriver not found. Browser automation disabled."
info "Download: https://chromedriver.chromium.org/downloads"
}
}
} else {
info "Skipping ChromeDriver"
}
Write-Host ""
# 5. Start Tauri Desktop
info "Starting ZCLAW Desktop..."
Set-Location "$ScriptDir/desktop"
# Check if port 1420 is in use
$port1420 = netstat -ano | Select-String ":1420.*LISTENING"
if ($port1420) {
$pid1420 = ($port1420 -split '\s+')[-1]
if ($pid1420 -match '^\d+$') {
warn "Port 1420 is in use by PID $pid1420. Killing..."
& taskkill /T /F /PID $pid1420 2>$null
Start-Sleep -Seconds 1
}
}
if ($Dev) {
info "Development mode enabled"
info "Press Ctrl+C to stop all services..."
try {
pnpm tauri dev
} finally {
Cleanup
}
} else {
$exe = "src-tauri\target\release\ZClaw.exe"
if (Test-Path $exe) {
info "Starting built application..."
Start-Process $exe
ok "ZCLAW Desktop started"
} else {
info "Built app not found, using dev mode..."
pnpm tauri dev
}
}