DeepSHPlugins
dsh-update-notifier 项目预览
GITHUB / COMMUNITY PROJECT

dsh-update-notifier

工具与集成JavaScriptMIT

每小时检查 npm 上已安装插件的新版本,并询问升级其中哪些。

2 Starsstuarthu 更新时间 2026-08-22
访问 GitHub 仓库
dsh-update-notifier 项目预览

项目介绍

中文

每小时检查 npm 上已安装插件的新版本,并询问升级其中哪些。

English

Checks npm hourly for newer versions of the installed plugins and asks which ones to upgrade.

项目信息与收录信号

快照 2026-09-11
作者 / 组织
stuarthu
仓库
stuarthu/dsh-update-notifier
GitHub Stars
2
Forks
0
开发语言
JavaScript
许可证
MIT
最近推送
2026-08-22
Manifest
数据中检测到声明

公开仓库不自动等于可商用;许可证与当前兼容性以原项目文档为准。Manifest 和数据评分不构成安装安全认证。

数据评分

55/ 100
维护活跃
87
文档与实用信息
85
生态关注度
14
安装便捷信号
75
项目声明信号
100

近 20 天仍在更新;README 含完整安装与使用说明;关注度尚低(2)。

评分来自已有数据快照的五维模型,仅作浏览参考,不是实际使用评测或安全检测结论。

安装与使用

所有项目资料与许可均以对应 GitHub 仓库为准。

dsh plugin --profile web add dsh-update-notifier

复制命令不会自动执行。请先阅读仓库文档,确认环境要求与许可证。

项目截图

仓库 README

GitHub 原文

已保存的仓库文档快照;文档抓取时间未记录,可能与上方目录介绍处于不同版本。安装前请核对当前仓库说明。

dsh-update-notifier

English | 中文

Hourly — or on demand, with /check-updates — check for newer versions of your installed DeepSeek Harness (dsh) plugins, with a one-click approval bubble to upgrade them.

Nothing in dsh tells you a plugin you installed has moved on; you find out by remembering to run npm view yourself. This plugin closes that gap: it compares every installed plugin against the registry once an hour and, when something is newer, asks you — in the session, as a real question bubble — which ones to upgrade. Tick the ones you want and the agent runs the upgrade in front of you. It never upgrades anything on its own.

Behavior

Once an hour (configurable), for every npm package backing a loaded plugin:

  • Look up the registry's latest and compare it with the version installed

in your profile's node_modules. Comparison is semver-proper — prereleases ordered correctly, downgrades never suggested — and a version that isn't a strict X.Y.Z is skipped rather than guessed at.

  • Ask, in one bubble. Anything newer becomes a multi-select question

rendered by dsh itself (dsh-chrome 0.1.2 -> 0.1.3, one option per plugin), attached to your most recently active session. It costs no model turn and no tokens, and it is replayed if you reconnect.

  • Hand the ticked ones to the agent, as a follow-up message telling it to

run

  pnpm --dir <profileDir> add <pkg>@<latest> ...

The agent wakes immediately and you watch the upgrade happen. Pair this with dsh-hot-reload and the new version applies live, without restarting dsh.

/check-updates

Don't want to wait for the hour to come round? Type /check-updates in the session:

/check-updates
check-updates · 2 updates — see the question above (7 plugins checked)

It runs a full cycle immediately, against the session you typed it in, and the row settles as soon as the registry sweep finishes — the bubble it raises is an ordinary one, answerable whenever, surviving a refresh. Where no bubble can be shown at all, the settlement carries the pnpm ... add command instead, so the answer is never just "you can't".

Packages the registry could not be reached about — a network failure, a timeout, a 5xx, a rate-limit, or an answer with no version in it — are counted in the settlement rather than passed off as up to date, and a sweep where *nothing* could be reached settles as an error, not as "no updates". The two counts add up: 5 plugins checked, 2 unreachable means seven were swept. Cancelling the row stops the sweep, so a check you cancel cannot pop a bubble at you a minute later.

The manual check ignores the decline memory below: you asked, so you get the full list, including versions you left unticked earlier. It does not disturb the hourly schedule, and it declines to run — with a reason — while a bubble is already open or a check is already in flight.

The command appears wherever dsh composes a command registry — which @deepseek-ai/dsh-base does, so any profile built on it has /check-updates. It is registered through ctx.inject, so a headless profile without one still loads the plugin and keeps its hourly checks.

Asked once

You are asked about a given version once (by the hourly cycle — the command above overrides this):

  • Unticked ones are declines, recorded in

<profileDir>/.dsh-update-notifier.json and never offered again — across restarts — until the registry's latest changes to some other version that still beats what you have installed. Delete that file to be asked afresh.

  • Approvals are not recorded: a successful upgrade makes that version

current anyway, and one that failed is worth re-offering after a restart.

  • A bubble you never answered (session ended, dsh stopped) is not a

decline — you will be asked again.

With no live session yet, the offer is held: it is retried right after your next message and on the next hourly cycle. It is also held where nothing can render the bubble at all — a headless profile, or one that composes the userQuestions service with no UI registered against it — and there the available updates and the exact upgrade command go to the log as well, because no message of yours is going to make a bubble appear.

Install

dsh plugin --profile web add dsh-update-notifier

Then restart dsh once (bundle patch layers load at boot). Works in any profile — swap web for whichever profile you use; it checks the profile it is loaded into. Needs Node 18+, for global fetch; any dsh host has it.

Compatibility

Built and tested against dsh 0.1.0-rc.6 (Node 22 / 24). It uses only public host services, so it degrades rather than breaks if one is absent:

Host surfaceUsed for
loader.entries()finding which packages back the loaded plugins
userQuestions.ask()rendering the approval bubble
userQuestions.providernot promising a bubble no UI has registered to render
agents.get(sessionId)resolving the session's live agent
agent.followup()waking that agent to run the upgrade
session/event (user/message)tracking the most recently active session
agent/disposedwithdrawing a bubble whose session died
commands.register()the /check-updates command
agents.roots()not promising a bubble ask() would refuse

userQuestions and commands are resolved when needed rather than declared as dependencies, so the plugin still loads in a headless profile that has neither.

Opting out

A plugin that does not want to be offered for upgrade can say so in its own package.json:

{ "dsh": { "updateNotifier": false } }

Use exclude (below) to silence a plugin you do not control.

Configuration

Set on the update-notifier row in your profile's cordis.patch.yml:

KeyDefaultMeaning
interval3600000ms between checks (clamped to a 60000 minimum)
initialDelay10000ms before the first check after boot
registryhttps://registry.npmjs.orgnpm-compatible registry to query
exclude[]package names to never check or mention
fetchTimeout10000per-request registry timeout, ms (minimum 1000)
profileDirautoabsolute path to the profile dir (auto-detected from the loader base URL if omitted)

Security

  • Nothing is upgraded without your click. This plugin never spawns a package

manager. It composes the bubble and, on approval, the instruction the agent then executes in plain sight.

  • No registry prose reaches the UI or the model. Only the package name, read

from your own profile, and a version string that passes /^[0-9A-Za-z.+-]{1,64}$/ are ever put into the bubble or the agent message — never a description, README, or changelog fetched from the registry.

  • The follow-up message carries source.kind: "plugin", names exactly the

approved packages, and tells the agent not to touch anything else.

Limitations — read this

  • It asks; it does not verify. Once you approve, the upgrade is the agent's

to run. A failure is visible in the session, but this plugin neither retries it nor checks afterwards that the new version is really installed.

  • Only registry-installed plugins are seen. A plugin linked from a local

checkout, or built into dsh, has no package under the profile's node_modules and is skipped silently — no bubble, no log line.

  • Only the latest dist-tag is consulted. There is no support for pinned

ranges, next/beta channels, or holding a package back at a major version; a plugin whose newest release you never want should use exclude.

  • One bubble at a time. While a bubble waits for an answer the hourly checks

skip — and /check-updates refuses with "an upgrade question is already open" — so anything published meanwhile is picked up on the first cycle after you answer.

  • A decline is keyed to that exact version, not to "anything up to it": if

the registry's latest moves to a different version that still beats yours — including a lower one after an unpublish — you are asked again.

  • The bubble needs a session that dsh can attach a question to. Registry

failures, degraded loader state, and an unwritable state file all degrade to logging; only two things disable the plugin outright — no plugin loader on the context, and a profile dir it cannot locate — and it says which in the log.

License

MIT © Stuart Hu

使用前核对

安装步骤、兼容版本与授权范围以原项目当前文档为准。Stars 和评分是快照中的导航信号。

安装与排错 · 项目问题反馈

同类项目