把工作区里其余在制品一并入库,主要是工作台产品化的推进:
后端:新增 capability_definition / project / my_app_center / office_skill
接口与 action_definition / skill_definition / project / user_app_center
模型,config 加路由健康上报。
前端:新增 frontend/src/skills(Office 技能与 workbuddy 复刻)、
项目管理、应用中心、能力目录页,以及配套 api / store / config;
聊天侧新增 SpecialistChip / SpecialistPanel / SkillStrip / AppChatRail
等组件。
清理:移除旧 views/tools 下的单页工具(已并入工作台)、_frozen 冻结组件、
cmd/inspect_oa_debug 调试入口,以及两份调试笔记。
其它:文档与启动脚本同步。
(这批改动与上一提交的 SY23 工作并行进行,此前已在同一工作区内交织。)
Co-Authored-By: Claude Code <noreply@anthropic.com>
264 lines
8.9 KiB
PowerShell
264 lines
8.9 KiB
PowerShell
param(
|
|
[switch]$Force,
|
|
[switch]$SkipPreflight,
|
|
[switch]$SkipSmoke,
|
|
[switch]$SkipBackendBuild,
|
|
[switch]$SkipFrontendInstall,
|
|
[string]$BindHost = "127.0.0.1"
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$BackendPort = 10232
|
|
$FrontendPort = 10231
|
|
$RepoDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$AppDir = Join-Path $RepoDir "eai_agentplatform"
|
|
$BackendDir = Join-Path $AppDir "backend-go"
|
|
$FrontendDir = Join-Path $AppDir "frontend"
|
|
$BackendBin = Join-Path $BackendDir "bin\eai_agentplatform-server.exe"
|
|
$DebugLogDir = Join-Path $RepoDir "debuglog"
|
|
$null = New-Item -ItemType Directory -Force -Path $DebugLogDir
|
|
|
|
$RunId = Get-Date -Format "yyyyMMdd_HHmmss"
|
|
$BackendLog = Join-Path $DebugLogDir "backend_$RunId.log"
|
|
$BackendErrLog = Join-Path $DebugLogDir "backend_$RunId.err.log"
|
|
$FrontendLog = Join-Path $DebugLogDir "frontend_$RunId.log"
|
|
$FrontendErrLog = Join-Path $DebugLogDir "frontend_$RunId.err.log"
|
|
$BackendPidFile = Join-Path $DebugLogDir "backend.pid"
|
|
$FrontendPidFile = Join-Path $DebugLogDir "frontend.pid"
|
|
|
|
$KnownProcessNames = @("eai_agentplatform-server", "node", "npm", "npm.cmd")
|
|
$StartedProcesses = @()
|
|
|
|
function Write-Step {
|
|
param([string]$Message)
|
|
Write-Host ""
|
|
Write-Host "==> $Message" -ForegroundColor Cyan
|
|
}
|
|
|
|
function Test-CommandExists {
|
|
param([string]$Name)
|
|
return $null -ne (Get-Command $Name -ErrorAction SilentlyContinue)
|
|
}
|
|
|
|
function Get-ProcessNameSafe {
|
|
param([object]$Process)
|
|
if ($null -ne $Process) {
|
|
return $Process.ProcessName
|
|
}
|
|
return "unknown"
|
|
}
|
|
|
|
function Get-PortPids {
|
|
param([int]$Port)
|
|
try {
|
|
$connections = Get-NetTCPConnection -LocalPort $Port -State Listen -ErrorAction Stop
|
|
return @($connections | Select-Object -ExpandProperty OwningProcess -Unique)
|
|
} catch {
|
|
return @()
|
|
}
|
|
}
|
|
|
|
function Resolve-Port {
|
|
param(
|
|
[int]$Port,
|
|
[string]$Label
|
|
)
|
|
|
|
$pids = @(Get-PortPids -Port $Port)
|
|
if ($pids.Count -eq 0) {
|
|
Write-Host (" [OK] {0} :{1} is free" -f $Label, $Port)
|
|
return
|
|
}
|
|
|
|
Write-Host (" [!] {0} :{1} is in use:" -f $Label, $Port)
|
|
foreach ($portPid in $pids) {
|
|
$proc = Get-Process -Id $portPid -ErrorAction SilentlyContinue
|
|
$name = Get-ProcessNameSafe -Process $proc
|
|
Write-Host (" - {0} (PID {1})" -f $name, $portPid)
|
|
}
|
|
|
|
if (-not $Force) {
|
|
throw ("{0} port :{1} is in use. Stop it manually or rerun with -Force." -f $Label, $Port)
|
|
}
|
|
|
|
foreach ($portPid in $pids) {
|
|
$proc = Get-Process -Id $portPid -ErrorAction SilentlyContinue
|
|
$name = Get-ProcessNameSafe -Process $proc
|
|
if (($null -ne $proc) -and (($KnownProcessNames -contains $proc.ProcessName) -or ($name -like "eai_agentplatform-server*"))) {
|
|
Stop-Process -Id $portPid -Force
|
|
Write-Host (" stopped {0} (PID {1})" -f $name, $portPid)
|
|
} else {
|
|
throw ("Port :{0} is used by a non-project process ({1} / PID {2}). Aborting." -f $Port, $name, $portPid)
|
|
}
|
|
}
|
|
}
|
|
|
|
function Wait-Http {
|
|
param(
|
|
[string]$Url,
|
|
[string]$Label,
|
|
[int]$TimeoutSec = 60
|
|
)
|
|
|
|
$deadline = (Get-Date).AddSeconds($TimeoutSec)
|
|
while ((Get-Date) -lt $deadline) {
|
|
try {
|
|
Invoke-WebRequest -UseBasicParsing -Uri $Url -TimeoutSec 2 | Out-Null
|
|
Write-Host (" [OK] {0} is ready: {1}" -f $Label, $Url)
|
|
return
|
|
} catch {
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
}
|
|
|
|
throw ("{0} did not become ready within {1}s: {2}" -f $Label, $TimeoutSec, $Url)
|
|
}
|
|
|
|
function Start-TrackedProcess {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$FilePath,
|
|
[Parameter(Mandatory = $true)][string]$WorkingDirectory,
|
|
[string[]]$ArgumentList = @(),
|
|
[Parameter(Mandatory = $true)][string]$StdoutPath,
|
|
[Parameter(Mandatory = $true)][string]$StderrPath
|
|
)
|
|
|
|
$startParams = @{
|
|
FilePath = $FilePath
|
|
WorkingDirectory = $WorkingDirectory
|
|
RedirectStandardOutput = $StdoutPath
|
|
RedirectStandardError = $StderrPath
|
|
PassThru = $true
|
|
}
|
|
if ($null -ne $ArgumentList -and $ArgumentList.Count -gt 0) {
|
|
$startParams.ArgumentList = $ArgumentList
|
|
}
|
|
|
|
$proc = Start-Process @startParams
|
|
|
|
$script:StartedProcesses += $proc
|
|
return $proc
|
|
}
|
|
|
|
function Cleanup-StartedProcesses {
|
|
foreach ($proc in $StartedProcesses) {
|
|
if (($null -ne $proc) -and (-not $proc.HasExited)) {
|
|
Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
|
|
try {
|
|
Write-Host "==> eai_agentplatform Windows dev launcher"
|
|
Write-Host (" repo : {0}" -f $RepoDir)
|
|
Write-Host (" backend : {0} (port {1})" -f $BackendDir, $BackendPort)
|
|
Write-Host (" frontend : {0} (port {1})" -f $FrontendDir, $FrontendPort)
|
|
Write-Host (" bind host: {0}" -f $BindHost)
|
|
|
|
if (-not $SkipPreflight) {
|
|
Write-Step "Preflight"
|
|
if (-not (Test-Path $BackendDir)) { throw ("Missing backend directory: {0}" -f $BackendDir) }
|
|
if (-not (Test-Path $FrontendDir)) { throw ("Missing frontend directory: {0}" -f $FrontendDir) }
|
|
if (-not (Test-CommandExists "go")) { throw "Missing go on PATH." }
|
|
if (-not (Test-CommandExists "node")) { throw "Missing node on PATH." }
|
|
if (-not (Test-CommandExists "npm.cmd")) { throw "Missing npm on PATH." }
|
|
Write-Host " [OK] Preflight passed"
|
|
} else {
|
|
Write-Step "Preflight skipped"
|
|
}
|
|
|
|
Write-Step "Prepare dependencies"
|
|
if (-not $SkipBackendBuild) {
|
|
Write-Host " [.] Build backend"
|
|
Push-Location $BackendDir
|
|
try {
|
|
& go build -o $BackendBin ".\cmd\server"
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
} elseif (-not (Test-Path $BackendBin)) {
|
|
throw ("Backend binary not found: {0}" -f $BackendBin)
|
|
}
|
|
|
|
$NodeModulesDir = Join-Path $FrontendDir "node_modules"
|
|
if (-not (Test-Path $NodeModulesDir)) {
|
|
if ($SkipFrontendInstall) {
|
|
throw "node_modules is missing and frontend install was skipped."
|
|
}
|
|
|
|
Write-Host " [.] Install frontend dependencies"
|
|
Push-Location $FrontendDir
|
|
try {
|
|
& npm.cmd install
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
} else {
|
|
Write-Host " [OK] Frontend dependencies already installed"
|
|
}
|
|
|
|
Write-Step "Check ports"
|
|
Resolve-Port -Port $BackendPort -Label "backend"
|
|
Resolve-Port -Port $FrontendPort -Label "frontend"
|
|
|
|
Write-Step "Launch services"
|
|
$env:PORT = [string]$BackendPort
|
|
$backendProc = Start-TrackedProcess `
|
|
-FilePath $BackendBin `
|
|
-WorkingDirectory $BackendDir `
|
|
-StdoutPath $BackendLog `
|
|
-StderrPath $BackendErrLog
|
|
Set-Content -Path $BackendPidFile -Value $backendProc.Id
|
|
Wait-Http -Url ("http://127.0.0.1:{0}/api/health" -f $BackendPort) -Label "backend"
|
|
|
|
$frontendProc = Start-TrackedProcess `
|
|
-FilePath "npm.cmd" `
|
|
-WorkingDirectory $FrontendDir `
|
|
-ArgumentList @("run", "dev", "--", "--host", $BindHost, "--port", [string]$FrontendPort) `
|
|
-StdoutPath $FrontendLog `
|
|
-StderrPath $FrontendErrLog
|
|
Set-Content -Path $FrontendPidFile -Value $frontendProc.Id
|
|
|
|
if ($BindHost -eq "0.0.0.0") {
|
|
$frontendHealthUrl = ("http://localhost:{0}/" -f $FrontendPort)
|
|
} else {
|
|
$frontendHealthUrl = ("http://{0}:{1}/" -f $BindHost, $FrontendPort)
|
|
}
|
|
Wait-Http -Url $frontendHealthUrl -Label "frontend"
|
|
|
|
if (-not $SkipSmoke) {
|
|
Write-Step "Smoke login"
|
|
$payload = @{ username = "admin"; password = "admin123" } | ConvertTo-Json
|
|
try {
|
|
$null = Invoke-RestMethod `
|
|
-Uri ("http://127.0.0.1:{0}/api/auth/login" -f $BackendPort) `
|
|
-Method Post `
|
|
-ContentType "application/json" `
|
|
-Body $payload `
|
|
-TimeoutSec 5
|
|
Write-Host " [OK] admin login passed"
|
|
} catch {
|
|
Write-Warning ("admin login failed: {0}" -f $_.Exception.Message)
|
|
}
|
|
}
|
|
|
|
Write-Step "Done"
|
|
Write-Host ("Frontend : http://localhost:{0}/" -f $FrontendPort)
|
|
Write-Host ("Backend : http://127.0.0.1:{0}/" -f $BackendPort)
|
|
Write-Host ("Backend log : {0}" -f $BackendLog)
|
|
Write-Host ("Backend err : {0}" -f $BackendErrLog)
|
|
Write-Host ("Frontend log : {0}" -f $FrontendLog)
|
|
Write-Host ("Frontend err : {0}" -f $FrontendErrLog)
|
|
Write-Host ("PIDs : backend={0} frontend={1}" -f $backendProc.Id, $frontendProc.Id)
|
|
Write-Host ""
|
|
Write-Host "Examples:" -ForegroundColor Yellow
|
|
Write-Host " powershell -ExecutionPolicy Bypass -File .\start_dev_10231_10232.ps1"
|
|
Write-Host " powershell -ExecutionPolicy Bypass -File .\start_dev_10231_10232.ps1 -Force"
|
|
Write-Host " powershell -ExecutionPolicy Bypass -File .\start_dev_10231_10232.ps1 -SkipSmoke"
|
|
} catch {
|
|
Cleanup-StartedProcesses
|
|
throw
|
|
}
|