DeepSeek Harness Hub
← 返回列表

更新检查器Airmetro/dsh-update-checker

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
✓ 可直接安装

面向 DeepSeek Harness Web GUI 的常驻 Cordis 插件:自动检查 DeepSeek…

自动检查通过:npm 包已发布且 engines 声明满足基线;该结论来自程序自动检查,未经人工实机验证。 · 最近上游提交 2026/9/17 · 已提供中文文档

DeepSeek Harness 主程序与插件更新管理:npm/GitHub 双源 semver 比对、多语言横幅、一键更新(主程序自动备份/校验/回滚,插件临时目录安装)、更新后看门狗重启。Update management for DeepSeek Harness and its plugins: dual-source semver checks, locale banner, one-click updates with backup/rollback, watchdog restart.

综合分
44.2
GitHub 分
44.2
用户评分
★ Stars
17
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add dsh-update-checker
npm 包 dsh-update-checker 已校验归属本仓库,走 npm 安装最省事
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查✓ 自动检查通过

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

npm 包dsh-update-checker @ 1.4.23
Node 引擎未声明 engines.node
dsh CLI 依赖未声明 dsh 版本约束
入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/17 15:50:31

用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-update-checker

面向 DeepSeek Harness Web GUI 的常驻 Cordis 插件:自动检查 DeepSeek Harness 主程序与已安装第三方插件的新版本(原独立的 dsh-plugin-checker 已在 v1.1.0 合并进来),向用户提示,并支持一键更新(带成功/失败反馈)。

功能特性

- 完整更新生命周期 — 检查、备份、更新、回滚、重启,一个插件全部完成。
- 主程序检查 — 对比已安装的 @deepseek-ai/dsh 与 npm 最新版(全量 packument、稳定版优先、semver 感知)。预发布版本只有在与当前部署同频道时才会安装——跨频道提升(如 rc → alpha)会以 E_PRERELEASE 拒绝,除非显式开启 allowPrerelease,因此绝不会把主框架升进非预期的预发布通道。
- 第三方插件检查 — 扫描已安装的非官方插件(布局无关,支持 pnpm hoisted 的多位置 node_modules),逐一与 npm/GitHub 双源对比(目标版本取较高者);无发布源的本地工具归入 ignored。同名插件多位置时优先组合所属 profile 的副本(其余记为 copies 供区分),可逐个"不再提醒"排除(excludedPlugins,设置页可一键恢复)。
- GitHub 更新通道 — 对 GitHub 域使用专用 HTTPS 客户端(兼容本地自签名证书代理;npm registry 仍走严格校验),带重定向跟随、大小上限与超时;codeload tarball 解压前校验构建产物。
- 界面内横幅 — 跟随 DSH 界面语言(zh/en),显示有更新 / 已是最新 / 失败三种状态,支持"不再提示";更新横幅展示变更说明 brief(vX→vY + 风险等级,有 GitHub release 正文时附更新要点)。
- 安全的一键更新 — 主程序:dry-run 守卫(计划内有 remove 即中止)→ 快照备份(版本清单 + main-snapshot 里的 @deepseek-ai 整树副本,供离线回滚)→ 布局自适应安装(原位或 -g)→ 安装后回读校验 installed==latest;插件:临时目录安装 + 拷贝、依赖版本核对、npm ≥ 12 自动补 --allow-scripts 构建原生依赖。更新(与回滚)会持久化回 profile 的 package.json + 锁文件(pnpm install --lockfile-only / npm install --package-lock-only),之后的 install 不会再把插件悄悄拉回旧版——不再出现「同一插件反复提醒更新」的死循环。
- 真回滚 — 主程序 POST /rollback、插件 POST /plugin-rollback;GET /backups.json 列出两者备份。
- 看门狗重启 — 启动器从当前进程 argv 派生,杀 PID + 端口双保险;恢复确认 = 端口监听 + HTTP 200 探测(GET /restart-status.json)+ 从插件自身路由读回的实例 id,"端口有人应答"不再被当成"新版本已经起来"。
- 写操作安全 — 所有写路由除 { "confirm": true } 外还要求回环来源(127.0.0.1/::1),局域网客户端无法远程触发更新/重启/回滚。
- 零配置可移植 — profile 目录 / 组合文件 / 部署根由插件自身安装位置自动推导;状态、备份与日志遵循 DSH_HOME(再退回 ~/.dsh)。任何机器无需改代码。

Host 与 Client

- Host(lib/index.js)— HTTP 路由:status.json(检查)、suppress、update(支持 dry 预览)、rollback、backups.json、restart、restart-status.json、plugins.json、plugin-update、plugin-rollback、plugin-exclude。
- Client(lib/client.js)— 在根级 shell.overlay 插槽渲染两个横幅:主程序横幅(更新状态)与插件横幅(可更新插件,支持单个 / 全部更新)。页面加载时各检查一次,之后每 6 小时复查;设置页「检查更新」另提供回滚按钮。

安装与装载

该包是一个 profile bundle(其清单声明了 dsh.bundle.patch)。

1) 把包放进 $DSH_HOME/profiles/node_modules/,让 profile 能解析到它。
⚠️ 绝不要在 $DSH_HOME/profiles 目录里直接跑 npm install——该目录没有
package.json,npm 会把整个 node_modules 判为多余并清空(数据丢失)。
安全方式 A —— 临时目录安装后只拷贝本包:
npm i dsh-update-checker --prefix  --no-save
cp -r /node_modules/dsh-update-checker $DSH_HOME/profiles/node_modules/
安全方式 B —— 手动拷贝包目录(git clone 或解包 tarball 后整目录拷入)。

2) 在 $DSH_HOME/profiles/web/cordis.patch.yml 增加组合行

$DSH_HOME/profiles/web/cordis.patch.yml
- insert:
- id: dsh-update-checker
name: 'dsh-update-checker'

然后让 patch HMR 生效(或重启 dsh web)并刷新页面。

图文安装步骤与常见问题:见 docs/INSTALL.md。

配置与可移植性

所有路径运行时自动检测——没有任何硬编码:

- 插件 / profile 目录 — 由插件自身安装位置(import.meta.url)推导。
- $DSH_HOME — profiles 根目录的父目录(状态文件、备份、重启日志都在这里)。
- 组合文件 — 默认 $DSH_HOME/profiles/web/cordis.patch.yml。
- 部署根 — 先 junction realpath 解析,再 DSH_DEPLOY_ROOT,然后 process.cwd(),最后 npm 全局前缀(npm root -g 的父目录,v1.4.9 起支持 npm -g 全局安装形态)。
- systemd / npm -g 逃生口:自动探测万一没命中你的布局时,把 DSH_DEPLOY_ROOT 设为包含 node_modules/@deepseek-ai/dsh 的目录(Linux 上通常是 /lib)。
- node / npm 可执行文件 — resolveNodeExe() 定位真实 node:DSH_UC_NODE_EXE 覆盖 → npm_node_execpath → process.execPath(若确实是 node)→ 常见安装目录 → PATH。这就是 DSH Desktop(Electron,process.execPath 是 electron.exe)能跑 npm 更新插件的原因;若你的桌面端把 node 打包在别处,设 DSH_UC_NODE_EXE 指向它即可。若你的 node 由 mise / asdf / nvm 管理、PATH 里只有版本管理器的 shim(如 ~/.local/share/mise/shims/node),shim 目录旁并没有 npm;v1.4.22+ 会通过 node -p process.execPath 在 shim 后解析出真实二进制。如果仍失败(或想免去这次探测),把 DSH_UC_NODE_EXE 设为真实二进制,如 mise which node / asdf which node。
- 重启启动器 — 自适应:在部署根下探测常见启动脚本名;web 端口读取运行中的 webServer.port。
- 调优环境变量 — DSH_UC_UPDATE_PORT 指定更新 worker 停止/启动/探测的端口(默认 3080);DSH_UC_RESTART_WINDOW_MS 指定首次启动偏慢时继续观察的时长(默认 150000,观察期间进度记录持续刷新)。

平台与安装布局支持

- 检测(检查类功能) — 布局无关,可在任何机器工作。
- 一键更新与重启 — 针对开发时的布局调优:
- 仅 Windows — 重启流程 spawn PowerShell。
- 主程序更新自适应:部署根有 package.json 时原位 npm install,否则 npm install -g;两种形态都先过 dry-run 守卫并在安装后回读校验版本。
- 插件更新 — 临时目录安装 + 拷贝,兼容 npm 11/12+。
- 其它平台/布局下横幅与版本检查仍可用。Linux/macOS 上主框架更新路由现在会立即以 501 E_PLATFORM_UNSUPPORTED 拒绝(该平台的安装/重启仍需改代码),而不是卡在 8% 并残留横幅;插件更新与回滚可用。完整 POSIX 支持是自然的下一步。

说明

- Host 代码改动需要重启服务才生效(加载器缓存已导入模块);client 改动由 HMR 拾取,下次刷新页面即生效。
- update/rollback/restart/suppress/settings 等写路由由 { "confirm": true } 且回环来源(127.0.0.1/::1)双重守护。
- npm install 前会向 $DSH_HOME/dsh-update-checker-backups// 写入备份(部署 package.json + package-lock.json + 两份 @deepseek-ai 版本清单 + backup-meta.json + main-snapshot 里 @deepseek-ai 框架整树副本),主程序与插件都有对应回滚路由;主程序回滚在 main-snapshot 存在时直接从磁盘恢复,而不是从 registry 重新安装旧版本。

更新日志

- v1.5.0 — syncProfilesToDeploy 改为建链接而非复制(修复主程序更新之后启动崩溃):
- 根因:函数名与日志字段 junctionSkipped 都写着"链接",但新建路径从未建过链接——用的是 cp(src, dst, { recursive: true, force: true })。已存在且 realpath 指向同一份的条目会被跳过(实机 236 个里跳过 228 个),而 profile 里尚不存在的包(0.1.6-alpha.1 更新带来的 8 个)被实体复制进 $DSH_HOME/profiles/node_modules/@deepseek-ai/。
- 为何致命:dsh 的 healProfilesModuleFallback/ensureSymlink 只接管符号链接或 dsh 托管的模块代理目录,真实目录会直接抛错 dsh:  exists and is not a symlink or dsh-managed module proxy; remove it so dsh can manage the installation fallback,且发生在 composeProfile 阶段——Web 服务监听之前,于是下一次启动直接崩掉;而更新本身却报告成功(main-profile-sync total:236 junctionSkipped:228 failed:[])。
- 修复:写入路径改为 mkdir + symlink(src, dst, process.platform === "win32" ? "junction" : "dir"),profile 只保留指向部署侧唯一一份的链接——这也正是 healProfilesModuleFallback 期望的形态。
- 自愈:目标已存在但不是部署副本时会安全回收——符号链接(含悬空链接)直接重建;实体目录必须 package.json 的 name 与部署侧一致才替换;其余一律原封不动并记一条失败(refusing to replace),顺带堵上第二个此前未被报告的隐患:fs.cp(..., { force: true }) 对"同名但来自别处"的目录不会报错,而是覆盖那个包的文件、留下其余内容,把它静默毁掉。
- 回归测试:scripts/integration-sync-profiles.test.mjs 从真实 worker 源码里提取 syncProfilesToDeploy 执行(避免测试与实现漂移),覆盖六个场景——新包建为链接、残留实体副本被回收、同名外来目录绝不被删除、悬空链接被重建、非 dsh 前缀包被忽略、deploy 树不可读时安全退出。同一套用例对 1.4.23 的 worker 4/6 失败,对本版 6/6 通过。
- 安装后的健康检查现在证明"新进程真的起来了":原先只要端口有人应答就算成功——GET / 返回 200 就扫资源,返回 401/403/407 直接判成功——于是在 composeProfile 阶段就崩掉(根本没有服务器)的构建也会被报告为"更新成功"。现在宿主把自己当前的 instanceId 交给 worker,worker 从插件自身的路由读回(update-progress.json,其次 status.json,两者都无需浏览器会话即可访问):读到不同的 id 才说明新构建确实起来了;读到相同的 id 说明重启前那个实例还在应答,本次更新判失败。探针无法判断时(插件未组合、路由尚未就绪、宿主较旧没传 id)保持原有行为,不把可能健康的更新误判为失败。
- 预发布闸门改为按"频道"判断,而不再问"是否存在正式版":原条件是 isPrerelease(target) && !allowPrerelease && hasStable,而 hasStable 的含义是"npm 上存在非预发布版本"。@deepseek-ai/dsh 至今发布的全部版本都是 rc/alpha,hasStable 恒为 false,这道闸门从未生效:allowPrerelease: false 的部署照样被从 rc 升到了 alpha。现在按预发布标识(alpha/beta/rc/正式版)比较——同频道升级放行,跨频道提升以 E_PRERELEASE 拒绝并在文案里指明 allowPrerelease 设置;数据缺失时失败开放(宁可不拦,也不误拦)。
- 状态、备份与日志遵循 DSH_HOME:原先只按"本包装在哪个 node_modules"推导 home,装在 …/profiles/node_modules 之外时会把状态写到程序文件旁边。现在:布局确实是 Harness home 时仍以安装位置为准(DSH_UC_PROFILE_NODE_MODULES 覆盖与测试隔离因此不受影响),否则退回 DSH_HOME,再退回 ~/.dsh。
- 已被此 bug 影响的机器如何自救:把 $DSH_HOME/profiles/node_modules/@deepseek-ai/ 下的真实目录移走(不要删,先备份),下次启动 dsh 会自动把它们重建为 junction。

- v1.4.23 — 主程序实时进度、残留更新状态自愈、插件安全替换(issue #17 #18 #20 #21 #25,PR #23 #24):
- 依赖树检查阶段有真实进度(#18 及"6% → 64%"反馈):此前下载阶段在整个 npm install --dry-run(数分钟)里一直停在 4–6%,然后直接跳到 64%。现在每个阶段都有单调递增的"爬坡"计时器,每秒重写一次进度记录(phaseCreepPercent,已导出并单测),npm/tarball 的真实计数只把下限往上抬。里程碑整体重排(下载 10→55、停止服务 58、安装 62→78、校验 84→87、同步声明 88、重启 92→95、健康检查 96、等待恢复 97–98、完成 100),任何阶段都不再瞬移;启动服务的 30 秒与重启观察期间同样持续刷新进度。
- 重启改为"继续观察"而不是直接判失败(#18):安装、完整性校验、版本声明同步都成功之后,重启失败不再终止更新。worker 进入 restart-pending 状态持续刷新进度,重新探测端口并按需重新拉起启动器,最长等待 DSH_UC_RESTART_WINDOW_MS(默认 150000 毫秒),之后才以 E_RESTART 结束——记录里带 installed、restartPending: true,文案明确"安装本身已成功"。期间端口起来即判定成功。
- 进度计数修正(#18):安装阶段不再用硬编码的 587 去除 npm 的 http 行计数;总数改为从真实 lockfile 读取(countLockPackages,未知时 null),done 按总数封顶,界面上不会再出现 done > total(如 1338/587)。横幅同时提示"关闭此页面不会中断更新"。
- 前端需要认证不再被误判为服务坏了(#18,实机场景):健康检查原先要求 GET / 返回 200,于是在 / 返回 401/403(口令/令牌保护界面)的机器上,每一次安装成功最后都以 E_RESTART: update installed  but restart/health failed: GET / -> 401 收尾,而紧接着的崩溃自愈又把服务拉起来了——用户被告知"更新失败",实际早已成功。健康判定现在抽成纯函数 classifyHealthStatus:200 → 继续做 dist/assets 全量校验;401/403/407 → 服务活着但前端受认证保护,判定更新成功并跳过资源扫描(记录 main-update-health-auth-gated);超时、5xx 与其它 4xx 仍判失败。E_RESTART 文案也同时给出启动器错误与健康检查问题。
- 残留进度/状态自愈(#25):修掉 writeProgress 里被缓存记录覆盖 at 时间戳的问题——at 会永远停在下发第一次写入的时刻,这正是"更新中断后看起来仍是更新中"或"正在跑的更新看起来过期"的根因。进度记录现在写入属主 workerPid/hostPid;isStaleProgress 在属主进程已消失时判为陈旧(无 pid 时按 10 分钟无更新判定),Host 在启动时与读取时把它改写成 running:false + phase:error + code:E_INTERRUPTED 并释放更新锁。陈旧锁不再阻塞新更新 10 分钟:超过 2 分钟拉起宽限期且无存活 worker 的锁会被丢弃。
- worker 崩溃不再留下 running:true(#25):uncaughtException/unhandledRejection 与 main() 的致命异常都会写入一条 error 进度并释放锁,此前进程直接消失。startService/taskkill 的 spawn 补上 error 监听(POSIX 的 ENOENT、批处理文件的 EINVAL 以前会变成未处理的 error 事件、把 worker 打断在更新中途),拉起失败也改为快速失败而不是干等 30 秒。
- 插件替换改为"先暂存后交换"(#21):backupAndReplace 先把新内容拷到目标旁的 .dsh-uc-staging-,再把旧目录改名为 .dsh-uc-trash-,然后把暂存树改名就位,最后尽力删除回收站。此前"先删后拷"在 Windows 上遇到运行中宿主映射的原生模块(如 better_sqlite3.node)会在已经删掉全部文件之后才报 EPERM,把插件掏成只剩那个被占用文件(连 package.json 都没了)、并连带拖垮宿主。现在交换前任何失败都不会动已装包,被占用的回收站留待下次更新清理。"不再提示"两个按钮也不再互相写对方的开关。
- 瞬时请求失败不再触发整页刷新(#20):client 的 1.5 秒状态探针把任何一次失败请求(LLM 流式输出、工具执行、代理抖动)都当成"服务重启过",下一次成功就无条件 location.reload(),导致对话过程中整页刷新。现在改为由服务端 instanceId 驱动:只有实例真的变化才刷新,且同一实例最多刷新一次(sessionStorage 守护),瞬时失败被完全忽略。
- locale 服务时序修复(#22/#23):client 半身改为等待 locale 服务(ctx.inject(["slots", "locale"]))后再注册字典与插槽绑定,不再在 apply 时读 ctx.get("locale") 静默退化为 fallbackT()(永远中文),英文界面下不再显示中文。
- POSIX 主程序更新快速失败(#24):Linux/macOS 上主框架 /update 路由在创建锁、备份、拉起 Windows 专用 PowerShell 之前就返回 501 E_PLATFORM_UNSUPPORTED,不再卡在 8% 并残留横幅。完整 POSIX 支持仍待上游 PR #19。

- v1.4.22 — 版本管理器 shim 解析(issue #17):
- resolveNodeExe() 通过 shim 执行 node -p process.execPath 反查真实 Node,getNpmCli() 不再回退到不存在的路径,而是抛出带 DSH_UC_NODE_EXE 提示的 ENPMCLI,避免 npm 阶段出现 MODULE_NOT_FOUND。

开发

- lib/index.js — Host 半身:纯 ESM,仅依赖 Node 内置模块,无构建步骤;纯函数以命名 ESM 导出暴露,供单元测试。
- lib/client.js — Client 半身:纯 JS(window.__ModuleLoader__),仅依赖 react,无构建步骤。
- 测试:npm test(Node ≥ 20 内置测试运行器,无第三方依赖)。
- scripts/restart-service.ps1 — 手动服务重启辅助脚本(需带 -ExecutionPolicy Bypass 运行)。

许可证

MIT

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群