dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
在内置插件设置里新增「检查更新」标签页:每个已安装插件一行,显示 npm 最新版本并提供更新按钮。每行还会报告 DSH 运行时兼容性。注册表按 .npmrc 逐级读取(环境变量 → profile → 用户级,取第一个命中),未配置时并发探测镜像与公共源,内部源不会与公共源竞速。版本从哪个注册表读到,就由它安装。
A DeepSeek Harness plugin that adds a Check updates button to the Built-in plugins settings section. Click it and the plugin scans every installed plugin bundle for (1) the latest published version on the npm registry and (2) its compatibility with the running DSH runtime — then shows one row per bundle.
It lives beside the read-only inventory tab and contributes no configuration of its own. It reports, and for any bundle with a published update it offers a single Update button (the same installBundle primitive the GUI's Add plugin dialog uses). Enabling, disabling, or removing a bundle is still done in the sidebar Plugins page or via dsh plugin.
| Check | Source | Notes |
|---|---|---|
| Update availability | npm registry (latest dist-tag vs the installed version) | Registry-only. Bundles installed from a tarball / git / path publish nothing, so they are reported as Unsupported rather than falsely Up to date. |
| Compatibility | the bundle's @deepseek-ai/dsh* peerDependencies vs the running DSH version | Reuses @deepseek-ai/dsh-app-boot's evaluatePluginCompatibility, the same helper the launcher applies on boot. An exact-version exemption granted in compatibility.json shows as Compatible (exempted). |
Compatibility and update availability are computed independently — a slow or unreachable registry can never hide an incompatible peer range, and a local-only bundle still gets a compatibility verdict.
Which registry the scan asks: no longer a hardcoded registry.npmjs.org. The host reads the configuration itself (environment → the profile's .npmrc → the user's ~/.npmrc, first hit wins) and then probes the candidates concurrently, taking the first success. Three cases: nothing configured → race the launcher's mirror against the public registry; the public default configured (npm writes registry=https://registry.npmjs.org/ into ~/.npmrc on its own) → keep it and add the mirror behind it, since both are public and nothing leaks; anything else configured (a corporate or internal registry) → that one alone, never raced against a public registry, because racing would leak internal package names to third parties. The difference is large behind a slow link — measured on one machine, the public registry answered in ~11 s where a mirror answered in ~0.2 s, and racing means a slow registry cannot hold up a fast one even when it is listed first. A bundle that declares publishConfig.registry still uses that registry. The winning registry travels with the row and is reused by the one-click update, so the version is read from, and installed from, the same place.
The host half declares only
webServer, andremoteis a browser-side service; in this cordis version, touching an undeclared service throws (cannot get property ... without inject). The host therefore cannot ask the plugin manager for registries — reading the configuration, as above, is what that constraint requires.
Open Settings → Built-in plugins. The section now has two tabs:
The check is on demand: click the button, the host scans, and the table fills in. One broken manifest or an unreachable registry is isolated to its own row — it never blanks the whole report.
dsh install-plugin dsh-plugin-update-checker
Installing from the registry matters for this plugin in particular: a github:
install is pinned to a commit in the profile lockfile, so re-running the same
spec never picks up a newer release, and the panel reports it as Unsupported
(it can only compare registry versions). From 0.1.4 on, plain version numbers
resolve normally and the panel's own Update button works.
Open the sidebar Plugins page → Add plugin.
In the source field, enter one of these install specs (the launcher resolves them through installBundle, the same primitive the GUI uses):
github:windrover/dsh-plugin-update-checker
# or the full URL:
https://github.com/windrover/dsh-plugin-update-checker
Restart to load the new bundle:
dsh check # iron rule #1: preflight before restart
dsh restart # reloads the web profile; the new bundle loads
Open Settings → Built-in plugins → Check updates → Check updates.
The Check button's fetch('/api/plugin-update-checker/scan') runs inside the
authenticated browser session, so it needs no manual token.
This repository is public, so installing directly from GitHub works without any extra authentication. On networks where
registry.npmjs.orgis unreachable, the launcher usesregistry.npmmirror.comautomatically.
Clone the package where your profile can link it:
# e.g. inside your DSH workspace
git clone https://github.com/windrover/dsh-plugin-update-checker dsh-plugin-update-checker
Link it into your profile. Add a link: dependency + a bundles entry to the profile manifest:
// ~/.dsh/profiles/web/package.json
{
"dependencies": {
"dsh-plugin-update-checker": "link:/abs/path/to/dsh-plugin-update-checker"
},
"dsh": { "profile": { "bundles": [ "…", "dsh-plugin-update-checker" ] } }
}
Then install. npm install rejects the link: protocol in this profile — use pnpm (the profile is a pnpm workspace), which is what dsh wires under the hood:
cd ~/.dsh/profiles/web
pnpm install --registry=https://registry.npmmirror.com # link: deps don't hit the network
dsh's wire_link_plugin_deps auto-symlinks any @deepseek-ai/* the plugin
imports into its own node_modules, but it does not handle plain npm packages —
so pre-link the one real dependency yourself (the documented link-plugin gotcha:
a link: plugin can't resolve packages that aren't hoisted into its tree):
mkdir -p dsh-plugin-update-checker/node_modules
ln -sfn ~/.npm/_npx/<active-dsh-hash>/node_modules/semver \
dsh-plugin-update-checker/node_modules/semver
Restart and open it (dsh check && dsh restart, then the same Settings path as Option A).
One bundle, two halves:
lib/index.js → lib/host/update-checker.js) registers POST /api/plugin-update-checker/scan, which walks the profile's bundles (via ctx.remote.pluginManager.listBundles(), falling back to scanning node_modules), reads each manifest, evaluates peer compatibility, and probes the registry. cordis.patch.yml adds the Loader row.lib/client.js) registers a tab into the settings.plugins.tab slot of the Built-in-plugins section and renders the result with react (require("react")) and the design tokens DSH already exposes. The bundle id equals the package name — the contract dsh-client-modules enforces.node test/client-contract.test.mjs
Pins the browser-half contract (id == package name, one settings.plugins.tab registration, renderable body). The host scan was exercised against the live profile during development and returns { ok, dshVersion, checkedAt, plugins: [...] }.