Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Batch 5 (P0): GrowthIntegration 接入 Tauri - Kernel 新增 set_viking()/set_extraction_driver() 桥接 SqliteStorage - 中间件链共享存储,MemoryExtractor 接入 LLM 驱动 Batch 6 (P1): 输入验证 + Heartbeat - Relay 验证补全(stream 兼容检查、API key 格式校验) - UUID 类型校验、SessionId 错误返回 - Heartbeat 默认开启 + 首次聊天自动初始化 Batch 7 (P2): 死代码清理 - zclaw-channels 整体移除(317 行) - multi-agent 特性门控、admin 方法标注 Batch 8 (P2): Pipeline 模板 - PipelineMetadata 新增 annotations 字段 - pipeline_templates 命令 + 2 个示例模板 - fallback driver base_url 修复(doubao/qwen/deepseek 端点) Batch 9 (P1): SpeechHand/TwitterHand 真实实现 - SpeechHand: tts_method 字段 + Browser TTS 前端集成 (Web Speech API) - TwitterHand: 12 个 action 全部替换为 Twitter API v2 真实 HTTP 调用 - chatStore/useAutomationEvents 双路径 TTS 触发
358 lines
11 KiB
PowerShell
358 lines
11 KiB
PowerShell
# ZCLAW Full Stack Start Script
|
|
# Starts: PostgreSQL (Docker) -> SaaS Backend -> Admin Web -> 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 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 Admin dev server (kill process tree to ensure node.exe children die)
|
|
# Next.js turbopack may use 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 Admin process on port $adminPort (PID: $adminPid)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# 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 (3000-3002 = Next.js + turbopack)
|
|
foreach ($port in @(8080, 3000, 3001, 3002)) {
|
|
$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"
|
|
$saasExe = if (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"
|
|
}
|
|
$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 Web (Next.js management dashboard on port 3000)
|
|
if (-not $NoSaas) {
|
|
info "Checking Admin dashboard..."
|
|
|
|
$port3000 = netstat -ano | Select-String ":3000.*LISTENING"
|
|
if ($port3000) {
|
|
$pid3000 = ($port3000 -split '\s+')[-1]
|
|
if ($pid3000 -match '^\d+$') {
|
|
ok "Admin dashboard already running on port 3000 (PID: $pid3000)"
|
|
}
|
|
} else {
|
|
if (Test-Path "$ScriptDir\admin\package.json") {
|
|
info "Starting Admin dashboard on port 3000..."
|
|
|
|
$proc = Start-Process -FilePath "cmd.exe" -ArgumentList "/c cd /d `"$ScriptDir\admin`" && pnpm dev" -PassThru -WindowStyle Minimized
|
|
$Jobs += $proc
|
|
Start-Sleep -Seconds 5
|
|
|
|
$port3000Check = netstat -ano | Select-String ":3000.*LISTENING"
|
|
if ($port3000Check) {
|
|
ok "Admin dashboard started on port 3000 (PID: $($proc.Id))"
|
|
} else {
|
|
warn "Admin dashboard may still be starting. Check http://localhost:3000"
|
|
}
|
|
} else {
|
|
warn "Admin directory not found. Skipping."
|
|
}
|
|
}
|
|
} else {
|
|
info "Skipping Admin 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
|
|
}
|
|
}
|