src/public/AI/Start-AitherService.ps1
|
#Requires -Version 7.0 <# .SYNOPSIS Start an backend service. .DESCRIPTION Starts the specified backend service by invoking its start script. Supports waiting for startup confirmation. .PARAMETER Name Service name or alias. Required. Available services and their aliases: - AitherNode (Node, MCP) - MCP Server - AitherCanvas (Canvas, Comfy, ComfyUI, ImageGen) - Image Generation - AitherReasoning (Reasoning, Traces) - Thinking Traces - AitherPulse (Pulse, Events) - Event Bus - AitherVeil (Veil, Dashboard, UI) - Dashboard - AitherPrism (Prism, Video) - Video Frame Extraction - AitherTrainer (Trainer, Training) - Model Training - vLLM Orchestrator (Orchestrator) - General LLM (Docker) - vLLM Reasoning (Reasoning-vLLM) - Deep reasoning LLM (Docker) - vLLM Vision (Vision-vLLM) - Multimodal LLM (Docker) - vLLM Coding (Coding-vLLM) - Code generation LLM (Docker) .PARAMETER Port Override the default port for the service. .PARAMETER ShowOutput Display startup progress and status. .PARAMETER PassThru Return result object instead of display output. .PARAMETER Wait Wait for service to fully start before returning. .PARAMETER List Show all available services and their status. .EXAMPLE Start-AitherService -Name Node # Starts AitherNode MCP server .EXAMPLE Start-AitherService -Name Comfy -ShowOutput -Wait # Starts ComfyUI (AitherCanvas) and waits for it to be ready .EXAMPLE Start-AitherService -List # Shows all available services and their current status .NOTES Part of the AitherZero module. #> function Start-AitherService { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory, Position = 0)] [string]$Name, [Parameter()] [int]$Port, [Parameter()] [switch]$ShowOutput, [Parameter()] [switch]$PassThru, [Parameter()] [switch]$Wait ) # Service definitions $AitherServices = @{ AitherNode = @{ Port = 8080; Script = '0762'; Alias = @('Node', 'MCP'); Desc = 'MCP Server' } AitherReasoning = @{ Port = 8093; Script = '0764'; Alias = @('Reasoning', 'Traces'); Desc = 'Thinking Traces' } AitherPulse = @{ Port = 8081; Script = '0765'; Alias = @('Pulse', 'Events'); Desc = 'Event Bus' } AitherCanvas = @{ Port = 8188; Script = '0734'; Alias = @('Canvas', 'Comfy', 'ImageGen'); Desc = 'Image Generation' } AitherVeil = @{ Port = 3000; Script = '0766'; Alias = @('Veil', 'Dashboard', 'UI'); Desc = 'Dashboard' } AitherPrism = @{ Port = 8106; Script = '0780'; Alias = @('Prism', 'Video'); Desc = 'Video Extraction' } AitherTrainer = @{ Port = 8107; Script = '0779'; Alias = @('Trainer', 'Training'); Desc = 'Model Training' } vLLMOrchestrator = @{ Port = 8200; Script = $null; Alias = @('Orchestrator', 'LLM'); External = $true; Desc = 'vLLM Orchestrator (Docker)' } vLLMReasoning = @{ Port = 8201; Script = $null; Alias = @('Reasoning-vLLM'); External = $true; Desc = 'vLLM Reasoning (Docker)' } vLLMVision = @{ Port = 8202; Script = $null; Alias = @('Vision-vLLM'); External = $true; Desc = 'vLLM Vision (Docker)' } vLLMCoding = @{ Port = 8203; Script = $null; Alias = @('Coding-vLLM'); External = $true; Desc = 'vLLM Coding (Docker)' } } # Resolve service name $svcName = $null if ($AitherServices.ContainsKey($Name)) { $svcName = $Name } else { foreach ($svc in $AitherServices.Keys) { if ($AitherServices[$svc].Alias -contains $Name) { $svcName = $svc break } } } if (-not $svcName) { Write-AitherLog -Level Warning -Message "Service '$Name' not found. Available: $($AitherServices.Keys -join ', ')" -Source 'Start-AitherService' return } $def = $AitherServices[$svcName] $svcPort = if ($Port) { $Port } else { $def.Port } # Check if already running $conn = Get-NetTCPConnection -LocalPort $svcPort -State Listen -ErrorAction SilentlyContinue if ($conn) { if ($ShowOutput) { Write-AitherLog -Level Information -Message "✓ $svcName already running on port $svcPort (PID: $($conn.OwningProcess))" -Source 'Start-AitherService' } $result = [PSCustomObject]@{ Name = $svcName; Status = 'AlreadyRunning'; Port = $svcPort; PID = $conn.OwningProcess } if ($PassThru) { return $result } return } # External services if ($def.External) { Write-AitherLog -Level Warning -Message "$svcName is an external service. Start it manually." -Source 'Start-AitherService' return } if (-not $def.Script) { Write-AitherLog -Level Warning -Message "$svcName has no start script defined." -Source 'Start-AitherService' return } if ($PSCmdlet.ShouldProcess($svcName, "Start service on port $svcPort")) { $scriptPath = Get-AitherScriptsPath $startScript = Get-ChildItem -Path $scriptPath -Filter "$($def.Script)*.ps1" | Select-Object -First 1 if (-not $startScript) { Write-AitherLog -Level Warning -Message "Start script $($def.Script) not found for $svcName" -Source 'Start-AitherService' return } if ($ShowOutput) { Write-AitherLog -Level Information -Message "▶ Starting $svcName on port $svcPort..." -Source 'Start-AitherService' } # Start in background $params = @('-NoProfile', '-File', $startScript.FullName) if ($ShowOutput) { $params += '-ShowOutput' } if ($Port) { $params += @('-Port', $svcPort) } Start-Process pwsh -ArgumentList $params -WindowStyle Hidden if ($Wait) { $maxWait = 15 for ($i = 0; $i -lt $maxWait; $i++) { Start-Sleep -Seconds 1 $check = Get-NetTCPConnection -LocalPort $svcPort -State Listen -ErrorAction SilentlyContinue if ($check) { if ($ShowOutput) { Write-AitherLog -Level Information -Message "✓ $svcName started (PID: $($check.OwningProcess))" -Source 'Start-AitherService' } $result = [PSCustomObject]@{ Name = $svcName; Status = 'Started'; Port = $svcPort; PID = $check.OwningProcess } if ($PassThru) { return $result } return } } Write-AitherLog -Level Warning -Message "$svcName may not have started. Check logs." -Source 'Start-AitherService' $result = [PSCustomObject]@{ Name = $svcName; Status = 'Timeout'; Port = $svcPort; PID = $null } if ($PassThru) { return $result } } else { if ($ShowOutput) { Write-AitherLog -Level Information -Message "→ $svcName starting in background" -Source 'Start-AitherService' } $result = [PSCustomObject]@{ Name = $svcName; Status = 'Starting'; Port = $svcPort; PID = $null } if ($PassThru) { return $result } } } } |