# pi-launcher macOS / Windows 桌面启动器:按需启动 [pi-agent](https://www.npmjs.com/package/@agegr/pi-web) 的本地 Web UI,免去手动开终端、敲命令、等端口、点浏览器的重复操作。 基于 [Wails v2](https://wails.io/) (Go + Vue 3) 构建。逻辑与 [`dsh-launcher`](../dsh-launcher) 几乎一致,仅替换为目标 CLI 与图标。 --- ## 这是什么 `@agegr/pi-web` 是一个 npm 全局安装的命令行工具,启动后会: 1. 拉起本地 HTTP 服务(默认端口 `30141`) 2. 浏览器访问 `http://localhost:30141/` `pi-launcher` 把这串动作封装成一个独立的 `.app`(macOS)/ `.exe`(Windows): - 启动前自检:Node / pi-web 命令 / 凭据 / 30141 端口 - 一键启动 → 等端口就绪 → 自动开浏览器 → 最小化到 Dock - 一键停止 / 一键安装(`npm install -g @agegr/pi-web`) / 一键升级 - 退出时自动清理:杀子进程、释放端口、不留孤儿 node 适合场景:日常用 pi 但不想每次都开终端敲命令。 --- ## 截图 (启动器窗口 1040 × 1280,深色背景,左右两栏:左环境检查,右操作 + 日志) --- ## 安装 pi CLI(目标程序) 启动器只是壳,真正干活的 `pi` 命令需要先手动装一次: ```bash npm install -g @agegr/pi-web ``` 启动器自带的「安装 / 升级」按钮会帮你跑同样的命令,不用自己再开终端。 > **注意**:`@agegr/pi-web` 默认会拉取一份 Electron 浏览器壳 + 本地凭据目录 `~/.pi/`(类比 `dsh` 的 `~/.dsh/`)。首次启动器自检会提示你 `pi-web login`。 --- ## 编译启动器本身 需要: - Go ≥ 1.25 - Node ≥ 18 - Wails v2:`go install github.com/wailsapp/wails/v2/cmd/wails@latest` - macOS 编译产物需要 macOS;Windows 同理(见下方说明) ### macOS ```bash ./scripts/build-mac.sh # 产物: build/bin/pi-launcher.app ./scripts/install-app.sh # 复制到 /Applications/ 并刷新 LaunchServices 图标缓存 ``` ### Windows 在 Windows 上跑: ```bat scripts\build-windows.bat ``` > Wails v2 跨平台必须本机编译,Mac 上 build 不了 Windows exe。 --- ## 开发模式 ```bash wails dev ``` Vite 热重载前端 + Go 后端,浏览器另开 devtools:http://localhost:34115 --- ## 核心架构 ``` pi-launcher/ ├── main.go # Wails 入口 + macOS 窗口配置 + --selftest 调试模式 ├── app.go # 后端:CheckEnv / Start / Stop / Install / Update ├── wails.json # 项目元数据(name / outputfilename) ├── go.mod ├── build/ │ ├── darwin/Info.plist │ ├── windows/icon.ico │ └── appicon.png / iconfile.icns # 应用图标(替换此处换图标) ├── frontend/ │ ├── src/App.vue # 单文件 SPA,环境检查 + 操作面板 + 日志 │ ├── src/main.js │ ├── package.json │ └── vite.config.js ├── scripts/ │ ├── build-mac.sh # macOS 构建脚本 │ ├── build-windows.bat │ └── install-app.sh # 复制到 /Applications + 刷新图标缓存 └── README.md ``` ### 后端关键点 - `initNpmPrefix()` — 启动时一次性 `npm prefix -g` 缓存,后续读缓存 - `buildChildEnv()` — 给子进程手动塞 `/opt/homebrew/bin` 等路径,GUI 进程 `~/.zshrc` 不读 - `waitForPort(30141, 30s)` — 轮询端口 LISTEN 替代等 URL 字符串 - `killPITree()` + `freePort(30141)` — 退出 / 停止时双保险,杀进程树 + 精准释放端口 - 全部外部命令都包 `recover()` + 超时,任何子命令崩都不会拖垮 GUI ### 前端关键点 - 单文件 `App.vue`,分左右两栏:左环境检查(Node / pi / 凭据 / 端口),右操作按钮 + 实时日志流 - 通过 Wails `EventsOn` 订阅 `pi:install:log` / `pi:install:done` 拿到 npm 子进程实时输出 - `Start` 成功后自动调 `WindowMinimise` 收进 Dock --- ## 与 dsh-launcher 的差异 | 项 | dsh-launcher | pi-launcher | |---|---|---| | 目标 CLI | `@deepseek-ai/dsh` | `@agegr/pi-web` | | 命令名 | `dsh` | `pi-web` | | 凭据目录 | `~/.dsh/.credentials.yaml` | `~/.pi/.credentials.yaml`(待确认) | | 端口 | 3080 | 30141 | | 进程匹配 | `dsh/lib/bin.js` / `dsh-pet` | `pi-web` 相关进程(待定) | | 安装包名 | `@deepseek-ai/dsh` | `@agegr/pi-web` | | 启动 URL | `http://127.0.0.1:3080/` | `http://localhost:30141/` | | 图标 | `build/appicon.png` | 同位置替换 | 迁移思路:把 `app.go` 里所有 `dsh` 字面量改成 `pi`、`dshPkg` 常量改成 `@agegr/pi-web`、`HomeDshDir` 改成 `HomePiDir`(`~/.pi`),端口 `3080` 改成 `30141`,再换图标即可。 --- ## 自检模式(调试用) 不启 GUI,直接调后端走完流程: ```bash ./build/bin/pi-launcher --selftest ``` 会打印:`nodeOK` / `piPath` / `piVer` / `cred` / `portBusy` / 进程列表 / `waitForPort` 测试结果。 --- ## 已知问题 - **Windows 图标闪烁**:首次安装 Windows 版后任务栏图标可能延迟更新,等几秒或重新 pin。 - **macOS Dock 图标缓存**:`scripts/install-app.sh` 已处理 `lsregister -f` + Dock 重启,通常一次就好。 - **端口 30141 被占**:启动器会自动 `kill -9` 残留 PID,但如果你跑别的服务也用 30141 会被误杀——届时改 `waitForPort` / `freePort` 的端口号。 --- ## License 个人项目,MIT。