前言¶
DeepSeek Harness(DSH)的理念是「一切皆插件」,但按官方链路,写进 dsh.profile.bundles 的 bundle 会随进程启动加载、长期驻留。想临时停用一个第三方插件,就得改 profile manifest、再重启。同时 DSH 有一条关键架构要求:可选第三方插件只能放在 dependencies,不得写入 dsh.profile.bundles——也就是说,官方静态层并没有给这类插件提供运行时启停的位置。
dsh-bundle-manager 补的就是这一环:它经 Loader API 在进程内挂载/卸载 bundle 行,即时生效、无需重启、不改写 profile manifest,并提供命名预设与自愈式失败回退。下面逐项介绍。
这是什么¶
dsh-bundle-manager 由 KaramachiA217 维护,MIT 许可证,定位是 DeepSeek Harness 可选第三方插件包的运行时挂载管理器。安装后它自己作为框架 bundle 进入官方静态层,并在设置页提供「插件挂载管理」区块;被管理的第三方插件则只放在 dependencies 里,由它在运行时挂载。
两条架构约束先交代清楚:
- 可选第三方插件只能放在
dependencies,不得写入dsh.profile.bundles; - 本插件是唯一在运行时挂载这些插件的框架 bundle。
核心功能¶
草稿开关与一次性应用¶
在设置页的本地草稿中切换插件开关,点击 Save & Refresh 一次性应用整张表:主机侧 diff 出需要创建/移除的挂载并持久化,随后硬刷新页面,使客户端半部对齐。apply 走串行队列,单次上限 30 秒。
命名预设¶
可以把当前草稿组合保存为命名预设:未提交的切换会合并进快照,保存新名称的预设会自动激活。之后从下拉框切换预设即可;删除支持多选,带不可逆确认,并拒绝删除 default 预设与当前活动预设。
自愈式失败回退¶
坏插件不会拖垮其他插件:出错的插件落入 Failed 分组(含 kind、尝试次数、错误信息),其余插件继续工作。内置 20 秒挂载看门狗;启动时按分组并行,组数由 DSH_PM_BOOT_GROUPS 控制,取值 1–8。
安全机制¶
framework 白名单保护核心 bundle(标记为 framework-protected);注册表原子写入并保留 .bak 最近可用副本;支持自动旧路径迁移。
与官方静态层双轨共存(v0.5)¶
v0.5 引入了官方静态层(dsh.profile.bundles)与 bm 运行时层之间的可逆切换:
- import-to-bm:把静态层里的插件导入 bm,交给运行时管理;
- export-to-bundles / export-all-to-bundles:把 bm 管理的插件导出回官方静态层,后者可作为移除 bm 前的安全网批量导出全部。
被静态层覆盖的插件在 bm 中只读显示为 superseded-by-static。导入/导出会编辑 profile manifest,是「永不改写 manifest」规则的三个显式例外,且全部走 A 级冗余:原子写入 + .bm.bak 备份 + JSON.parse 回滚、一键批量回滚、依赖组提示、框架硬保护。
注意:轨道切换(导入/导出)需要重启;bm 运行时层自身的挂载/卸载是零重启。
卸载半程(v0.5)¶
卸载分两步:先由 bm 注销注册表行(只清 bm 自有文件,不动 manifest),再引导执行官方 dsh plugin remove pkg...(支持批量)。先清注册表行是为了保持可逆:若官方移除失败,包降级为休眠依赖(已安装、空闲),可在设置页重新开启(重写注册表行)恢复管理。另有响应式 GC,清理绕过 bm 被外部移除的包的注册表行,并记录一条可见的 failed 条目。
围栏 API¶
上述能力经围栏 API /bundle-manager/api(browser-trust fence)暴露,共十个接口:list、apply、preset/save、preset/switch、preset/delete、import-to-bm、export-to-bundles、export-all-to-bundles、import/rollback、uninstall。
安装与启用¶
用官方 CLI 安装,一步完成依赖添加,随后 reconcile 会把包追加到 dsh.profile.bundles:
dsh plugin --profile <profile-name> add dsh-bundle-manager
安装后 CLI 生成的 profile 布局形如:
{
"dependencies": { "dsh-bundle-manager": "^0.5.3" },
"dsh": { "profile": { "bundles": ["dsh-base", "dsh-web-app", "dsh-settings-ui", "dsh-bundle-manager"] } }
}
升级时重新运行并加 @latest:
dsh plugin --profile <profile-name> add dsh-bundle-manager@latest
运行环境要求 Node >= 20;peerDependencies 包含 dsh-settings-ui >=0.3.0、@deepseek-ai/cordis >=4.0.0-rc.0、@deepseek-ai/dsh-host-webserver >=0.1.0-rc.0、@deepseek-ai/dsh-client-runtime >=0.1.0-rc.0、@deepseek-ai/dsh-client-ui-slots >=0.1.0-rc.0。
本地开发与测试¶
本地开发时,先用 npm pack 构建 tarball,再用官方 CLI 安装本地包(或 file: 依赖),每次改动需重新打包:
npm pack
dsh plugin --profile <profile-name> add ./dsh-bundle-manager-<ver>.tgz
已知差异:在 rc.6 上 link: 挂载会因 ESM 解析失败,请改用 file: tarball。
测试与 CI 各有一条命令:
npm test # 离线回归,210 断言,mock ctx 驱动围栏 API
npm run ci # 5 步门禁:语法 + 测试 + 密钥扫描 + 净化 + 打包白名单
兼容性¶
- dsh 0.1.0-rc.5:已在官方桌面 shell(仅框架 bundle)验证。
- rc.6(2026-08-17 验证):与 rc.5 同上游提交
47f9438,运行时挂载/卸载、framework 白名单、失败隔离、预设、注册表持久化与客户端半部均零代码适配通过。 - rc.7(2026-08-19 验证):bm 唯一使用的 kit 面
settings.section在 rc.7 上不变;kit 锁定 npm 发布版dsh-settings-ui@0.2.22,不依赖 kit 0.3.0 的pluginCard/settingsScope。
完整中文手册见仓库的 MANUAL.md。
适用场景与注意事项¶
适合的用户:
- 需要频繁启停第三方插件、不想每次改 manifest 再重启的 DSH 用户;
- 想把不同插件组合保存为预设、按任务一键切换的用户;
- 想先在 bm 运行时层试用静态层插件、再决定是否固化(或反向导出)的用户。
使用前注意:
- 轨道切换(import-to-bm / export-to-bundles / export-all-to-bundles)需要重启,且是「永不改写 manifest」的仅有的三个例外;bm 运行时层的挂载/卸载零重启。
- apply 为串行队列、30 秒上限;预设删除是不可逆操作,
default与当前活动预设受保护。 - 家族单轨说明:其他第一方家族插件(mcp / search / proxy / skill / balance 等)保持 dependencies-only 单轨,由 bm 在运行时挂载,不参与导入/导出;双轨是面向外部用户的可选增强。
- 插件以当前 dsh 进程权限运行,安装前应检查源码与许可证。
小结¶
dsh-bundle-manager 把第三方插件的启停从「改 manifest + 重启」变成设置页里的一次点击,失败隔离与双轨共存让试错成本可控。如果你的 DSH profile 里插件较多,值得一试。
- 社区目录页(独立站点,与 DeepSeek / 幻方无官方从属关系):https://www.skillhub.cn/plugins/KaramachiA217/dsh-bundle-manager
- GitHub 仓库:https://github.com/KaramachiA217/dsh-bundle-manager