前言¶
DSH(DeepSeek Harness)桌面端通过 electron-updater 的 staging 机制控制 nightly 版的放量比例:官方 feed 里的 stagingPercentage(0–100)决定多少人会收到新版。技术上,一台机器是否入圈,取决于它本地 .updaterId 文件中 UUID 的确定性桶值。这意味着有些机器的桶值天生偏后,放量比例不够大就永远收不到更新。
dsh-staging-hunter 解决这个问题:它把 .updaterId 钉在一个目标桶值(默认 1%),并在文件被应用改回随机值时自动修正。维护者是 ChenXu233,MIT 许可,客户端类插件。
这是什么¶
一句话:一个 DSH 桌面端插件,用来固定 electron-updater 的 staging 身份,让本机稳定落在夜间版灰度的第一批。
它不改安装包来源,也不跳过签名校验。改的只是本地一个“我是谁”的标签。
工作方式:钉住 .updaterId 的低位桶值¶
先看 DSH 桌面端判断本机是否入圈的原始逻辑(位于 app.asar -> node_modules/electron-updater/out/AppUpdater.js):
stagingPercentage = parseInt(updateInfo.stagingPercentage, 10) / 100
const val = UUID.parse(stagingUserId).readUint32BE(12)
const percentage = val / 0xffffffff
return percentage < stagingPercentage // 严格小于
关键点有两个:
- 桶值是 UUID 的确定性哈希,取自 UUID 第 12–15 字节。一台机器一旦有
.updaterId,就永远落在固定桶位。 - 这是严格小于比较。只要
stagingPercentage大于本机桶值,本机就在圈内。
因此把桶值压低即可稳定入圈。插件的行为(按 README):
- 启动时读
.updaterId;若桶值已低于上限,就沿用现有身份,不换 UUID。 - 否则生成一个合法 v4 UUID,把
bytes[12..15]精确写成目标桶值,备份原文件后写回。 - 把钉住的 UUID 存进
.staging-hunter.json(sidecar),保证跨启动身份稳定。 - 用
fs.watch加上定时巡检守着文件:被应用改回随机值时立刻改回来。 - 插件卸载时自动关闭 watcher 与定时器。
安装与启用¶
从 npm 安装(推荐):
dsh plugin add dsh-staging-hunter
按提示批准后重启 DSH,插件会自动挑一个低位桶 UUID 并开始守护。
也可以从源码或手工挂进 profile,仓库不会自动写你的 profile。两种方式:
作为 bundle 包,先把仓库放进 profile 的 node_modules(Windows 用目录联接,避免触发 pnpm 重装):
cmd //c mklink /J "%USERPROFILE%\.dsh\profiles\desktop\node_modules\dsh-staging-hunter" "E:\git\dsh-staging-hunter"
然后在 ~/.dsh/profiles/desktop/package.json 的 dependencies 与 dsh.profile.bundles 里各加一行 "dsh-staging-hunter"。
或者直接写进 profile 的补丁层,在 ~/.dsh/profiles/desktop/cordis.patch.yml 追加:
- insert:
- id: dsh-staging-hunter
name: 'dsh-staging-hunter'
config:
targetPercentage: 1
改完重启 DSH 桌面端,启动日志里应出现:
[staging-hunter] pinned updaterId (startup) -> <uuid> bucket=1.000000%
[staging-hunter] watching ...\.updaterId ceiling=1% pinnedBucket=1.000000%
日志出现这两条,说明身份已钉住且守护已启动。
配置项¶
可选配置如下,不配置时使用默认值:
| 键 | 默认 | 说明 |
|---|---|---|
enabled |
true |
总开关 |
targetPercentage |
1 |
桶值上限(%)。桶值低于它即视为在第一批 |
uuid |
'' |
钉死的 UUID;留空自动挑选/生成 |
updaterIdPath |
'' |
.updaterId 路径覆盖;留空自动探测 |
checkIntervalMs |
60000 |
巡检间隔;0 表示只靠 fs.watch |
典型用法¶
默认即装即用:部署后重启 DSH 桌面端,再从启动日志确认插件已完成初始化。日志里第一条是启动时钉住 updaterId 的结果,第二条说明守护目标与上限已生效。
如果机器上的 .updaterId 路径不在默认探测范围内,用 updaterIdPath 指过去;如果要换一个自备的 UUID,填 uuid,留空则插件自动生成。甲乙双方如需只在文件变化时响应,可把 checkIntervalMs 设为 0,完全交给 fs.watch。
适用场景与注意事项¶
适合想稳定跟 nightly 版、且机器因桶值偏高长期收不到新版的 DSH 桌面端用户。
需要注意几点:
- 完整性不受影响。插件只改本地身份标签,安装包仍从官方地址下载,并按 feed 里的
sha512与安装器publisherName验签。 - 需要重启。
AppUpdater用Lazy缓存stagingUserIdPromise,写回的值在下一次启动的更新检查中才生效。 - nightly 本身有风险,会稳定收到 rc 版本,可能遇到崩溃或破坏性变更。
- 行为变化:旧行为是“不在圈内就停在当前版本”,装插件后会持续跟进最新 nightly。
- 插件以当前 DSH 进程权限运行,安装前应检查源码与许可证。许可证为 MIT,仓库公开可查。README 标注兼容
dshReleases: 0.2.1-rc.5。
结尾¶
dsh-staging-hunter 做的事很窄:理解 electron-updater staging 的哈希分桶,然后用一个持久化的低位 UUID 加文件守护把本机固定在第一批。适合明确想跟 nightly 的人,不想跟的话不必装。
目录页:https://www.skillhub.cn/plugins/ChenXu233/dsh-staging-hunter
GitHub:https://github.com/ChenXu233/dsh-staging-hunter