DeepSeek Harness 的更新助手:一次扫描覆盖 DeepSeek Harness 本体和每个 profile 的插件,说清改了什么、风险多大,只更新你确认过的那些。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-update-copilot
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:hezhongtang/dsh-update-copilot
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
DeepSeek Harness 的更新助手:追踪 dsh 本体、官方 bundle 和所有已装插件——跨全部 profile 按包合并展示;插件更新带预检闸门一键执行,本体代执行更新(始终钉最新健康版本,全套兼容闸门,仅限可写的全局 npm 安装),补丁名体检捕捉被 dsh 升级静默丢弃的配置。
English | 中文
为什么做这个
DSH 迭代很快,插件生态同样如此。每个 profile 通过 pnpm spec 安装插件——npm 版本号、GitHub commit 锁定、本地 link: 目录——每种通道各有各的过期方式。手动检查意味着挨个仓库跑一遍;无脑全自动升级则等于把环境交给第三方代码。
这个插件走中间路线:全部检测、汇总变更、只更新你点过的东西。 更新就是一键——按钮和动作之间没有确认仪式,且只会作用于该包显示出的合格 profile。DSH 本体是带闸门的操作(ADR-0001):在可写的全局 npm 安装上,本体卡片可以在全套兼容闸门之后代执行更新——始终钉到雷达验证过的最新版本(绝不执行 dist-tag 字符串),解析出降级时除非显式 force 否则拒绝。其余安装形态(npx 等)保持「复制命令」行为,且本体绝不参与任何自动更新批次。
功能
| 🔭 全量雷达 | 一次扫描覆盖 dsh 本体 + 官方 bundle(dsh-base、dsh-web-app)+ 所有 profile 的插件依赖 |
| 🔄 双通道 | npm registry 版本(完整 semver 比较,含 prerelease)+ git 上游(pinned commit vs HEAD)。link:/file: 本地目录只列出、不探测、不管理 |
| 🤖 Agent 工具 | update_copilot_scan / update_copilot_preflight / update_copilot_update / update_copilot_core——对 Agent 说一句「有没有更新」,得到有数据支撑的回答;扫描按包合并(一个包一行),自动推断的挂载关系只用于展示;官方包跟随 harness 安装(本体更新走 update_copilot_core),每个直接依赖仍按自身更新策略处理。profile 参数在 preflight/update 上可选:不传时 preflight 逐个评估所有装有该包的 profile,update 也只在那些合格 profile 中执行 |
| 🖥 Web 界面 | 设置旁的侧栏入口(徽章在挂载时补齐、启动扫描后刷新)打开紧凑雷达弹窗,旁边就是**「⚡ 一键更新」快捷按钮**——不必打开任何视图,点击即按序更新所有落后且可自动更新的插件(运行中显示 n/m 进度并禁用,完成显示 ✓/✗ 反馈,失败或需重启时自动打开弹窗看明细)。弹窗承载完整雷达,共用同一折叠布局——「DeepSeek Harness 本体」卡片默认收起,插件拆成「可更新」「已最新」两组(已最新默认折叠、点击展开),自动推断的挂载关系始终跟随父行。插件跨 profile 合并成一行(每个已在的 profile 的当前 → 最新版本内联列出),挂载的包可在父行下展开披露,同时保留独立归属和更新操作——子项「更新」只更新子项,父项普通「更新」只更新父项,「更新 bundle」只处理过期且合格的目标(父项过期先更新父项,再按每条关系的 profile 范围更新过期的挂载子项)。点一次「更新」只在该包明确列出的合格 profile 中执行,工具栏「一键更新全部」按序跑完所有合格的落后包(在弹窗内勾选「点击按钮时自动更新」后,点侧栏按钮一发现有落后插件就自动开始这一轮,dsh 本体绝不参与这一自动批次)。所有变更操作共用一个 UI 操作锁;更新或刷新状态未结束时禁止刷新。更新过程通过 SSE 实时推送进度(解析依赖 / 下载中 / 重试中阶段),直接渲染成每行进度条;更新从不静默——无论这轮更新由谁发起(自动更新、一键更新快捷键、Agent 工具、另一个标签页),运行期间侧栏按钮的徽章会变成跳动的「更新中」圆点,弹窗常驻「正在更新:包名(profile)…」横幅(含当前阶段 / 百分比),所有更新按钮同步禁用,更新一结束列表自动刷新;无论这轮更新由谁发起,雷达里匹配的那一行都会内联同一根实时进度条(发起行走 SSE 流,其余座位经 2 秒轮询镜像),新一轮更新开始时该行残留的上一次结果自动清除——后台静默更新不会再和前台点击撞出「更新中」报错 |
| 🛡 更新护栏 | 同源 POST + 显式 confirm、严格目标 allowlist、单并发锁、5 分钟超时;预检硬拦截门拒绝目标 dsh 确实会弄坏的更新(缺失 named export),显式 force 才可越过;npm/github 通道只走官方 dsh plugin CLI,link:/file: 本地目录与官方 @deepseek-ai/* 包一律拒绝——本地检出请在它自己的仓库里更新;空包 dist-tag / husk 发布(无入口、无 dsh.bundle、tarball 极小)在解析目标版本时直接跳过并拒绝安装 |
| 🩹 补丁名体检 | dsh 的补丁装载器对 cordis.patch.yml 每条记录做严格名校验,钉住的包名不存在时整条静默跳过(含 config)——0.1.7-rc.2 把 dsh-llm-deepseek 改名为 dsh-llm-deepseek-api-key,用户自定义模型列表无声失效,唯一信号是一行 stderr。雷达现在把每个 profile 的补丁文件对照装载器全部解析来源(依赖树、声明的 bundles、两层 node_modules、bundle 补丁行)做体检,钉住已消失名字的条目以横幅呈现,附修复方式与逐 profile 验证命令(`dsh --profile --dump-config 2>&1 >/dev/null |
| 🧯 Host 导出检查 | 扫描第三方插件对 @deepseek-ai/* 的 named import,对照当前(以及本体有新版本时的目标)DSH host 包实际导出。peer 范围拦不住「范围合法、导出没了」——这种错误会在启动时整棵插件树挂掉。雷达本体卡片和插件行给出提醒,并附带可复制的 cordis.patch.yml 禁用片段与 dsh plugin remove 命令。DSH 已经起不来时,不经过 dsh web,直接跑 node …/dsh-update-copilot/lib/cli.js |
| 🚦 peer 范围预检预警 | 对每个插件声明的 @deepseek-ai/* peerDependencies,用含 prerelease 规则的 semver 对照运行中 dsh(以及本体落后时的升级目标)——^0.1.0-rc.8 对 0.1.2-rc.1 这种版本号里看不出来的坑会被点亮。预警以行徽标呈现、随更新结果返回;无法解析的范围保持沉默,预检自身的任何故障都不会阻断扫描或更新。Release 说明与提交里的破坏性变更标记同样被扫描,并入预检预警。 |
| 🧭 升级卡 corridor + 分层预检 | 预检输出对齐社区三层失败签名(link-time / mount-time / run-time,外加 storage / peer / breaking-card):layerFindings 携带 action level、证据与修复建议。跨 host 版本会先走 oh-my-dsh 升级卡 corridor——缺边即停(没有 curated 卡的 hop 不会假装安全);session 格式 V2→V3→V4 只向前迁移,跳变要求先快照。已知 run-time 契约坑(prepareCall、Session.events、registerContinuableSetup 等)做静态能力风险提示。 |
| 🩹 更新后连带体检 | 更新成功后重新体检 profile 的全部插件成员,而不只是被更新的包——pnpm 会整树重写共享依赖,没被动过的兄弟插件也可能被连累。新增的 broken/missing 行会出现在更新结果里,并标注为连带损坏。 |
| ↩️ 更新历史与回滚 | 每次变更前,更新助手把已装版本、spec、pinned commit 和 bundle patch 原文快照进 $DSH_HOME 下自己的历史目录(每包保留 10 份,尽力而为)。回滚 = 以旧 target 走现有带确认的更新流程——行上有两段式回滚按钮。离线 CLI 可列出快照与手工回滚命令:node …/lib/cli.js history [profile] [package]。 |
| 🌐 完整双语 | 所有面向用户的文案——弹窗、徽章、更新错误——跟随界面语言(中/英);Agent 工具路径保留稳定英文标识 |
安装
# 从 npm 安装(推荐)
dsh plugin --profile web add dsh-update-copilot
# 或者直接从 GitHub 仓库安装
dsh plugin --profile web add github:hezhongtang/dsh-update-copilot
重启 dsh web,点击侧栏设置旁的**「更新助手」**入口。其他 profile 用法相同(--profile <name>)。
使用
问你的 Agent
「帮我看看插件有没有更新」
Agent 会调用 update_copilot_scan,对落后项跑 update_copilot_preflight、先呈现风险,然后等你拍板。更新工具在没有 confirm: true 时直接拒绝执行。
或者用弹窗
设置旁的侧栏按钮打开紧凑雷达弹窗(ESC 或点击遮罩关闭)。按钮右侧的**「⚡ 一键更新」**在点击时直接开跑(不经过弹窗):按序更新所有落后且可自动更新的插件,运行中按钮显示 n/m 进度、徽章变跳动圆点,完成短暂显示 ✓/✗ 后恢复;失败或需重启时自动打开弹窗展示明细。在弹窗内勾选「点击按钮时自动更新」后,点侧栏按钮还会在发现有落后插件时立即自动开始「一键更新全部」,进度直接显示在弹窗里。
更新过程全程可见:无论由谁发起——侧栏自动更新、你点的行内更新、Agent 工具(update_copilot_update)、另一个浏览器标签页——弹窗没开时,侧栏按钮的徽章会变成跳动的圆点(悬停提示正在更新的包名);弹窗打开时,顶部常驻一条「正在更新:包名(profile)…」横幅,跟随服务端实时阶段(解析依赖 / 下载中 / 重试中)与百分比。横幅出现期间所有变更操作(行内「更新」、「更新 bundle」、「一键更新全部」)都会禁用,避免后台更新与前台的点击抢同一把锁而撞出「正在更新中,请稍候」的报错。批量跑序(「一键更新全部」「更新 bundle」)行内直接呈现队列状态:正在执行的那行显示「更新中…」与实时进度条,还没轮到的那行按钮变成**「待更新」**(悬停提示当前项完成后自动开始),已跑过的行则保持原样,避免把旧扫描的「可更新」误读成未开始;更新结束后列表自动刷新出新版本。
弹窗即完整雷达:本体卡片的**单一「更新本体」操作(始终取雷达验证过的最新版、绝不执行 dist-tag 字符串;在可写的全局 npm 安装上,两步确认按钮代跑带闸门的 npm install -g 并报告重启要求与回滚命令——npx 等其余形态仅展示命令)、全部已装插件跨 profile 合并成一行(每个 profile 的当前 → 最新版本内联展示)、可展开的挂载关系,以及每行一个一键「更新」按钮。子项行的「更新」只作用于子项,父项普通「更新」只作用于父项;「更新 bundle」跳过当前目标,在父项符合条件且过期时先运行父项,再按每条关系的 profile 范围依次运行过期的已选挂载子项,并报告进度与结果。每个包都带明确的合格 profile,不会按同名依赖盲目更新全部 profile。工具栏的「一键更新全部」**仍是独立的全局操作,按序跑合格的落后包。更新过程由 SSE 实时推送到每行进度条。更新完成后,结果报告 dsh 重启要求,弹窗显示重启横幅。
Agent 工具一览
| 工具 | 读/写 | 用途 |
|---|---|---|
update_copilot_scan |
读 | 全量扫描:核心 + 所有 profile,按包合并(10 分钟缓存,force 强制刷新) |
update_copilot_update |
写 | 执行一次已确认的更新——不传 profile 时只在该包明确列出的合格 profile 中执行;npm/github 通道走官方 dsh plugin CLI(瞬时失败自动重试——最多 3 次、指数退避加全抖动;版本不存在、鉴权被拒等确定性错误快速失败)。link:/file: 本地目录不由助手管理,请在它自己的 checkout 内更新。target 可回滚到确切的旧版本;force: true 覆盖预检硬拦截(仅在用户明确同意后传入) |
update_copilot_preflight |
读 | 一个包的门检决策,不触发任何变更:按 profile 给出 ok / warning / blocked,附拦截证据(目标 dsh 缺失的导出)、peer 范围预警、release notes 与 commits 的破坏性变更信号 |
update_copilot_core |
写 | 执行已确认的 DSH 本体更新。始终以最新健康发布版为目标,先解析成具体版本(绝不执行 dist-tag 字符串),解析出降级时无 force 拒绝。执行前过全套闸门:升级卡片走廊、session 格式存储边界、跨全部 profile 的逐插件导出证据;force 仅在用户同意后覆盖,证据保留在结果里。只在可写的全局 npm 安装上执行——npx / 不可溯源的启动会返回手工命令。结果必带 requiresRestart 与回滚命令 |
工作原理
每个依赖 spec 先分类到通道,每个通道有自己的比较方式。扫描结果按包跨 profile 合并:同一个包装在 web / headless / desktop,就只出现一行,携带每个 profile 的通道与版本,以及明确的合格更新 profile。每个 profile 内,活动 bundle 的包内 patch 若挂载至少两个生产依赖,会展示仅用于呈现的挂载关系;多个父包声明同一子项时,先选已验证子项更多的父包,再按包名确定归属。挂载关系不转移更新归属,每个直接依赖仍按自身策略更新;bundle 更新沿用所选关系的 profile 范围。link: 与 file: 本地依赖保持本地;官方 @deepseek-ai/* 包只报告,不能独立更新。
什么才算一行插件: profile manifest 里 dsh.profile.bundles 声明的包(宿主真正加载的那份清单),外加所有 link: / file: 本地开发检出——尚未激活也保持可见,外加活动 bundle 的已验证 patch 挂载子项——宿主正是通过 patch 的 insert 记录加载这些插件。manifest 里的其它普通依赖(顺手装进来的 CLI、服务端运行时等)不是 dsh 插件,也不会渲染成插件行;否则同一个 GitHub 仓库的真插件旁边会多出一个幽灵更新按钮。manifest 没有 bundle 清单时回退为展示全部依赖。
| 通道 | spec 示例 | 当前版本 | 最新版本 |
|---|---|---|---|
| npm | ^0.1.4 |
已装 package.json 的版本 |
registry 全量文档中的最新版 |
| github | github:owner/repo#sha |
pnpm-lock.yaml 锁定的 commit |
GitHub API 查询的上游 HEAD |
| linked | link:../my-plugin |
已装 package.json 版本 |
—(不探测;在其自身仓库内管理) |
npm 通道刻意不信任 latest dist-tag:monorepo 子包的这个 tag 常年滞后,会把实际比 tag 更新的安装误报为落后。版本比较采用完整 semver 优先级(含 prerelease),因此 0.1.0-rc.6 > 0.1.0-rc.5、1.0.0 > 1.0.0-rc.1 都成立。
更新通过严格校验的路径执行,绝不拼接 shell:npm/github 通道走 dsh plugin --profile <p> add <target>——和人手动输入的是同一条路径——目标字符串经过 allowlist 校验;link:/file: 本地目录绝不触碰。DSH 本体走独立的带闸门执行器:目标先解析成具体的钉定版本(绝不执行 tag 字符串),安装形态必须是可写的全局 npm 安装,且闸门——走廊、存储边界、跨全部 profile 的逐插件导出证据——通过后才 spawn npm install -g @deepseek-ai/dsh@<版本>;闸门同时产出咨询级预警(补丁钉住的名字目标版本不再发布),升级成功后逐 profile 的 post-flight --dump-config 探测把新装载器的跳过行并入同一组预警;运行中的进程永远不会是被更新的那个,因此变更必然报告重启要求与回滚命令。瞬时失败自动重试:最多共 3 次,间隔采用指数退避 + 全抖动(基准 1s、上限 8s),避免一批更新在网络恢复瞬间同时扎堆重试;确定性错误——包或版本不存在(E404、ETARGET)、鉴权被拒(E401/403)——跳过剩余次数快速失败。子项、父项和 bundle 操作都只按包行里明确列出的合格 profile 执行;「一键更新全部」仍是独立的全局操作,绝不因同名依赖而更新全部 profile。
DSH 起不来时
第三方插件若 import { 某个已删除的名字 } from '@deepseek-ai/…',loader 会让整棵 plugin tree 失败,更新助手的 Web 界面也出不来。这时在任意能跑 Node 的 shell 里:
node ~/.dsh/profiles/web/node_modules/dsh-update-copilot/lib/cli.js
# 本地 link 安装:
node /path/to/dsh-update-copilot/lib/cli.js
只对照当前磁盘上的 DSH(不查 npm、不预演目标版本),因此 DSH 起不来时也能跑。已不兼容时退出码为 1,并打印禁用 / 卸载命令。要从一次失败的更新中恢复,用 history 子命令列出更新前快照与手工回滚命令:
node ~/.dsh/profiles/web/node_modules/dsh-update-copilot/lib/cli.js history # 所有 profile
node …/lib/cli.js history web my-plugin # 单个包
安全性
- 变更路由有两个:
POST /dsh-update-copilot/update(插件)与POST /dsh-update-copilot/update-core(带闸门的本体更新):强制同源且校验实际传输协议,必须显式confirm: true,不信任转发协议请求头。TLS 终止代理可设置其公开 HTTP(S) origin 至DSH_UPDATE_COPILOT_PUBLIC_ORIGIN;请求必须精确匹配,配置无效时拒绝所有请求。 - 官方
@deepseek-ai/*包和 dsh 本体绝不自动更新;本体只在显式确认的动作下执行,且仅限可写的全局 npm 安装。 - 所有上游查询均为只读(
registry.npmjs.org、api.github.com、git ls-remote)且带硬超时;单项查询失败只降级该项,不影响整体扫描。
限制
- 每次有变更的更新都需要重启
dsh才生效:结果返回requiresRestart: true,弹窗显示重启提示。不做进程内热重载。 link:/file:本地目录在雷达中列出但绝不探测、绝不更新:请在它自己的仓库内管理(git pull)。- GitHub API 未认证时限流 60 次/小时——破坏性变更信号会优雅降级为无信号。
- 裸
git+https://spec 只报告、不提供比较通道。 - Host 导出检查是静态 named import:动态
import()、运行时才碰到的 API、以及import * as ns不会标出来。官方@deepseek-ai/*包不扫。目标版本只 pack 与 DSH 同版本线的@deepseek-ai/dsh-*;pack 失败或独立版本的包(cordis、schemastery)跳过,不报假不兼容。 - peer 范围检查覆盖常见范围写法(caret、tilde、区间、并集、通配、精确)并遵循 node-semver 的 prerelease 规则;生僻写法按「无法评估」保持沉默。历史快照尽力而为——目录不可写时只是没有回滚建议,更新本身绝不会被阻断。
参与贡献
欢迎提 Issue 和 PR:hezhongtang/dsh-update-copilot。代码库刻意保持小巧、零依赖——host 是纯 ESM,浏览器端是手写 CJS bundle,无需搭建任何构建环境。
许可
MIT © 2026 hezhongtang
链接
同类插件
yjh051108/dsh-routing-suite★ 7003
一个仓库三件套:DSH 插件包的运行时注入器(注入、热重载、卸载、开发侧挂区一键转正、路由自愈,外带设置页插件管理:列出、卸载、拖入文件夹内化)、任务感知的思维模式路由 agent 预设(router-standard / router-spec / router-react)、以及分级两级任务协议(commit_star / lock_stage / revise_do / edit_plan / mark_task / redteam_verdict 六个工具,任务状态落盘)。注入器实现直接在库内,安装的是它自己的行为而不是一份依赖清单。
strukto-ai/mirage#dsh★ 3666
把文件系统与 bash 提供者换成 mirage 虚拟工作区:文件工具与 shell 命令作用于挂载的资源(RAM、S3、Redis、Slack、Gmail、Notion、Postgres)而非宿主磁盘,支持按挂载点设置读/写/执行模式、按命令选择沙箱(进程内 monty、pyodide、quickjs;远程 docker、e2b、daytona),并可在虚拟终端中安装 CLI(git、gh、slack、linear、ntn、gws,或自行注册的程序树)作为命令头词。
hust-open-atom-club/oh-dsh★ 325
社区发行版:TUI、桌面端与 Web UI 统一体验,分层安装、一步到位。
weijiafu14/pi2dsh★ 206
Pi Host ABI 兼容引擎:装一次之后,npm 上的 Pi 扩展原包经 `dsh plugin add <pi-package>` 直接作为 DSH 原生插件挂载。已在官方 DSH 上端到端验证 pi-mcp-adapter(完整 MCP 管理面:OAuth、resources、prompts、MCP Apps、elicitation、sampling)、@tintinweb/pi-subagents、pi-code、pi-hermes-memory、pi-background-tasks;`pi2dsh inspect` 在安装前报告一个包的兼容情况。
lire1131/dsh-undo-savepoint★ 166
DSH 撤销/回退系统:配置变更自动存档,一键撤销/恢复/回退到任意版本,支持 WebUI 与离线 CLI/GUI 工具(DSH 启动失败也能救)。
Fishquito7/dsh-skill-mcp-panel★ 155
在 DSH Web 设置中管理技能与 MCP 服务器:技能卡片热启停、工作区作用域、分组、批量迁移与拖拽导入,以及 stdio/HTTP MCP 增删改查、连接测试、密钥脱敏,并附带统一 dsh-panel 命令行。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。