← 返回列表
需源码安装
基于官方 Deepseek Harness 打包的桌面客户端,方便直接安装使用
暂不能直接安装(需源码编译或环境不满足):仓库 package.json 标记 private,未发布到 npm,需从源码安装。 · 最近上游提交 2026/9/4 · 已提供中文文档
综合分
35
GitHub 分
35
用户评分
—
★ Stars
5
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add lijian-ui/dsh-desktop仓库 package.json 标记 private,未发布到 npm,需从源码安装,改用 GitHub 源安装
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查需源码安装
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-desktop @ 0.2.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖要求 0.1.1-rc.2 · 最新 ? 兼容
✓入口文件main/exports/bin 已声明
仓库 package.json 标记 private,未发布到 npm,需从源码安装
验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/18 12:13:01
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-group@deepseek-ai/cordis-plugin-hmr@deepseek-ai/cordis-plugin-include@deepseek-ai/cordis-plugin-loader@deepseek-ai/cordis-plugin-timer@deepseek-ai/dsh@deepseek-ai/dsh-agent@deepseek-ai/dsh-agent-default-model@deepseek-ai/dsh-agent-presets@deepseek-ai/dsh-anonymous-user-id@deepseek-ai/dsh-api-gateway用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-desktop(DeepSeek Harness 桌面端)
简体中文 | English
基于官方 npm 包 @deepseek-ai/dsh 的 Electron 桌面壳。方案 A 的核心思路:
Electron 主进程通过子进程启动官方 dsh web,再把其本地 HTTP 页面加载进窗口,
从而把官方 WebUI 包装成一个独立桌面应用。
原则:不引用、不改动官方 dsh 任何源码,仅消费官方 npm 包,跟随其 npm update 升级。
架构概览
flowchart TB
subgraph Main["Electron 主进程(我们的代码,零原生模块)"]
Mgr["DshManagerspawn 官方 dsh + 端口解析崩溃自动重启"]
Win["BrowserWindow加载 http://127.0.0.1:port"]
Tray["系统托盘显示窗口 / 重启 / 退出"]
Menu["中文菜单栏重启 / 关于 / 退出"]
end
subgraph Child["官方 dsh 子进程(系统 Node 运行)"]
Cli["@deepseek-ai/dsh CLIdsh web --host 127.0.0.1 --port 0"]
Http["HTTP 服务 + Agent 核心+ 前端静态资源"]
end
Mgr -- "spawn(系统 Node,承担原生模块 / Node 版本)" --> Cli
Cli -- "stdout 解析端口" --> Mgr
Cli --> Http
Mgr -- "端口就绪" --> Win
Win -- "关闭 → 隐藏到托盘" --> Tray
Tray -- "显示主窗口" --> Win
Menu -- "重启 dsh 服务" --> Mgr
- 官方主包只暴露 CLI,没有可 import 的运行时 API,因此采用进程外 spawn。
- 原生模块(node-pty / koffi)与 Node 版本要求全部由系统 Node 跑的官方子进程承担,
Electron 侧无需 electron-rebuild,无 ABI 负担。
- 打包版:dsh 及其全部依赖由 asarUnpack 解包到真实文件系统,主进程用
「系统 Node 绝对路径 + dsh/lib/bin.js」启动子进程(见「打包版如何找到系统 Node」)。
- 后续若官方发布 embed/SDK,可演进到方案 B(file:// + IPC 桥接),前端代码无需改动。
环境要求
| 依赖 | 版本要求 | 说明 |
|------|----------|------|
| 系统 Node.js | ^22.19.0 \|\| >=24.0.0 | dsh 官方的硬性要求,由子进程使用 |
| npm | 随 Node 自带 | 用于安装依赖 |
| Electron | ^43.0.0(开发依赖) | 仅负责窗口与显示 |
注意:Electron 内置的 Node 版本不满足 dsh 要求,但无所谓——
dsh 跑在独立的系统 Node 子进程里,Electron 只负责显示页面。
打包版如何找到 Node 运行时
v0.2.0 起内置精简 Node 运行时(resources/node-runtime/),打包版无需用户预装 Node,
开箱即用。桌面端按以下顺序解析 Node 可执行文件:
1. 内置 Node 运行时(打包版自带,优先)——resources/node-runtime/node.exe(Win)或 bin/node(macOS)
2. config.json 显式配置 nodePath(自定义时用)——例如 macOS:
{ "nodePath": "/usr/local/bin/node" }
3. 自动探测(nvm → Homebrew → 官方路径),且每个候选都会做版本校验
(dsh 要求 ^22.19 || >=24),不满足的旧版(如系统 v18)自动跳过
内置 Node 由 scripts/fetch-node.cjs 从 node/ 官方发行包精简生成到 vendor/,
打包时经 electron-builder.yml 的 extraResources 打进安装包。
开发模式(npm run dev)无内置目录,走 2/3 步探测。
若探测失败且未配置,启动会报错提示。打包版同时要求 dsh 及其全部依赖
被 asarUnpack 解包(electron-builder.yml 已配置 /node_modules/),
因为系统 Node 无法读取 asar 压缩包内的文件。
安装与运行
进入项目目录
cd electron-app
安装依赖(会同时装上官方 @deepseek-ai/dsh 与 Electron)
npm install
开发模式:先编译 TypeScript,再启动 Electron
npm run dev
或分两步
npm run build # 编译 src -> dist
npm start # 启动 electron .
首次启动会:
1. 主进程 spawn 官方 dsh web --host 127.0.0.1 --port 0;
2. 从子进程 stdout 解析实际端口(系统自动分配,避免冲突);
3. 创建窗口加载 http://127.0.0.1:,看到的就是官方 WebUI。
macOS 未签名应用安装说明
当前版本未做 Apple 开发者签名与公证,首次安装/启动时 macOS Gatekeeper
会拦截,常见报错与解决方法如下:
| 报错提示 | 原因 | 解决方法 |
|----------|------|----------|
| 「无法验证开发者」/「Apple 无法检查其是否包含恶意软件」 | Gatekeeper 拦截未签名应用 | 右键应用图标 → 选择「打开」→ 弹窗中再点「打开」(仅首次,之后可直接双击) |
| 「已损坏,无法打开。您应该将它移到废纸篓」 | 下载文件被加了隔离标记(quarantine) | 终端执行 xattr -dr com.apple.quarantine "/Applications/DeepSeek Harness 桌面端.app" |
| 「打不开,因为来自身份不明的开发者」 | 同上 | 系统设置 → 隐私与安全性 → 点击「仍要打开」 |
以上均只需在首次处理一次;应用本体功能不受影响,仅跳过 Gatekeeper 检查。
说明:未签名应用在部分系统设置下可能仍提示,此时请检查「系统设置 → 隐私与安全性 → 安全性」,
确认「允许从以下位置下载的应用」中选择了「App Store 和被认可的开发者」之外的选项。
配置
API Key
推荐用环境变量注入(最安全,不写入文件):
export DEEPSEEK_API_KEY="你的密钥"
npm run dev
或在项目根创建 config.json(已被 .gitignore 忽略,切勿提交):
{
"apiKey": "你的密钥",
"host": "127.0.0.1",
"port": 0,
"extraArgs": []
}
配置优先级:环境变量 > config.json > 内置默认。
其他参数
- host:监听地址,默认 127.0.0.1(仅本机,不暴露网络)。
- port:传 0 让系统分配空闲端口;也可固定(如 3080)。
- extraArgs:需要原样透传给 dsh web 的额外命令行参数数组。
- nodePath:系统 Node.js 绝对路径(打包版必须,见下文「打包版如何找到系统 Node」)。
config.json 的读取位置
桌面端按顺序查找 config.json,找到即用、不合并:
| 场景 | 路径 |
|------|------|
| 开发模式(npm run dev) | 项目根:electron-app/config.json |
| 打包版 Windows | %APPDATA%\dsh-desktop\config.json,即 C:\Users\\AppData\Roaming\dsh-desktop\config.json |
| 打包版 macOS | ~/Library/Application Support/dsh-desktop/config.json |
目录名取 Electron 的 app.getName()(打包后为 package.json 的 name 字段,即 dsh-desktop;
注意不是 productName「DeepSeek Harness 桌面端」——该值只配在 electron-builder.yml,
不会进入打包后 app.asar 的 package.json),文件不存在时忽略,全部走默认值/环境变量。
目录结构
electron-app/
├── package.json # 依赖与脚本(含官方 @deepseek-ai/dsh、electron-builder)
├── tsconfig.json # TypeScript 配置(CommonJS 输出到 dist/)
├── electron-builder.yml # 打包配置(重点:npmRebuild:false + asarUnpack 原生模块)
├── .npmrc # 国内镜像源(npmmirror + Electron 二进制镜像)
├── .gitignore
├── README.md
├── scripts/
│ ├── build-native.cjs # 打包前置:物化 koffi 原生二进制(best-effort)
│ ├── generate-icon.cjs # 图标生成:官方 SVG → build/icon.ico / icon.png(依赖 sharp)
│ ├── publish-lib.mjs # 发布公共模块:产物扫描、版本解析、发布说明加载
│ └── publish-github.mjs # 发版脚本:gh CLI 创建 GitHub Release 并上传产物
└── src/
├── main/ # 主进程代码(Node)
│ ├── index.ts # 入口:生命周期、IPC、菜单/托盘串联、错误兜底
│ ├── dsh-process.ts # 核心:DshManager(spawn + 端口冲突重试 + 崩溃自动重启)
│ ├── window.ts # 创建 BrowserWindow、关闭→托盘拦截、加载失败兜底错误页、按端口重加载
│ ├── menu.ts # 中文应用菜单(文件/编辑/视图/窗口/帮助 + 重启/关于/退出)
│ ├── tray.ts # 系统托盘(显示窗口/重启 dsh/退出,关闭窗口后常驻入口)
│ ├── config.ts # 配置读取与 dsh 环境变量组装
│ └── log.ts # 统一日志工具
└── preload/ # 预加载脚本(方案 A 预留桌面集成接口)
└── index.ts # 暴露 window.dshDesktop(平台/版本/打开外部链接/重试)
健壮性设计
桌面端在「启动」与「存活」两个维度做了容错,避免白屏或静默崩溃:
| 场景 | 行为 |
|------|------|
| 端口冲突重试 | 若显式配置了固定端口且该端口被占用,自动顺延端口重试(最多 10 次)后再失败。默认 --port 0 由系统分配,不会冲突。 |
| 子进程崩溃自动重启 | dsh 子进程运行期间异常退出时,按指数退避(1s→2s→4s…)自动重启,最多 5 次;重启成功后窗口无缝刷新到新端口。 |
| 加载失败兜底 | 页面加载超时或 did-fail-load(如 dsh 崩溃)时,渲染中文错误页,提供「重新连接」按钮,点击即重启 dsh。 |
| 启动彻底失败 | 首次启动即失败且无窗口时,弹窗提示后退出;有窗口时展示错误页,而非白屏。 |
| 关闭 → 系统托盘 | 点窗口右上角 X(或 Cmd+W)不退出应用,隐藏到系统托盘常驻;托盘菜单「显示主窗口」/双击托盘图标恢复。托盘不可用(个别 Linux 桌面)时关闭窗口直接退出,避免窗口丢失。 |
| 主动退出 | 托盘或菜单「退出」显式结束应用;退出时按进程树 tree-kill,dsh 拉起的孙进程一并清理。 |
重试/重启入口有三处:菜单「文件 → 重启 dsh 服务」、错误页「重新连接」按钮、macOS Dock 重建。
窗口恢复入口有三处:托盘菜单/双击、macOS Dock 激活、二次启动实例聚焦。
打包与原生模块分发
生产分发使用 electron-builder。核心难点是原生模块(node-pty / koffi)随包正确分发,
我们的处理原则是「不让 Electron 重编译、只负责解包」:
1. npmRebuild: false(关键)
原生模块由系统 Node 运行的 dsh 子进程加载,绝不能让 electron-rebuild 把它们
编译成 Electron 内置 Node 的 ABI,否则子进程一加载就崩。配置见 electron-builder.yml。
2. asarUnpack 解包原生目录
Node 无法从 asar 压缩包内加载 .node / .dll / .exe,必须把
node_modules/node-pty/、node_modules/koffi/ 等解包到真实文件系统。
3. build:native 物化 koffi 二进制
koffi 不在 npm 包内附带预编译二进制(运行时自下载到临时目录)。scripts/build-native.cjs
在打包前主动把它物化进 node_modules/koffi/win32_x64/koffi.node,随包分发,
避免打包后首次运行依赖联网。该步骤失败不阻断打包(运行时仍可自下载)。
打包命令
开发调试用的免安装目录(验证打包结构)
npm run pack
Windows 安装包(NSIS .exe)
npm run build:electron:win
macOS 双架构(同时产出 x64 + arm64)
npm run build:electron:mac
其他平台 / 自定义参数:透传给 electron-builder
npm run build:electron -- --linux
build:electron 是主命令(build:native → tsc → electron-builder),
平台参数通过 -- 透传:Windows 用 --win,macOS 双架构用 --mac --x64 --arm64。
产物输出到 dist-electron/(已在 .gitignore 忽略)。
发布到 GitHub Release
1. 先打包(产出 dist-electron/ 下的安装包 + latest.yml / latest-mac.yml 更新元数据)
npm run build:electron:win
2. 发布(创建/更新 GitHub Release 并上传全部产物)
npm run release:github
- 前置:安装并登录 gh CLI(winget install --id GitHub.cli && gh auth login)。
- tag:自动取 package.json 的 version,生成 v{version}(如 v0.2.0)。
- 发布说明:默认文案;在项目根创建 RELEASE_NOTES.md 即可自定义(Markdown 全文作为 Release Notes)。
- 重复发布同版本:脚本检测到已存在的 release 时会更新说明并 --clobber 覆盖同名附件。
- 产物范围:dist-electron/ 顶层所有 .exe / .dmg / .AppImage / .deb / .zip / .yml / .blockmap(排除 builder- 调试文件)。
自动更新
v0.2.0 起内置 electron-updater,走 GitHub Release 通道:
- 打包时(publish 已配置 GitHub provider)生成 latest.yml(Windows)/ latest-mac.yml(macOS)
- 客户端启动 60 秒后自动检查,发现新版本自动下载,下载完弹窗「立即重启 / 稍后」
- 帮助菜单「检查更新」可手动触发;每小时定时检查
- 发布时务必保证 latest.yml + .zip(macOS 更新用 zip,不是 dmg)+ .blockmap 都上传,
否则对应平台无法增量更新(release:github 的产物范围已覆盖)
注意事项
- 自定义图标:官方 Harness 黑色鲸鱼图标已由 scripts/generate-icon.cjs 自动生成到
build/icon.ico(多尺寸)与 build/icon.png,无需手工维护。
- 国内镜像:.npmrc 已配置 npmmirror 与 Electron 二进制镜像,Electron 下载不受影响。
- 首次打包耗时:npm install 会下载 Electron 与官方 dsh 的原生依赖,建议使用国内源。
- dev-preview 风险:@deepseek-ai/dsh 处于 rc 阶段,版本升级可能带来破坏性变更,
建议锁定版本并在升级后回归测试(端口解析正则依赖其 stdout 格式)。
已知限制与后续演进
- 此方案不是终态:官方 webserver 注释已预留 file:// + IPC 的桌面形态。
待官方发布正式的 embed/SDK 后,可将传输层从 HTTP 替换为 IPC,前端代码无需改动。
- 端口:当前通过 loopback HTTP 通信,本机任意进程都能访问该端口。方案 B 可消除此面。
- dev-preview 风险:@deepseek-ai/dsh 处于 rc 阶段,版本升级可能带来破坏性变更,
建议锁定版本并在升级后回归测试(端口解析正则依赖其 stdout 格式)。扫码进群