dsh-plug-store:把社区插件商店搬进 DSH 设置页

前言

DSH 的安装入口是 dsh plugin 命令行。社区插件分散在各处,找一个能用的插件通常要先浏览目录、复制命令、再回到终端执行;命令拷错或装到错误的 profile 里,排查成本比插件本身还高。下面介绍的 qianyumeng0228/dsh-plug-store 是一个宿主插件,它把 DSH 插件目录渲染成宿主设置页里的一个分区,并在界面上直接调用 dsh plugin 完成安装、更新、卸载和备份,省去复制命令这一步。插件由 qianyumeng0228 维护,分类在客户端一侧,发布在 npm 与 GitHub 上。

这是什么

一句话定位:在 DeepSeek Harness 内部提供插件商店能力的宿主插件。它不是独立站点,而是挂在宿主 settings.section 槽位上的一段界面。

它解决三个具体问题:

  • 目录浏览与命令行安装之间隔着一次人工复制,插件在页面里直接执行。
  • 更新是否真的生效,语义上一是指命令返回码,二是指版本有没有真的变化,两者不等价,插件按后者判定。
  • 安装任务的进度和历史缺乏持久化,重启后无从复盘。

目录由 qianyumeng0228/dsh-store 每日构建并发布到 GitHub Pages,当前收录 29,593 个社区插件,其中 14,344 个为开箱即装。

需要明确的是,dsh-store 是社区仓库,与 DeepSeek / 幻方没有官方从属关系。DSH 的理念是「一切皆插件」,本仓库属于社区对该理念的实现。

核心功能

真实执行安装命令,而不是给一段命令让你自己跑。 所有操作都是对 dsh plugin 的 shell 调用,针对正确的 profile,并把实际发生的事情回读出来。pnpm 在重新添加一个已固定版本的依赖时会以退出码 0 回答 “Already up to date”,因此更新流程显式带上目标版本再回读当前安装版本:界面只有在版本真的移动时才显示「已更新」,没有变化时显示「无变化」。

实时进度和持久化任务日志。 操作作为排队任务执行,进度来自 pnpm 的 ndjson reporter(解析 / 下载 / 链接 / 构建、当前包、字节数)。失败时把 13 种 ERR_PNPM_* 错误码映射为自然语言提示。日志写入 ~/.dsh/store-data/tasks.json,重启后仍在;被打断的任务显示为 interrupted,不会静默消失,已完成和失败的行可以一键清除。

「可更新」是按本机计算出来的。 判定依据是本机已装版本与目录目标版本之间的比较,而不是数据里的一个标记字段。本地链接和非 registry 依赖(file:、link:、workspace:、git+…)会被排除,不会被提议一个会覆盖它们的更新。

中文优先的目录。 描述优先使用中文;仅英文的条目在构建时机器翻译(已发布目录中覆盖 99%),仍缺失的在页面内按需补译。中 / EN 切换只在确实存在两种语言时出现。

主题预览墙。 主题卡片展示从各仓库 README 提取的真实截图(相对路径按 raw.githubusercontent.com 解析,blob 链接重写),只保留横向截图,点击进入 lightbox 可前后翻看。

浏览规模上的设计。 真实分页(每页 24 / 48 / 96,记忆选择),17 个双语分类,支持按名称 / 描述 / 标签搜索,筛选条件包括可安装 / 官方 / 本周新增 / 可更新 / 已收藏 / 已安装,7 种排序(含随机),卡片与列表两种视图,可折叠的「最近添加」和「安装最多」栏目,底部队列栏把多次安装合并成一个确认的批次。

收藏、屏蔽、备份、诊断。 收藏和屏蔽记录保存在浏览器本地;备份导出当前 profile 的已装列表及其 cordis patch 为可读 JSON,用于迁移;诊断检查 dsh CLI、profile 目录、数据源和嵌入页面的实时布局。

滚动条只保留一条。 页面以 iframe 嵌入并按内容实际高度拉伸,滚动统一由宿主设置列承担。弹层(详情模态框、队列栏、toast、lightbox)在每次滚动时重新锚定到可视窗口;拉伸测量读的是真实内容末尾而非 scrollHeight,因此切换到较短的标签页时 iframe 会缩回去。

安装与启用

安装命令来自 README,两条官方形式如下:

# npm 发布版
dsh plugin --profile <profile> add dsh-plug-store

# 或直接从 GitHub 安装 —— 无需构建步骤,运行时零依赖
dsh plugin --profile <profile> add github:qianyumeng0228/dsh-plug-store

截至抓取时,npm 上发布的是 0.1.21,而仓库 package.json 中的版本是 0.1.28。README 明确建议在 npm 发布追上之前优先使用上面的 github: 形式,因为 GitHub 源始终是最新的。许可证为 MIT,运行时依赖为空,peer dependency 为 @deepseek-ai/cordis ^4.0.1。

装完后重启宿主,或者让 profile 的 HMR 接管:插件声明了 bundle,dsh.bundle.patch 通常无需重启就能重载它。

界面位置:Settings → Plugin Store(设置页 → 插件商店),注册在宿主的 settings.section 槽位上。UI 同时也通过宿主的 loopback 端口在 /dsh-store/ 提供,可以直接在浏览器打开。

两个使用要点:

  • DSH Desktop 用户不要走 CLI。 在桌面机上执行 --profile web 会把内容写进 profiles/web,Desktop 应用并不加载它,设置页里不会出现入口。桌面端应使用应用自带的 plugin manager 安装。
  • 它作用于哪个 profile,按以下顺序解析:插件配置里的 profile → 插件自身安装目录所在的 profile(~/.dsh/profiles/<profile>/…)→ DSH_PROFILE → web。装进 desktop 因此操作的就是 desktop。

该插件需要一个基于 cordis 的 DSH 宿主,开发验证针对 0.2.1-rc.2。在不受支持的宿主上,设置页分区不会挂载。

典型用法

安装后打开设置页进入插件商店,可以按以下路径操作:

1、在商店内搜索、按分类筛选,或用「可更新」筛选出本机已装但目录有新版本的插件。列表里每张卡片反映的是本机实际状态,不是目录里的静态标记。
2、点某个插件查看详情(主题类插件会显示仓库 README 中提取的截图)。需要安装就直接点安装,排进队列;页面底部的队列栏会把多次点击合并成一次确认后批量执行。
3、安装过程中观察进度条和任务日志,日志同时持久化到 ~/.dsh/store-data/tasks.json。失败时日志里给出从 ERR_PNPM_* 映射来的提示。
4、对已安装的插件执行更新或卸载。卸载在界面上是两步确认;更新只显示真正发生版本变化的情况。
5、需要迁移时,用备份功能导出 JSON;需要排查环境时,用诊断检查 CLI、profile 目录、数据源和嵌入页面布局。

命令行层面,插件本身不新增一套 CLI 命令,所有能力都通过 /dsh-store/ 下的路由提供。

API 与数据

所有路由位于 /dsh-store/ 之下,其中 api/* 有访问防护。

GET  /api/capabilities        能力发现;UI 看到它后切换到宿主模式
GET  /api/installed           已装包的名称、版本、类型与来源仓库
POST /api/install             {source:"npm",name,version?} 或 {source:"github",repo,ref?} → 202 {taskId}
POST /api/update             载荷同上;返回 from / to / changed
POST /api/uninstall           真实移除,界面上两步确认
GET  /api/tasks               排队中、运行中与已完成的任务及其进度
POST /api/tasks/clear         只清除已完成和失败的行
GET  /api/backup              profile 插件列表与 cordis patch 的 JSON
GET  /api/diagnose            CLI、profile、数据源与嵌入布局健康检查
GET  /data/plugins.json       目录代理,带本地缓存与远程兜底

标识符在到达 CLI 之前先校验:npm 源必须是包名,GitHub 源必须是完整的 owner/repo(只给 repo 尾巴会拼出一个不合法的 github:dsh-xxx),任何以 - 开头的值都会被拒绝,避免被解析成选项参数。

GET /api/installed 同时返回名称和详情,因为目录里的显示名与本机依赖键经常不一致(目录里的 yujunzhixue-dsh-purge 在磁盘上是 dsh-purge);只按其中一种匹配会静默丢掉一半已装列表。

目录数据不打包进插件本身。插件通过自身的同源路由 /dsh-store/data/plugins.json 读取目录,并把快照缓存在 ~/.dsh/store-data/plugins.json,缓存 24 小时,过期后在后台刷新一次——打开商店的速度不依赖当时 CDN 是否可达。响应使用 gzip 协商与弱 ETag。快照刻意不 vendoring 进包里,是为了避免分发一份每天都会过期的固定副本,而上面的缓存已经提供了同样的首屏速度。

安全边界

插件以当前 dsh 进程的权限运行,安装前应自行检查插件源码与许可证。就 dsh-plug-store 自身而言,有几项工程上的约束值得了解:

  • api/* 路由要求 loopback 的 Host(localhost / 127.0.0.1 / [::1])并带上自定义 x-dsh-store: 1 头。跨站页面无法在没有 preflight 的情况下设置该头,而它会失去这个 preflight。页面本身和目录数据保持开放,因为它们是公开的。
  • 运行时零依赖,无遥测,唯一的外部请求是拉取目录。
  • 插件不读取任何凭证,写入只发生在 ~/.dsh/profiles/<profile>/(通过 dsh plugin)和 ~/.dsh/store-data/(自己的任务日志与数据缓存)。

适用场景与注意

适合一类人:希望把插件的发现、安装、更新、备份收敛到一个界面里,同时要求 UI 背后的命令确实被执行、结果确实可回读。如果你只是偶尔装一两个插件,命令行本身已经够用,这个插件的增量价值有限。

几点需要注意:

  • 依赖 cordis 宿主,且需与 @deepseek-ai/cordis ^4.0.1 兼容;不受支持的宿主上分区不挂载。
  • npm 发布版本落后于 GitHub 源,想拿最新修复就用 github: 形式。
  • DSH Desktop 上请用应用自带的插件管理器,不要用 --profile web 的 CLI 方式。
  • 它安装的是社区插件,目录本身是社区目录,不等于官方应用商店。

结尾

dsh-plug-store 的价值在于把「浏览目录」和「真实执行安装」合并到同一个界面里,并把进度和历史用任务日志留下来。它没有重新造一套包管理器,命令行它照用,只是把执行结果如实回读到界面。

目录页:https://www.skillhub.cn/plugins/qianyumeng0228/dsh-plug-store
GitHub:https://github.com/qianyumeng0228/dsh-plug-store

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜