← Back to home@ApakohZzz

DSHPluginHub-Market-Framework

DeepSeek Harness 插件市场通用模板框架(DSH Plugin Market framework)

Stars
0
Language
JavaScript
Created
Oct 3, 2026
Updated
Oct 5, 2026

Introduction

DSH 插件市场

它是一个插件市场,也是它自己的第一个插件。

DSH License deps e2e

中文 · English

插件市场浏览页:一行一个插件,宽屏两列,未安装的行尾是「+」

装上它,侧边栏会多出一个与内置「插件」平行的 插件市场 入口。进去可以浏览、搜索、一键安装收录的插件 —— 装完的插件出现在官方「插件」页里,默认未启用,什么时候开由你决定。


目录


为什么需要它

DSH 添加插件现在的路径是「插件页 → + 添加插件 → 手填 npm 包名 / 本地路径 / git 地址」,一次一个。 想装一批插件时这件事很烦,而且分发方还得保证每个插件都能被单独拉到。

插件市场把「一批插件」变成一个可以整体分发的包:

收录插件的源码就在市场包里面。 不依赖任何外部 registry、不依赖网络、也不需要在别处搭建索引。

marketplace/                  ← 市场包(本身就是一个 DSH bundle 插件)
├─ catalog.json               ← 收录目录(谁被收录、版本、说明)
├─ icon.png                   ← 市场自己的标志
└─ plugins/                   ← 收录插件的完整源码(自包含,随包一起分发)
   ├─ plugin-hello/           ← 最小 Host 插件
   ├─ plugin-quick-notes/     ← 纯客户端插件
   └─ plugin-session-tools/   ← 注册模型可见工具的插件

界面

浏览:一行一个插件,行尾只有一个动作

顶部是市场版本与统计胶囊,下面是搜索框、状态筛选(全部 / 已安装 / 已启用 / 可安装,都带实时计数) 与「刷新」「打开插件页」。列表刻意参考 ChatGPT Desktop 的插件清单:一行一个插件,行里只有 图标 · 名称 · 一句话说明 · 右侧一个动作。

状态行尾形状
未安装「+」
安装中圆形进度环
已安装未启用 / 已启用开关

装没装、启没启用看行尾形状就够了,不再挂重复的状态徽标。点行的任意位置(包括中间的说明文字) 都能进详情页。宽屏(≥1440px)下一排两个,上限就是两个。

详情

插件详情页:名称 / 版本 / 包名 / 说明,包含的组件,版本信息;右上角是卸载按钮与开关
区块内容
头部插件名字、版本号、插件 id(包名)、一段 description;右上角是安装 / 卸载 + 开关
包含的组件这个插件包含的每个 Loader 组件:图标、id、描述、右侧运行状态
版本信息目录 id / 包名 / 目录版本 / 已装版本 / 目录路径 / profile 内软链
  • 无论插件本体是否启用,都会列出它包含的组件 —— 插件还没装载时, 行数据来自市场从它源码的 cordis.patch.yml 里静态解析出的声明。
  • 装之前不显示每一行的启用/停用状态(那时还谈不到)。
  • 安装会写入 profile 并让插件代码在本机进程内运行,这条操作后果直接写在页面上; 「市场怎么运作的」这类背景知识收在标题右侧的 (i) 浮窗里。
(i) 浮窗长这样 (i) 浮窗:使用说明 + 市场是怎么运作的

安装

点「安装」就开始装。进度由那一行行尾的圆形进度环表达(installBundle 不回报百分比, 所以不编造精度);成功后顶部浮出一条提示,几秒后自动消失。

事件提示
安装 / 更新成功顶部浮动提示
启用 / 停用 / 卸载成功什么都不弹 —— 开关已经把结果说清楚了
任何失败结果条(含可展开的诊断)—— 失败必须留痕

卸载是破坏性操作,会确认一次。

装完之后

官方插件页的「已安装」分组里出现了刚装的插件,开关默认关闭

插件出现在官方「插件」页的 已安装 分组里,开关默认关闭;启用、停用、卸载都在官方那边照常可用。 市场不接管官方插件页,它只是把插件送进去。


安装市场

在「插件」页 → + 添加插件,用任一方式:

方式填什么
本地路径(推荐)本仓库 marketplace/ 目录的绝对路径,例如 /path/to/DSHPluginHub/marketplace
git 仓库要指向子目录,不能只填仓库地址 —— 见下
npm 包发布之后填包名

关于 git 地址:本仓库根目录没有 package.json —— 包本体在 marketplace/ 子目录里 (根目录只有 README / LICENSE / 文档)。所以「填仓库地址就能装」是不成立的: 安装器把 spec 直接交给 pnpm add,它不会自动去子目录里找包。 要用 git 方式,得填带子目录的形式,例如 git+https://<host>/<you>/DSHPluginHub-Market-Framework.git#path:/marketplace (也可以用 file: 前缀的本地路径变体)。最省事、也最不会出错的是上面那条「本地路径」。

装完刷新一次页面,侧边栏就会出现「插件市场」。


它为什么能「自包含 + 闭环」

  1. 收录即分发。 收录插件的源码就在市场包内部,不需要外部 registry。
  2. 安装走官方逻辑。 市场把内部目录的绝对路径交给官方 pluginManager.installBundle(), 官方用当前 profile 的 pnpm 执行 pnpm add <绝对路径>,于是 profile 的 node_modules 里 出现一个指向市场包内部的软链。
  3. 官方刷新即同步。 你在官方插件页(或市场里)刷新市场插件版本后,市场包源码被整体替换, 而软链天然指向新源码 —— 所有已装插件无需重装就拿到了新版本。这是闭环的关键。
  4. 默认不启用。 安装后插件出现在官方插件页的 Bundles 分组里,市场紧接着调用官方的 行级开关把它置为「未启用」。

机制细节、勘验证据与失败模式见 docs/ARCHITECTURE.md。

不变量:市场自己不落任何安装代码,安装 / 卸载 / 启停一律调官方服务; 官方的兼容性闸门、构建脚本审批、失败回滚语义全部照旧生效。


仓库结构

marketplace/          市场插件包(自包含)
  catalog.json        收录目录(单一数据源)
  cordis.patch.yml    市场自己的激活层
  icon.png            市场标志
  lib/                构建产物(Loader 入口 + 客户端 bundle)
  src/host/           Host 半边源码
  src/client/         客户端半边源码(ui/ 下按视图分文件)
  plugins/*           收录插件(每个都是可独立安装的 DSH bundle 包)
scripts/              构建、收录、离线验证
tools/                真实浏览器验收工具链(CDP + 临时 profile)
docs/                 方案、架构、验收、上手指南
  images/             README 用的实机截图
AGENTS.md             维护本仓库需要知道的一切(给人和 AI 用)

开发与验证

# 构建与收录
node scripts/build-client.mjs          # 构建客户端 bundle(--check 只校验)
node scripts/sync-catalog.mjs          # 收录 plugins/ 到 catalog.json(--check 只校验)

# 离线套件(提交前必须全绿)
node scripts/verify.mjs                # 用真实 dsh --dump-config 验证组合与软链
node scripts/check-client-bundle.mjs   # 在 vm 里真执行客户端工厂脚本 + 渲染烟测
node scripts/check-client-state.mjs    # 用真实 RemoteResult 样例驱动状态机
node scripts/simulate.mjs              # 用桩上下文真跑 Host 半边与安装编排
node scripts/verify-plugins.mjs        # 收录插件的静态校验
node tools/render-logo.mjs             # 由 icon.png 缩出 README 用的大图
node tools/icons.mjs                   # 图标流水线:GPT 生图 → 后处理 → 小尺寸目视验收图

# 真实浏览器端到端(Edge headless + 临时 profile,不碰你自己的 profile)
node tools/dsh-preview.mjs --port 18855 --bundle ./marketplace --keep
node tools/market-e2e.mjs --port 18855 --entry plugin-hello     # 期望 exit 0
node tools/dsh-preview.mjs --port 18855 --stop
套件结果
scripts/verify.mjs29/29
scripts/build-client.mjs --check0(产物与源码同步)
scripts/sync-catalog.mjs --check0(目录与 plugins/ 同步)
scripts/check-client-bundle.mjs51/51(渲染烟测 + 官方几何 + 类名反向检查 + 主题/交互)
scripts/check-client-state.mjs38/38
scripts/simulate.mjs39/39
scripts/verify-plugins.mjs137 项检查,0 error
tools/market-e2e.mjs117/117(真实 Edge headless,退出码 0)

端到端成功运行后会更新 tools/market-e2e-receipt.json,记录实际条数与测试脚本的 SHA-256。 verify.mjs 默认用这份回执核对中英文计数;回执缺失、损坏或脚本变更后尚未重跑都会失败。 无需设置 DSH_E2E_TOTAL;若手动提供,该值也必须与回执一致。发布时应一并同步成功回执。

端到端要跑两条分支:带 Loader 行的插件(plugin-hello)与纯客户端插件 (plugin-quick-notes)。

这里说准确一点:plugin-quick-notes 的 Host 实现是空的,但它仍然声明了一行 (cordis.patch.yml 里 - id: dsh-plugin-quick-notes),因为启停/卸载需要两侧对称。 所以这两条覆盖的是「Host 有实现」与「Host 是空壳」,不是「有行 vs 完全没行」—— 真正零行的插件不在收录样例里,那是官方加载器的行为,本市场造不出来。

逐条实测结果与对应的用户要求见 docs/ACCEPTANCE.md。 想加插件见 docs/ADD-A-PLUGIN.md, 想知道「改这个仓库必须注意什么」见 AGENTS.md。


已知限制

  • 改了插件 Host 半边源码后需要重启 DSH。 DSH 的 HMR 只热重载客户端 bundle, 第三方插件的 Host 源码不会热更新。
  • 首次装完市场需要刷新一次页面,客户端 bundle 才会进入引导图。
  • 组合行的刷新时机:刚装完一个插件时,它的 Loader 行可能还没进入组合, 详情页的「包含的组件」会如实显示为「已关闭 / 未装载」;重新加载页面后就是真实状态。
  • 组件行图标用市场图标兜底:官方那种「每个组件一个独立图标」用的是上游模块自己的图标资源, 第三方拿不到,所以我们统一用市场图标。

边界与取舍

  • 只做自包含分发。 不支持「目录里放一个 registry 包名,安装时去公网拉」—— 那会破坏「市场自包含」这个核心卖点。
  • 不绕过官方权限模型。 市场调用的是官方 pluginManager,因此官方的兼容性闸门、 构建脚本审批、失败回滚语义全部照旧生效。
  • 不改 DSH 自身。 市场只是官方服务的消费者。
  • 零第三方依赖。 包括测试工具链在内,本仓库不引入任何 npm 依赖; 连截图裁剪都是用 CDP 的 clip 参数做的。

Licensed under the terms in LICENSE.