dsh-staging-hunter:把 DSH 桌面端留在夜间版灰度第一批

前言

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):

  1. 启动时读 .updaterId;若桶值已低于上限,就沿用现有身份,不换 UUID。
  2. 否则生成一个合法 v4 UUID,把 bytes[12..15] 精确写成目标桶值,备份原文件后写回。
  3. 把钉住的 UUID 存进 .staging-hunter.json(sidecar),保证跨启动身份稳定。
  4. 用 fs.watch 加上定时巡检守着文件:被应用改回随机值时立刻改回来。
  5. 插件卸载时自动关闭 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

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜