Files
SuBlog/content/posts/dsh-launcher-intro/index.md
T

7.0 KiB
Raw Blame History

title, published, updated, description, image, tags, difficulty
title published updated description image tags difficulty
DSH Launcher — 一个把 DeepSeek Harness 装进桌面 GUI 的启动器 2026-08-28 2026-08-28 介绍 DSH Launcher,一个用 Wails v2 + Go + React 编写的跨平台桌面启动器(Windows / macOS / Linux),按「目录 + 版本」一键启动 DeepSeek Harness:实例管理、npm 版本查询、实时日志、插件市场,推 tag 自动构建发布三端安装包。 /posts/dsh-launcher-intro/img/cover.svg
DSH
DeepSeek
Wails
Go
React
桌面应用
CI/CD
入门

DSH Launcher 是什么

DSH Launcher 是一个跨平台桌面 GUI 启动器(Windows / macOS / Linux),用来以「指定目录 + 指定版本」的方式启动 DeepSeek Harness(DSH),并可视化地查询版本、管理实例、查看实时日志、安装插件。

DSH 的启动方式本质是一条 npx -y @deepseek-ai/dsh@<版本> web 命令(在某个工作目录里运行)。启动器把「选目录 + 选版本 + 启动/停止 + 看版本」封装成了开箱即用的图形界面。

DSH Launcher 主页

插件市场

为什么做这个

写这个启动器主要为了解决两个真实的痛点:

  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)流程是:推 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 也要跟着升。

快速上手

# 下载对应平台安装包(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。

开源信息

欢迎 Star、提 Issue,或者直接来提功能需求 🙂