Back to home@wangxilhy23

dsh-wx-desktop

deepseek harness 桌面端插件

Stars
0
Language
JavaScript
Created
Aug 19, 2026
Updated
Aug 19, 2026
GitHub repo

Introduction

dsh-wx-desktop — DeepSeek Harness 桌面端

把 DeepSeek Harness 装进一个原生桌面窗口:独立 Electron 应用,自包含 dsh 运行时——无需目标机器安装 Node、无需 dev checkout、无需全局 dsh。启动时自动拉起 dsh(复用你已配置的 web profile,因此已安装的全部插件——vision-toolkit、ModLens、dsh-wx-skin 等——开箱即用),并在原生窗口中渲染完整 Web GUI。

工程同时以 DSH 插件 形态存在:可挂载到 web profile,在浏览器 GUI 的侧栏增加「桌面端」入口,一键拉起桌面应用。

特性

  • 完全自包含:打包内置完整 @deepseek-ai/dsh 运行时(runtime/dsh-runtime/),用 Electron 内嵌 NodeELECTRON_RUN_AS_NODE + --expose-internals)运行——没有 Node 的机器也能启动
  • 复用已运行 dsh 安装,杜绝 junction 冲突:桌面端启动时先探测 $DSH_HOME/profiles/node_modules 的 junction 已被哪个 dsh 安装占用(例如正在运行的 web 端 dev checkout)。若已被占用,则复用同一个安装resolveActiveDshInstall),避免两个不同版本的 dsh 互相抢占同一组 junction 导致 EPERM 崩溃;同时保证桌面端与 web 端加载完全相同的 profile 与插件。仅在没有其他 dsh 在运行时才回退到内置自包含 runtime。
  • 内嵌启动 dshdsh web --port 0,OS 自动分配端口,与已有 127.0.0.1:3080 服务互不冲突。
  • 100% 插件兼容:加载的是完整 dsh web GUI——host 插件在 dsh 进程内照常运行,client 插件(dsh.client 包)经 window.__DSH_BOOT__ 图照常加载。零改动。
  • 原生窗口体验:应用菜单、窗口尺寸记忆由 OS 接管;锁定的 WebContents(contextIsolation + sandbox),外部链接走系统浏览器。
  • 单实例:二次启动聚焦已有窗口。
  • 优雅关闭:关窗 → dsh 子进程 SIGTERM → 超时强杀,不留残留进程;启动失败自动终止子进程(无孤儿)。
  • 自定义品牌图标:内置 DeepSeek 蓝色系鲸鱼图标(build/icon.ico / build/icon.png),用于安装程序、桌面快捷方式与任务栏。

快速开始(开发)

npm install                  # 安装 electron / electron-builder / tsdown / typescript
npm run install:dsh-runtime  # 安装自包含 dsh 运行时(runtime/dsh-runtime/,约 220MB)
npm run dev                  # 构建 host+client 并启动桌面端

桌面端会按以下顺序定位 dsh 运行时(src/electron/main.mjs 内实现):

  1. 环境变量 DSH_DESKTOP_DSH(显式覆盖,可指向 bin.js、dsh 仓库目录,或 PATH 上的 dsh 命令)
  2. 已活跃的 dsh 安装:读取 $DSH_HOME/profiles/node_modules/@deepseek-ai/dsh junction 目标。若该 junction 正被另一个 dsh 安装(例如正在运行的 web 端 dev checkout)占用,则复用那个安装——共享同一组 junction,避免 EPERM 冲突,并加载与 web 端一致的 profile(resolveActiveDshInstall
  3. 自包含运行时runtime/dsh-runtime/(开发)或 resources/dsh-runtime/(打包)——用 Electron 内嵌 Node 运行,无需系统 Node(无其他活跃安装时使用)
  4. dev checkout 预构建 CLI D:\deepseek-harness\apps\cli\lib\bin.js(开发者便利,需要系统 node)
  5. dev checkout 源码模式 / 任意 dsh 命令(PATH)

无需 Node:自包含路径用 Electron 内嵌 Node(process.execPath + ELECTRON_RUN_AS_NODE=1 + --expose-internals)运行预构建的 dsh lib/bin.js——目标机器不必安装 Node.js,也不需要 dev checkout。DSH_DESKTOP_NODE 可显式指定系统 node(仅开发回退用)。

启动超时:默认 180s(首次运行需初始化 profile);用 DSH_DESKTOP_BOOT_TIMEOUT_MS(毫秒)覆盖。启动失败时,dsh 子进程会被自动终止(不残留孤儿进程),错误对话框会显示 dsh 最近的 stdout/stderr 以便排查。

profile:默认复用用户 ~/.dsh(含全部已装插件与历史会话);若不存在,dsh 自动初始化默认 profile(基础 GUI)。可用 DSH_HOME 指向其他位置。

作为 DSH 插件挂载

工程带 cordis.patch.ymldsh.bundle.patch)与浏览器半(dsh.client),可安装进 web profile:

dsh plugin --profile web add link:E:\code\work\wxDshPlugin\dsh-wx-desktop
# 或从工程目录:
dsh plugin --profile web add link:.

挂载后刷新 http://127.0.0.1:3080,侧栏出现「桌面端」入口;点击会经 host 半的本地路由(POST /dsh-wx-desktop/open)拉起本机桌面应用。

桌面应用默认由 host 半通过系统 node + 本包自带启动脚本拉起(零 PATH 配置);如需指向已打包的 exe,在 profile 的 cordis.patch.yml 中给该行加配置:

- id: ui-dsh-wx-desktop
  name: dsh-wx-desktop
  config:
    desktopCommand: "D:\\path\\to\\DeepSeek Harness Desktop.exe"

构建与打包

npm run build               # tsc (host 半) + tsdown (client bundle)
npm run install:dsh-runtime # 安装自包含 dsh 运行时(打包前置步骤)
npm run package             # install:dsh-runtime + 构建 + electron-builder → dist/
npm run typecheck           # host + client 两套 tsc --noEmit

打包产物(dist/ 目录):

  • DeepSeek Harness Desktop-<version>-setup.exe —— NSIS 安装程序(双击安装,含桌面快捷方式)
  • win-unpacked/ —— 免安装的解压即用目录

说明:打包时 electron-builder.ymlextraMetadata.main: src/electron/main.mjs 覆盖 Electron 入口(package.json 的 main 仍是 DSH 插件半 lib/index.js,两者互不干扰);extraResourcesruntime/dsh-runtime/ 装进 resources/dsh-runtime/。二进制下载走 npmmirror 镜像,可被 ELECTRON_MIRROR / ELECTRON_BUILDER_BINARIES_MIRROR 覆盖。runtime/ 不入 git(220MB,可随时用脚本重建)。

工程结构

src/
  index.ts            host 半:注册 /dsh-wx-desktop/open 路由(回环源校验,spawn 桌面端)
  client/index.ts     浏览器半:侧栏「桌面端」入口 + 启动状态(纯 DOM,自愈挂载)
  electron/main.mjs   Electron 主进程:解析 dsh、spawn、端口解析、窗口、生命周期
build/
  icon.ico            应用图标(安装程序 / 快捷方式 / 任务栏,DeepSeek 蓝色系鲸鱼)
  icon.png            图标源 PNG(256px)
runtime/dsh-runtime/  自包含 @deepseek-ai/dsh 运行时(打包用,不入 git)
cordis.patch.yml      挂载插件行(dsh.bundle.patch)
scripts/dev.mjs       开发运行器:build → electron
scripts/package.mjs   electron-builder 打包
scripts/install-dsh-runtime.mjs  安装自包含运行时(幂等)

与 web 端同时运行(junction 处理)

桌面端与 web 端共用同一 $DSH_HOME。dsh 启动时会维护 $DSH_HOME/profiles/node_modules 下的扁平依赖 junction,并让它们指向当前运行中的 dsh 安装的依赖闭包。若两个不同版本的 dsh(如桌面端内置 runtime 与 web 端 dev checkout)同时启动,后启动的一方会尝试 unlink 前一方正占用的 junction,在 Windows 上报 EPERM 而启动失败。

resolveActiveDshInstall() 通过读取 @deepseek-ai/dsh junction 的目标来识别当前活跃的 dsh 安装;若已有一个活跃安装,桌面端就复用同一个(而不是启动自己的内置 runtime)。这样:

  • junction 指向一致,healProfilesModuleFallback 变成 no-op,不再互相抢占
  • 桌面端加载的 profile / 插件与 web 端完全一致(ModLens、vision-toolkit 等全部可见)
  • 只有没有其他 dsh 在运行时,才回退到内置自包含 runtime(保持"无 Node 也能启动"的自包含设计)

常见问题

  • 桌面端启动弹 "Error launching CrashSender.exe" / 0x80000003:通常是 dsh 启动阶段因 junction 冲突失败,或 Electron 无法在 userData 目录创建 SingletonLock(多为运行环境权限受限)。先确认 web 端与桌面端是否共用同一 $DSH_HOME(本工程已通过复用活跃安装规避);若是权限问题,检查 %APPDATA%\dsh-wx-desktop 目录可写。
  • 桌面端插件列表没有 ModLens:确认 $DSH_HOME/profiles/web/node_modules/@liustack/modlens 已安装,且桌面端与 web 端使用同一个 profile(本工程默认如此)。

说明与后续演进

  • 当前采用「自包含内嵌 dsh + Electron 内嵌 Node + HTTP 加载」——这是本工程选择的稳妥落地路径。DSH 官方架构笔记(2026-07-19-gui-layering-and-rpc-protocol.md)预留了更深的形态:渲染进程用 file:// 加载 dist、fetch 经 IPC 桥(AbstractApiClientdoFetch 子类 + host 侧 toFetchHandler(api) 同构点)。那是后续演进方向,不需要改动 DSH 本体即可接入。
  • 安装包体积较大(自包含 dsh 运行时约 220MB):这是「无 Node 也能启动」的固有代价。如目标机器确定有 Node/dsh,可跳过 install:dsh-runtime 减小体积。