workflows/default/go.ps1
|
#!/usr/bin/env pwsh <# .SYNOPSIS Launch the .bot UI server and open the browser. .DESCRIPTION This script starts the web-based task management UI and automatically opens it in your default browser. The UI server runs in the background. .NOTES Press Ctrl+C to stop the server when done. #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [int]$Port = 0, [Parameter(Mandatory = $false)] [switch]$Headless ) $ErrorActionPreference = "Stop" # Get directories $BotDir = $PSScriptRoot $UIDir = Join-Path $BotDir "systems\ui" $ServerScript = Join-Path $UIDir "server.ps1" # Migrate legacy folder names if needed (defaults→settings, prompts→recipes, adrs→decisions) $oldDefaults = Join-Path $BotDir "defaults" $newSettings = Join-Path $BotDir "settings" if ((Test-Path $oldDefaults) -and -not (Test-Path $newSettings)) { Rename-Item $oldDefaults $newSettings } $oldInner = Join-Path $BotDir "prompts\workflows" if (Test-Path $oldInner) { Rename-Item $oldInner (Join-Path $BotDir "prompts\_prompts_tmp") } $oldPrompts = Join-Path $BotDir "prompts" $newRecipes = Join-Path $BotDir "recipes" if ((Test-Path $oldPrompts) -and -not (Test-Path $newRecipes)) { Rename-Item $oldPrompts $newRecipes $tmp = Join-Path $newRecipes "_prompts_tmp" if (Test-Path $tmp) { Rename-Item $tmp (Join-Path $newRecipes "prompts") } } $oldAdrs = Join-Path $BotDir "workspace\adrs" $newDec = Join-Path $BotDir "workspace\decisions" if ((Test-Path $oldAdrs) -and -not (Test-Path $newDec)) { Rename-Item $oldAdrs $newDec } # Initialize structured logging $controlDir = Join-Path $BotDir ".control" if (-not (Test-Path $controlDir)) { New-Item -Path $controlDir -ItemType Directory -Force | Out-Null } $logsDir = Join-Path $controlDir "logs" if (-not (Test-Path $logsDir)) { New-Item -Path $logsDir -ItemType Directory -Force | Out-Null } Import-Module "$PSScriptRoot\systems\runtime\modules\DotBotLog.psm1" -Force -DisableNameChecking Initialize-DotBotLog -LogDir $logsDir -ControlDir $controlDir -ProjectRoot (Split-Path $BotDir -Parent) # Import theme module (provides Write-Status with -Type parameter) Import-Module "$PSScriptRoot\systems\runtime\modules\DotBotTheme.psm1" -Force -DisableNameChecking Write-BotLog -Level Info -Message "go.ps1 launched. BotDir=$BotDir" Write-Status " Starting .bot UI..." -Type Info Write-BotLog -Level Debug -Message "" # Check if a server is already running for this project $uiPortFile = Join-Path $controlDir "ui-port" if (Test-Path $uiPortFile) { $existingPort = (Get-Content $uiPortFile -Raw).Trim() if ($existingPort -match '^\d+$') { try { $resp = Invoke-WebRequest -Uri "http://localhost:$existingPort/api/info" -TimeoutSec 2 -ErrorAction Stop if ($resp.StatusCode -eq 200) { # Verify the server belongs to THIS project, not a different one $thisProjectRoot = (Resolve-Path (Join-Path $BotDir "..")).Path $serverInfo = $resp.Content | ConvertFrom-Json $serverProjectRoot = $serverInfo.project_root if ($serverProjectRoot -and ($serverProjectRoot -ne $thisProjectRoot)) { # Different project's server on this port — start a new instance Write-BotLog -Level Warn -Message " Port $existingPort is used by a different project ($serverProjectRoot)" Write-BotLog -Level Warn -Message " Starting a new server instance..." } else { $url = "http://localhost:$existingPort" Write-Status " Server already running on port $existingPort" -Type Success if (Get-Command Open-Url -ErrorAction SilentlyContinue) { Open-Url $url } else { Start-Process $url } Write-Status " Browser opened at $url" -Type Success Write-BotLog -Level Debug -Message "" exit 0 } } } catch { Write-BotLog -Level Debug -Message "Server not responding on stale port — continuing with fresh start" -Exception $_ } } } # Check if server script exists if (-not (Test-Path $ServerScript)) { Write-BotLog -Level Error -Message " Error: UI server script not found at:" Write-BotLog -Level Error -Message " $ServerScript" Write-BotLog -Level Debug -Message "" Write-BotLog -Level Warn -Message "Please ensure the .bot/systems/ui/ directory exists and contains server.ps1" exit 1 } # Start the UI server Write-Status " Starting UI server..." -Type Info Write-BotLog -Level Debug -Message " Location: $UIDir" Write-BotLog -Level Debug -Message "" # Build server arguments $serverArgs = @("-File", "`"$ServerScript`"") if ($Port -gt 0) { $serverArgs += "-Port", $Port.ToString() } # Remove stale port file so we only read the new server's port if (Test-Path $uiPortFile) { Remove-Item $uiPortFile -Force } # Start the server (visible window by default; -Headless suppresses it for tests/CI) if ($Headless) { Start-Process pwsh -ArgumentList $serverArgs -NoNewWindow } else { Start-Process pwsh -ArgumentList $serverArgs } # Wait for the server to write its selected port $resolvedPort = 0 for ($i = 0; $i -lt 20; $i++) { Start-Sleep -Milliseconds 250 if (Test-Path $uiPortFile) { $raw = (Get-Content $uiPortFile -Raw).Trim() if ($raw -match '^\d+$') { $resolvedPort = [int]$raw break } } } if ($resolvedPort -eq 0) { $resolvedPort = if ($Port -gt 0) { $Port } else { 8686 } Write-BotLog -Level Warn -Message " Could not detect server port, assuming $resolvedPort" } $url = "http://localhost:$resolvedPort" if (Get-Command Open-Url -ErrorAction SilentlyContinue) { Open-Url $url } else { Start-Process $url } Write-Status " Browser opened at $url" -Type Success Write-BotLog -Level Debug -Message " Server is running in a separate window (port $resolvedPort)." Write-BotLog -Level Debug -Message "" |