dsh-plugin-upgrader

DSH PLUGIN开发与运行时

仓库 zuwenyin/dsh-plugin-upgrader

开发与运行时 L5 · 运行验证通过 安全审查:低风险 可信度:金 可安装插件
安装这个插件

dsh-plugin-upgrader 是 zuwenyin 维护的 开发与运行时 类 DSH 可安装插件, 仓库为 zuwenyin/dsh-plugin-upgrader,许可证 MIT。 下面按「装什么、怎么装、验没验过、跑起来要注意什么」逐项列出。

一句话选型结论

按资料字段整理

dsh-plugin-upgrader 是开发与运行时类的 DSH 可安装插件,验证等级 L5 · 运行验证通过,安全审查为低风险,有可直接复制的安装命令。验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么;涉及密钥或系统权限的,建议先在隔离环境试装。

分类开发与运行时 收录类型可安装插件 验证等级L5 · 运行验证通过 安全审查低风险
验证等级 L5 L5 · 运行验证通过
GitHub 星标 1 复刻 0 · 未关闭 issue 1
最近更新 2026-10-30 创建于 2026-10-22
README 15.1 KB 正文体量,越大说明说明书写得越细

安装

可安装插件
在 DSH 里执行,装完用 dsh plugin list 确认已挂上;标了 L4 / L5 的命令已在沙盒里真实跑通
dsh plugin --profile web add github:zuwenyin/dsh-plugin-upgrader
  1. 1
    确认版本与运行环境

    仓库没有标注兼容版本与 Node.js 要求,先确认你的 DSH 版本能装,再继续。

  2. 2
    执行安装命令

    在 DSH 里执行上面的命令;多包仓库要注意区分具体子包名,别装错包。

  3. 3
    确认已挂载

    用 dsh plugin list 查看列表里是否出现这个插件,出现即挂载成功。

  4. 4
    试跑并检查权限

    加载后跑一个最小用例,确认它能正常工作;同时看它申请了哪些文件、命令或网络权限。

兼容 DSH 版本未标注版本不匹配时安装会报错
Node.js 要求未标注来自仓库 package.json 的 engines 字段
前置依赖无需要同时安装的同级依赖
npm 包名未发布到 npm可用 npm view 查看包信息

能做什么

开发与运行时
字段来自项目仓库与公开索引,中文说明由本站标注

上游标签

deepseek-harnessdshdsh-pluginplugin-managerversion-manager

验证等级与安全审查

L5 · 运行验证通过
自动化流程结论,不是人工审核
验证等级L5 · 运行验证通过在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来
安全审查低风险静态分析结论,未标注不代表已通过审查
仓库健康度活跃按仓库活跃度与最近更新时间给出
可信度金综合仓库活跃度与验证结果

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 验证等级 L5:安装和运行都在沙盒里跑通过,装完能直接用的概率高。
  • 静态安全审查为低风险,没有发现明显可疑行为。
  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有声明 Node.js 版本要求,版本不匹配可能装不上。
  • 验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么。

更适合

  • 需要在开发与运行时场景里给 DSH 补能力的人。
  • 想装完就能用、不想自己排依赖的人。
  • 能接受在本地装依赖、愿意自己确认权限的人。

不太适合

  • 只使用 DSH 官方内置能力、不接受第三方插件的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
插件验证等级安全审查星标兼容版本安装命令
dsh-plugin-upgrader当前 L5 · 运行验证通过 低风险 1 未标注 有
deepseek-harness L3 · 安装规范通过 低风险 24.6 万 未标注 无
rea L4 · 沙盒安装通过 低风险 2.6 万 0.1.1-rc.2 有
dsh-TUI L4 · 沙盒安装通过 中风险 4,292 0.1.7-rc.2 等 5 个 有
mirage L3 · 安装规范通过 低风险 3,681 未标注 无
dashi-taskboard L4 · 沙盒安装通过 低风险 3,311 0.1.1-rc.2 有

仓库档案

开发与运行时
字段来自项目仓库与公开索引,中文说明由本站标注
作者 / 维护方zuwenyin仓库 dsh-plugin-upgrader · 默认分支 main
分类开发与运行时dev
收录类型可安装插件声明了 dsh.bundle、可用 dsh plugin add 安装的条目
开发语言未标注仓库主语言
许可证MIT商用或二次分发前请确认条款原文
星标 / 复刻 / issue1 / 0 / 1收录时的数值,非实时
创建 / 更新2026-10-22 · 2026-10-30最后推送 2026-10-30
本站收录2026-10-30首次进入本站目录的时间

README 全文

15.1 KB
作者原文,中文版优先;只做安全转义,不改内容

dsh-plugin-upgrader


> 给 DeepSeek Harness(DSH)的「插件」页补上一键升级和版本历史 / 回滚。

DSH 自带的插件页能装、能卸、能看已安装列表,但缺两件事:一次把全部插件升到最新,以及退回某个旧版本。
这个插件在插件页里加一个「版本」标签,把这两件事补齐。

English · 中文

功能

  • 一键升级 —— 一次把全部可升级插件升到最新版,带进度、逐项结果和失败原因。
  • 升级不卸载 —— 换版本走 in-place 替换,插件不会被卸下来再装回去(详见下文)。
  • 看得见的进度 —— 升级时直接显示 pnpm 的原始输出(含换源重试、lockfile 校验),
    每步都有已用时计时和不确定态进度条,卡住时可以一键取消。
  • 多选升级 —— 勾选任意几个插件,只升级选中的这些。
  • 版本历史 / 回滚 —— 展开任意插件即可看到已发布的全部版本(含发布时间与引擎要求),点一下切到那个版本。
  • 一键跳 GitHub —— 每行的 GH 按钮打开插件仓库主页;点版本号直接进该版本的 GitHub 发布页。
  • 镜像落后会标出来 —— 配置的镜像还没同步、但上游已经发布的版本会单独标一行,
    而不是假装已经是最新版。

> 要改这个仓库?先读 AGENTS.md。 那里逐条写了「已经实现并且必须继续成立」
> 的行为、对应代码位置和守护它的测试。上面这些功能里,GH 链接和 in-place 升级都曾经
> 被无意改掉过一次。

界面位置

插件页顶部标签栏多出一个「版本」标签,与「已安装」「发现」并列:

  • 顶部统计:可升级数量 / 已安装数量 / 每个插件的版本数
  • 「一键升级」升全部可升级插件;下面一条选择栏负责「升级选中」
  • 「检查更新」强制刷新 registry 缓存(默认缓存 5 分钟)
  • 搜索框按包名过滤
  • 每个插件一行,展开「历史 (n)」后是该插件的完整版本列表
  • GH 打开仓库主页(没有仓库的插件不显示该按钮)
  • 版本列表里每个版本号本身就是链接,点开直接进 GitHub 的发布页:
  • 该版本打过 tag → releases/tag/v(tag 是否真实存在由 GitHub tag 列表确认,
    不是猜的,所以不会点进 404)
  • 该版本没打 tag,或 GitHub 列表读不到(限流 / 离线)→ 退回仓库的发布列表 releases,
    不在页面上放一个点进去是 404 的版本号

安装

在「插件」页的发现标签里搜索 dsh-plugin-upgrader,点安装即可。
桌面版请用它自带的插件管理界面安装,命令行改动不了正在运行的桌面 profile。

用 dsh 命令行(把 web 换成你自己的 profile 名):

dsh plugin --profile web add dsh-plugin-upgrader

从源码安装:

git clone https://github.com/zuwenyin/dsh-plugin-upgrader.git
cd dsh-plugin-upgrader
dsh plugin --profile web add "$PWD"

装好后打开「插件」页,顶部会多出「版本」标签。不需要重新构建,也不用重启。

工作原理

浏览器端读不到 profile 的依赖清单,也无法可靠直连 npm(CORS、私有源、token),
因此所有包操作都放在宿主端:

路由 作用
GET /api/plugin-upgrader/overview 已安装插件 + 各插件已发布版本(registry packument,5 分钟缓存,20 秒超时,最多 4 个并发)
POST /api/plugin-upgrader/job 提交一批升级 / 切换步骤,立即返回 job id
GET /api/plugin-upgrader/job?id=… 轮询进度、当前阶段、已用时、逐项结果与实时日志
POST /api/plugin-upgrader/cancel 中断当前步骤(任何一次安装,包括退回老路径后的重试)

所有路由仅限本机回环访问:批量操作会安装软件包,配对设备或跨站页面一律拒绝。

为什么升级不卸载插件

pluginManager.installBundle 对已安装的包名会以 already-installed 拒绝,
pnpm 根本不会跑。所以换版本的顺序是:

  1. 先直接 install;
  2. 被拒绝时,把 profile package.json 里那条依赖临时摘掉(先写 journal),再 install ——
    pnpm 写回新版本,插件不被卸载,加载器里的实例不断,启用状态也不用恢复;
  3. 只有第 2 步主动放弃(manifest 读不了 / install 失败 / 被拒绝)时,
    才退回 remove + install 的老路径。

旧版本号会回传给界面,用于提示这是降级。

> 实现在 1.2.0 就有了,但 1.2.0–1.4.0 在桌面端从未真正生效:
> profileDirFrom() 只认 DSH_PROFILE_DIR / DSH_HOME + DSH_PROFILE,而桌面壳启动宿主时
> 不导出这些变量(它直接把 profile 目录当作子进程的 cwd),于是第 2 步第一行就放弃了,
> 每次升级都悄悄走 remove + install。1.4.1 加了 cwd 回退之后才真正走这条路。
> 细节见 AGENTS.md 第 2 条。

升级中断后 profile 还能自己长回来

第 2 步要在「依赖条目已经删掉、新版还没装上」的窗口里改 profile 的 package.json。
如果进程正好在这段时间被杀掉,插件就从 manifest 里消失了,等于装不回去。
所以删除之前先写 package.json.upgrader-journal.json:下次插件加载时会读它,
manifest 里确实缺这条就补回去,已经装上就只清掉记录,记录和 manifest 对不上就忽略。
恢复失败只是打日志,不会拦住标签页加载。

enabled 状态保留

卸载会丢掉插件原有的启用 / 禁用状态,因此任何真的卸载过插件的步骤都会在装完后
按操作前的状态重新 setBundleEnabled(src/host/install.ts:251 restoreEnabledState),
禁用中的插件升级后仍然是禁用状态。in-place 那条路不卸载,所以本来就不需要恢复。

为什么升级有时候要好几分钟

不是这个插件慢,是 pnpm 慢。pnpm 11 在 install 前会拿锁文件里的每个条目去 registry
重新核对一次(Verifying lockfile against supply-chain policies),国内镜像
(registry.npmmirror.com)对不少包会 ETIMEDOUT,于是走 10 秒 → 1 分钟的重试阶梯。
真正卸载再安装的那种降级路径要跑两条 pnpm 命令,两段各等一次。

旧版本在这里什么都不显示,进度条只在「整步完成」时动一格,所以看起来就是死住了。
现在宿主端订阅了 plugin-manager/install-log 和 plugin-manager/install-state,
把 pnpm 的原始输出、当前阶段、重试次数实时转进 job 日志,界面同时显示已用时和
不确定态进度条:慢的时候你能看见它在重试,而不是盯着一个不动的 0%。

阶段一共四个:verifying(在校验锁文件)→ installing → applying / cancelling。
锁文件校验那一行会连续几分钟不动,单看和「卡死」一样,所以单独给它一个阶段名。

顺带修掉的两个坑:

  • 心跳改成定时器(2 秒),不再按「完成一步」写。单步超过 15 分钟以前会被误判成
    「job 已放弃」,于是一个健康的任务被作废,还能再并进来一批。
  • 退回老路径时那一次重新安装以前用 requestId: undefined,导致那一段无法取消;
    现在每次安装都有自己的 id,取消在任何阶段都有效。

写入锁超时说人话

profile 的 package.json 由 harness 用同目录的 package.json.lock 串行化。
manager 自己的预算是 120 秒,而 atomic-write 给不写预算的调用方的默认值是 2 秒,
所以偶尔能看到:

atomic-write: timed out waiting for the writer lock at …/package.json.lock

这句话只报一个文件名和一个 pid,用户无法处理。现在失败信息会先读那把锁,再说清楚是
「另一个操作正在改写,等它结束再试」还是「锁没释放,重启 DSH 会自愈」,
原文放在方括号里保留,方便搜索或贴进 issue。

自己那一行不能自己升级

批量升级的第一步是卸载,而卸载的正是此刻在跑的那段代码。所以「一键升级」永远跳过本插件自己,
自己那一行落后时走插件页自己的安装流程;页面没有提供安装入口时明确说一句,
而不是让人点一个必然失败的按钮。

同一时刻只跑一批

宿主端一次只允许一个 job。重复提交会拿到 409 busy(带正在跑的那个 job id),
界面据此接管那一批的进度显示,而不是弹一条看不懂的错误:

  • 新开一个插件页标签、或在进度跑着时再点「一键升级」,都会看到正在进行的那一批
  • overview 里带 active 字段,标签页一挂载就能接上正在跑的任务
  • job 每 2 秒刷一次心跳时间戳,宿主重启后遗留的「僵尸 job」会按心跳超时自动作废,
    不会永久占着位置让之后所有升级都撞 busy

主进程重启会让正在跑的 job 中断,界面会把这种情况显示为失败而不是永远转圈。

项目结构

dsh-plugin-upgrader/
├── AGENTS.md             **改代码前先读**:不可退化的行为 + 守护测试
├── src/                  源码(TypeScript)
│   ├── index.ts          宿主端入口:路由注册、job 调度、加载时恢复 manifest
│   ├── host/             宿主端逻辑(Node,无 DOM)
│   │   ├── overview.ts   组装 overview 载荷(含并发上限)
│   │   ├── registry.ts   registry packument 拉取 / 裁剪、GitHub tag 列表、镜像缺口
│   │   ├── install.ts    单步安装:in-place 替换、remove 回退、enabled 状态恢复
│   │   ├── manifest.ts   profile package.json 读写、journal、加载时恢复
│   │   ├── lock.ts       读 profile 写入锁、把锁超时翻成人话
│   │   ├── progress.ts   从 pnpm 原始输出推断 job 阶段
│   │   ├── bundle.ts     插件元数据(来源分类、多语言字段、图标)
│   │   ├── repo.ts       仓库 URL 归一化
│   │   ├── version.ts    semver 比较、发布页链接
│   │   ├── http.ts       回环校验、JSON 读写
│   │   └── manager.ts    宿主 pluginManager 服务的最小类型契约
│   └── client/           浏览器端(拆成模块,由 esbuild 打成一个文件)
│       ├── index.ts      createPlugin(require):槽位注册入口
│       ├── components/   Tab / PluginRow / VersionLine / JobPanel
│       ├── boot.ts       reload 前确认 boot 文档还有效(见 AGENTS.md 第 4 条)
│       ├── copy.ts       zh / en 文案
│       ├── styles.ts     作用域 CSS
│       ├── hooks.ts      locale 订阅、overview 拉取、外观插件判定
│       ├── api.ts        fetch 封装、job 轮询
│       ├── format.ts     版本号 / 日期 / 外部链接
│       ├── env.ts        window 上的最小类型声明
│       └── types.ts      载荷类型
├── lib/                  构建产物(**已提交**,见 AGENTS.md 第 12 条)
│   ├── index.js          宿主端入口(tsc 输出)
│   ├── host/*.js         宿主端模块 + .d.ts
│   └── client.js         浏览器端单文件 bundle(含 __ModuleLoader__ 包装)
├── scripts/build.mjs     构建脚本:tsc 编译宿主端 + esbuild 打包 client(加 --watch 即 dev)
├── scripts/verify-pack.mjs            发布前核对 tarball 里都有什么
├── scripts/verify-build-committed.mjs 核对 `lib/` 与源码一致且已提交
├── test/                 node:test 单元测试(.ts,Node 24 直接剥离类型)
├── locale/               (保留)语言包
├── assets/icon.svg       图标
├── cordis.patch.yml      bundle 注册
└── package.json

浏览器端虽然拆成了多个 .ts 模块,但最终由 esbuild 打成一个 lib/client.js,
外面套上 window.__ModuleLoader__.load({ id, factory(require) { … } })。
运行时它只能 require('react') 这类由宿主提供的模块,不能 require 自己的其它文件,
所以「拆模块」只发生在源码层,产物仍然是单文件。

开发

本项目用 pnpm 管理依赖(package.json 里钉了 packageManager,CI 也用 pnpm):

pnpm install       # 只装依赖(不会构建,见下)
pnpm run dev       # 监听 src/,宿主端和浏览器端改完即编译(Ctrl+C 停止)
pnpm run build     # tsc 编译宿主端 + esbuild 打包 client → lib/
pnpm run typecheck # tsc 检查 src 和 test
pnpm test          # node:test 单元测试(.ts 直接运行)
pnpm run check     # 以上全部(typecheck + build + test + pack 检查 + 产物是否已提交)

lib/ 是提交进仓库的,不是构建垃圾:DSH Store 审核固定 commit,不会为了补齐
运行时文件去执行 prepare。所以 pnpm install 不再触发构建(安装期脚本会被审核
直接否决),构建挂在 prepack 上;改完 src/ 必须 pnpm run build 并把 lib/
一起提交,pnpm run check 会替你核对。详见 AGENTS.md 第 12 条。

改任何代码前先读 AGENTS.md。 那里列的是「已经实现、不能再退回」的行为,
每条都附了代码位置和守护它的测试名;pnpm run check 全绿只说明没写坏,不说明没改坏
(很多行为没有对应测试,比如「自己那一行不出现在批量升级里」之外的边界情形)。

新增或修改测试后,问一句:这个测试真的会红吗? 把被测的字符串或分支临时改成哨兵值
再跑一次,确认它失败,然后改回来。不会失败的测试等于没写。

宿主端在 src/index.ts(webServer 前缀路由 /api/plugin-upgrader),
浏览器端在 src/client/index.ts(注册 plugins.tab 槽位)。

pnpm run dev 会并行跑两个监听器:tsc --watch 负责 lib/index.js 和
lib/host/**,esbuild 负责 lib/client.js,两者输出互不覆盖。注意 esbuild
打包时会直接剥掉类型而不做检查,所以改浏览器端时顺手跑一次 pnpm run typecheck。

改完代码后必须重新构建(profile 里的 link: 指向本目录,但加载的是 lib/,
不是 src/),并把重建后的 lib/ 一起提交。pnpm run dev 已经替你重建了产物,
但插件本身不会热更新——要让宿主重新加载本插件,无需重启应用:先
pluginManager.setBundleEnabled(name, false) 再 setBundleEnabled(name, true)。

发布

见 RELEASING.md。首次手动发一次,之后打 v* tag 由 CI 通过 npm trusted publishing 自动发布:

pnpm publish --access public   # 仅首次

许可

MIT

常见问题

6 问
答案由本站依据条目字段整理,不引用上游原文
dsh-plugin-upgrader 怎么安装?

在 DSH 里执行 `dsh plugin --profile web add github:zuwenyin/dsh-plugin-upgrader` 即可。

dsh-plugin-upgrader 的验证等级是什么意思?

L5 · 运行验证通过。在 dsh 沙盒中完成安装与运行冒烟——装得上、跑得起来

dsh-plugin-upgrader 安全吗?

低风险。

dsh-plugin-upgrader 装之前要先确认什么?

先看它会读写哪些文件、执行哪些命令、连接哪些网络地址;验证等级只说明装得上、跑得起来,不等于安全。涉及密钥或系统权限的,建议先在隔离环境试装。

dsh-plugin-upgrader 用的是什么许可证?

上游标注为 MIT。商用或二次分发前请到仓库确认许可证原文。

这条记录的数据可靠吗?

本站按仓库名去重后合并整理,字段以作者仓库与 npm 元数据为准;安装命令、仓库地址与 README 保持原文,带 L4 / L5 标记的安装命令已在隔离沙盒里真实跑通。

开发与运行时
按星标排序,可作替代方案

rea

rea

L4 · 沙盒安装通过 2.6 万 星

dsh-TUI

dsh-TUI

Claude Code 风格全屏终端 UI:像素鲸鱼顶栏、实时工作状态行、思考流式展开。

L4 · 沙盒安装通过 4,292 星

mirage

mirage

把文件系统与 bash 提供者换成 mirage 虚拟工作区:文件工具与 shell 命令作用于挂载的资源(RAM、S3、Redis、Sla

L3 · 安装规范通过 3,681 星

dashi-taskboard

dashi-taskboard

把当前已安装并运行中的 Codex Taskboard 嵌入 DeepSeek Harness 侧边栏,并通过 Launcher 运行时描述

L4 · 沙盒安装通过 3,311 星

插件的元信息来自作者仓库;分类、验证等级与安全结论的中文说明为中文整理,最近核验 —。