🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

插件商店 yunhuantian/dsh-plugin-hub

DeepSeek Harnessv0.2.6
yunhuantian6 天前有提交已提供中文文档扫描:高危

DeepSeek Harness(DSH)插件商店:Harness Web UI 里的图形化应用商店,浏览、搜索并一键安装 GitHub 上的 dsh-plugin(topic:dsh-plugin / #dsh-plugin 仓库)…

39.5/100
综合分
7
GitHub 星标
1,831
npm 周下载
—/5
用户评分

数据截至 2026/10/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-plugin-hub
npm 源 · dsh-plugin-hub 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · market
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 6 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-plugin-hub @ 0.2.6
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 07:30:41

🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0
🔴 扫描:高危尚无人工评估

静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。

命令参数由运行时变量拼接读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 143 处,展示前 110 条)
  • 读取本地文件
    lib/hub/src/host/index.js:143
    if (existsSync(file)) {
  • 读取本地文件
    lib/hub/src/host/index.js:144
    const id = readFileSync(file, 'utf8').trim().slice(0, 64);
  • 读取本地文件
    lib/hub/src/host/index.js:163
    return readdirSync(dir);
  • 写入本地文件
    lib/hub/src/host/index.js:171
    mkdirSync(dir, opts);
  • 删除本地文件
    lib/hub/src/host/index.js:177
    rmSync(path, opts);
  • 读取本地文件
    lib/hub/src/host/index.js:543
    const manifest = JSON.parse(readFileSync(this.profile.packageJsonFile, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/index.js:555
    const patch = readFileSync(this.profile.patchFile, 'utf8');
  • 请求外部主机registry.npmjs.org
    lib/hub/src/host/index.js:635
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, { signal: AbortSignal.timeout(10000) });
  • 发起网络请求
    lib/hub/src/host/index.js:635
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, { signal: AbortSignal.timeout(10000) });
  • 请求外部主机registry.npmjs.org
    lib/hub/src/host/index.js:728
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, { method: 'HEAD', signal: AbortSignal.timeout(8000) });
  • 发起网络请求
    lib/hub/src/host/index.js:728
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, { method: 'HEAD', signal: AbortSignal.timeout(8000) });
  • 读取本地文件
    lib/hub/src/host/index.js:776
    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 请求外部主机api.npmjs.org
    lib/hub/src/host/index.js:1006
    const res = await fetch(`https://api.npmjs.org/downloads/range/${start}:${end}/${encodeURIComponent(packageName)}`, { signal: AbortSignal.timeout(10_0
  • 发起网络请求
    lib/hub/src/host/index.js:1006
    const res = await fetch(`https://api.npmjs.org/downloads/range/${start}:${end}/${encodeURIComponent(packageName)}`, { signal: AbortSignal.timeout(10_0
  • 写入本地文件
    lib/hub/src/host/index.js:1111
    writeFileSync(join(target, 'SKILL.md'), skill.content ?? '', 'utf8');
  • 写入本地文件
    lib/hub/src/host/index.js:1124
    writeFileSync(join(target, rel), buf, 'utf8');
  • 读取密钥环境变量
    lib/hub/src/host/index.js:1185
    if (mode === 'e2e' && !process.env.DEEPSEEK_API_KEY) {
  • 执行外部命令来自配置/变量
    lib/hub/src/host/index.js:1193
    const child = spawn(process.execPath, [bin, ...args], { cwd: benchPkg, env: { ...process.env, DSH_HOME: resolveDshHome() }, stdio: 'ignore', windowsHi
  • 发起网络请求
    lib/hub/src/host/index.js:1376
    const res = await fetch(target, {
  • 写入剪贴板
    lib/client.js:15680
    void navigator.clipboard?.writeText(cmd).catch(() => void 0);
  • 写入剪贴板
    lib/client.js:16867
    void navigator.clipboard?.writeText(cmd).catch(() => void 0);
  • 写入剪贴板
    lib/client.js:18586
    await navigator.clipboard.writeText(s);
  • 写入剪贴板
    lib/client.js:18714
    void navigator.clipboard?.writeText(cmd).then(() => {
  • 写入本地文件
    lib/hub/src/host/store-db.js:202
    mkdirSync(dir, { recursive: true });
  • 发起网络请求
    lib/hub/src/host/github.js:51
    const res = await fetch(url, { headers: { ...this.headers(), ...extraHeaders }, signal: AbortSignal.timeout(20000) });
  • 发起网络请求
    lib/hub/src/host/github.js:71
    const res = await fetch(url, { headers: { 'User-Agent': 'dsh-plugin-hub' }, signal: AbortSignal.timeout(20000) });
  • 发起网络请求
    lib/hub/src/host/github.js:131
    const res = await fetch(`${NPM_API}/downloads/point/last-month/${encodeURIComponent(packageName)}`, { signal: AbortSignal.timeout(10000) });
  • 执行外部命令运行时拼接
    lib/hub/src/host/installer.js:91
    ? spawn(`${cmd} ${cmdArgs.map(escapeWinArg).join(' ')}`, { cwd, shell: true, windowsHide: true, env: { ...process.env, NO_COLOR: '1', HTTP_PROXY: '',
  • 执行外部命令来自配置/变量
    lib/hub/src/host/installer.js:92
    : spawn(cmd, cmdArgs, { cwd, shell: false, windowsHide: true, env: { ...process.env, NO_COLOR: '1', HTTP_PROXY: '', HTTPS_PROXY: '', http_proxy: '', h
  • 执行外部命令固定命令
    lib/hub/src/host/installer.js:105
    spawn('taskkill', ['/pid', String(child.pid), '/t', '/f'], { windowsHide: true, stdio: 'ignore' });
  • 读取本地文件
    lib/hub/src/host/installer.js:136
    if (!existsSync(filename))
  • 读取本地文件
    lib/hub/src/host/installer.js:139
    return JSON.parse(readFileSync(filename, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/installer.js:149
    const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/installer.js:167
    const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/installer.js:173
    if (!existsSync(patchFile))
  • 读取本地文件
    lib/hub/src/host/installer.js:175
    const document = parseDocument(readFileSync(patchFile, 'utf8'));
  • 写入本地文件
    lib/hub/src/host/installer.js:230
    writeFile(profile.packageJsonFile, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8').catch((err) => {
  • 写入本地文件
    lib/hub/src/host/installer.js:306
    await mkdir(dirname(filename), { recursive: true });
  • 写入本地文件
    lib/hub/src/host/installer.js:308
    await writeFile(temporary, content.endsWith('\n') ? content : `${content}\n`, 'utf8');
  • 写入本地文件
    lib/hub/src/host/installer.js:309
    await rename(temporary, filename);
  • 执行外部命令固定命令
    lib/hub/src/host/installer.js:593
    const child = spawn('git', args, { cwd, windowsHide: true, env: { ...process.env, GIT_TERMINAL_PROMPT: '0' } });
  • 删除本地文件递归
    lib/hub/src/host/installer.js:605
    await rm(target, { recursive: true, force: true });
  • 发起网络请求
    lib/hub/src/host/npm-probe.js:32
    const res = await fetch(url, { method: 'HEAD', signal, redirect: 'follow' });
  • 写入本地文件
    lib/hub/src/host/list-sources.js:26
    mkdirSync(dir, { recursive: true });
  • 读取本地文件
    lib/hub/src/host/list-sources.js:172
    if (!existsSync(path))
  • 读取本地文件
    lib/hub/src/host/list-sources.js:174
    const bytes = readFileSync(path);
  • 发起网络请求
    lib/hub/src/host/list-sources.js:179
    const res = await fetch(target, {
  • 写入本地文件
    lib/hub/src/host/list-sources.js:237
    writeFileSync(file, stored);
  • 读取本地文件
    lib/hub/src/host/list-sources.js:276
    if (!existsSync(file))
  • 读取本地文件
    lib/hub/src/host/list-sources.js:278
    return openMarketIndex(readFileSync(file));
  • 删除本地文件
    lib/hub/src/host/list-sources.js:283
    rmSync(listFile(id, home), { force: true });
  • 写入本地文件
    lib/hub/src/host/list-sources.js:351
    writeFileSync(listFile(id, home), stored);
  • 执行外部命令运行时拼接
    lib/hub/src/host/publish.js:34
    ? spawn(`${cmd} ${args.map(escapeWinArg).join(' ')}`, { cwd, shell: true, windowsHide: true, env: { ...process.env, NO_COLOR: '1' } })
  • 执行外部命令来自配置/变量
    lib/hub/src/host/publish.js:35
    : spawn(cmd, args, { cwd, windowsHide: true, env: { ...process.env, NO_COLOR: '1' } });
  • 执行外部命令固定命令
    lib/hub/src/host/publish.js:47
    spawn('taskkill', ['/pid', String(child.pid), '/t', '/f'], { windowsHide: true, stdio: 'ignore' });
  • 发起网络请求
    lib/hub/src/host/publish.js:66
    const res = await fetch(url, {
  • 读取本地文件
    lib/hub/src/host/publish.js:86
    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/publish.js:211
    if (req.writeReadme !== false && m.description && !existsSync(join(m.dir, 'README.md')) && !existsSync(join(m.dir, 'readme.md'))) {
  • 写入本地文件
    lib/hub/src/host/publish.js:214
    writeFileSync(join(m.dir, 'README.md'), readme, 'utf8');
  • 读取本地文件
    lib/hub/src/host/publish.js:218
    if (!existsSync(join(m.dir, '.git'))) {
  • 发起网络请求
    lib/hub/src/host/publish.js:295
    const res = await fetch(`${NPM_REGISTRY}/-/whoami`, {
  • 发起网络请求
    lib/hub/src/host/publish.js:311
    const res = await fetch(`${NPM_REGISTRY}/${encodeURIComponent(m.pkgName).replace(/%2F/g, '/')}`, { signal: AbortSignal.timeout(15_000) });
  • 发起网络请求
    lib/hub/src/host/catalog-sync.js:5
    const res = await fetch(CATALOG_URL, { signal: AbortSignal.timeout(15_000) });
  • 读取本地文件
    lib/hub/src/host/plugins-state.js:401
    if (!existsSync(dir))
  • 写入本地文件
    lib/hub/src/host/plugins-state.js:402
    mkdirSync(dir, { recursive: true });
  • 读取本地文件
    lib/hub/src/host/plugins-state.js:416
    if (!existsSync(file))
  • 读取本地文件
    lib/hub/src/host/plugins-state.js:418
    return JSON.parse(readFileSync(file, 'utf8'));
  • 写入本地文件
    lib/hub/src/host/plugins-state.js:439
    writeFileSync(pluginOverridesFile(home), `${JSON.stringify(current, null, 2)}\n`, 'utf8');
  • 写入本地文件
    lib/hub/src/host/plugins-state.js:498
    writeFileSync(pluginStatusFile(home), `${JSON.stringify(current, null, 2)}\n`, 'utf8');
  • 读取本地文件
    lib/hub/src/host/security-scan.js:54
    entries = readdirSync(dir);
  • 读取本地文件
    lib/hub/src/host/security-scan.js:65
    st = statSync(full);
  • 读取本地文件
    lib/hub/src/host/security-scan.js:119
    text = readFileSync(join(dir, f), 'utf8');
  • 读取本地文件
    lib/hub/src/host/conflict-check.js:27
    entries = readdirSync(dir);
  • 读取本地文件
    lib/hub/src/host/conflict-check.js:38
    st = statSync(full);
  • 读取本地文件
    lib/hub/src/host/conflict-check.js:66
    pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/conflict-check.js:79
    text = readFileSync(file, 'utf8');
  • 读取本地文件
    lib/hub/src/host/conflict-check.js:95
    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/conflict-check.js:106
    const manifest = JSON.parse(readFileSync(profile.packageJsonFile, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/version-guard.js:33
    const pkg = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/version-guard.js:142
    if (!existsSync(readmePath)) {
  • 读取本地文件
    lib/hub/src/host/version-guard.js:146
    const versions = documentedVersions(readFileSync(readmePath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/version-guard.js:175
    if (!existsSync(patchPath)) {
  • 读取本地文件
    lib/hub/src/host/version-guard.js:179
    const patch = readFileSync(patchPath, 'utf8');
  • 读取本地文件
    lib/hub/src/host/version-guard.js:205
    if (existsSync(profile.packageJsonFile)) {
  • 读取本地文件
    lib/hub/src/host/update-check.js:17
    if (!existsSync(profile.packageJsonFile))
  • 读取本地文件
    lib/hub/src/host/update-check.js:21
    const pkg = JSON.parse(readFileSync(profile.packageJsonFile, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/update-check.js:32
    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 请求外部主机registry.npmjs.org
    lib/hub/src/host/update-check.js:56
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal, redirect: 'follow' });
  • 发起网络请求
    lib/hub/src/host/update-check.js:56
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`, { signal, redirect: 'follow' });
  • 请求外部主机api.github.com
    lib/hub/src/host/update-check.js:69
    const res = await fetch(`https://api.github.com/repos/${repoFullName}/releases/latest`, {
  • 发起网络请求
    lib/hub/src/host/update-check.js:69
    const res = await fetch(`https://api.github.com/repos/${repoFullName}/releases/latest`, {
  • 读取本地文件
    lib/hub/src/host/backup.js:30
    for (const name of readdirSync(dir)) {
  • 读取本地文件
    lib/hub/src/host/backup.js:32
    const st = statSync(target);
  • 读取本地文件
    lib/hub/src/host/backup.js:42
    if (!existsSync(root))
  • 读取本地文件
    lib/hub/src/host/backup.js:45
    for (const name of readdirSync(root)) {
  • 读取本地文件
    lib/hub/src/host/backup.js:48
    if (!statSync(dir).isDirectory())
  • 读取本地文件
    lib/hub/src/host/backup.js:51
    if (existsSync(manifestPath)) {
  • 写入本地文件
    lib/hub/src/host/backup.js:73
    mkdirSync(dir, { recursive: true });
  • 删除本地文件
    lib/hub/src/host/backup.js:79
    rmSync(target, { force: true });
  • 写入本地文件
    lib/hub/src/host/backup.js:87
    copyFileSync(db.path, target);
  • 写入本地文件
    lib/hub/src/host/backup.js:99
    copyFileSync(src, join(dir, name));
  • 写入本地文件
    lib/hub/src/host/backup.js:104
    mkdirSync(profileDir, { recursive: true });
  • 写入本地文件
    lib/hub/src/host/backup.js:109
    copyFileSync(src, join(profileDir, name));
  • 写入本地文件
    lib/hub/src/host/backup.js:121
    writeFileSync(join(dir, 'manifest.json'), `${JSON.stringify(entry, null, 2)}\n`, 'utf8');
  • 删除本地文件递归
    lib/hub/src/host/backup.js:134
    rmSync(entry.path, { recursive: true, force: true });
  • 读取本地文件
    lib/hub/src/host/diagnostics.js:15
    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
  • 读取本地文件
    lib/hub/src/host/diagnostics.js:24
    if (profile === null || !existsSync(profile.packageJsonFile))
  • 读取本地文件
    lib/hub/src/host/diagnostics.js:27
    const pkg = JSON.parse(readFileSync(profile.packageJsonFile, 'utf8'));
  • 写入本地文件
    lib/hub/src/host/diagnostics.js:113
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    lib/hub/src/host/diagnostics.js:116
    writeFileSync(path, `${body}\n`, 'utf8');
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
涉及外部主机:registry.npmjs.org、api.npmjs.org、api.github.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-ui-primitives@deepseek-ai/dsh-typert-protocol@deepseek-ai/cordis-plugin-loader@deepseek-ai/dsh-api-gateway@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-client-ui-settings-general@deepseek-ai/dsh-client-ui-sidebar@deepseek-ai/dsh-client-ui-slots
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 浏览搜索GitHub插件
  • 一键安装插件
  • 查看依赖影响图
market-index-2026.10.282026-10-28
· 这是什么 DSH 官方「插件 → 发现」页可读的插件市场索引(format 1)。这一份只收认证通过的插件:认证版本与 npm 最新版本一致。 · 内容 · market-index.json:121 条,全部带 certified 标签;13 个分类 · certified.json:认证快照(包名 + 认证版本 + 认证人 + 时间) · legacy-report.md:17 个认证版本已过期的插件(dist-tag 回退,未纳入) · 怎么用 在 DSH 的「插件 → 发现」里添加索引源: 或直接下载本页的 market-index.json 自建托管。索引地址必须是 http(s) 直链且不能 302。 与程序包分开发布:索引会随认证进度单独更新,不需要为数据改动发新的 npm 版本。
v0.2.72026-10-28
· 这一版做了什么 · 商店外壳收成一行:去掉左侧 176px 竖排导航,所有区块改为顶部横向标签,内容区回到全宽。 · 百科彻底停用:baike 默认关闭之外,导航入口、详情页「百科」标签、wikiHub / wiki 两个接口全部跟着开关走,关掉后不会再出现内容。 · 接入官方「插件 → 发现」页:新增 market-index.json(官方 format 1),官方 plugin-market 读取后可直接浏览与安装。 · 数据 · 插件表 171 条(本轮新增 21 个,含视频、Git 面板、IM 桥接、插件体检等) · 官方发现页索引 121 条,全部为认证条目(认证版本 == npm 最新版本) · 资产 · dsh-plugin-table-0.2.7.zip:插件表(dpmidx / json / md) · dsh-modpacks-0.2.7.zip:三个整合包 + 验证记录 认证索引单独发布(见 market-index-2026.10.28)。
v0.2.62026-10-26
· 整合包一键安装 整合包页每套都有一个按钮,装整个包(串行装、已装的自动跳过、失败会列出是谁)。 · 整合包简介 DPMIDX 元数据新增 intro:一句话 description 之外,作者可以写多行简介交代定位、选品理由和使用前提。商店的整合包页会在选中后展开显示。 · 百科的外部仓库停用 百科依赖的 Blue-Whale-Harness 目录与信任徽章索引(dsh-hub-index)默认关闭 —— 数据质量不由我们控制。要恢复就在设置里写 external_sync=1。 · 修一个静默故障 build-client.mjs 之前会删掉整个 dist/,把插件表与整合包产物一起清空。现在只删自己的中间文件。 · 关于版本号 0.2.5 在 npm 侧产生了无法批准、也无法删除的暂存记录(approve/reject 均 404),该版本号无法发布。内容完全一致,改用 0.2.6 发布,npm 与这里同步。 · 下载 · dsh-plugin-table-0.2.6.zip —— 插件表(150 个) · dsh-modpacks-0.2.6.zip —— 三个整合包 + 可用性验证结果 第三方作者自己建列表/整合包:见 docs/build-list-and-pack.md。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-plugin-hub — DSH 插件商店 DeepSeek Harness 里的图形化插件商店,嵌在官方「插件」页里:自动识别、认证列表、整合包、一键安装、健康度、发布与审计。一个 npm 包带 20 个可单独开关的内部插件,另随包预置 16 个离线条目,装好即有内容。 商店自己的认证索引同时以官方 format 1 发布(当前 121 条),可以直接配进官方「插件 → 发现」页。 支持 DSH 0.1.x 与 0.2.x 两条版本线 · MIT · 当前 0.2.7(2026-10-28) 当前状态 一、已停用 / 默认关闭 | 功能 | 开关 | 现在的状态 | 想用时怎么恢复 | | 插件百科 | baike | 默认关,并且入口、详情 tab、数据接口三处一起关 | 「内置扩展」里打开百科;外部目录还需 meta external_sync=1 | | 外部目录同步 | 元数据 external_sync | 默认关(Blue-Whale 等外部仓库) | 写 external_sync=1 后再同步 | | 信任徽章同步 | — | 已移除(0.2.6 起 trust 子插件并入质量门禁) | 无需恢复 | | 更新日志生成 | changelog | 默认关 | 「内置扩展」里打开 |
展开完整文档(README 剩余 1 节)
dsh-plugin-hub — DSH 插件商店

DeepSeek Harness 里的图形化插件商店,嵌在官方「插件」页里:自动识别、认证列表、整合包、一键安装、健康度、发布与审计。一个 npm 包带 20 个可单独开关的内部插件,另随包预置 16 个离线条目,装好即有内容。

商店自己的认证索引同时以官方 format 1 发布(当前 121 条),可以直接配进官方「插件 → 发现」页。

支持 DSH 0.1.x 与 0.2.x 两条版本线 · MIT · 当前 0.2.7(2026-10-28)

当前状态

一、已停用 / 默认关闭

| 功能 | 开关 | 现在的状态 | 想用时怎么恢复 |
| 插件百科 | baike | 默认关,并且入口、详情 tab、数据接口三处一起关 | 「内置扩展」里打开百科;外部目录还需 meta external_sync=1 |
| 外部目录同步 | 元数据 external_sync | 默认关(Blue-Whale 等外部仓库) | 写 external_sync=1 后再同步 |
| 信任徽章同步 | — | 已移除(0.2.6 起 trust 子插件并入质量门禁) | 无需恢复 |
| 更新日志生成 | changelog | 默认关 | 「内置扩展」里打开 |
| 技能商店 | skill-store | 默认关 | 「内置扩展」里打开 |
| 诊断报告导出 | diagnostics | 默认关 | 「内置扩展」里打开 |

两件事值得单独说明:

- 百科是「真关」了,不是只关了个壳。 0.2.6 只把 defaultEnabled 设成 false,但顶部导航是硬编码数组、host 的 wikiHub / wiki 直接读库 —— 结果插件看着关了,百科条目照样出得来。0.2.7 把门控补到三处:顶部标签不显示、详情页不显示百科 tab、接口直接返回空 / 明确报错。数据仍在库里,重新打开开关即可恢复,不删库。
- 外部目录为什么关。 百科原本依赖 Blue-Whale-Harness 的外部目录,数据质量不可控;目录内容随时会被上游改掉,而这又直接影响商店里看到的东西。现在整条链路由 external_sync 元数据门控,默认不碰外部文件。

二、这轮改进了什么

| 改进 | 之前 | 现在 |
| 商店外壳 | 左侧 176px 竖排导航,内容区只剩 856px | 顶部横向标签,12 个视图,内容区回到 1020px |
| 功能门控 | 插件开关只管「服务起不起」,入口照旧在 | 导航 / 详情 tab / 接口三处跟开关走 |
| 数据存放 | 插件表与整合包写在 hub 包里,改数据要发版本 | 数据搬进独立仓库,改数据只推数据 |
| 认证 | 只认「这个包」 | 按版本认证:认证版本 ≠ 当前版本就是 legacy |
| 官方发现页 | 完全没接入 | 根目录 market-index.json,121 条认证条目 |
| 整合包 | 只能看成员列表 | 可点进详情、一键安装、带简介与安装顺序 |

三、这轮更新了什么

0.2.7 的主要变化:顶部标签外壳、百科门控补全、官方发现页接入、认证索引 76 → 121。
完整内容见文末版本历史。

怎么用

装好后不新增自己的入口,而是作为一项出现在 DSH 自带的「插件」页里:

侧栏「插件」 → 插件商店

进去是商店本体,12 个视图全在顶部一排标签上:

自动识别 / 认证列表 / 整合包 / 百科* / Skill 商店* / 已安装 / 内置扩展 / 健康度* / 发布 / 开发脚手架 / 审计日志 / 设置

带 的由内建插件提供,插件关掉后标签直接不出现(不是灰掉,是不占位)。

0.1.x 上落点不同:那时是侧栏底部一个独立按钮 + 全屏弹层,外加一个独立设置页。
0.2.3 起改为嵌进官方「插件」页,看起来就是这个页面本就有的功能。

一个包,20 个内部插件

0.2 起 hub 的组织方式与 DSH 本体一致 —— @deepseek-ai/dsh 是一个包,内部装着 60+ 个 dsh- 条目;hub 同样一次发布、一次安装,内部由 20 个可单独开关的插件组成,每个都在 DSH 的「设置 → 插件」清单页里各占一行(共 21 行:本体 + 20)。

基础内核 Foundation

| 条目 | 名称 | 提供 | 默认 |
| dsh-plugin-hub | 插件商店(核心) | Remote pluginStore | 开 |
| hub-ext-store-db | 商店数据库 / Store Database | pluginStoreDb | 开 |
| hub-ext-github | GitHub 通道 / GitHub Channel | pluginGithub | 开 |
| hub-ext-npm-probe | npm 可用性探测 / npm Probe | pluginNpmProbe | 开 |
| hub-ext-seed-catalog | 预置插件目录 / Seed Catalog | pluginSeedCatalog | 开 |
| hub-ext-registry | 索引同步 / Registry Sync | pluginRegistry | 开 |
| hub-ext-installer | 安装引擎 / Install Engine | pluginInstaller | 开 |

安全与质量 Safety & Quality

| 条目 | 名称 | 提供 | 默认 |
| hub-ext-security | 安全扫描 / Security Scan | pluginSecurity | 开 |
| hub-ext-conflict | 安装冲突检测 / Conflict Detection | pluginConflict | 开 |
| hub-ext-quality | 质量门禁 / Quality Gate | pluginQuality | 开 |

hub-ext-trust(信任徽章同步)已在 0.2.5 并入质量门禁,名册从 21 条收敛到 20 条。

发布流水线 Publishing

| 条目 | 名称 | 提供 | 默认 |
| hub-ext-publish | 一键发布 / One-click Publish | pluginPublish | 开 |
| hub-ext-version-guard | 版本一致性守卫 / Version Guard | pluginVersionGuard | 开 |
| hub-ext-changelog | 更新日志生成 / Changelog Drafter | pluginChangelog | 关 |

洞察与内容 Insight & Content

| 条目 | 名称 | 提供 | 默认 |
| hub-ext-usage | 用量与费用 / Usage & Cost | usagePricing | 开 |
| hub-ext-health | 插件健康度 / Plugin Health | pluginHealth | 开 |
| hub-ext-update-check | 版本更新检测 / Update Check | pluginUpdateCheck | 开 |
| hub-ext-dependency-graph | 依赖影响图谱 / Dependency Graph | pluginDepGraph | 开 |
| hub-ext-baike | 插件百科 / Plugin Wiki | pluginWiki | 关 |
| hub-ext-skill-store | 技能商店 / Skill Store | skillStore | 关 |

运维 Operations

| 条目 | 名称 | 提供 | 默认 |
| hub-ext-backup | 备份与回滚 / Backup & Rollback | pluginBackup | 开 |
| hub-ext-diagnostics | 诊断报告导出 / Diagnostics Export | pluginDiagnostics | 关 |

依赖是声明式的,不是硬注入

内部插件之间声明依赖(如 registry → store-db + github、publish → security),运行时由统一的 activate() 判定:

用户关掉「商店数据库」 └─→ registry / installer / npm-probe / seed-catalog / update-check / dependency-graph / baike 全部上报「依赖阻塞」并主动让位(不提供服务、不注册 UI、不报错) └─→ 把「商店数据库」再打开,整条链自动恢复

这样做而不是用 cordis 的 inject 硬依赖,是因为硬依赖会造成 "提供者被用户停用 → 消费者永久 pending" 的死锁。声明式依赖下,任何一方被关掉都是干净的「阻塞」状态,随时可逆。

为什么把实用插件直接装进包里:插件越多,逐个下载、逐个安装的链路越长(网络、限频、版本错配、装到一半失败)。内置之后,装一次 hub 就有 20 个能力可用,仓库里也不必再维护 20 个独立包与 20 套发布流程。

离线预置目录(避免"空白商店")

商店内容正常来自 GitHub 镜像同步(几百个仓库、几百次请求、几分钟)。新装用户在同步跑完之前看到的是空白。hub-ext-seed-catalog 把 16 个公认实用的插件写进包里,装好立刻可见、可看详情、可安装:

| 方向 | 预置插件 |
| 视觉 | @liustack/modlens、@anionex/dsh-vision-toolkit |
| 界面 | dsh-better-sidebar、@deepseek-harness-tui/dsh-tui、@deepseek-ai/dsh-client-ui-aqua、dsh-reasoning-effort |
| 记忆 | @mnemon-dev/dsh-mnemon |
| 输入与开发 | dsh-at-file、dsh-open-in-vscode、@omdsh-dev/dsh-genui |
| 成本与上下文 | dsh-cost-meter、dsh-context |
| 效率 | dsh-notification、dsh-skill-viewer |
| 商店同类 | dshmarket、dsh-web-plugin-manager |

写入规则是只插不覆盖:某个包一旦被真实同步写入过,预置就绝不覆盖它(真数据有 README、版本历史、issues)。目录版本用日期,升级后下次启动自动刷新自己的行。
列表里这类条目标「预置」徽章。

两级开关

1. 安装级:hub 的 cordis.patch.yml 每行可写 disabled: true(部署策略);
2. 日常级:侧栏「插件」→ 插件商店 →「内置扩展」,按分组管理,写本机 storages/plugin-store/plugins.json,重启 dsh 后生效。

⚠️ 默认关闭的四个插件(changelog / baike / skill-store / diagnostics)在 patch 里不写 disabled: true:写了 loader 就不会加载它们,模块也就没机会读设置页的开关,表现为"打开了没反应"。默认关闭一律由模块自己让位实现,开关才可逆。

关掉一个插件=它启动时让位(不提供服务、不注册界面),商店核心功能完全不受影响。

内建插件做什么

用量与费用 —— 价格表带日期,可回溯历史价

会话里每个请求的 token、缓存命中率时间图表(滚轮缩放 / 拖动平移 / 双击复位),并按 版本化价格表同时算两个数:

- 当时价:请求发生时刻生效的价格表 → 等于当时实际计费
- 现价:最新价格表 → 同样的用量放在今天要多少钱
- 两者不同就显示差额(+$0.0123 比当时贵 / −… 比当时便宜)

价格表按生效日期分版本,调价只追加新版本,历史不可变:

| 版本 | 生效(UTC) | 关键变化 |
| 2026-08-15 | 2026-08-15 00:00 | 基线:DeepSeek V4 Flash(0731)$0.22 / 缓存命中 $0.007 / 输出 $0.66 |
| 2026-09-10 | 2026-09-10 04:00 | V4.1 Flash 上线:$0.15 / 缓存命中 $0.003 / 输出 $0.60,高峰单价 ×2 |
| 2026-09-14 | 2026-09-14 04:00 | V4 Pro 并入 Flash 计费(请求自动路由,按 Flash 单价计) |

高峰规则:工作日 UTC 01:00–04:00 与 06:00–10:00 单价翻倍,其余为空闲价。
OpenAI / Anthropic / Google / Qwen / 智谱 / Moonshot 的价格一并内置。

计费口径与 DSH 的 token-meter 对齐:usage.inputTokens 就是未缓存输入桶,计费输入 = 未缓存 + 缓存读取 + 缓存写入。未收录的模型不估算,显式提示而不是假装。

插件健康度 / 版本更新检测 / 依赖影响图谱

- 健康度:按活跃度、发布节奏、社区反馈(stars / downloads / open issues)打分(0–100)与等级(healthy / attention / stale),给出信任等级与排行。
- 更新检测:本机已装版本 vs 上游最新(npm registry 优先,回落 GitHub releases,缓存 6h),列出可升级清单。
- 依赖影响图谱:升级 / 卸载前先看清会牵连谁(直接依赖 + 反向依赖)。

安全与质量:装之前先体检

- 安全扫描:危险脚本、敏感文件读取、动态执行、可疑外联;critical 直接拦截安装/发布。
- 冲突检测:UI 槽位占用(single 槽独占)、包名撞车、依赖版本冲突。
- 质量门禁:发布前 8 项检查(声明完整、构建产物、README、许可、版本规范…)。

发布流水线:一个动作从本地到线上

- 一键发布:GitHub 建仓/推送 + npm 发布双通道,带分段进度;发布前自动过安全扫描。
- 版本一致性守卫:对齐 package.json / README 更新日志 / profile 安装来源 / 包内子插件 exports。专治"包升了文档没升""加了子插件行忘了加 exports"。
- 更新日志生成(默认关):从 git 历史按 Conventional Commits 归并成 README 风格草稿。

运维:翻车了能回来

- 备份与回滚:VACUUM INTO 导出一致性数据库副本 + 插件开关 + profile 清单,只留最近 10 个;回滚前先把当前状态另存,因此回滚本身也可回滚。
- 诊断报告导出(默认关):环境 + 20 个内建插件状态 + profile 依赖 + 索引统计 + 最近审计,打包成 Markdown,不含任何令牌明文。

插件百科(默认关,当前停用)

把插件元数据、README 要点、依赖与相关插件汇总成可检索条目。0.2.6 起默认停用:它依赖的外部目录仓库(Blue-Whale-Harness)数据质量不稳,先关掉,等改成自建目录再开。
0.2.7 补齐了门控 —— 关掉之后导航、详情 tab、wikiHub / wiki 接口全部让位。

技能商店(默认关)

跨生态收集 SKILL.md 技能包,检索并一键安装到本地技能目录。

商店核心功能

- 自动识别:从 GitHub topic:dsh-plugin 自动同步来的条目,12 分类、7 种排序(随机 / 健康度 / stars / 评分 / 下载 / 更新 / 名称)、搜索、已安装过滤
- 认证列表:只显示经人工核验、且认证版本与当前版本一致的条目(见下节)
- 整合包:按场景组好的成套插件,可看简介、安装顺序、一键装
- 安装:npm registry 直装或 GitHub 克隆;写 profile 的 cordis.patch.yml,由 cordis 实时生效
- 已安装:系统 / 下载 / 自创作 三类之下再按归属分组展示 —— 商店自己的插件单列「插件商店」组,与系统组件彻底分开;逐条启停(受保护的系统条目会被拦截)、按分类批量开关、卸载
- 质量门:依赖完整性 + 启动目录需求检查,装前拦截
- 安全扫描:发布前扫描高风险模式(自动驳回)
- 发布:填 Markdown 图文介绍 → GitHub + npm 双通道一键发布(自备 token)
- 审计:安装 / 卸载 / 启停 / 评分 / 发布全量落库,带操作者身份,可追溯
- 镜像同步:把 GitHub 上 topic:dsh-plugin 仓库元数据缓存进本地 SQLite(并发池 + 会话缓存),列表与搜索不再受网络与限频影响
- 依赖拓扑:插件的依赖与被依赖关系图
- 生态接入:跑分机(dsh-bench)的本地状态读写与一键触发跑分

认证列表与整合包

认证不是「这个包不错」,而是某个具体版本的可用性结论:

plugin_certs(package_name PK, version, publisher, certified_at)
状态 = cert.version === 当前版本 ? certified : legacy

升级一次就要重新核验一次,这样才不会出现「半年前认证过 0.3.0,仓库早改成 0.9.0 了,页面上还挂着认证标」。认证写入是 insert or replace,同一插件反复认证只会覆盖那一行, 不需要先删旧记录;新增条目也一样 —— 幂等。

当前数据(dsh-plugin-registry 仓库):

| 指标 | 数量 |
| 插件表条目 | 171 |
| 已认证 | 171(其中 121 条的认证版本 = 当前版本) |
| 官方索引收录 | 121 |
| 整合包 | 3(日常增强 13 / 开发与调试 14 / 读写与创作 11) |

整合包按场景手工组包,不是「某个分类的合集」:成员互斥(一个插件只属于一个包),有安装顺序与角色(如「模型来源」「记忆后端」),并经过三重验证 —— npm 可解析、 tarball 可取、整包 pnpm install --lockfile-only 能解出完整依赖图。验证不过的成员会被剔除,并在包说明里写明剔除了谁。

接进官方「发现」页

官方插件市场(@deepseek-ai/dsh-plugin-market)只认它自己的索引格式,配置项是 Config.indexes。hub 仓库根目录的 market-index.json 就是按 format 1 生成的,在 profile 的 cordis.patch.yml 里加一段即可:

- id: plugin-market
name: "@deepseek-ai/dsh-plugin-market"
config:
indexes:
- "https://gh-proxy.com/https://raw.githubusercontent.com/yunhuantian/dsh-plugin-hub/main/market-index.json"
cacheTtlMs: 300000

几点实测结论:

- 官方读取器用 fetch(url, { redirect: 'error' }),索引地址不能 302。raw.githubusercontent.com 直连不通,改成 gh-proxy 前缀后是 200;
- 索引里只放已认证条目,全部打 certified 标签,与商店的「认证列表」同一套数据;
- 硬规则:versions 非空、精确 SemVer、publishTimestamp 是整数秒、localizedText 必须含 en、git 源要 40 位小写 commit、分类/label 只能引用顶部声明过的 id。生成脚本跑完会逐条过一遍官方 parseMarketIndex,不合法不落盘。

同步是单向的:商店自己的列表与整合包仍走 DPMIDX,官方索引只是它的一个只读投影。两边的定位也不同 —— 官方发现页负责「发现 + 安装」,商店负责健康度、依赖图、认证、整合包、发布与审计。

自己做列表 / 整合包

.dpmidx 不绑定本商店 —— 任何人都能生成一份自己的列表或整合包,别人用链接或文件导入即可。

- 手把手教程:docs/build-list-and-pack.md —— 输入怎么写、怎么构建、怎么自检、常见错误
- 二进制格式规范:docs/market-index-format.md —— 头部布局、记录结构、多源合并规则
- 整合包设计:docs/modpack-architecture.md —— 为什么列表和整合包要用 kind 分开

最小例子(整合包):

{
"kind": 1,
"meta": { "name": "我的包", "publisher": "我", "description": "一句话", "intro": "详细说明\n第二行" },
"entries": [
{ "name": "dsh-ops", "url": "https://registry.npmjs.org/dsh-ops/-/dsh-ops-0.4.1.tgz" }
]
}

node scripts/build-market-index.mjs my-pack.json my-pack.dpmidx

安装

npm 安装(推荐)
dsh plugin --profile web add dsh-plugin-hub

本地构建后安装(开发调试)
npm install
npm run build # tsc 编译 host + esbuild 打包 client
dsh plugin --profile web add <本包目录>

装好后:侧栏「插件」页里多出 插件商店 一项,点进去就是商店本体;GitHub Token、镜像同步、内置扩展开关都在它的「设置」/「内置扩展」里。首次使用建议先在「设置」里点「立即同步」。

桌面端要完全退出再启动(含托盘图标)。profile 的补丁与依赖是在启动时读的,只关窗口不退出进程,装完看不到新界面。

架构

dsh-plugin-hub(一个 npm 包,单仓五区) ├─ packages/hub/ 商店本体:contracts / host / extensions / client ├─ packages/hub-health/ 健康度(依赖 hub-score) ├─ packages/hub-score/ 跑分:computeHealth 纯算法 ├─ packages/hub-wiki/ 百科 ├─ packages/hub-market-index/ DPMIDX v2/v3 索引格式(零依赖,第三方可直接 import) ├─ cordis.patch.yml 一次插入 21 行:本体 + 20 个内建插件 ├─ lib/ 分发产物(build 生成) ├─ market-index.json 官方 format 1 索引(121 条认证条目) └─ docs/ 格式规范、组包教程、整合包设计

- Host:PluginStoreService 以 Typert Remote(pluginStore)暴露 20+ 个远程方法;node:sqlite 持久化;installer.ts 走 pnpm 安装并改写 profile 补丁。
- 依赖与开关的耦合面:只有两个状态文件 —— storages/plugin-store/plugins.json(开关)与 plugins-status.json(运行状态)。插件之间不通过 cordis 服务互依,依赖是名册里的声明 + 运行时判定,任一方停用都不会把对方拖死(详见上文「依赖是声明式的」)。
- Client:一个包只能有一份 client 产物(DSH 的 dsh.client 契约),所以各内建插件的 UI 都在这份 bundle 里,按开关决定是否注册。
- 契约单一来源:contracts/pricing.ts 同时被 host 编译与 client 内联,价格表因此不可能两边不一致。
- 数据与代码分家:插件表、认证、整合包放在 dsh-plugin-registry 仓库,hub 只负责读;改数据不必发 hub 版本,商店用「资源清单」一次注册全部来源。

开发

npm run build:host # tsc -p tsconfig.host.json
npm run build:client # node scripts/build-client.mjs → lib/client.js
npm run build # 两者
npm run typecheck # host + client 双侧类型检查
npm run check:contract # 契约往返自检:host 返回体 ⨯ zod 契约(防「字段被剥离 → UI 空白」)

若 tsc 不在 PATH:node node_modules/typescript/bin/tsc -p tsconfig.host.json。
构建脚本不许清空 dist/ —— 那里放的是分发产物(表格与下载文件),历史上被清过三次。

加一个内建插件

1. packages/hub/src/host/plugins-state.ts 的 HUB_PLUGINS 里加一条描述符(id / 分组 / requires / 行 id / 服务名 / 默认开关);
2. 该插件要用到的新逻辑放 packages/hub/src/host/<name>.ts(纯函数/类,可被 host 与插件共用);
3. packages/hub/src/extensions/<id>.ts 写 host 半边,形状固定:

ts
export const name = 'dsh-plugin-hub/extensions/<id>';
export const provide = ['<service>'];
export const inject: string[] = [];
export function apply(ctx: any): void {
activate(ctx, '<id>', () => {
ctx.provide('<service>', () => ({ /* ... / }));
});
}

activate 负责读开关、递归判定依赖、上报 disabled/blocked/active;
4. hub 的 cordis.patch.yml 加一行 - id: hub-ext-<id> / name: dsh-plugin-hub/extensions/<id>;
5. package.json 的 exports 加 ./extensions/<id>(漏了会装上去 import 失败; version-guard 内建插件专门查这个)。

目录

packages/
hub/src/
contracts/
remote.ts # zod v4 wire 契约(TYPERT_REMOTE / TYPERT),20+ 个 Remote pricing.ts # 版本化价格表(带生效日期)+ 费用计算(host/client 共用) host/ index.ts # PluginStoreService(Remote + 定时同步 + 内建插件开关) plugins-state.ts # 20 个内建插件的名册 + 依赖判定 + 开关/状态文件 store-db.ts # SQLite(镜像缓存 / 评分 / 审计 / 依赖边 / 认证) list-sources.ts # 资源清单注册 + 来源刷新(数据与代码分离) seed-catalog.ts # 离线预置插件目录(16 个,只插不覆盖) github.ts # GitHub 搜索 + 镜像同步(并发池) installer.ts # 安装 / 卸载 + profile 补丁 quality-gate.ts # 质量门 conflict-check.ts # 安装冲突检查 security-scan.ts # 安全扫描 publish.ts # GitHub + npm 双通道发布 version-guard.ts # 版本一致性检查 changelog.ts # 从 git 历史起草更新日志 update-check.ts # 已装版本 vs 上游最新 backup.ts # 快照 / 回滚(VACUUM INTO) diagnostics.ts # 诊断报告生成 extensions/ # 20 个内建插件的 host 半边(各为一个独立 cordis 条目) _runtime.ts # activate():开关 + 依赖判定 + 状态上报的唯一实现 client/ index.tsx # 核心 UI 注册(官方「插件」页条目 / 字典 / 内建插件 UI 挂载) StoreApp.tsx # 商店外壳(顶部标签 + 视图切换 + 门控) views.tsx # 自动识别 / 认证列表 / 整合包 / 详情 / 已安装 / 发布 / 审计 / 健康度 extensions-view.tsx # 内置扩展开关 icons.tsx # 跨版本图标适配层(0.1.x 与 0.2.x 的图标导出名不同) store.css # 样式(--dsw- 主题变量) hub-health/ hub-score/ hub-wiki/ hub-market-index/ scripts/ build-market-index.mjs # ← DPMIDX 构建(随包分发) contract-check.mjs # 契约 1:1 自检 docs/ market-index-format.md build-list-and-pack.md modpack-architecture.md

版本历史

项目 2026 年 7 月起步(本地迭代,未公开),8 月 14 日发布第一个公开版本。
下面按时间正序列出全部公开版本;再往下是逐版详情。

| 日期 | 版本 | 这一版干了什么 |
| 2026-07 | — | 项目起步,本地迭代(无公开版本) |
| 2026-08-14 | 0.1.0 | 首个公开版本:图形化商店、评分、依赖图、审计、镜像同步 |
| 2026-08-15 | 0.1.1 | 已安装三分类管理 + 质量门 + 自创作插件识别 |
| 2026-08-15 | 0.1.3 | 「用量」tab、多模型费用估算、npm / GitHub 双下载源 |
| 2026-08-16 | 0.1.4 | 一键发布 + 发布前安全扫描 + 全框架国际化 |
| 2026-08-16 | 0.1.5 | 插件百科、健康度排行榜、冲突检查、分类 6 → 12 |
| 2026-08-16 | 0.1.6 | 随机推荐防刷榜 + 7 种排序 |
| 2026-08-19 | 0.1.7 | Skill 商店、同步提速(20 分钟 → 2-3 分钟)、跑分 tab |
| 2026-08-19 | 0.1.8 | 修构建产物(0.1.7 是残缺产物,请用 0.1.8) |
| 2026-09-12 | 0.2.0 | 一个包 20+ 内建插件、离线预置目录、价格表版本化 |
| 2026-10-14 | 0.2.1 | 适配 DSH 0.2.x(peer 范围 + 质量门误报 + 设置页 i18n) |
| 2026-10-14 | 0.2.2 | 修 typert codec:0.2.x 上 Remote 契约被拒 |
| 2026-10-14 | 0.2.3 | 商店融进官方「插件」页,去掉独立入口与设置页 |
| 2026-10-14 | 0.2.4 | 商店条目改成「点进去」,不再把整块商店铺在列表里 |
| 2026-10-25 | 0.2.5 | 未发布:版本号在 npm 侧被一条清不掉的暂存记录占住,跳过 |
| 2026-10-26 | 0.2.6 | DPMIDX v2/v3、版本级认证、整合包、数据与代码分家 |
| 2026-10-28 | 0.2.7 | 顶部标签外壳、百科门控补全、官方发现页接入(121 条) |

0.1.2 从未发布,版本号直接跳过。

怎么查看某个历史版本

不依赖 GitHub Release,直接看 npm 上的包: bash
npm view dsh-plugin-hub versions --json # 所有已发布版本
npm view dsh-plugin-hub@0.1.8 dist.tarball # 那个版本的 tarball 地址
npm pack dsh-plugin-hub@0.1.8 # 下下来解开

解开的包里就带着当时的 README(每个版本都把自己的更新日志写进去), lib/ 里是当时的真实产物。0.1.x 的日志记得最细,可以当编年史看。

0.2.7(2026-10-28)

商店外壳:左栏取消,改顶部标签

左侧 176px 竖排导航实际只放了 12 个词,却把内容区挤到 856px。改成顶部横向标签后:

- 内容区回到 1020px(面板固定 1060px,两侧各留 20px);
- 卡片网格按 minmax(240px, 1fr) 自动填充,同一宽度下从 3 列变回 4 列;
- 12 个视图(自动识别 / 认证列表 / 整合包 / 百科 / Skill 商店 / 已安装 / 内置扩展 / 健康度 / 发布 / 开发脚手架 / 审计日志 / 设置)平铺,不再需要"先找左栏";
- 窄窗口下标签横向滚动,不会挤成一团;
- 当前视图被门控掉时自动退回「自动识别」,不会停在空白页。

百科:从「关了个壳」到「真关」

0.2.6 把 baike 的 defaultEnabled 设成 false,但:

- 顶部导航是硬编码数组,百科标签照旧显示;
- 详情页的百科 tab 只看插件有没有注册 UI;
- host 的 wikiHub / wiki 直接读库,不看开关。

于是插件"关了"、内容还在。0.2.7 三处一起补:导航项带 gate: 'baike',详情 tab 过滤,wikiHub 返回空集、wiki 抛「已关闭」错误。数据保留,开回来即可用。

接进官方「发现」页

- 新增根目录 market-index.json:官方 format 1,121 条,全部 certified 标签;
- profile 里给 plugin-market 配 indexes(配置见上文),官方「插件 → 发现」不再是空态;
- 生成脚本在 dsh-plugin-registry 仓库,三层过滤:npm 上存在 → 有认证 → 认证版本 = 最新版本;
- 只同步认证条目,不把 171 条全丢过去 —— 官方页面上「能装」比「很多」重要。

认证索引三轮扩充

| 轮次 | 条目 | 做了什么 |
| 首轮 | 76 | 只收「认证版本 = 当前版本」的条目 |
| 第二轮 | 100 | 刷新 24 条过期认证 |
| 第三轮 | 121 | 新增 21 个插件并逐条核验 |

仍有 17 条挂在 legacy(16 条是作者改了 dist-tag 回退、1 条 npm 上查不到),宁可不收,也不给"认证"两个字掺水。

0.2.6(2026-10-26)

数据与代码分家

插件表、认证、整合包原本写在 hub 包里,改一行数据就要发一个 npm 版本。现在搬到 dsh-plugin-registry 独立仓库:

- sources.json 是单一入口,{ kind, name, file, entries },file 按清单自身位置解析;
- 商店「资源清单」一次注册全部来源;同一 URL 重导时 id 不变(id = sha1(URL)),于是「刷新」就是原地覆盖,不会出现同名两份;
- 改数据只推数据仓库,hub 版本不动。

DPMIDX v2 / v3

- 魔数 DPMIDX + 版本字节 + kind 字节(0 列表 / 1 整合包),记录 28 字节;
- v3 头部第 32 字节起是 metaBytes,其后是 UTF-8 JSON 元数据 { name, publisher, description, intro, createdAt, certification };
- description 是一句话,intro 是多行详细简介(整合包页展示);
- 去重按「名称 + 地址」,但只有指向具体产物的地址才参与判重 ——仓库根地址只进 repoGroups(),否则 monorepo 里不同插件会被错误合并。

认证改成版本级
plugin_certs(package_name, version, publisher, certified_at),
cert.version === 当前版本 才算 certified,否则 legacy。写入用 insert or replace,反复认证幂等,不需要先删旧行。

商店拆成两区 + 独立整合包页

- 自动识别:GitHub 同步来的全部条目;
- 认证列表:人工核验过的条目,带署名与认证时间;
- 整合包:独立一页,显示简介、安装顺序、成员角色,可一键装。

整合包

按场景手工组包(日常增强 / 开发与调试 / 读写与创作),成员互斥、独占角色唯一,逐个验证 npm 可解析、tarball 可取、整包依赖图可解;验证不过的成员剔除并在说明里写明。

其它

- 单仓五区(packages/hub + hub-health + hub-score + hub-wiki + hub-market-index),入口名不变,重构对运行时零影响;
- 删除 trust 子插件,信任相关判定并入质量门禁,名册 21 → 20;
- 外部目录同步默认停用(external_sync 门控);
- 插件表 150 条,附署名与分类。

0.2.5(2026-10-25,未发布)

内容只有一条:修 issue #7 —— 自指激活行被误判为「未安装的包」,bundle 型插件全装不上。

安装器在检查依赖时,把插件补丁里指向自己的那一行当成"要装但没装的包",于是 bundle 型插件(自带 cordis.patch.yml 的那种)一律装不上。修法是识别自指行并跳过。

这个版本号没能发出去:npm 侧留下了一条 approve / reject 都返回 404 的暂存记录,任何凭证都清不掉,只能跳过。代码全部包含在 0.2.6 里,功能上没有缺失。

0.2.4(2026-10-14)

商店条目改成「点进去」

0.2.3 把商店注册进官方「插件」页后,plugins.item 的 summary 与 page 两个视图被同一个组件渲染 —— 结果整块商店界面(含顶部导航、列表、工具栏)被塞进了插件列表里,那一行比别的条目高十几倍。现在按 view 分流:summary 只出标题、简介与「打开」按钮, page 才是商店本体。

0.2.3(2026-10-14)

商店融进官方「插件」页,不再有自己的一套入口

0.1.x 时商店是侧栏底部一个独立按钮 + 全屏弹层,外加一个独立的设置页。0.2 起改为注册进官方「插件」页(plugins.item,与官方自带的插件条目并列),点开即进入商店本体 ——界面上看不出这是额外装的一个插件。同时:

- 去掉侧栏按钮与全屏弹层(连同它的 CSS 与文案键);
- 去掉 hub 自己的设置页(settings.section):Token 与镜像同步在商店的「设置」里本来就有,只有内置扩展开关是独有的,拆成商店内的「内置扩展」视图;
- hub 自身的插件组成没有变:bundle patch、内部扩展名册、client inject 都原样。

跨版本图标适配(0.2.x 上侧栏按钮整块消失的那个 bug)

0.1.x 把尺寸写进图标名(IconCloseOutline16),0.2.x 改成不带尺寸后缀 + Regular/Medium 变体(IconCloseOutlineRegular,尺寸走 size prop)。按某个版本的名字直接 import,在另一个版本上拿到的是 undefined,渲染时 React 抛 error #130 ("Element type is invalid")—— 它发生在 slot 里,整条 slot 会崩掉,界面上什么都不出现。

- 新增 icons.tsx:按「0.2.x 名 → 0.1.x 名」依次取,都取不到用内置 SVG 兜底,保证任何版本上都渲染出真组件;图标集中在一处,以后换版本只改一个文件。

清理

- 删除 _archived-insights-0.1.x/(0.1.x 遗留的死代码);
- 删除 38 条无人使用的 CSS 规则(整组 dps-job-、dps-ins-、健康度排名残留,以及随弹层一起消失的 dps-overlay / dps-mask / dps-entry);
- 删除 19 个无人引用的 i18n 键(zh/en 同步删);
- 删除 openStore / openStoreStore / closeStore 三个已无用的导出。

实测(真实 dsh 0.2.0-rc.2):tsc 双通过、check:contract 全部通过、启动 0 条 did not activate、浏览器 0 条 console 错误,「插件」页里能看到「插件商店」条目并使用。

0.2.2(2026-10-14)

修 dsh 0.2.x 上 typert 契约不兼容(0.2.1 的补漏)

0.2.1 放宽 peer 范围后 hub 能在 0.2.x 上安装,但启动时 typert-loader 会拒绝 hub 的 Remote 契约:invocation "dsh-plugin-hub#pluginStore/list" parameter codec has no
create() factory,整条 typert-loader 条目激活失败 → 商店的 Remote 接口全部不可用。
(这个失败在 0.2.1 之前被「整包被跳过」掩盖着,所以一直没暴露。)

根因:0.2.x 把 wire codec 取 schema 的方式从直挂字段改成了惰性工厂 —— requireStrictCodec 现在要求 typeof codec.create === 'function'。
官方生成物(.typert.host.js)的形状是
{ mode: 'strict', typeSymbol, create: () => zodSchema }。

- strict() 现在两个字段都给:create 喂 0.2.x、schema 留给 0.1.x,老 runtime 忽略未知字段、新 runtime 只认 create,互不干扰;
- 实测(真实 0.2.0-rc.2 启动):告警从 2 entries did not activate 降到 1 —— typert-loader 不再失败,只剩尚未适配 0.2.x 设置 API 的 dsh-connector。

0.2.1(2026-10-14)

适配 dsh 0.2.x(issue #6)

- 7 个 @deepseek-ai/dsh- peer 从 ^0.1.0-rc.6 拓宽为 ^0.1.0-rc.6 || ^0.2.0-rc.1:
原范围在 semver 上结构性排除所有 0.2.x,导致 dsh 0.2.0-rc.2 上安装被兼容性检查拒绝,而且 9 个已发布版本共用同一组范围、没有可降级的目标;
- 移除 @deepseek-ai/dsh-client-runtime peer:该包在 0.2 线上已不再发布(停在 0.1.1-rc.2),而内建 client 产物自 0.2 适配起就不再引用它 —— 这条 peer 是漏清理的残留;
- version-guard 新增一项发布前检查:逐个核对 dsh- peer 的范围是否覆盖运行中的 harness 版本,覆盖不到就给出该补哪一段范围。补上这次漏掉的那道闸。

质量门误报修复(issue #4)

- 提取 import 的正则原本允许关键字紧贴一个收尾引号,于是
if (argument === "--import" || argument === "--loader") 被读成
import" || argument === ",提出 || argument === 这种伪包名 → 判定「依赖不完整」
→ 拦截安装并回滚。受害插件(dsh-damage-pulse@4.0.8)的真实依赖其实是完整的;
- 现在按三种真实形态提取(from '…' / import '…' / import('…') / require('…')),关键字与引号之间必须有真分隔符;并加一道兜底:裸名要长得像 npm 包名才认;
- 拦截回滚时一并 reconcile dsh.profile.bundles,避免出现「依赖已删、bundle 条目还在」的悬空 profile。

设置页跟随 Harness 语言(PR #5,来自 @Oonatech)

- 设置区此前完全没拿到 t,42 处可见文案是硬编码字面量,所以无论 Harness 语言是什么都显示中文(不是缺翻译,是组件从没去查);
- 现在全部走词表(新增 57 个 settings. 键,zh/en 对称),label 也不再绕过词表。

其它

- 移除 hub 代管的「连接器」设置与配套 Remote(connectorStatus / connectorConfigSet): dsh-connector 0.2 起自带设置命名空间与浏览器卡片,两个入口改同一份配置只会互相打架。

0.2.0(2026-09-12)

架构:一个包、20+ 个可开关的内部插件(与 DSH 本体同构)

- 4 个曾独立发包的扩展(dsh-usage / dsh-health / dsh-baike / dsh-skill-store)并入 hub,改为包内独立 cordis 条目(dsh-plugin-hub/extensions/);
- 名册扩到 21 条(0.2.5 并入 trust 后为 20 条),分 5 组(基础内核 / 安全与质量 / 发布流水线 / 洞察与内容 / 运维);
- 内建插件声明依赖(registry → store-db + github、publish → security 等),运行时由 activate() 递归判定;依赖没开就上报 blocked 并主动让位,随时可逆—— 不用 cordis 硬 inject,避免"提供者停用 → 消费者永久 pending"死锁;
- patch 一次插入 22 行(本体 + 21),在「设置 → 插件」清单页每行可见、可单独停用;
- 设置页新增按分组的插件管理区:状态(运行中 / 已关闭 / 依赖阻塞 / 加载失败)、依赖与被依赖、开关计数;
- ⚠️ 默认关闭的插件在 patch 里不写 disabled: true(写了设置页开关就失效)。

离线预置目录(新增能力)

- seed-catalog 内建插件随包发布 16 个实用插件清单,装好即可浏览/安装,不必等镜像同步(492 个仓库、几分钟)跑完;
- 写入只插不覆盖:真实同步数据永远优先;目录版本按日期,升级后自动刷新自己的行;列表里标「预置」徽章。

新增能力

- version-guard:对齐 package.json / README 更新日志 / profile 来源 / 子插件 exports;
- changelog:从 git 历史按 Conventional Commits 起草 README 风格更新日志;
- update-check:已装版本 vs 上游最新(npm 优先、回落 GitHub releases,缓存 6h);
- backup:VACUUM INTO 一致性快照 + 回滚(回滚前先备份当前状态);
- diagnostics:一键导出环境/清单/状态/审计为 Markdown(不含令牌明文)。

用量与费用:价格表带日期

- 价格表版本化(effectiveFrom / effectiveTo),新增 2026-09-10(V4.1 Flash)与 2026-09-14(V4 Pro 并入 Flash 计费)两版;
- 每个请求同时给出「当时价」与「现价」及差额,回答"调价前后差多少";
- 支持高峰/空闲时段倍率(工作日 UTC 01:00–04:00 / 06:00–10:00 ×2);
- 新增 pricingTable Remote:其它插件可复用同一份价格表,不必各自硬编码单价。

适配 DSH 0.1.5-rc.1

- client 注入清单去掉新版已移除的 dsh-client-runtime,补上 dsh-client-ui-conversation / dsh-api-remotes;
- client 外部化清单以新版种子表为准(react / cordis / slots / primitives / dockkit);
- 用量视图数据改从 chat target 的 legacy.nodes 取(新版把 ConversationSnapshot
拆成了 {views, activeTargets})。

已安装视图:hub 的东西归 hub,不再冒充系统组件

- 新增「插件商店」分组:商店本体 + 包内子插件(dsh-plugin-hub/extensions/*)统一归到这里,并跟随商店本体的安装方式归类(本地 file: ⇒ 自创作,npm ⇒ 下载);
- 归因:这些子插件在 Loader 里是独立条目、又不在 profile 的依赖表里,旧逻辑把它们当成了 DSH 基建 —— 实测 20/21 个被扫进「其他系统组件」,商店自己的插件混在系统堆里;
- 「其他」从此只属于系统轨(标签改为「其他系统组件」);非系统插件的兜底分组改为「第三方插件」——用户装的东西不会再被标成系统组件;
- 包内子插件不提供单独的「卸载」入口(它们随商店包一起装卸),但可以单独开关,关闭等同于设置页里关掉该内建插件;
- 子插件行直接显示真实运行状态(运行中 / 已关闭),不再是一列空状态。

修复

- host 服务重复声明 ctx 与基类冲突的编译错误(改名 appCtx);
- 节点费用公式把已计入的缓存桶再减一次的问题(与 token-meter 语义对齐);
- 状态文件从 extensions.json / extensions-status.json 改名为 plugins.json / plugins-status.json(旧文件仍兼容读取,不必重配)。

0.1.8(2026-08-19)

修复构建产物缺失:build-client 的清理步骤在部分沙箱/环境下被安全组件拦截,构建中断,lib/client.js 长期未更新 —— 连接器设置区、跑分 tab 等新功能没进产物。
本次修复构建(清理失败不再中断),并重新发布完整产物。

说明:0.1.7 是残缺产物版本(npm 已锁定无法覆盖),请用 0.1.8。

0.1.7(2026-08-19)

- Skill 商店:浏览、搜索、一键安装对话中可调用的技能(SKILL.md),装进 $DSH_HOME/skills/,重启后直接说「用 xx 技能」;
- 全生态收录:从 5 个 GitHub 主题(dsh-skill / claude-skills / agent-skills / skills / claude-skill)合并 150 个仓库,首批 28 个技能;
- 双维分类(生态:DSH 专用 / 通用;用途 12 类);SKILL.md 全文渲染 + 一键装卸;
- 详情页「跑分」tab:消费 dsh-bench 报告,支持现场 Mock 跑分(零 token)与端到端跑分;
- 设置页「连接器」区:dsh-connector 的 IM 桥接配置(0.2.1 已移除,交由插件自管);
- 镜像同步提速:并发池(认证 8 / 匿名 4)+ npm 下载量缓存,200+ 仓库从约 20 分钟降到 2-3 分钟。

0.1.6(2026-08-16)

- 防刷榜排序:发现页默认「随机推荐」—— 每日种子伪随机(当天顺序稳定、次日轮换、无法预测),刷 star / 下载量排不到前面;另提供 7 种排序可选并记忆选择;
- 列表每行附带健康度快照分,可一键按健康度降序;
- 修复客户端契约不同步导致的 list rejected "filters"。

0.1.5(2026-08-16)

- 插件百科:百科页 + 详情页百科 tab,回答"这插件有什么用、能带来什么价值";
- 接入 Blue-Whale-Harness 目录,合并 1800+ 社区条目(去重后 1953 条);
- 对接 dsh-hub-index 信任徽章(官方 / 认证 / 社区 / 未审核);
- 健康度排行榜:Top 20,五项加权(活跃度 30 / 发布渠道 15 / Bug 信号 25 / 社区规模 20 / 版本节奏 10),前三名金/银/铜;详情页附评分构成与 SVG 趋势图;
- GitHub 讨论区 tab(只读 issue,5 分钟缓存);
- 安装冲突检查、版本更新检测、已安装归属校验、安装后提示所需环境变量;
- 分类 6 → 12;写操作限流;开发脚手架改走"本地安装 → 商店一键发布"。

0.1.4(2026-08-16)

- 一键发布:GitHub 建仓 + 推代码 + topics + Release,和 / 或 npm 发布; Markdown 图文介绍、公开 / 私人、标签选择、全程进度;
- 发布安全扫描:8 类高风险(远程下载执行 / 环境变量外传 / 恶意依赖等)直接驳回;
- 令牌仅本次使用,绝不持久化;
- 下载量改为 npm 官方真实数据,未发布的显示「未查询到」;
- 全框架国际化(跟随 dsh 界面语言);安装进度条;
- 修复重复激活行导致启动崩溃、git push 波动重试。

0.1.3(2026-08-15)

- 对话用量 tab:逐请求 token 折线图(输入 / 输出 / 缓存命中率),可缩放拖拽;
- 多模型费用估算,价格表带版本号与生效日期,未知模型不估算;
- 详情页同时提供 npm / GitHub 两个安装按钮,GitHub 失败自动 clone 兜底;
- 安装失败可展开 pnpm 完整报错;
- 修复缓存命中率算出 >100%、GitHub 装到 Release 版本而非默认分支、Windows 下 pnpm 转义。

0.1.1(2026-08-15)

- 已安装三分类(系统 / 下载 / 自创作)+ 子分组折叠 + 分类级一键启停 + 18 个核心组件保护;
- 质量门:依赖完整性(缺依赖自动回滚)+ 启动目录需求(缺目录装好保持禁用);
- 自创作插件识别(file: / link: / workspace:),显示源码路径与发布状态;
- 商店自身可管理、可卸载;下载来源标注(npm 直装 / GitHub 源码);
- 修复禁用行没写真实 loader entry id、同步后搜不到自己。

0.1.0(2026-08-14)

首个发布:图形化插件商店(浏览 / 搜索 / 筛选 / 一键安装)、本地评分评论、依赖拓扑图、操作审计日志、GitHub Token 配置、定时镜像同步、插件开发脚手架、下载来源标注。

许可

MIT
预览分享卡片长什么样 ↓yunhuantian/dsh-plugin-hub
分享 · DeepSeek Harness Hub
yunhuantian/dsh-plugin-hub

DeepSeek Harness(DSH)插件商店:Harness Web UI 里的图形化应用商店,浏览、搜索并一键安装 GitHub 上的 dsh-plugin(topic:dsh-plugin / #dsh-plugin 仓库)…

这是你的仓库?认领条目

回到顶部