DeepSeek Harness 前端插件怎么加载?DSH plugin 的 Client 模块机制
DeepSeek Harness 的 dsh-client-modules 是 client 模块系统的 Node 半,ctx.clientModules 是它的注册表:它扫描声明了 dsh.client 的包,组合 window.__DSH_BOOT__ 的 entry 图,并在 /plugins 下提供 combo 脚本(来源)。 插件不止能给模型加能力,还能给界面加部件——一个带设置卡片、面板或自定义视图的插件,后端那半管数据、前端这半管呈现,而把这两半接起来的就是这套 client 模块机制。这篇讲它怎么发现、怎么组合、怎么加载;怎么写带界面的插件见《怎么开发一个 UI 插件》,整棵树的分层见《DeepSeek Harness 架构是怎样的》。
为什么插件会有「前端部分」
一个 DSH plugin 可以同时带后端与前端两半:后端注册能力、前端提供界面,而前端那半需要一套机制把它送进浏览器——这正是 client 模块系统存在的理由(来源)。 把需求拆开:
- 界面也是插件能力的一部分:设置卡片、状态面板、自定义视图,这些都需要前端代码,不能只靠后端注册。
- 浏览器不认识 Node 包:后端是 Node 世界,页面是浏览器世界,两者之间必须有人把「哪些前端模块要加载」组织出来。
- 加载关系不宜散落:如果每个插件各自约定自己的加载路径,页面就得为每个插件写一套逻辑;集中管理才能保持扩展性。
- 界面能力不该拖累无界面场景:不是所有运行方式都需要界面,所以这套机制必须是可选的,而不是主干的一部分。
DeepSeek Harness 的 Client 模块系统是什么
DeepSeek Harness 的 dsh-client-modules 是 client 模块系统的 Node 半,ctx.clientModules 是管理它的注册表(来源)。 三个要点:
- 它是前端与后端的桥:Node 半负责发现与组织,浏览器半负责真正加载;两侧通过一份组合结果对接,彼此不必知道对方的细节。
- 注册表集中管理:哪些包有前端部分、各自入口是什么,都由
ctx.clientModules这一侧掌握;插件的声明在这里被收集,加载关系也从这里生成。 - 不是主干能力:它服务 Web GUI,无界面运行方式并不依赖它——这也决定了它的加载与失败只影响界面,不影响对话链路本身。
怎么发现并组合前端模块
client 模块系统扫描声明了 dsh.client 的包,把它们的入口组合成 window.__DSH_BOOT__ 的 entry 图(来源)。 发现到加载的流程:
- 扫描声明:只有标注了
dsh.client的 DSH plugin 才会被当成带前端部分的包;没声明的不进入这套流程,即便它本身是个功能完整的插件。 - 组合 entry 图:把各包的前端入口汇成一张启动图,写进
window.__DSH_BOOT__——这一步决定了「页面启动时要拉起哪些前端模块」。 - 页面按图加载:浏览器从这张图知道该请求哪些模块,逐个拉取并挂载,界面部件由此出现。
entry 图与 window.DSH_BOOT 的作用
window.__DSH_BOOT__ 是 DeepSeek Harness 在浏览器侧承载前端启动信息的入口对象,client 模块系统把声明过 dsh.client 的包组合成一张 entry 图写进它(来源)。 三点理解:
- 它是两个世界之间的交接点:Node 半把「要加载什么」写进去,浏览器半从里面读出来,交接发生在一个对象上而不是一堆约定上。
- entry 图是有序的:前端模块之间存在先后与依赖,图的形式让加载顺序有据可依,而不是碰运气。
- 排查界面问题从这里入手:某个插件的前端部件不出现时,先看它有没有进入这张 entry 图——这能立刻区分「声明没生效」与「加载后出错」两类问题。
脚本怎么提供:/plugins 与 combo
DeepSeek Harness 的前端模块脚本在 /plugins 下以 combo 形式提供,加载关系集中在 client 模块系统这一侧(来源)。 两点理解:
- 按组合提供:浏览器按组合结果取脚本,不必为每个插件单独约定加载路径;路径约定收敛在
/plugins下,因而增加插件不需要改动页面侧的加载逻辑。dsh-host-webserver是它的消费方之一。 - 属 Web GUI 栈可选能力:它不在 agent loop 主干上,所以无界面场景可以完全不涉及——这也是为什么「插件装了但界面没变」有时是因为你当前用的不是 web profile,而不是插件有问题。
想给 Web GUI 加功能的插件,可在「设置 → 插件市场」即 DSH Plugin Hub 里找现成实现。
理解 Client 模块机制的注意事项
把 client 模块系统理解成「前端模块的发现与组合器」,就不会和插件能力本身混淆。
- Node 半只负责组织:真正渲染由浏览器半完成,出了界面问题要分两段看。
- 要靠
dsh.client声明:没声明就不被纳入前端加载图,哪怕它有前端代码。 - 入口集中在
__DSH_BOOT__:页面据此决定加载什么,排查先看它在不在图里。 - 脚本走
/plugins组合路径:加载关系集中管理,插件增多不必改页面约定。 - 它是可选的:无界面运行不依赖它,没看到界面变化先确认当前是不是 web profile。
- 只影响界面不影响对话:即便前端加载失败,agent loop 主干照常运行。
- 整棵树的坐标见《DeepSeek Harness 架构是怎样的》;写带界面的插件见《怎么开发一个 UI 插件》。
常见问题
**DeepSeek Harness 的 dsh-client-modules 是 client 模块系统的 Node 半,负责把前端模块组织进 Web GUI。** 它通过 ctx.clientModules 这个注册表管理模块,扫描哪些包声明了前端入口,再据此组装页面要加载的模块图。
**DSH plugin 通过在包声明里标注 dsh.client 来表明自己带有前端模块。** 在 DeepSeek Harness 里,client 模块系统会扫描这些声明,把对应的包纳入前端加载图;没有这个标注的包不会被当成前端模块处理。
**window.__DSH_BOOT__ 是 DeepSeek Harness 在浏览器侧承载前端启动信息的入口对象。** client 模块系统把声明过 dsh.client 的包组合成一张 entry 图,写进这个对象,页面据此知道该加载哪些前端模块。
**DeepSeek Harness 的前端模块脚本在 /plugins 路径下以 combo 形式对外提供。** 这样浏览器只按组合结果请求需要的脚本,而不必为每个 DSH plugin 单独约定一套加载路径,加载关系的管理集中在 client 模块系统这一侧。
**前端模块不属于 DeepSeek Harness 的 agent loop 主干,而是 Web GUI 栈的可选能力。** 也就是说,无界面运行方式并不依赖它;只有当你要用图形界面、并且插件带前端部分时,这套 client 模块机制才参与进来。
相关术语
- dsh-client-modules
- dsh-client-modules 是 DeepSeek Harness 中 client 模块系统的 Node 半,负责扫描前端入口声明并组织 Web GUI 要加载的模块图。— DeepSeek Harness 官方文档 - Client 模块子系统
- ctx.clientModules
- ctx.clientModules 是 DeepSeek Harness 暴露的客户端模块注册表,管理声明了 dsh.client 的包及其前端入口。— DeepSeek Harness 官方文档 - Client 模块子系统
- dsh.client
- dsh.client 是包声明里的前端入口标注,声明后该包才会被 DeepSeek Harness 的 client 模块系统纳入前端加载图。— DeepSeek Harness 官方文档 - Client 模块子系统
- window.__DSH_BOOT__
- window.__DSH_BOOT__ 是 DeepSeek Harness 浏览器侧承载前端启动信息的入口对象,由 client 模块系统组合出的 entry 图写入。— DeepSeek Harness 官方文档 - Client 模块子系统
来源
- DeepSeek Harness 官方文档 - Client 模块子系统· deepseek-harness
- DeepSeek Harness 官方文档 - 架构总览· deepseek-harness