dsh-desktop
Minimal Electron desktop shell embedding the official DeepSeek Harness web profile
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 16, 2026
- Updated
- Aug 22, 2026
Introduction
dsh-desktop
基于官方 DeepSeek Harness 构建的最小 Electron 桌面壳:在 Electron 主进程内启动官方 web profile,把浏览器界面装进一个沙箱化的原生窗口,并提供托盘、单实例、有序退出、驻留开关与安装包构建。
它不是 Harness 的替代品,也不 fork 上游源码。智能体、模型、工具、会话和 Web UI 全部来自官方 @deepseek-ai/dsh-* 包;本仓库只负责「窗口 + 托盘 + 进程生命周期 + 一个极窄的启动适配面」。
设计原则
- 极窄兼容面:整个仓库只有
src/boot.ts一个文件 import 官方包。上游破坏性变更首先、也只在该文件里体现。 - 精确锁版本:上游各包独立发布且
latestdist-tag 陈旧,因此所有@deepseek-ai/*依赖都精确 pin 到0.1.0-rc.6,不写^。升级 = 显式改版本 + 重跑check。 - 轻量:不内置插件市场/自动更新器;v1 只有窗口、托盘、单实例、loopback-only、安全导航锁与打包。
- 安全优先:渲染进程
sandbox+contextIsolation、无 Node 集成、无 preload/IPC 桥、导航锁同源、外链白名单协议、webserver 强制127.0.0.1:0。
架构
flowchart LR
subgraph EL["Electron 主进程"]
M["main.ts<br/>单实例 · fail-loud · 有序退出"]
B["boot.ts(唯一兼容面)<br/>boot() + provideCmdline() + 注入 agent-presets root"]
D["desktop.ts<br/>沙箱窗口 + 托盘 + 导航锁 + 驻留开关"]
end
subgraph HOST["官方 DSH 插件树(web profile)"]
W["dsh-base + dsh-web-app<br/>webserver / agent / tool / session / 前端 dist"]
P["agent-presets<br/>standard / code / cordis / minimal(来自 dsh 包)"]
end
R["沙箱 renderer<br/>官方 Web UI"]
M --> B --> HOST --> W
B --> P
M --> D --> R
W <-->|"loopback HTTP + WebSocket (127.0.0.1:0)"| R
详见 docs/architecture.md 与 docs/compatibility.md。
快速开始
npm install # 安装依赖(会下载 Electron 二进制)
npm run dev # 编译并启动 Electron
首次运行会在
~/.dsh/profiles/web/初始化官方 web profile(与dsh --profile web一致)。 实际对话需要DEEPSEEK_API_KEY(可放在~/.dsh/.env,与官方一致)。 模型选择、命令菜单、Agent 预设都来自@deepseek-ai/dsh包自带的config/agent-presets,已随依赖自动安装。
驻留开关
关闭窗口时的行为由环境变量控制,默认关闭即退出(最不容易误解):
DSH_DESKTOP_MINIMIZE_TO_TRAY=1 npm run dev # 关闭窗口 → 隐藏到托盘,托盘「Quit」才退出
| 值 | 行为 |
|---|---|
未设置 / 0 / false | 关闭窗口 = 退出应用 |
1 / true / yes / on | 关闭窗口 = 隐藏到托盘(驻留) |
打包
打包依赖 electron-builder(已列入 devDependencies)。打包前需要完整的 npm install(不要 --ignore-scripts,Electron 二进制与原生模块需要脚本完成)。
npm run package:dir # 目录版(调试用,输出 dist/)
npm run dist:win # Windows NSIS 安装包(x64,可自选安装目录)
npm run dist:win:local # 推荐:自动处理「用户名带撇号」等本机坑的封装(见下)
npm run dist:mac # macOS DMG
- 图标:Windows 安装包/EXE 使用
build/app-icon.png(官方蓝鲸图标,256×256)。它由build/app-icon.ico经npm run gen:icon放大生成——原始.ico最大只有 225×225,而 electron-builder 要求 ≥256×256。换源图标后重跑npm run gen:icon即可。 dist:win:local封装脚本(scripts/dist-win.mjs):①自动检测用户名里是否有撇号/引号,若有就把本次构建的 home 重定向到项目内的.dsh-build-home/(已 gitignore,绕过 MSB4100,不污染项目外路径);②默认走https://npmmirror.com/mirrors/electron/镜像下载 Electron zip(国内到 GitHub 常超时ETIMEDOUT),如需自定义镜像设ELECTRON_MIRROR即可。- 打包产物在
dist/。macOS 目标当前未配.icns图标,会回退到默认图标;如需要可补一个 512×512 的build/app-icon.png并设置mac.icon。
体积为什么大(正常现象)
安装包约 120–150 MB(解包后 500+ MB),主要构成:
- Electron 运行时本身(~200 MB)+ node-pty/koffi 等原生模块。
- 完整的 DeepSeek Harness(~195 个
@deepseek-ai/*包):agent 循环、LLM 适配器、工具、会话持久化、沙箱、subprocess、终端,以及官方 Web 前端(dsh-web-frontend的构建产物 + 全部ui-*客户端插件)。 - 附带各包的
.map/.d.ts文件(未做体积裁剪)。
这与社区桌面版(安装包 141 MB)是同一量级——本质是「把整个 Harness + 浏览器 UI + Electron 一起装进安装包」。若后续要瘦身,可优先排除 .map/.d.ts、裁剪用不到的 CLI 依赖。
依赖闭包:为什么把 195 个包显式列出来
Harness 大量用 peerDependencies(cordis、cordis-plugin-*、dsh-invariants 等都是 peer)。npm 会装这些 peer,但 electron-builder 只打包 dependencies 闭包、丢弃 peer-only 的包,导致安装后启动报 ERR_MODULE_NOT_FOUND: Cannot find package '@deepseek-ai/cordis-plugin-group'。
解决:把 node_modules 里全部 @deepseek-ai/* 包显式列入 dependencies(scripts/gen-deps.mjs 自动生成)。升级 Harness 版本后重跑 npm run gen:deps 即可同步。
客户端插件为什么必须 asarUnpack
浏览器端的插件(ui-*、client-runtime 等)不是直接 require,而是宿主通过 ~/.dsh/profiles/node_modules 里的符号链接(healProfilesModuleFallback 创建)解析、再走 /plugins/<id>/client.js 下发。若 node_modules 被封进 app.asar,符号链接就会指向 app.asar/node_modules/... 这种虚拟路径(Windows junction 指向它是死链接),客户端插件被静默跳过,界面报 dsh-client-app-shell: pending (slots, sessions, layout)。
解决:build.asarUnpack 把 package.json + node_modules/** 解包成真实文件,src/paths.ts 的 unpackedAsarPath() 把 app.asar/... 映射到 app.asar.unpacked/...,让符号链接指向真实目录。这不会额外增肥(asar 本就不压缩,解包前后体积一样)。
Windows 打包前置:Visual Studio Build Tools(必须)
Harness 含原生 C++ 模块 node-pty(Shell/PTY 执行的后端,依赖链 dsh-base → dsh-subprocess-local → node-pty)。它自带 Node 平台的预编译二进制,但没有 Electron 43 对应 ABI 的预编译产物,所以 electron-builder 的 @electron/rebuild 会回退到 node-gyp 源码编译。若本机没有 MSVC,就会报:
⨯ Error: Could not find any Visual Studio installation to use
⨯ node-gyp failed to rebuild '...\node_modules\node-pty'
解决:安装 Visual Studio 2022 Build Tools,勾选 「使用 C++ 的桌面开发」 工作负载(含 MSVC v143、Windows SDK、CMake),然后重跑打包:
- 下载:https://visualstudio.microsoft.com/zh-hans/downloads/#build-tools-for-visual-studio-2022
- 安装时勾选「使用 C++ 的桌面开发」。
- 重开终端,再执行
npm run dist:win。
安装 VS 后,electron-builder 会把 node-pty(以及 koffi 等其它原生模块)针对 Electron ABI 重新编译,打包即可完成。
为什么必须 MSVC:
node-gyp在 Windows 上只认 MSVC(cl.exe)。Dev-C++ 的 MinGW(gcc)、VS Code(纯编辑器)都无法替代。node-pty 只为 Node 提供预编译二进制、不为 Electron 提供,所以任何 Electron 版本都需现场编译,绕不开 MSVC。C 盘没空间:用精简的
vs_BuildTools.exe(不是完整 VS),在「安装位置」页把 Build Tools 与下载缓存改到 D 盘,主体(MSVC + Windows SDK,几个 GB)就落在 D 盘;C 盘只留少量不可移动的共享组件。勾选工作负载后还可在「安装详细信息」里去掉用不到的组件以缩小体积。Windows 用户名含撇号(如
sh'y)会触发另一个错:@electron/rebuild把 Electron 头文件缓存放到了C:\Users\sh'y\.electron-gyp\,这个带撇号的路径会被嵌入 MSBuild 表达式,报MSB4100 ... 应为布尔值而不是 ...。直接用npm run dist:win:local即可自动把 home 重定向到项目内的.dsh-build-home/,无需手动设环境变量。
MSB8040: 此项目需要缓解了 Spectre 漏洞的库:node-pty 的 winpty 构建开启了 Spectre 缓解,需要额外安装「Spectre 缓解库」组件(默认 C++ 工作负载不含它)。VS Installer →「修改」→「单个组件」→ 搜Spectre→ 勾选MSVC ... x64/x86 Spectre-mitigated libs(winpty 用到 ATL,如有C++ ATL ... Spectre Mitigations也一并勾选)→「修改」。该组件同样落在 Build Tools 的安装盘,不占 C 盘。另:npm 11.17 的
allow-scripts会默认拦截安装脚本(npm warn allow-scripts ... node-pty ...)。这不影响开发运行(node-pty 自带 Node 预编译二进制),也不影响上面的打包流程(electron-builder 会自行 rebuild),无需额外批准。
校验
npm run check # build + typecheck + 单元测试
npm run typecheck
npm test # 纯逻辑单元测试(不依赖 Electron 运行时)
目录结构
build/
app-icon.ico 官方蓝鲸图标(窗口 / 托盘 / EXE 共用)
src/
main.ts Electron 入口:进程生命周期编排
boot.ts 兼容面:唯一 import 官方包的地方(注入 agent-presets root)
desktop.ts 窗口/托盘/导航锁/驻留开关的 Electron 适配
window.ts BrowserWindow 安全配置(纯函数,可测)
tray.ts 托盘(加载官方图标并缩放)
shutdown.ts 幂等、有界的有序退出
loopback.ts loopback URL + webServer.port 结构读取(纯函数)
policy.ts 导航/外链安全策略(纯函数)
patches.ts profile patch 层组合 + agent-presets 注入(纯函数)
config.ts 启动配置解析(驻留开关,纯函数)
paths.ts asar→unpacked 路径映射(纯函数,可测)
tests/ 上述纯逻辑的单元测试
docs/ 架构与兼容性契约
扩展点
- 改窗口/托盘行为:
src/desktop.ts、src/window.ts、src/tray.ts,纯 Electron,不碰兼容面。 - 换图标:替换
build/app-icon.ico即可(窗口、托盘、EXE 三处共用)。 - 给 Harness 加插件:编辑
~/.dsh/profiles/web/cordis.patch.yml(官方 patch 层,本壳不拦截)。 - 升级 Harness:改
package.json里@deepseek-ai/*的精确版本,跑npm run check。变更若落在src/boot.ts使用的 API 上,见 docs/compatibility.md。
与社区桌面版的关系
本仓库参考了 anywhere-labs/deepseek-harness-desktop 的「薄 Electron 宿主」思路,但刻意缩小范围:去掉插件市场、pnpm 管理、自动更新、profile 切换器等,只保留桌面体验的最小闭环,从而把安全面与维护面都压到最低。
License
MIT