diff --git a/.gitignore b/.gitignore index b67e665..69b7d1b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ output pyproject.toml uv.lock node_modules +dist diff --git a/package/README.txt b/package/README.txt new file mode 100644 index 0000000..ab67da4 --- /dev/null +++ b/package/README.txt @@ -0,0 +1,26 @@ +PicoBot + +## 快速开始 + +1. 双击 start-gateway.vbs 启动服务 +2. 浏览器打开 http://127.0.0.1:19876 + +## 首次使用 + +1. 先配置 API Key,在命令行执行: + picobot.exe init +2. 按提示输入 Provider 类型、API Key、模型名称 +3. 配置保存在 %USERPROFILE%\.picobot\config.yaml + +## 命令行 + + picobot.exe gateway 启动服务端(默认 127.0.0.1:19876) + picobot.exe gateway --port 8080 指定端口 + picobot.exe agent 连接远程 Gateway + picobot.exe init 重新配置 + +## 后台运行 + +- 双击 start-gateway.vbs -- 完全无窗口 +- 双击 start-gateway.bat -- 可看到启动状态 +- PowerShell: .\start-gateway.ps1 start diff --git a/package/start-gateway-ps.bat b/package/start-gateway-ps.bat new file mode 100644 index 0000000..67b7b2b --- /dev/null +++ b/package/start-gateway-ps.bat @@ -0,0 +1,3 @@ +@echo off +powershell -ExecutionPolicy Bypass -File "%~dp0start-gateway.ps1" %* +pause diff --git a/package/start-gateway.bat b/package/start-gateway.bat new file mode 100644 index 0000000..bf7a922 --- /dev/null +++ b/package/start-gateway.bat @@ -0,0 +1,37 @@ +@echo off +title PicoBot Gateway + +:: Locate exe (prefer same-dir for distribution, fallback to target/ for dev) +set EXE= +if exist "%~dp0picobot.exe" ( + set EXE=%~dp0picobot.exe +) else if exist "%~dp0..\..\target\release\picobot.exe" ( + set EXE=%~dp0..\..\target\release\picobot.exe +) else if exist "%~dp0..\..\target\debug\picobot.exe" ( + set EXE=%~dp0..\..\target\debug\picobot.exe +) else ( + echo [ERROR] picobot.exe not found. Build first: cargo build --release + pause + exit /b 1 +) + +echo [INFO] Starting PicoBot Gateway in background... +echo [INFO] exe: %EXE% + +:: /B = background, no new window +start "" /B "%EXE%" gateway + +echo [INFO] Gateway started +echo [INFO] URL: http://127.0.0.1:19876 +echo [INFO] WebSocket: ws://127.0.0.1:19876/ws + +:: Wait a moment and check if still running +timeout /t 2 /nobreak >nul +tasklist /fi "imagename eq picobot.exe" 2>nul | find "picobot.exe" >nul +if %errorlevel% equ 0 ( + echo [OK] Gateway is running +) else ( + echo [WARN] Gateway may have failed to start, check logs +) + +pause diff --git a/package/start-gateway.ps1 b/package/start-gateway.ps1 new file mode 100644 index 0000000..9b2f060 --- /dev/null +++ b/package/start-gateway.ps1 @@ -0,0 +1,68 @@ +# PicoBot Gateway management script +param( + [ValidateSet("start", "stop", "status")] + [string]$Action = "start", + [int]$Port = 19876 +) + +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path + +$ExePaths = @( + "$ScriptDir\picobot.exe", # distribution: same dir + "$ScriptDir\..\..\target\release\picobot.exe", # dev: release build + "$ScriptDir\..\..\target\debug\picobot.exe" # dev: debug build +) +$Exe = $ExePaths | Where-Object { Test-Path $_ } | Select-Object -First 1 + +if (-not $Exe) { + Write-Host "[ERROR] picobot.exe not found. Build first: cargo build --release" -ForegroundColor Red + exit 1 +} + +Write-Host "[INFO] exe: $Exe" -ForegroundColor Gray + +switch ($Action) { + "start" { + $existing = Get-Process -Name "picobot" -ErrorAction SilentlyContinue + if ($existing) { + Write-Host "[WARN] picobot already running (PID: $($existing.Id))" -ForegroundColor Yellow + exit 0 + } + + $proc = Start-Process -FilePath $Exe ` + -ArgumentList "gateway", "--port", $Port ` + -WindowStyle Hidden ` + -PassThru + + Start-Sleep -Seconds 1 + if (-not $proc.HasExited) { + Write-Host "[OK] Gateway started (PID: $($proc.Id))" -ForegroundColor Green + Write-Host " URL: http://127.0.0.1:$Port" -ForegroundColor Gray + Write-Host " WebSocket: ws://127.0.0.1:$Port/ws" -ForegroundColor Gray + } else { + Write-Host "[ERROR] Gateway failed to start (exit code: $($proc.ExitCode))" -ForegroundColor Red + } + } + "stop" { + $procs = Get-Process -Name "picobot" -ErrorAction SilentlyContinue + if (-not $procs) { + Write-Host "[INFO] picobot is not running" -ForegroundColor Gray + exit 0 + } + $procs | ForEach-Object { + Write-Host "[INFO] Stopping picobot (PID: $($_.Id))" -ForegroundColor Yellow + $_.Kill() + } + Write-Host "[OK] Stopped" -ForegroundColor Green + } + "status" { + $procs = Get-Process -Name "picobot" -ErrorAction SilentlyContinue + if ($procs) { + $procs | ForEach-Object { + Write-Host "[RUNNING] picobot (PID: $($_.Id), Mem: $([math]::Round($_.WorkingSet64/1MB, 1))MB)" -ForegroundColor Green + } + } else { + Write-Host "[STOPPED] picobot is not running" -ForegroundColor Gray + } + } +} diff --git a/package/start-gateway.vbs b/package/start-gateway.vbs new file mode 100644 index 0000000..33e9aa9 --- /dev/null +++ b/package/start-gateway.vbs @@ -0,0 +1,32 @@ +' PicoBot Gateway 后台启动脚本 +' 双击运行即可,完全无窗口 + +Set WshShell = CreateObject("WScript.Shell") + +Set fso = CreateObject("Scripting.FileSystemObject") +scriptDir = fso.GetParentFolderName(WScript.ScriptFullName) + +' 把当前目录切到脚本所在目录,避免相对路径问题 +WshShell.CurrentDirectory = scriptDir + +' 依次查找 exe:同目录 → release → debug +exePath = scriptDir & "\picobot.exe" +If Not fso.FileExists(exePath) Then + exePath = scriptDir & "\..\..\target\release\picobot.exe" + If Not fso.FileExists(exePath) Then + exePath = scriptDir & "\..\..\target\debug\picobot.exe" + End If +End If + +' 转成绝对路径,确保 Run 能正确找到 +exePath = fso.GetAbsolutePathName(exePath) + +If Not fso.FileExists(exePath) Then + MsgBox "picobot.exe not found." & vbCrLf & "Build first: cargo build --release", 48, "PicoBot" + WScript.Quit 1 +End If + +' Launch in background (0=hidden window, False=don't wait) +WshShell.Run """" & exePath & """ gateway", 0, False + +MsgBox "PicoBot Gateway started in background." & vbCrLf & "Open http://127.0.0.1:19876", 64, "PicoBot" diff --git a/scripts/build-release.ps1 b/scripts/build-release.ps1 new file mode 100644 index 0000000..b6b24a4 --- /dev/null +++ b/scripts/build-release.ps1 @@ -0,0 +1,57 @@ +# PicoBot build & package script +# Usage: .\scripts\build-release.ps1 +# Output: dist\picobot-vX.X.X.zip + +$ErrorActionPreference = "Stop" +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$Root = Split-Path -Parent $ScriptDir + +# Read version +$CargoToml = Get-Content "$Root\Cargo.toml" -Raw +$Version = if ($CargoToml -match 'version\s*=\s*"([^"]+)"') { $Matches[1] } else { "0.1.0" } +$PackageName = "picobot-v$Version-windows-x86_64" +$DistDir = "$Root\dist\$PackageName" + +Write-Host "=== PicoBot v$Version Build ===" -ForegroundColor Cyan + +# Step 1: build frontend +Write-Host "[1/4] Building web frontend..." -ForegroundColor Yellow +Push-Location "$Root\web" +try { + npm run build + if ($LASTEXITCODE -ne 0) { throw "web build failed" } +} finally { + Pop-Location +} + +# Step 2: build Rust backend +Write-Host "[2/4] Building Rust release..." -ForegroundColor Yellow +Push-Location $Root +try { + cargo build --release + if ($LASTEXITCODE -ne 0) { throw "rust build failed" } +} finally { + Pop-Location +} + +# Step 3: assemble dist directory +Write-Host "[3/4] Assembling package..." -ForegroundColor Yellow +New-Item -ItemType Directory -Force -Path $DistDir | Out-Null + +# exe + package contents +Copy-Item "$Root\target\release\picobot.exe" $DistDir +Copy-Item "$Root\package\*" $DistDir + +# Step 4: zip +Write-Host "[4/4] Creating zip..." -ForegroundColor Yellow +$ZipPath = "$Root\dist\$PackageName.zip" +if (Test-Path $ZipPath) { Remove-Item $ZipPath } +Compress-Archive -Path $DistDir -DestinationPath $ZipPath + +# Cleanup +Remove-Item -Recurse -Force $DistDir + +Write-Host "" +Write-Host "=== Done ===" -ForegroundColor Green +Write-Host "Package: dist\$PackageName.zip" -ForegroundColor Green +Write-Host "Size: $([math]::Round((Get-Item $ZipPath).Length/1MB, 1)) MB" -ForegroundColor Gray