From f22b44a0003416fb8dbfec7fd4661e313d7ed46c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 5 Jul 2026 21:05:14 +0000 Subject: [PATCH] Auto-detect free port and add one-click launcher start.ps1/start.sh now fall back to the next free port instead of crashing when the configured port is already taken (e.g. by another local app), and auto-open the dashboard in the browser once it's up. install.ps1 also creates a desktop shortcut (Launch-Dashboard.bat) so the dashboard can be started without typing any commands. --- Launch-Dashboard.bat | 4 ++++ install.ps1 | 18 ++++++++++++++++-- start.ps1 | 29 +++++++++++++++++++++++++++-- start.sh | 23 ++++++++++++++++++++++- 4 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 Launch-Dashboard.bat diff --git a/Launch-Dashboard.bat b/Launch-Dashboard.bat new file mode 100644 index 0000000..adc52e1 --- /dev/null +++ b/Launch-Dashboard.bat @@ -0,0 +1,4 @@ +@echo off +cd /d "%~dp0" +powershell -NoLogo -ExecutionPolicy Bypass -File "%~dp0start.ps1" +pause diff --git a/install.ps1 b/install.ps1 index 75e4eec..0645188 100644 --- a/install.ps1 +++ b/install.ps1 @@ -75,10 +75,24 @@ if (-not (Test-Path .git)) { } } +$launcher = Join-Path $PSScriptRoot "Launch-Dashboard.bat" +$desktop = [Environment]::GetFolderPath("Desktop") +if ((Test-Path $launcher) -and (Test-Path $desktop)) { + $shortcutPath = Join-Path $desktop "Agentic OS Dashboard.lnk" + $shell = New-Object -ComObject WScript.Shell + $shortcut = $shell.CreateShortcut($shortcutPath) + $shortcut.TargetPath = $launcher + $shortcut.WorkingDirectory = $PSScriptRoot + $shortcut.Description = "Launch the Agentic OS dashboard" + $shortcut.Save() + Write-Host "Desktop shortcut created: $shortcutPath" +} + Write-Host "" Write-Host "=== Installation complete! ===" Write-Host "" Write-Host "Next steps:" Write-Host " 1. Edit data/settings.json with your API keys" -Write-Host " 2. Run .\start.ps1 to launch the dashboard" -Write-Host " 3. Open http://127.0.0.1:8080 in your browser" +Write-Host " 2. Double-click the 'Agentic OS Dashboard' shortcut on your Desktop" +Write-Host " (or run .\start.ps1 / .\Launch-Dashboard.bat manually)" +Write-Host " 3. Your browser will open automatically once the server is ready" diff --git a/start.ps1 b/start.ps1 index 700f52d..a30da8b 100644 --- a/start.ps1 +++ b/start.ps1 @@ -36,11 +36,36 @@ $pythonArgs = @($python.Args) & $pythonCommand @pythonArgs -m pip install -r requirements.txt --quiet -$port = & $pythonCommand @pythonArgs -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>$null -if (-not $port) { $port = "8080" } +$configuredPort = & $pythonCommand @pythonArgs -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>$null +if (-not $configuredPort) { $configuredPort = "8080" } +$configuredPort = [int]$configuredPort + +function Find-FreePort { + param([int]$StartPort, [int]$MaxAttempts = 20) + for ($p = $StartPort; $p -lt $StartPort + $MaxAttempts; $p++) { + $listener = $null + try { + $listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Parse("127.0.0.1"), $p) + $listener.Start() + return $p + } catch { + continue + } finally { + if ($listener) { $listener.Stop() } + } + } + throw "No free port found between $StartPort and $($StartPort + $MaxAttempts - 1). Close some other application or free a port and retry." +} + +$port = Find-FreePort -StartPort $configuredPort +if ($port -ne $configuredPort) { + Write-Warning "Port $configuredPort is already in use (another app, or a leftover Agentic OS process) - using $port instead." +} Write-Host "Dashboard: http://127.0.0.1:$port" Write-Host "Press Ctrl+C to stop" Write-Host "" +Start-Job -ScriptBlock { Start-Sleep -Seconds 2; Start-Process "http://127.0.0.1:$using:port" } | Out-Null + & $pythonCommand @pythonArgs server.py --port $port diff --git a/start.sh b/start.sh index f165161..a143397 100755 --- a/start.sh +++ b/start.sh @@ -24,11 +24,32 @@ fi $PYTHON -m pip install -r requirements.txt --quiet 2>/dev/null # Get port from settings or default -PORT=$($PYTHON -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>/dev/null || echo "8080") +CONFIGURED_PORT=$($PYTHON -c "import json; f=open('data/settings.json'); d=json.load(f); print(d.get('dashboard',{}).get('port',8080)); f.close()" 2>/dev/null || echo "8080") + +# Find a free port starting at CONFIGURED_PORT (in case it's already taken by another app) +PORT="$CONFIGURED_PORT" +for _ in $(seq 1 20); do + if ! (exec 3<>"/dev/tcp/127.0.0.1/${PORT}") 2>/dev/null; then + break + fi + exec 3>&- 2>/dev/null || true + PORT=$((PORT + 1)) +done + +if [ "$PORT" != "$CONFIGURED_PORT" ]; then + echo "WARNING: Port ${CONFIGURED_PORT} is already in use - using ${PORT} instead." +fi echo "Dashboard: http://127.0.0.1:${PORT}" echo "Press Ctrl+C to stop" echo "" +# Best-effort auto-open browser once the server is up +( sleep 2 + if command -v xdg-open &>/dev/null; then xdg-open "http://127.0.0.1:${PORT}" &>/dev/null + elif command -v open &>/dev/null; then open "http://127.0.0.1:${PORT}" &>/dev/null + fi +) & + # Start server $PYTHON server.py --port "${PORT}"