Releases: luomious/deepseek-harness-desktop
Releases · luomious/deepseek-harness-desktop
Release list
v1.1.7 — dialog null 防御与更新检查健壮性
v1.1.7 — dialog null 防御与更新检查健壮性
Bug 修复
Bug 1(中):菜单"检查更新"缺 .catch() 保护
checkForUpdates(false)是 async 函数,菜单 click handler 中调用但未 catch- 如果内部抛出未预期异常,会变成 unhandled promise rejection
- 修复:添加
.catch(err => console.error(...))
Bug 2(中):dialog 调用缺少 mainWindow null 防御
- 所有
dialog.showMessageBox(mainWindow, ...)/dialog.showMessageBoxSync(mainWindow, ...)直接引用 mainWindow - 如果用户在更新检查期间关闭主窗口,mainWindow 为 null 可能导致异常
- 修复:checkForUpdates 和 performUpdate 内引入
const win = (mainWindow && !mainWindow.isDestroyed()) ? mainWindow : null局部变量 - 所有 dialog 调用改用
win,进度窗口 parent 改为undefined(Electron 允许无 parent) - 菜单"关于"同样修复
代码质量改进
pluginWin声明位置从 IPC 区移至openPluginManager函数前,消除前向引用preload.js末尾补换行符- 清理已删除的
logs/截图和release_notes_v113.md/release_notes_v114.md
测试
- v1.1.7 专项测试:15/15 通过
- v1.1.3 安全专项:41/43(2 个旧测试正则误报)
- v1.1.4 专项:12/12 通过
- v1.1.4 静态扫描:16/17(1 个 innerHTML 误报,有 esc 转义保护)
- isNewer:15/15 通过
- 启动回归:全部通过(启动/HTTP 200/8s 无崩溃/退出无孤儿进程)
文件
src/main.js:1531 行 / ~71KBsrc/preload.js:675 字节(8 白名单方法)app.asar:76457 字节
v1.1.6 — 修复、安全加固与插件管理增强
v1.1.6 修复、安全加固与插件管理增强
🐛 严重 Bug 修复
- 修复 src/main.js 加载即崩溃:commit 4ee96d7 在新增 zlib 导入时误将
const os = require('os')替换掉,导致os.homedir()抛 ReferenceError、应用无法从源码启动。已恢复 os 导入(commit 84e5ce3) - 修复打包产物与源码不一致:重新打包 app.asar,确保发布物包含 v1.1.5 全部修复(此前 asar 仍是 v1.1.4 时代代码,自动更新/版本获取等修复未进包)
✨ 插件管理增强
- 安装/卸载后列表自动刷新:新增
plugin:listIPC 与前端refreshInstalled(),安装或卸载插件后已安装列表即时更新,无需重启插件管理窗口(替代原先卸载后整页 reload) - 错误信息友好化:新增
friendlyPnpmError(),把 pnpm 原始英文输出(网络错误/权限不足/包不存在/依赖冲突/IGNORED_BUILDS 等)解析为可读的中文提示 - IGNORED_BUILDS 识别为部分成功:pnpm 10+ 安全策略拦截依赖构建脚本时(node-pty 等原生模块),包实际已安装,UI 现在标记为"安装成功 + 警告"而非"失败"
- 插件列表过滤核心依赖:
getInstalledPlugins()不再展示@deepseek-ai/dsh-base/@deepseek-ai/dsh-web-app等核心包,只列出可管理的第三方插件,避免误导
🔒 安全加固
- 拦截服务端重定向:主窗口补
will-redirect处理(此前仅拦截客户端导航),外部站点 302/307 跳转一律拦截,杜绝钓鱼/误导面 - 插件管理窗口导航白名单:仅放行原始 data: URL 的重载(卸载插件后 location.reload()),杜绝窗口被引导到外部页面继承 preload 注入的 electronAPI
- 进度窗口导航封锁:更新进度窗口禁止一切导航
- CSP:进度窗口与插件管理窗口的 data: HTML 增加 Content-Security-Policy
- 拒绝 HTTPS 降级重定向:更新检查只跟随 https 重定向,拒绝降级到 http://
✅ 验证
- 语法检查 + 整文件加载冒烟测试通过
- 导航守卫行为测试 10/10(will-redirect 拦截/放行、导航白名单、同 URL 重载)
- asar 与源码逐字节一致,部署验证通过
使用
- 桌面版:重启 DeepSeek Harness.exe 生效
- 源码:npm install -g @deepseek-ai/dsh 后运行
v1.1.5 — Bug 修复与安全加固
v1.1.5 Bug 修复与安全加固
🐛 严重 Bug 修复
- 修复自动更新实际执行失败的根因:
performUpdate用process.execPath(Electron 可执行文件 electron.exe / 打包 exe)执行 npm-cli.js,会启动 Electron GUI 而非执行 npm,导致更新必然失败。改用findDshBin()定位的 node.exe 直接执行,更新超时放宽至 3 分钟(npm install -g 可能耗时 1-2 分钟) - 修复
getInstalledVersion主路径完全失效:旧代码把 npm 参数(list -g ... --json)错误地传给 dsh bin.js 执行(spawn node dsh-bin.js list -g ...),永远拿不到版本,全靠兜底路径。改为 node 直接执行 npm-cli.js 查询全局版本 - 修复
getInstalledVersion兜底被跳过:npm list 失败(如包未安装 exit 1)会抛错直接跳出外层 try,导致后续 fallback 永远不执行。拆分为独立 try 块,fallback 1(findDshBin 反推)+ fallback 2(npm prefix -g)双保险 - 修复跨平台 node 定位失败:
where node是 Windows 专属命令,macOS/Linux 上会抛错,且兜底路径全是 Windows 路径(C:\Program Files\nodejs),导致非 Windows 平台找不到 node 无法启动。改为按平台选择 where/which,兜底路径分平台(/usr/local、/opt/homebrew 等)
🔒 安全加固
- 主窗口移除 preload 注入:主窗口加载的是远程 DSH Web UI(http://127.0.0.1:3080),此前会注入 preload 暴露
electronAPI(可调用 checkUpdate 弹窗等)。移除后远程内容零权限,preload 仅保留给插件管理窗口(本地 data: URL) - URL 校验从 startsWith 升级为精确 origin 匹配:
will-navigate原用url.startsWith(DSH_URL),http://127.0.0.1:3080.evil.com这类 URL 可绕过校验并继承权限。新增isDSHOrigin()严格比较 protocol/host/port - 进度窗口版本号 HTML 转义:版本号来自 npm registry(远程数据),拼入 HTML 前转义,防 HTML 注入
- 路径白名单补充 cmd 元字符:
%!^等 PowerShell/cmd 解析字符加入拒绝列表
🛠️ 健壮性修复
- DSH 崩溃检测不再依赖 stdout 文本:
startDSH原通过检测 stdout 是否包含127.0.0.1判断"已启动",若输出格式变化则标志永不置位,崩溃时既不弹窗也不退出。改为基于 promise 结算状态(spawn 成功即 settle),逻辑可靠 - 修复 activate 白屏(真正修完):v1.1.4 声称修复 macOS 激活白屏,但原逻辑仅在服务未运行时加载 UI —— 若服务已在运行,窗口会永远停在 loading.html。现无论服务状态,激活后都加载 Web UI
- 停止服务统一无 shell 执行:taskkill / powershell / fuser 全部改为
shell: false,与项目"全程无 shell"安全策略一致 - 重定向相对路径解析:getLatestVersion 跟随 301/302 时,location 可能为相对路径,现用
new URL(location, base)解析为绝对 URL - 端口占用验证支持 gzip 响应:若 DSH 返回 gzip 压缩 HTML,原逻辑读原始字节判断
__DSH_BOOT__会误判"端口被占用",现先解压再判断;解压异常时回退原始字节,避免 promise 永不结算导致应用卡死 - 更新后"稍后重启"分支 loadURL 补 catch:避免 unhandled rejection
- pnpm/npm CLI 兜底路径分平台:findPnpmBin / findNpmCli 的 fallback 在 macOS/Linux 使用 /usr/local/lib/node_modules 等路径
- 目录选择对话框指定 parent 窗口:dialog:selectFolder 绑定插件管理窗口,避免在 modal 上错位
- 核心依赖卸载硬保护:
@deepseek-ai/dsh、@deepseek-ai/dsh-base、@deepseek-ai/dsh-web-app在主进程层禁止卸载(原仅 UI 提示,可被绕过) - file: 协议路径规范化:本地插件路径前缀大小写不敏感识别(File:/FILE:),并清理尾部反斜杠/斜杠,防 pnpm 解析异常
- loading.html 加载补 catch:避免本地文件加载失败导致 unhandled rejection
- 更新失败自动恢复服务:更新流程开始前已 stopDSH,若 npm install 失败(网络/超时/权限),catch 分支现自动重启 DSH 服务并重新加载 UI,不再让应用停在"服务已停止"状态
✅ 验证
- 语法检查通过(main.js + preload.js)
- 逻辑回归测试 21/21 通过(isDSHOrigin 前缀绕过、escVer 转义、跨平台 where/which、路径元字符、版本反推)
- 真实环境验证:dsh 版本反推成功(0.1.0-rc.6)、npm-cli.js 定位成功
- 未提交的 v1.1.5 工作区改动(端口占用校验、启动早期快速失败、spawn 事件 resolve、关于对话框 await)已随本版本入库
使用
- 桌面版:重新打包后运行 DeepSeek Harness.exe
- 源码:npm install -g @deepseek-ai/dsh 后运行
v1.1.4 稳定性与健壮性修复
v1.1.4 稳定性与健壮性修复
修复内容
稳定性
- pnpmCmd 空指针防御:
findDshBin()找不到 node 时不再 TypeError 崩溃,改为抛出清晰错误提示 - 更新后服务自动重启:选择"稍后重启"时自动重启 DSH 服务并重新加载 Web UI,不再出现更新后服务停止的断连状态
- macOS activate 白屏修复:Dock 点击重新激活时自动检测并重启 DSH 服务
安全性
- validateArg 补全:路径校验正则补充反引号(
`)和美元符($),完整兑现"拒绝所有 shell 元字符"承诺
体验优化
- 静默更新检查不弹窗:启动时自动检查更新改为只记日志,不再弹更新对话框打断用户;仅手动检查(帮助菜单)才弹窗
- 崩溃提示时机修正:DSH 服务意外退出时,仅当主窗口可见才弹错误框,避免启动早期/退出期间误弹
测试
- 语法检查通过
- 安全专项 43/43、新修复验证 12/12、isNewer 15/15、静态安全扫描 15/15
- 启动链路(DSH 服务 + 3080 + HTTP 200)通过
- 退出无孤儿进程通过
v1.1.3 安全硬化与稳定性修复
v1.1.3 安全硬化与稳定性修复
🔒 安全修复
- 修复插件管理窗口存储型 XSS:恶意本地插件包名不再直接拼入 HTML(esc 转义 + data-name 事件委托),杜绝注入脚本调用 electronAPI
- 收紧 IPC 权限隔离:插件安装/卸载/选目录仅允许插件管理窗口调用(新增 isPluginManagerSender),主窗口的 DSH Web UI(远程内容)无法再操作插件
- isTrustedSender 精确化:不再用 getAllWindows 全放行,改为精确窗口引用
🐛 Bug 修复
- 修复更新检查版本比较全错:checkForUpdates 中 getInstalledVersion() 缺 await(local 是 Promise 对象导致 isNewer 误判)
- 修复更新完成后"稍后重启"仍立即重启:现在正确读取用户选择
- 修复更新进程用 shell 执行 npm:改为 node + npm-cli.js 直接执行(shell:false)
- 修复 npm 仓库挂起卡死:getLatestVersion 加 15 秒超时保护
✅ 验证
- 安全专项测试 43/43 通过
- 插件管理端到端 18/18 通过(注入拦截 + 真实安装/卸载)
- 启动链路回归通过(3080 端口 / HTTP 200 / UI 正常 / 无崩溃)
- 退出无孤儿进程验证通过
使用
- 桌面版:直接运行 DeepSeek Harness.exe(便携版)
- 源码:npm install -g @deepseek-ai/dsh 后运行
DeepSeek Harness Desktop v1.1.2
v1.1.2 修复(5个潜在Bug)
严重
- 可移植性问题:getInstalledVersion() 硬编码了用户路径,换电脑/用户名就失效,改为 npm prefix -g 动态获取
- 插件管理 PATH 问题:runCmd('dsh', ...) 用裸命令,双击启动时 npm-global 不在 PATH,改用 findDshCommand() 绝对路径
中等
- 假成功 Bug:runCmd 失败时静默返回空串,插件安装失败也显示"安装成功",改为失败时抛 Error
- 参数引号缺失:runCmd 参数含空格时拼接错误(如含空格的本机插件路径),自动加双引号包裹
- 版本比较错误:原 isNewer 无法正确比较 pre-release 版本(如 rc.6 vs rc.9),改为完整 semver 解析
低
- About 对话框硬编码版本号,改为从 package.json 动态读取
测试覆盖
- 启动链路(端口 3080 就绪)
- HTTP 200 正常
- 退出无孤儿进程
- isNewer 9/9 semver 测试用例通过
- runCmd 含空格路径测试通过
- 绝对路径 dsh 安装/卸载链路验证
DeepSeek Harness Desktop v1.1.1
v1.1.1 修复
- 修复退出孤儿进程:关闭窗口后 dsh 服务不再残留占用 3080 端口
- 修复更新检查 301 重定向:registry.npmjs.org HTTP→HTTPS 重定向导致无法获取最新版本
- 窗口关闭时等待端口释放后再退出
v1.1.0 功能
- Electron 桌面封装,双击启动 DSH Web UI
- 自动检查 DSH 更新(帮助→检查更新)
- 插件管理(Ctrl+P:安装/卸载/本地插件)
- 系统托盘与快捷键支持
v1.1.0 - 桌面版首发
DeepSeek Harness Desktop v1.1.0
🎉 首次发布
基于 Electron 的 DeepSeek Harness 桌面封装应用。
✨ 功能
- 🖥️ 原生 Windows 桌面体验
- 🔄 自动检查 DSH 版本更新(一键 npm 更新)
- 🧩 插件管理(npm 远程插件 + 本地文件夹插件)
- 📋 系统菜单栏(文件/视图/插件/帮助)
📦 安装
- 下载 \DSH-Desktop-1.1.0-Portable.zip\
- 解压到任意目录
- 运行 \DeepSeek Harness.exe\
⚠️ 前提条件
需先安装 DSH:
\\sh
npm install -g @deepseek-ai/dsh
\\
🧩 插件开发
支持自定义插件!菜单 → 插件 → 插件管理 → 安装本地插件