feat: add DSH Launcher desktop app intro article (Wails multi-platform launcher)
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
---
|
||||
title: DSH Launcher — 一个把 DeepSeek Harness 装进桌面 GUI 的启动器
|
||||
published: 2026-08-28
|
||||
updated: 2026-08-28
|
||||
description: 介绍 DSH Launcher,一个用 Wails v2 + Go + React 编写的跨平台桌面启动器(Windows / macOS / Linux),按「目录 + 版本」一键启动 DeepSeek Harness:实例管理、npm 版本查询、实时日志、插件市场,推 tag 自动构建发布三端安装包。
|
||||
image: /posts/dsh-launcher-intro/img/cover.svg
|
||||
tags: ['DSH', 'DeepSeek', 'Wails', 'Go', 'React', '桌面应用', 'CI/CD']
|
||||
difficulty: 入门
|
||||
---
|
||||
|
||||
## DSH Launcher 是什么
|
||||
|
||||
[DSH Launcher](https://github.com/wishesl/dsh-launcher) 是一个**跨平台桌面 GUI 启动器**(Windows / macOS / Linux),用来以「指定目录 + 指定版本」的方式启动 [DeepSeek Harness(DSH)](https://github.com/deepseek-ai/DeepSeek-Harness),并可视化地查询版本、管理实例、查看实时日志、安装插件。
|
||||
|
||||
DSH 的启动方式本质是一条 `npx -y @deepseek-ai/dsh@<版本> web` 命令(在某个工作目录里运行)。启动器把「选目录 + 选版本 + 启动/停止 + 看版本」封装成了开箱即用的图形界面。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 为什么做这个
|
||||
|
||||
写这个启动器主要为了解决两个真实的痛点:
|
||||
|
||||
1. **npx 会优先命中启动目录里的本地 `node_modules` 副本**——哪怕 npm 上已经发了新版,只要目录里有旧版,`npx @deepseek-ai/dsh web` 就永远跑旧版。想升级得先搞清楚"我到底在跑哪一份",非常容易记混。
|
||||
2. **版本查询 / 升级要敲一堆命令行**:`npm view @deepseek-ai/dsh versions`、`npx -y @deepseek-ai/dsh@latest web`……记不住,还容易敲错。
|
||||
|
||||
启动器的价值就一句话:**一个实例 = 一个目录 + 一个版本**,多个实例互不干扰,版本对照一目了然,再也不用手敲 npx 命令。
|
||||
|
||||
## 核心功能
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| **实例管理** | 每个实例绑定一个目录和一个版本;卡片式列表,状态指示灯区分 启动中 / 运行中 / 已停止 / 异常退出,支持一键 启动 / 停止 / 删除 / 打开网页 |
|
||||
| **版本查询** | 展示 npm `latest` / `next` dist-tag、全部版本历史与发布时间;本地实际版本通过读取目录 `node_modules/@deepseek-ai/dsh/package.json` 探测;官方 registry 优先,npmmirror 兜底 |
|
||||
| **实时日志** | 启动日志流式回显到右侧常驻面板,自动识别 Web 地址、区分崩溃与正常退出、清理孤儿进程 |
|
||||
| **插件市场** | 内置插件市场:发现 / 收藏 / 安装 / 卸载 DSH 插件,进度实时展示 |
|
||||
| **系统托盘** | 点 ✕ 默认最小化到托盘而非退出,DSH 继续后台运行;托盘菜单可启动/停止各实例 |
|
||||
| **单实例** | 重复启动 exe 只会把已运行实例的窗口唤回前台,不会开第二个窗口 |
|
||||
| **自动发布** | 推 `v*` 标签即触发 GitHub Actions 构建三端产物并发布 Release |
|
||||
|
||||
## 两个有意思的设计
|
||||
|
||||
### 1. 服务态与进程态分离
|
||||
|
||||
最初版本里,「顶部显示 DSH 已就绪 / 打开按钮」完全依赖启动器自己管理的进程状态:进程输出里正则抓 URL → TCP 探测 → 标记 ready。这套逻辑有个隐患——一旦进程管理状态和真实情况脱节(比如快速停止/重启时的竞态、冷启动时持久化状态泄漏),顶部就永远显示"运行中"却没有打开按钮。
|
||||
|
||||
后来把它拆成了**两套互不影响的独立状态**:
|
||||
|
||||
| 状态 | 判定依据 | 驱动什么 |
|
||||
|------|----------|----------|
|
||||
| **服务态**(dsh 已启动) | 配置端口能正常访问 DSH 服务(后端 HTTP 探测,2s 兜底轮询 + 启停/保存/删除即时重查) | 顶部「已就绪」+ 打开按钮 |
|
||||
| **进程态**(启动器在管理) | 启动器自己 spawn / kill 的进程生命周期 | 实例卡片的 启动 / 停止 按钮 |
|
||||
|
||||
好处:只要端口真的在服务,顶部就能打开——哪怕进程是被外部方式拉起来的;进程管理状态怎么折腾都不影响"能不能打开"。
|
||||
|
||||
### 2. 跨平台的进程管理抽象层
|
||||
|
||||
Wails v2 框架本身支持三端,但项目真正跨平台需要处理**进程树管理**这个平台差异最大的部分。抽象成了 `procattr_windows.go` / `procattr_unix.go` 两个文件:
|
||||
|
||||
| 能力 | Windows | macOS / Linux |
|
||||
|------|---------|----------------|
|
||||
| 启动 shell | `cmd /c`(解析 `.cmd` shim) | `sh -c` |
|
||||
| 子进程属性 | `HideWindow`(不闪控制台) | `Setsid`(独立会话/进程组) |
|
||||
| 进程树终止 | Job Object + `taskkill /T /F` | `kill(-pgid)` 组杀树 |
|
||||
|
||||
`dsh_process.go`、`install.go`、`market_ops.go`、`env.go` 全部改走统一的 `shellCommand()` / `killProcessTree()`,不再有散落的平台代码。
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 层 | 技术 |
|
||||
|----|------|
|
||||
| 桌面壳 / 后端 | **Wails v2.15.0** + **Go 1.25**(Windows / macOS / Linux 三端) |
|
||||
| 前端 | **React 18** + **TypeScript** + **Vite 3** |
|
||||
| 系统托盘 | `fyne.io/systray`(独立 goroutine 跑消息循环,三端通用) |
|
||||
| 单实例 | Wails `options.SingleInstanceLock` |
|
||||
| CI / 发布 | GitHub Actions:三平台矩阵自动构建 + Releases |
|
||||
|
||||
## 多平台发布踩过的坑
|
||||
|
||||
自动化发布([workflow](https://github.com/wishesl/dsh-launcher/blob/master/.github/workflows/release.yml))流程是:**推 `v*` 标签 → 三平台并行构建 → 统一发 Release**。过程中踩了几个典型坑:
|
||||
|
||||
1. **Ubuntu 24.04 移除了 webkit2gtk-4.0**:Wails v2.10.2 默认仍要 4.0,24.04 只有 4.1。解法是升级 Wails 到 **v2.15.0**,构建时加 `-tags webkit2_41`,并补装 `libsoup-3.0-dev`。
|
||||
2. **`macos-13`(Intel runner)已被 GitHub 下线**:macOS x64 产物改为在 arm64 runner 上用 `GOARCH=amd64` 交叉编译(Xcode 通用工具链原生支持)。
|
||||
3. **Go 版本水涨船高**:Wails v2.15 要求 Go 1.25,CI 的 `setup-go` 也要跟着升。
|
||||
|
||||
## 快速上手
|
||||
|
||||
```bash
|
||||
# 下载对应平台安装包(Releases 页)或自行构建
|
||||
git clone https://github.com/wishesl/dsh-launcher.git
|
||||
cd dsh-launcher
|
||||
wails build # Windows / macOS
|
||||
wails build -tags webkit2_41 # Linux(需 webkit2gtk-4.1 系统依赖)
|
||||
```
|
||||
|
||||
打开应用后:
|
||||
|
||||
1. 左侧「实例」→「+ 添加实例」→ 选择 DSH 启动目录 → 选版本 → 启动方式选**本地副本**(官方推荐)→ 保存;
|
||||
2. 卡片点「启动」,右侧日志面板自动弹出并实时滚动;
|
||||
3. 顶部出现「DSH 已就绪 · 名称 · 地址」后点它即可在浏览器打开 DSH web;
|
||||
4. 提示「本地副本未安装」时先点「安装到目录」,把该版本真实装进目录的 `node_modules`。
|
||||
|
||||
## 开源信息
|
||||
|
||||
- GitHub:[wishesl/dsh-launcher](https://github.com/wishesl/dsh-launcher)
|
||||
- Releases(三平台安装包):<https://github.com/wishesl/dsh-launcher/releases>
|
||||
- 技术选型参考:DSH 本质是 `npx @deepseek-ai/dsh@<版本> web` 跑在选定目录里,多实例互不干扰;一个目录对应一个版本,别混着用。
|
||||
|
||||
欢迎 Star、提 Issue,或者直接来提功能需求 🙂
|
||||
Reference in New Issue
Block a user