dsh-desktop
DeepSeek Harness 桌面端 -- 从 Electron 迁移到 Tauri(Rust 壳 + Node Sidecar)架构
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 22, 2026
- Updated
- Aug 22, 2026
Introduction
DSH Desktop
DeepSeek Harness 桌面端 —— 从 Electron 43.4.0 迁移到 Tauri (Rust) + Node Sidecar 架构,已在当前仓库实现并端到端验证。官方 DeepSeek Harness 内核随仓库保持最新(当前
dsh-v0.1.1-rc.2)。
本仓库是原桌面项目(deepseek-harness-desktop)的 Tauri 迁移实现:Tauri Rust 壳负责托盘、窗口与原生能力,Node Sidecar 承载完整的 Cordis host(照搬自上游),前端零改动加载真实 DSH web 应用。
1. 架构
┌──────────────────────────────────────────────────────────────┐
│ Tauri Rust 壳 (src-tauri/) │
│ ─ 应用生命周期,spawn Node sidecar (stdio 管道) │
│ ─ sidecar.rs: JSON-RPC 消息循环 (stdout 读取 -> 分发 -> │
│ stdin 响应) + SIDECAR_STDIN 全局发送器 (Tauri -> sidecar) │
│ ─ tray.rs: 单托盘 (setup 预建, Mutex 菜单重建, 防竞态) │
│ ─ native.rs: 17+ 原生能力 (dialog/shell/notification/...) │
│ ─ recovery.rs / profile_create.rs + Tauri 命令 │
│ (recovery_restart/exit, profile_create_submit/cancel) │
│ ─ updater.rs (ureq 真实版本检查) │
└───────────────▲────────────────────────────────┬────────────┘
│ JSON-RPC over stdio │ 加载 URL
┌───────────────┴────────────────────────────────▼────────────┐
│ Node Sidecar (sidecar/, dsh-plugin-desktop@2.0.2) │
│ ─ lib/sidecar-main.js: 完整 Cordis host boot │
│ ─ 照搬上游源码 (路由/业务/契约/client/native-ui) │
│ ─ tauri-runtime-bridge.ts: DesktopRuntime 经 RPC 实现 │
│ ─ 去 Electron: pnpm/terminal/runtime-environment (Node ABI) │
└───────────────▲──────────────────────────────────────────────┘
│ HTTP (127.0.0.1:<port>)
┌───────────────┴──────────────────────────────────────────────┐
│ 前端 (真实 DSH web 应用, 零改动) │
│ ─ client.js 注入 (dsh.client.inject + ./client 导出) │
│ ─ 渲染健康上报 -> health gate commit -> 启动完成 │
└──────────────────────────────────────────────────────────────┘
2. 特性
- 装完即用:安装包捆绑 Node 二进制(v22)与部署好的依赖目录,无需预装任何运行时
- 托盘单实例:防竞态多图标;中文菜单(打开 DSH 终端 / 导出诊断信息 / 配置文件 / 检查更新)
- 无黑窗口:PE Subsystem=GUI +
CREATE_NO_WINDOW+ stderr 转日志 - 官方图标:应用图标与托盘图标均来自上游
dsh-plugin-desktop/build/(app-icon / tray-icon-blue) - DeepSeek Harness 内核最新:
deepseek-harnesssubmodule 锁定官方 master(b150a551=dsh-v0.1.1-rc.2),@deepseek-ai/*依赖从 npm 安装最新 rc 版本 - 启动恢复 / 新建配置文件 交互窗口(recovery.html / profile-create.html,经 Tauri 命令 -> JSON-RPC 通知 sidecar)
3. 验证证据(全部实测)
| 验证项 | 命令 | 结果 |
|---|---|---|
| 一键验收 | node sidecar/tests/verify.mjs | ✅ ACCEPTANCE PASSED (6 checks) |
| 完整 host boot | 隔离环境 node lib/sidecar-main.js | ✅ 托盘注册×4 + shellReady + renderer-timeout (standalone 预期) |
| 端到端 | 隔离环境运行 Tauri exe | ✅ [sidecar] host booted — 窗口加载真实 web 应用,健康上报,启动提交 |
| 生产布局 | exe 旁 sidecar/ 资源 + node_modules | ✅ host booted |
| 安装包 | cargo tauri build (NSIS) | ✅ 53.8MB(含 Node 二进制 + 部署依赖),安装后可直接运行 |
| 安装版启动 | silent install 后运行 exe | ✅ 窗口出现 + host booted + webserver 返回 <title>DeepSeek Harness</title> |
| 图标一致性 | 提取安装版 exe 图标逐像素对比 | ✅ 与上游 app-icon.png 一致 |
| Rust 编译 | cargo check | ✅ |
| 托盘单实例 | tray.rs (setup 预建 + Mutex 重建) | ✅ 无竞态多图标 |
| 无黑窗口 | PE Subsystem=2 (GUI) + CREATE_NO_WINDOW + stderr pipe | ✅ |
| 中文托盘 | LANG=zh_CN.UTF-8 | ✅ 打开 DSH 终端 / 导出诊断信息… / 配置文件 / 检查更新… |
4. 构建与运行
# Rust 壳
cd src-tauri && cargo build
# Sidecar(构建 + 一键验收)
cd sidecar
pnpm install --ignore-scripts # 依赖从 npm (0.1.1-rc.2);配置见 pnpm-workspace.yaml
pnpm exec tsdown # 构建 lib/ (43 文件 + client.js)
node tests/verify.mjs # 一键验收
# 端到端(隔离环境,避免与已运行的旧版冲突)
cd src-tauri
APPDATA=<temp> DSH_HOME=<temp> ./target/debug/dsh-desktop.exe
# 出安装包(含打包 runtime:node.exe + 部署依赖)
cargo tauri build
5. 关键实现备注
- DesktopRuntime 是唯一 seam:
index.ts零改动,实现从ElectronDesktopRuntime换成TauriRuntimeBridge(JSON-RPC 代理) - JSON-RPC over stdio 双向:sidecar→Tauri 请求/通知(stdout),Tauri→sidecar 响应(stdin)+ 非请求通知(
trayInvoke/recoveryChoice/profileCreateSubmit) - pnpm v11 项目配置只认
sidecar/pnpm-workspace.yaml(.npmrc无效):shamefullyHoist: true+minimumReleaseAgeExclude缺一不可 - sidecar 自身即
dsh-plugin-desktop:package.json 改名 +node_modules/dsh-plugin-desktop自链接 +dsh.client.inject+./client导出,profile Loader 才能把桌面插件解析到 sidecar 的 lib/ - 生产路径解析:
DSH_SIDECAR_PATH> exe 旁sidecar/> exe 旁resources/sidecar/> dev 布局 - tauri resources 打包陷阱:glob 模式(
**/*)会把目录结构平铺,node_modules必须用目录映射逐项复制(tauri.conf.json的bundle.resources) - 图标生成:
cargo tauri icon会把 .ico 32x32 帧转坏,用scripts/make-ico.mjs(sharp 逐帧重采样 + 手工组装 BMP 帧 ICO)生成与上游逐像素一致的图标
6. 目录结构
dsh-desktop/
├── src-tauri/ # Tauri Rust 壳
│ ├── icons/ # 官方图标 (app-icon / tray-icon)
│ ├── src/
│ │ ├── main.rs / lib.rs # 入口 + Builder + 插件
│ │ ├── sidecar.rs # Node sidecar 进程管理 + RPC 循环
│ │ ├── rpc.rs # JSON-RPC 2.0 消息类型
│ │ ├── native.rs # 原生能力分发器 (17+ 方法)
│ │ ├── tray.rs # 单托盘 (防竞态)
│ │ ├── recovery.rs # 启动恢复窗口
│ │ ├── profile_create.rs # 新建配置文件窗口
│ │ └── updater.rs # 更新器
│ └── tauri.conf.json # 窗口/打包/资源映射
├── sidecar/ # Node sidecar
│ ├── src/ # TS 源码 (rpc-protocol / tauri-runtime-bridge / sidecar-main ...)
│ ├── lib/ # tsdown 构建产物 (提交)
│ ├── runtime/ # 生产运行时 (node.exe + 部署依赖, gitignored)
│ ├── web/ # 前端 (index.html / recovery / profile-create)
│ └── tests/smoke.mjs / verify.mjs
├── deepseek-harness/ # 官方 submodule (dsh-v0.1.1-rc.2)
└── scripts/make-ico.mjs # ICO 生成脚本
7. 迁移阶段状态总览
| Phase | 任务 | 状态 |
|---|---|---|
| 0 | Tauri 脚手架 + 最小 sidecar + shellReady→窗口 | ✅ 验证 |
| 1 | Sidecar 移植 host boot | ✅ 实测 boot 完整 host |
| 2 | RPC 协议层(双向) | ✅ |
| 3 | 原生能力逐个接通 | ✅ 核心全实现 |
| 4 | 去 Electron 引导 | ✅ 源文件改造 |
| 5 | 启动恢复 + profile-create 窗口 | ✅ 交互闭环 |
| 6 | 更新器与打包 | ✅ NSIS + 资源打包 + 安装版装完即用 |
| 7 | 测试对齐 | ✅ verify.mjs 一键验收 |