Skip to content

Releases: BOWLUNA/dsh-multi-instance

0.5.0 —— 窗格加固的静默失效,与第一次「真起窗口」的测试

Choose a tag to compare

@BOWLUNA BOWLUNA released this 24 Sep 07:10

0.5.0 —— 窗格加固的静默失效,与第一次「真起窗口」的测试

下载

文件 大小 说明
DSH.Multi-Instance-Setup-0.5.0.exe 111.5 MB 安装包(NSIS):可选安装目录、建快捷方式
DSH.Multi-Instance-0.5.0-x64.zip 152.9 MB 免安装:解压即用

需要 Windows 10 / 11(x64)。软件不捆绑 dsh,也不会在后台偷偷下载任何东西 ——
装完在界面里点「下载实例」,或接你已有的 DSH。


这一版修掉了一个「静默失效」

每个窗格的分区加固,从加进来那天起就没执行过。 这不是新引入的 bug,是这几版一直带着的。

main.js 里注册 will-attach-webview(负责给每个窗格的分区设 UA、装权限处理器)时,
挂在了 type === 'webview' 的内容上。但这个事件是在宿主窗口上触发的 ——
中间那句早退 if (type !== 'webview') return 恰好把唯一的宿主挡在门外,
于是处理器永远注册不上,hardenSession() 一次都没被调用过。

证据(修复前,npm run smoke 抓到的实际请求头)

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
dsh-multi-instance/0.4.0 Chrome/144.0.7559.236 Electron/40.10.2 Safari/537.36

这段 UA 本该被 setUserAgent(chromeUA()) 换成一支干净的 Chrome UA,实际没有。
日志里也从来搜不到 webview 挂载 partition= 那一行。

影响:每个窗格的浏览器会话都没做过 UA 与权限加固;被嵌页面能直接从 UA 读到
Electron 与本应用的名字、版本(指纹信息),而「壳子在 DSH 眼里就是一个普通浏览器」
这个前提是落空的。

修复后同一条断言由红转绿,UA 变为 … Chrome/152.0.7977.130 Safari/537.36。
另外加了一条护栏:今后只要出现「窗格报到了却没有挂载记录」,主日志里就会有
[guard] 窗格(实例 xxx)已挂载但没走 will-attach-webview … —— 这类失效不能再沉默。


新增:npm run smoke(窗口级冒烟测试)

这一版的第二件事,是让上面这类 bug 测得到。

此前仓库里的 57 条测试全是纯逻辑(配置读写、地址解析、CLI 参数),
它们能在任何无头环境里跑,代价是窗口里的东西一条都测不到 —— 而本项目的坑恰好大多长在窗口里。

npm run smoke 补的正是这一半:脚本自己在本机起一个「假 DSH」页面,
用一套测试配置起一次真应用,断言点落在**「那个页面确实被请求了」**上 ——
这是端到端证据,不是「配置文件里写了什么」这种间接指标。

  • 30 条断言(--scene=pane|empty|tile 三种场景),覆盖:
    Electron 版本对齐、userData 落点隔离、渲染层 boot、窗口显示、webview 挂载与加载、
    每格独立 partition、端到端请求、窗格发出的 UA、截图非空白、致命错误与退出码
  • 不需要网络、不需要真的 DSH、不需要任何凭据,也不碰你真实的配置(userData 指向临时目录)
  • 能直接验打包产物:node tools/smoke.js --exe="dist/win-unpacked/DSH Multi-Instance.exe"
    ——「源码能跑」和「发出去的那个 exe 能跑」是两件事
  • CI 新增 smoke (windows) job,失败时把 .tmp/smoke 传成 artifact 留档

其它修复

一次操作只占一个备份槽。 主进程保存状态时会把 panes / ui / collapsed 分三笔写,
原先每笔都轮转备份 ⇒ 三个备份槽被同一次拖动内部的中间态占满,
「给你留 3 份」实际只剩「回退一次拖动」的粒度。加了 3 秒轮转冷却后,
3 份备份真的对应最近 3 次操作。

依赖与仓库

  • electron 40.10.2 → 44.4.3(Chromium 144 → 152)。这是用 npm run smoke 三个场景实测过的,
    不是「dependabot 说没冲突」那种证据。
  • actions/setup-node v4 → v7。
  • CONTRIBUTING / SECURITY / CODE_OF_CONDUCT 三份原先只有中文的文档,顶部各加一段英文指引
    (明确以中文为准,并指向英文 README)—— 此前 README 中英双语而这三份不是,英文读者只能猜。
    没有仓促机翻三份长文档:说清现状比糊一份译文更诚实。

怎么自己复核(不用信上面的字)

git clone https://github.com/BOWLUNA/dsh-multi-instance.git
cd dsh-multi-instance
npm install
npm test        # 57 条纯逻辑
npm run smoke   # 30 条窗口级,本机起真应用

想让冒烟测试打印出它到底验证了什么,加 --keep,现场留在 .tmp/smoke/
(含截图 smoke.png 与主进程完整日志)。

npm 上仍然是 0.0.1 占位包,可用版本还没发上去 —— 请用上面的 Release 产物,或从源码跑。


MIT License · 本项目是独立的第三方外壳,与 DeepSeek 官方无隶属关系。
它不改 ~/.dsh 下的任何凭证文件,也不捆绑、不自动下载 dsh。

0.4.0 —— 配置损坏不再静默丢数据

Choose a tag to compare

@BOWLUNA BOWLUNA released this 24 Sep 05:42

配置坏了不再静默丢数据,外加一个能自己跑的图片资产护栏。

修了一个会吃掉配置的缺陷(P1)

读不出 config.json 时,旧代码只打一行日志、按空配置继续 —— 而紧接着任何一次写入都会用这份空配置把原文件覆盖掉:没有备份、没有残片,实例列表和窗格排布就此消失。

探针实测(修复前):损坏的残片 32 字节 → 一次 set()(比如改个主题)之后,主文件变成 38 字节的新内容,目录里只有 config.json 一个文件,没有任何东西可以回退。

现在:

  • 每次覆盖前,把上一位能解析的内容滚成 config.json.bak-1(旧的往后推,保留 3 份)
  • 读不出来时,先把手上的残片原样存成 config.json.corrupt-<时间戳>,再从最近的备份回退,并把回退结果写回主文件(自愈)
  • 两件事都写进 logs/main.log —— 以前它走的是 console.error,打包版里根本看不见
  • 备份链只收能解析的内容:一次坏盘不会把好备份一路挤掉,让「回退」退到另一个坏文件上

复验(修复后):坏盘 + 无备份 → 残片字节级保留,可手工抢救;坏盘 + 有 bak-1 → 实例列表原样回来。

npm 入口能回答最基础的两个问题

dsh-multi-instance --version   # 装成了什么
dsh-multi-instance --help      # 全部开关

这两条不需要 Electron(参数解析排在「找运行时」之前)—— 装完包的第一个动作不该先撞上「找不到运行时」。之前它们会被当成 Electron 参数透传,什么都不打印。

护栏

  • tools/check-binary-assets.js + CI 步骤:读 magic number 复验 *.png / *.ico。来历是这个项目真把 README 的图当文本处理坏过(d8eb824)。已用一份 base64 文本伪装的 PNG 验证过它确实会红 —— 那正是那次事故的签名。
  • .gitattributes:显式声明二进制资产。git 的自动检测只在新文件被 add 时生效,挡不住 patch / API 通道。

仓库

  • 落地页:https://bowluna.github.io/dsh-multi-instance/(docs/index.html,单文件、无外部依赖)
  • 徽章行以 Release 版本为准(npm 徽章移到末位并标注 placeholder —— 之前首页显示的是 npm 上那个 0.0.1 占位包)
  • 关掉空置的 Wiki / Projects 标签;合并后自动删分支;electron 家族依赖每周汇总成一个 Dependabot PR

测试

npm test:36 条 → 54 条(新增 13 条覆盖配置的读写 / 备份轮转 / 损坏回退 / 残片保留,5 条覆盖 CLI 参数解析)。零依赖、纯 Node,不需要图形界面。

下载

文件 说明
DSH Multi-Instance-Setup-0.4.0.exe 安装包 —— 可选安装目录,建桌面与开始菜单快捷方式
DSH Multi-Instance-0.4.0-x64.zip 免安装压缩包 —— 解压即用,不写注册表

需要 Windows 10/11。软件本身不含 dsh —— 装完在界面里点「下载实例」,或者接你已有的 DSH。

⚠️ npm 上现在仍然只有 0.0.1(占位空壳)。可用版本还没发上去,在那之前请用上面的产物。
想确认拿到的是不是真包:npm view dsh-multi-instance version 现在会返回 0.0.1。

实测记录(本轮踩到的另一件事)

打包在解包阶段就会失败,dist/ 里一个产物都没有 —— 起因是工具沙箱注入的批量删除守卫拦下了 electron-builder 解包前对 dist/win-unpacked 的删除。README 里原先那句「收尾清理报删除失败可以忽略,产物已生成」是错的,中英双侧已更正,并新增 npm run clean:dist(挂在 predist 钩子上,用同步 API 提前清目录)绕开它。

完整改动:CHANGELOG.md · 安装与排障:README

0.3.0 —— 固定用户数据落点,补上无头测试

Choose a tag to compare

@BOWLUNA BOWLUNA released this 24 Sep 04:15

dsh-multi-instance 0.3.0

把 DeepSeek Harness(dsh)的 Web 界面装进一个多窗格桌面客户端:
多开多个实例、每个实例一个窗格、自由排布与缩放、每格独立浏览器会话。

这个版本修掉了一个会丢用户数据的缺陷,并给仓库补上了能无头运行的测试。

下载哪个

文件 说明
DSH.Multi-Instance-Setup-0.3.0.exe 安装包(NSIS)—— 可选安装目录,建桌面与开始菜单快捷方式
DSH.Multi-Instance-0.3.0-x64.zip 免安装包 —— 解压即用,不写注册表,适合放 U 盘

文件名里的点是 GitHub 上传时把空格换掉的(本地产物名里是空格)。

需要 Windows 10/11。软件不含 dsh —— 装完在界面里点「下载实例」,或者接你已有的 DSH。

修了什么(重要)

用户配置会在改名后静默丢失。 Electron 的 app.getPath('userData') 默认等于 <appData>/<应用名>,
而应用名在开发态取 package.json 的 name、在打包态取 productName —— 于是开发态落在
%APPDATA%\dsh-multi-instance\,打包版落在 %APPDATA%\DSH Multi-Instance\。
这个项目改过三次名字,每改一次,旧目录里的实例列表、窗格排布和 Partitions/(持久化的登录态)
就留在原地没人认领。

实测现场:%APPDATA%\dsh-shell\config.json 里有 1 个窗格和 14MB 的 Partitions,
而当时的落点目录里只剩一个 ui 键。

这个版本把落点钉死,并在启动时做一次旧目录迁移:只在当前目录没有窗格时才动手,
取窗格最多的那一份 config.json,连带 Partitions/ 一起接过来。幂等,跑过一次之后不会再动。

如果你装过 0.2.0 或更早:升级后实例会自动接回来,日志里会有一行
[appdata] 已从 <旧目录> 迁移: config.json, Partitions(窗格 N 个)。

新增

  • npm test:36 条零依赖、纯 Node、不需要图形界面的用例,覆盖落点解析与迁移的全部分支
    (含幂等、坏配置、不覆盖已有会话、失败不抛)、实例地址解析、npm 入口的运行时查找。
    原先仓库里只有要起真窗口的 --selftest*,CI / SSH / 容器里一条都跑不了 —— 上面那个缺陷就是这么漏过去的。
  • GitHub Actions:push 与 PR 时在 Windows + Linux 上跑测试、语法检查、以及
    package.json 与 CHANGELOG.md 的版本一致性检查。
  • CHANGELOG.md / SECURITY.md / CONTRIBUTING.md / issue 表单 / PR 模板。
  • tools/social-preview.py:生成 1280×640 的社交预览图(配色直接取 style.css 的纸色变量)。

文档修正

  • 删掉一条实测为假的说法:「构建路径不要含中文」。electron-builder 26.15.3 在含中文的路径下能正常打包 ——
    这两个产物就是在原地(路径含中文)打出来的。
  • README 中英双侧补齐:目录导航、npm test 一节、落点钉死与自动迁移的说明、
    「升级后实例列表空了」的排障条目、相关项目互链、CI 徽章。

校验

  • npm test → PASS passed=36 failed=0(exit code 0)
  • 产物:exe 是有效 PE(MZ + PE\0\0 签名);zip 79 个条目、testzip() 无损坏
  • 产物内 resources/app.asar 的 package.json version = 0.3.0,
    且确实含 src/main/appdata.js(APP_DIRNAME 常量与迁移函数都在)
  • 真实数据上跑过迁移:从 %APPDATA%\dsh-shell\ 迁出 config.json + Partitions(1 个窗格),
    第二次运行为 skip-target-ok

完整变更:CHANGELOG.md