dsh 里每一项 agent 能力都由插件提供——模型、工具、skills、会话、沙箱、存储、循环、调度和 UI。插件以 bundle 形式分发,bundle 是配置行加它挂载的代码,而 bundle 插入的任何东西都仍然能被上面的层 patch。bundle 先从 dsh 安装目录解析,再从 profile 自己的 node_modules。
「一切皆插件」这种话通常是营销词。在 DeepSeek Harness 里,它更接近对启动过程的字面描述,而由此推出的 结论值得搞清楚——它同时解释了这个 harness 的灵活性和它的锋利之处。
这句话的准确含义
插件提供每一项 agent 能力:模型、工具、skills、会话、沙箱、存储、循环、调度、UI。Cordis 的服务与 事件是这些插件互相触达的方式。
结论是:不存在一个「你只能围着它配置」的特权内核。harness 启动时组装出一串配置行,而每一行都来自某个 插件。所以下面这条命令才是有意义的,而不是调试用的花招:
dsh --profile web --dump-config它打印整个运行中的系统,而其中每一行都是 patch 能命中的目标。
bundle:分发单位
你通常不是装单个插件,而是叠一个 bundle——Cordis 配置行及其挂载代码的分发格式。
这个定义里带着一条值得单独拎出来的保证:bundle 插入的任何东西,仍然能被它上面的层 patch。bundle 是起始位置,永远不是封死的盒子。
预览版自带三个:
| Bundle | 提供 |
|---|---|
dsh-base | 模型适配器、工具、持久化、沙箱与审批策略、设置、凭证、遥测 |
dsh-web-app | 浏览器能力,即网页 UI |
dsh-headless | 单次执行,无服务端 |
dsh-base 是一切的地基,其余是组装:web 是 base 加 web app,headless 是 base 加 headless。
两个自带 profile 的全部差别就这一点。
为什么这让 UI 可替换
如果浏览器 UI 是以 bundle 的形式到来、而不是就等于程序本身,那替换它就是一次配置改动。沙箱策略、
存储层、审批闸门同理——每一个都是 dsh-base 插入的一行,每一个都能被上面的 patch 层替换。
这才是这套架构真正的回报,也是为什么「harness」这个词比「app」更准确。harness 是你套在模型外面的 那副挽具;DeepSeek 押的注是:你应该能重新拴上其中任何一部分,而不需要 fork。
装 out-of-tree 插件
第三方插件装进 profile 自己的 node_modules:
dsh plugin --profile web add some-cordis-plugin子命令把参数直接转发给 pnpm,所以 pnpm 全套词汇可用——add、remove、update、版本号、workspace
协议。
当一个名字可能指向两样东西时,解析顺序就重要了:bundle 先从 dsh 安装目录找,再从 profile 自己的
node_modules 找。配合 patch 层,你拿到两个互相独立的杠杆——要么按名字遮盖一个包,要么不动包、
只覆盖它插入的具体那几行。
因为插件是按 profile 隔离的,两个 profile 可以各持互不兼容的插件集而互不干扰。这也是并行跑「实验配置」 和「你真正依赖的配置」的正确方式:克隆一份 profile,把有风险的插件装进克隆体,按名字启动你想要的那个。
patch 一个插件的行
patch 按标识符命中某一行,要么整行替换配置、要么插入新行。层的顺序是固定的——profile 列出的每个
bundle、profile 的 cordis.patch.yml、$DSH_HOME/cordis.patch.yml、最后 --patch。
实操上永远是同样三步:
dsh --profile web --dump-config,找到你要改的那一行的标识符- 在 profile 的
cordis.patch.yml里写一个命中该标识符的 patch - 再
--dump-config一次,确认组装结果就是你要的
跳过第三步,就是人们坚信「配置系统坏了」而其实只是某个更高的层赢了的由来。
代价在哪
灵活不是白来的。
每个插件都是一个会移动的 API 面。 这是 v0.1 开发者预览版,维护者明说核心插件和 API 会持续演进。 你针对某一行的具体形状写的插件,等于你已经同意去维护它。
调试是「组装形状」的。 行为出乎意料时,问题很少是「这段代码干了什么」,通常是「哪一层设了这个」。
这和多数工具需要的调试直觉不一样,而 --dump-config 与 --dump-default-config 的 diff 就是答案。
没有东西拦着你组装出一个不自洽的系统。 一个允许你替换审批策略的内核,也会允许你把它替换成「一律 放行」。patch 沙箱之前,先读懂你在 patch 什么。
常见问题
网页 UI 真的是插件吗?
是。浏览器能力来自叠在 dsh-base 上的 dsh-web-app bundle。headless profile 只是换成叠 dsh-headless,得到无服务端的单次执行。
怎么装第三方插件?
dsh plugin --profile <名字> <pnpm 参数>,它转发给 pnpm,装进该 profile 自己的 node_modules。
本地插件能覆盖自带的吗?
bundle 先从 dsh 安装目录解析、再从 profile 的 node_modules;而 bundle 之上的 patch 层可以替换它插入的任何一行。覆盖自带行为是设计好的路径,不是奇技淫巧。