每小时检查 npm 上已安装插件的新版本,并询问升级其中哪些。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-update-notifier
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:stuarthu/dsh-update-notifier
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
每小时——或用 /check-updates 随时手动触发——检查已安装的
DeepSeek Harness(dsh)
插件有无新版本,并用一个一键审批气泡让你决定是否升级。
dsh 本身不会告诉你某个已安装插件已经出了新版,只能靠自己记得去 npm view。
本插件补上这一环:每小时把每个已安装插件和注册表比对一次,发现更新时直接在会话里
弹出一个真正的提问气泡,问你要升级哪些。勾选之后由智能体当着你的面执行升级。
它绝不会擅自升级任何东西。
行为
每小时(可配置)对每个支撑已加载插件的 npm 包:
查询注册表的
latest,与 profile 的node_modules中已安装的版本比对。 版本比较严格遵循 semver——预发布版本排序正确,绝不建议降级;不符合严格X.Y.Z格式的版本会被跳过,而不是猜测其含义。用一个气泡询问。 所有更新的版本会汇总成一个多选提问,由 dsh 自己渲染 (
dsh-chrome 0.1.2 -> 0.1.3,每个插件一个选项),挂在你最近活跃的会话上。 它不占用模型轮次、不消耗 token,断线重连后还会重放。把勾选的交给智能体:以一条后续消息指示它执行
pnpm --dir <profileDir> add <pkg>@<latest> ...智能体会立即被唤醒,你可以直接看到升级过程。搭配
dsh-hot-reload使用,新版本无需重启 dsh 即可生效。
/check-updates
不想等下一个整点?在会话里输入 /check-updates:
/check-updates
check-updates · 2 updates — see the question above (7 plugins checked)
它会立即针对你输入命令的那个会话跑一轮完整检查,并在注册表查询结束的那一刻就
结算这条命令——它弹出的气泡就是一个普通气泡,你可以随时回答,刷新页面也不会丢。
如果当前根本无法弹出气泡,结算文本里会直接给出 pnpm ... add 命令,而不是只
告诉你"做不到"。
查询不到的包(网络故障、超时、5xx、限流,或响应里根本没有版本号)会在结算文本中
单独计数,而不会被当成"已是最新";如果所有包都查不到,这条命令会以错误结算,
而不是报告"没有更新"。两个数字相加即为本轮总数:5 plugins checked, 2 unreachable
表示一共查了 7 个。
取消这条命令会同时中止检查,因此被你取消的检查不会过一会儿又弹出气泡。
手动检查会忽略下面的拒绝记忆:既然是你主动问的,就把完整列表给你,包括你此前 未勾选的版本。它不会打乱定时检查的节奏;如果已有气泡未回答、或已有检查正在进行, 它会带着原因拒绝执行。
只要 dsh 组合了命令注册表,该命令就会出现——@deepseek-ai/dsh-base 就会组合它,
因此基于它的 profile 都能用 /check-updates。命令通过 ctx.inject 注册,所以
没有命令注册表的 headless profile 依然能加载本插件并照常执行定时检查。
只问一次
同一个版本只会问你一次(指定时检查;上面的命令可以越过这条规则):
- 未勾选的视为拒绝,记录在
<profileDir>/.dsh-update-notifier.json中, 跨重启永不再提,直到注册表的latest变成另一个仍然高于你已安装版本的 版本为止。删除该文件即可重新开始询问。 - 已批准的不会记录:升级成功后它自然就是当前版本;升级失败的话,重启后重新 提醒才是合理的。
- 你从未回答过的气泡(会话结束、dsh 停止)不算拒绝——下次仍会询问。
尚无活跃会话时,提醒会挂起:在你下一条消息之后立即重试,下一轮定时检查也会重试。
如果根本没有任何界面能渲染气泡——headless profile,或者虽然组合了 userQuestions
服务但没有任何 UI 向它注册 provider——提醒同样会挂起,并且会把可用更新和确切的
升级命令一并写入日志,因为这种情况下你再发消息也不会有气泡出现。
安装
dsh plugin --profile web add dsh-update-notifier
然后重启一次 dsh(bundle patch 层在启动时加载)。适用于任何 profile——把
web 换成你实际使用的 profile 即可,它检查的就是自己被加载进的那个 profile。
需要 Node 18+(依赖全局 fetch),任何 dsh 宿主都已满足。
兼容性
基于 dsh 0.1.0-rc.6(Node 22 / 24)构建并测试。它只使用宿主的公开服务,
因此某项缺失时只会降级而不会崩溃:
| 宿主接口 | 用途 |
|---|---|
loader.entries() |
找出哪些包支撑着已加载的插件 |
userQuestions.ask() |
渲染审批气泡 |
userQuestions.provider |
没有 UI 注册渲染时,不承诺会有气泡 |
agents.get(sessionId) |
解析会话对应的活跃智能体 |
agent.followup() |
唤醒该智能体执行升级 |
session/event(user/message) |
追踪最近活跃的会话 |
agent/disposed |
撤回会话已销毁的气泡 |
commands.register() |
注册 /check-updates 命令 |
agents.roots() |
避免承诺一个 ask() 会拒绝的气泡 |
userQuestions 和 commands 都是用到时才解析的,而不是声明为依赖,因此在两者
都不存在的 headless profile 中,插件依然能正常加载。
退出检查
不希望被提示升级的插件,可以在自己的 package.json 中声明:
{ "dsh": { "updateNotifier": false } }
对于不由你掌控的插件,用下面的 exclude 让它闭嘴。
配置
设置在 profile 的 cordis.patch.yml 里 update-notifier 那一行上:
| 键 | 默认值 | 含义 |
|---|---|---|
interval |
3600000 |
检查间隔毫秒数(下限钳制为 60000) |
initialDelay |
10000 |
启动后首次检查前的延迟毫秒数 |
registry |
https://registry.npmjs.org |
要查询的 npm 兼容注册表 |
exclude |
[] |
永不检查/提及的包名列表 |
fetchTimeout |
10000 |
单个注册表请求超时,毫秒(下限 1000) |
profileDir |
自动 | profile 目录的绝对路径(省略时从 loader base URL 自动探测) |
安全
- 未经点击不会有任何升级。 本插件从不自行启动包管理器,只负责组装气泡, 以及在你批准后生成那条由智能体当着你的面执行的指令。
- 注册表的自由文本不会进入 UI 或模型。 进入气泡和智能体消息的,只有来自你
本地 profile 的包名,以及通过
/^[0-9A-Za-z.+-]{1,64}$/校验的版本号——绝不 包含从注册表取回的描述、README 或变更日志。 - 后续消息的
source.kind为"plugin",明确列出已批准的包,并指示智能体不得 改动其他任何内容。
局限 —— 请务必阅读
- 它只负责询问,不负责验证。 你批准之后,升级就交给智能体执行了。失败会显示 在会话里,但本插件既不会重试,也不会事后确认新版本是否真的装上了。
- 只能看到从注册表安装的插件。 从本地检出 link 过来的插件,或 dsh 内置的
插件,在 profile 的
node_modules下没有对应的包,会被静默跳过——没有气泡, 也没有日志。 - 只查询
latestdist-tag。 不支持固定版本范围、next/beta通道,也无法 把某个包压在某个大版本上;对于永远不想升级的插件,请使用exclude。 - 同一时间只有一个气泡。 在它等待回答期间,定时检查会跳过,
/check-updates也会以"已有升级提问未回答"为由拒绝执行;这期间发布的新版本,会在你回答之后的 第一轮检查中被发现。 - 拒绝是针对那个确切版本的,而不是"到此为止的所有版本":如果注册表的
latest变成另一个仍然高于你当前版本的版本——包括 unpublish 之后降下来的 版本——你还是会被再次询问。 - 气泡需要一个 dsh 能挂载提问的会话。注册表故障、loader 状态异常、状态文件不可 写,都只会降级为日志;只有两种情况会让插件直接停用——上下文里没有插件 loader, 以及定位不到 profile 目录——此时日志中会明确说明是哪一种。
许可
MIT © Stuart Hu
链接
同类插件
omdsh-dev/dsh-notification★ 55
回合完成桌面通知,按结果分控 + 关键词过滤。
omdsh-dev/dsh-open-in-vscode★ 47
从 Web GUI 一键在 VS Code 中打开工作区目录。
whyihaveyou/dsh-suite#plugin-notify★ 38
回合完成、错误或待审批时推送 IM webhook(飞书/企微/钉钉/Slack/Discord/自定义)与本地通知。
THEWOLFWALKER/dsh-notifier★ 32
DSH 统一通知推送与远程控制:一个 `notify()` API 打通 25+ 渠道(Telegram / 钉钉 / 飞书 / 企业微信 / QQ 机器人 / WxPusher / PushPlus / Server 酱 / Bark / Discord / Slack / ntfy / webhook 等),timeSensitive / active / passive 分级路由并重试;五通道反向审批(Telegram 按钮 / 飞书卡片 / QQ / WxPusher / 微信 iLink);QQ/钉钉/飞书官方扫码登录;本地 Web 管理台;多 agent 路由;系统桌面通知——以及**手机指挥中心**:在手机上发 `!status` / `!stop` / `!retry` 遥控 agent,通知带可操作按钮(查看结果 / 重试 / 日志,点击回调 agent)。密钥脱敏、工具限流、零运行时依赖。
omdsh-dev/dsh-lark★ 24
DeepSeek Harness 的飞书/Lark 机器人渠道:每个会话驱动独立 agent,工具审批、模型提问与计划审阅都以卡片回到聊天,点按钮或直接回复即可作答;聊天里用 `/cd`、`/model`、`/new` 切工作区、换模型、重开会话,多个机器人各自独立并可在同群交接回合。
xmanrui/dsh-im★ 23
通过扫码把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉等)。