npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-plugin-offline-updater

v0.3.0

Published

DeepSeek Harness (DSH) plugin: check and update installed profile plugins from npm, with release-age guard and a safe-version fallback.

Readme

插件离线更新器(dsh-plugin-offline-updater)

DeepSeek Harness(DSH)的 Cordis 插件,用于在 Web GUI 中管理当前 profile 已安装用户插件的版本更新。

它会在侧栏增加一个「插件更新」入口,列出所有已安装的用户插件,逐个向 npm 源查询最新版本并与本地版本比较;有新版本时可直接更新,并遵守「新版本 24 小时发布年龄」限制。设置页最上方还提供「更新本插件」,用于更新插件自身。

功能

  • 插件列表:读取当前 DSH profile 中已安装的用户插件(availability === 'profile'),展示图标、名称、版本、启用状态(已启用/未启用)与描述,自动排除本插件自身;列表顺序与官方「已安装插件」页面一致(按去掉 scope 与 dsh- 前缀后的短名称排序)。读取 bundle 清单失败时回退到 profile package.json + node_modules/<pkg>/package.json。
  • 检查更新:按插件调用 npm registry(含 scoped 包与私有源),比较本地版本与 dist-tags.latest,显示「已是最新版本 / 发现新版本 / 检查失败」。
  • 24 小时新版本限制:按目标版本自身的发布时间判定,不足 24 小时(或发布时间未知)时弹窗确认;确认后该版本记入「已确认」,30 天内不再重复弹窗。
  • 稳妥版本:存在「已满 24 小时、高于当前版本且不高于 latest、非预发布」的版本时,确认弹窗额外提供「更新到稳妥版本」,一键安装该版本。
  • 更新前会话校验:只要还有会话未结束——智能体仍在生成/执行工具,或队列里还有待处理消息——更新请求会被直接拒绝(409,返回未结束会话数量),不会查询 npm、不会改动 profile;等这些会话完成或停止后再更新。只是打开着但空闲的会话、以及后台 job 不拦更新。
  • 两种更新模式:默认原位 pnpm add 升级;可在设置中开启「更新前先卸载旧插件」,改为 pnpm remove + pnpm add,与官方插件市场行为一致(安装失败会尽力回滚到原版本)。
  • 更新本插件:设置页最上方提供「更新本插件」,复用同一套检查/更新逻辑与 24 小时门槛,但始终原位 pnpm add(不受「更新前先卸载旧插件」影响);成功后弹窗提示重启 DSH,可直接重启或稍后手动重启。更新后即使刷新页面,设置项仍保留「等待重启」状态和「重启 DSH」按钮。只适用于以 npm registry 方式安装的本插件,link/file 等安装时该项禁用并说明原因。
  • 发布年龄白名单维护:以 --config.minimumReleaseAge=0 放行的过新版本,安装成功后会写入 profile pnpm-workspace.yaml 的 minimumReleaseAgeExclude,避免之后所有插件(含官方市场)安装被 ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION 拦下。
  • 列表分页:客户端分页,默认每页 10 条;刷新按钮会重新拉取列表并对当前页插件静默检查一次,不会自动更新。点击刷新后当前页所有行会同时显示「检查中…」并置灰,全部检查完成后结果一起出现。单行检查、整页刷新检查或插件更新进行期间,分页按钮全部禁用,避免把进行中的操作翻到页外;操作结束后恢复。
  • 并发检查数:设置里可选 4 / 6 / 8 / 10(默认 4,10 等于整页并发),决定右上角刷新时同时查询几个插件;每路查询都是一个独立的 pnpm view 子进程,档位越高刷新越快、对 pnpm 与源端压力越大。
  • 检查结果缓存:刷新(全局检查)的结果会缓存在页面内存里,每次刷新前先清空旧数据;在设置的「检查结果缓存时长」(默认 5 分钟,可选 5/10/30/60 分钟)内点单个插件的「检查更新」,直接复用该结果,不再重复查询 npm 源。更新成功后自动丢弃该行的缓存。
  • 跟随 DSH 的 registry 语义:读 pluginManager.registries()(等价于 profile 的 pnpm config get registry),私有/未知源只问它自己,绝不回退到公网镜像;查询与安装都通过 profile 自带的 pnpm 执行,自动继承 .npmrc 的认证、代理与 CA。
  • 更新后一键重启:只要当前这次 DSH 进程里更新过插件,页面右上角刷新按钮左侧就会出现一个电源图标(悬停提示「重启 DSH」;没更新过时不显示)。确认后插件会结束并重新拉起 DSH,让新版本插件代码立即生效;重启会中断正在运行的任务与会话。目前只有 Windows 桌面版支持自动重启,其它环境会提示手动重启。

环境要求

  • DSH 运行环境(dsh web 或 Electron ELECTRON_RUN_AS_NODE),Node.js ≥ 20(只需要 ESM 与 Node 内置模块;Host 端不使用全局 fetch)。
  • profile 内自带 pnpm(检查与更新都通过 profile 的 pnpm 执行;没有可用 pnpm 的环境无法检查或更新)。
  • 仅适用于 registry(npm)来源的 profile 依赖;link:、file:、portal:、workspace:、git:、https:、tarball 来源的插件不支持自动更新。
  • 纯 ESM,无构建步骤、无 TypeScript、无打包器、无第三方运行时依赖。

安装

插件已发布到 npmjs(包名 dsh-plugin-offline-updater),两种常规装法:

  • 在 DSH 的插件市场里搜索安装(市场按 npm 的 dist-tags.latest 取版本);
  • 或直接用当前 profile 自带的 pnpm 装进 profile:pnpm add dsh-plugin-offline-updater。

安装后侧栏会出现「插件更新」入口(可在「设置 → 插件 → 插件离线更新器」的详情页里关闭)。更新任意插件后需要重启 DSH 才会加载新版本代码:Windows 桌面版可以直接点页面右上角的「重启 DSH」按钮,其它环境请手动退出并重新打开;只改本插件自身的前端代码时刷新页面即可。

使用

  1. 打开侧栏「插件更新」,页面列出当前 profile 的已安装用户插件(每页 10 条)。
  2. 点击某行的「检查更新」,插件会查询 npm 源并给出结果;也可点右上角刷新按钮重新拉列表并对当前页做一次静默检查(只展示状态,不会自动更新)。点刷新后当前页所有插件行会同时变成置灰的「检查中…」,全部检查完成后结果一起刷新。检查或更新进行期间分页按钮会全部禁用,结束后恢复。刚刷新过、且仍在「检查结果缓存时长」窗口内时,单行「检查更新」会直接复用那次检查结果。
  3. 有新版本且发布时间已满 24 小时:直接更新。
  4. 新版本不足 24 小时:弹窗提示,可选择
    • 「继续更新」:忽略该版本的 24 小时限制(记入已确认);
    • 「更新到稳妥版本」:安装最近一个已满 24 小时的版本(无需确认,且不会记为已确认);
    • 「取消」:不做任何操作。 弹窗可用 Esc 或点击遮罩关闭。
  5. 更新完成后提示「已下载 vX.Y.Z,重启 DSH 后生效」,此时右上角出现「重启 DSH」电源图标:
    • 点一下会先确认(提示运行中的任务会被中断),确认后自动关闭并重新打开 DSH,新版本插件代码随即生效;
    • 不点也可以手动退出并重新打开 DSH;重启后按钮自动消失,直到下一次更新。

有会话还没结束时,更新会被拒绝并提示「还有 N 个会话尚未结束」,等它完成或停止后再点一次即可;只是打开着、没有在跑的会话不影响更新。

更新插件自身:在「设置 → 插件 → 插件离线更新器」的详情页最上方点「更新本插件」,流程与普通插件相同(检查 npm 源、24 小时门槛、稳妥版本),但始终原位安装;安装成功后立即弹窗提示重启 DSH,可选择「立即重启」或「稍后」。该项下方固定显示一行「当前版本 vX」,检查/更新时在同一行用 · 追加状态文案(如「检查中…」「已是最新版本」「已更新到 vX,重启 DSH 后生效」);文案过长时截断为省略号,鼠标悬停可看全文,这一行不会改变高度。

设置

设置入口位于「设置 → 插件 → 插件离线更新器」的 bundle 详情页,最上方是一个自身更新项,下面共三个开关和两个下拉选择:

| 设置 | 默认 | 说明 | | --- | --- | --- | | 更新本插件 | — | 检查 npm 源并原位更新插件自身;受 24 小时门槛约束,成功后提示重启。当前安装方式为 link/file 等非 registry 来源时按钮禁用。始终原位,不受「更新前先卸载旧插件」影响。 | | 侧栏入口 | 开 | 是否在侧栏显示「插件更新」入口,切换时实时挂载/卸载页面。 | | 忽略新版本 24 小时限制 | 关 | 开启后过新版本直接更新、不再弹窗,对所有插件全局生效。 | | 更新前先卸载旧插件 | 关 | 关闭为原位升级;开启后先 pnpm remove 再 pnpm add,模拟官方插件市场。removable === false 的插件在此模式下拒绝更新。 | | 并发检查数 | 4 | 右上角刷新时同时查询几个插件,下拉可选 4 / 6 / 8 / 10。每路查询是一个 pnpm view 子进程,档位越高越快、压力越大;10 等于整页(每页最多 10 条)并发。 | | 检查结果缓存时长 | 5 分钟 | 右上角刷新后可复用全局检查结果的时间窗口,下拉可选 5 / 10 / 30 / 60 分钟。窗口内单行「检查更新」不再请求 npm 源。 |

设置与「已确认版本」持久化在 ~/.dsh/plugin-offline-updater/settings.json(DSH_HOME 存在时以其为准)。

HTTP API

Host 半注册以下同源精确路由,前缀固定为 /api/dsh-plugin-offline-updater:

| 方法 | 路径 | 说明 | | --- | --- | --- | | GET/HEAD | /settings | 返回 { ok, sidebarEntry, ignoreReleaseAge, uninstallBeforeUpdate, checkConcurrency, checkConcurrencyOptions, checkCacheMinutes, checkCacheOptions, selfVersion, selfUpdatable, restartPending, selfRestartPending, selfUpdatedVersion, restartSupported, restartMode, hostPid } | | POST | /settings | 接受 { sidebarEntry?, ignoreReleaseAge?, uninstallBeforeUpdate?, checkConcurrency?, checkCacheMinutes? } 或 { key, value };checkConcurrency 只接受 checkConcurrencyOptions(4/6/8/10)里的档位,checkCacheMinutes 只接受 checkCacheOptions 中的档位,其余值 400 | | GET/HEAD | /plugins | 返回 { ok, plugins },每项含 name、version、title、description、可选 icon(data:image/...)、removable、enabled(该组合包在 profile 中是否启用) | | POST | /check | body { name },查询 npm 最新版本并计算是否需要确认 | | POST | /update | body { name, version?, force? },执行更新 | | POST | /restart | 结束并重新拉起当前 DSH(仅 Windows 桌面版;没有等待重启的更新时返回 409) |

/settings 里的 restartPending 表示「当前这个 DSH 进程里更新过插件、还没重启」,它按进程区分,重启后自动失效;restartSupported / restartMode 说明当前环境能否自动重启(desktop 或 cli / platform)。hostPid 是当前 Host 进程 pid:重启时页面只有观察到它变化(或旧 Host 先下线再恢复)才刷新,避免在进程被结束之前刷进旧 Host、因客户端模块 revision 不一致而启动失败。selfVersion 是当前进程实际加载的插件版本,selfUpdatable 表示当前 profile 中本插件是否为 npm registry 来源(link/file 等安装为 false,设置页的自身更新项会禁用)。selfRestartPending / selfUpdatedVersion 只针对本插件自身的更新:前者表示本进程更新过本插件且尚未重启,后者记录当时安装的版本;设置页刷新后据此恢复「已更新/等待重启」状态。

/check 返回 ok、name、currentVersion、latestVersion、publishedAt、ageHours、tooFresh、releaseAgeHours、updateAvailable、safeVersion、safePublishedAt、safeAgeHours、ignoreReleaseAge、acknowledged、needsConfirm、registry;拿不到 registry 数据时返回 502 { ok: false, error }。

/update 仅允许更新已安装且为 registry 来源的插件;本插件自身也可以通过它更新,但会强制走原位安装(忽略「更新前先卸载旧插件」),且要求自身是 npm registry 来源。version 必须为合法 semver 且能在源中找到。还有未结束的会话时返回 409 { ok: false, unfinishedSessions, error }(不会执行 pnpm);门槛不满足且未 force、未确认时返回 409 { needsConfirm: true, safeVersion, ... };已有更新在跑时也返回 409;未安装返回 404;pnpm 失败返回 502(错误经脱敏)。成功时返回 { ok, name, installedVersion, restartRequired: true, restartPending: true, updateMode: 'in-place' | 'reinstall', registry, application: 'restart-required' }。同一时间只允许一个更新正在执行。

所有接口(含 GET/HEAD 读取)都仅放行本机回环请求:缺失 Host/Origin 时视为非页面请求而放行(Desktop 代理可能剥离它们),存在时必须为回环且同源,sec-fetch-site: cross-site 一律拒绝,校验不通过返回 403。读取接口也校验,是为了防止 DNS rebinding 读到插件清单与设置。

目录结构

.
├─ package.json          # 包清单 + dsh.bundle / dsh.client 声明
├─ cordis.patch.yml      # 插入的 Loader 行(id: plugin-offline-updater)
├─ index.js              # Host 半:HTTP API、插件列表、检查/更新编排
├─ client.js             # Client 半:侧栏图标、插件列表页、设置卡、确认弹窗
├─ lib/
│  ├─ settings.js        # 设置与「已确认版本」持久化
│  ├─ registry.js        # registry 选择(DSH registryPlan 语义)+ pnpm view 结果解析 + semver 比较
│  ├─ install.js         # profile 目录 / pnpm 运行时解析、pnpm view 查询、pnpm add / remove+add
│  ├─ release-age.js     # minimumReleaseAgeExclude 白名单维护(guard 校验 + record 合并写盘)
│  └─ restart.js         # 重启 DSH:生成批处理助手,经 WMI 在应用进程树之外执行
├─ locale/
│  ├─ en.json            # 插件元信息(meta.title / meta.description)
│  └─ zh.json
├─ icon.svg              # 插件图标(package.json 导出 ./icon)
├─ LICENSE               # MIT
├─ README.md             # 本文件
├─ .github/workflows/
│  └─ publish.yml        # 推 v* tag 触发自动发布
├─ .gitattributes        # workflow 的 *.yml 强制 LF 入库
└─ .gitignore            # 不提交 node_modules / lockfile / 临时测试目录

发布到 npm 的 tarball 只包含 package.json、README.md、LICENSE 加上 files 白名单(index.js、client.js、lib/*.js、cordis.patch.yml、locale/*.json、icon.svg),共 14 个文件;仓库里的 .github/、.gitattributes、.gitignore 和本地临时目录不会随包发布。

开发

本地开发时可在仓库根目录做语法检查(改完 Host 端文件必做):

node --check index.js
node --check client.js
Get-ChildItem lib/*.js | ForEach-Object { node --check $_.FullName }
node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))"

把仓库目录以 link 方式安装进 profile 后即可调试:index.js 与 lib/ 的改动需要重启 DSH 才会加载,只改 client.js 时刷新页面即可。

已知限制

  • 只处理 registry(npm)来源的 profile 依赖。
  • 更新已安装插件后必须重启 DSH 才加载新版本代码。
  • 更新请求在还有未结束会话时会被拒绝(智能体运行中或队列里有待处理消息);检查与安装之间没有锁住会话,极端情况下仍可能有会话在安装过程中开始运行。
  • 自动重启目前只在 Windows 桌面版生效:DSH 没有对外的重启接口,插件只能结束当前进程再重新拉起,运行中的任务、终端与后台作业会被中断(会话本身会持久化)。dsh web 命令行部署与非 Windows 桌面版会提示手动重启。
  • 本插件不会把自己列进插件列表;自身更新从设置页最上方的「更新本插件」发起,且要求本插件以 npm registry 方式安装(link/file 等安装时该按钮禁用)。
  • 检查与更新完全依赖 profile 的 pnpm;无法执行 pnpm 的环境无法使用本插件。