一切皆插件
你刚才会话里用到的每一件东西 —— bash 工具、read/write/edit 文件操作、技能系统、 子代理、目标续跑、计划模式、甚至你正看着的这个 Web 界面 —— 在 DeepSeek Harness 里都不是内核写死的,而是一枚枚插进组合内核的插件。 内核只负责一件事:装配。
打开它的依赖清单,
你会发现几乎每一行都是一个插件包
这不是修辞。下面四个数字直接来自 @deepseek-ai/dsh 的发布包:
CLI 自己的描述只有一句 —— “profile 启动器 + 插件管理 + 浏览器 UI 别名”。
它不实现任何能力,它只是把插件按顺序装起来。
与 cordis-plugin-* 插件包
拼出完整编码 Agent
persistent-shell + 编辑器
不内置任何具体能力
点击卡片,把它们插进内核
右侧终端就是模型的「工具目录」—— 现实中,Agent 每一轮能看见什么, 完全取决于这个会话挂载了哪些插件。试试下方的预设按钮, 它们对应 DSH 里真实存在的三份预设清单。
插件怎么组合?
一层 patch 叠一层 patch
profile 不是一份写死的配置文件,而是一个按顺序叠加的补丁层栈: 组合包先铺底,用户层逐级覆盖,命令行最后一击。悬停/点击每一层看细节。
BUNDLES组合包 patch 层
dsh.profile.bundles 里按顺序列出的组合包(@deepseek-ai/dsh-base、dsh-web-app、dsh-headless…)各自带来一整片插件与默认配置,从 dsh 安装目录或 profile 自带的 node_modules 解析。
PROFILEprofile 用户层
$DSH_HOME/profiles/<name>/cordis.patch.yml —— 这个 profile 自己的定制:增删插件、改配置。第三方插件通过 dsh plugin --profile <name> … 用 pnpm 装进来。
HOMEhome 全局层
$DSH_HOME/cordis.patch.yml —— 跨 profile 生效的个人偏好,比如给所有会话统一换掉某个工具的实现。
CLI--patch 临时覆盖层
启动时用 --patch 指定的最后一层,做一次性实验而不碰任何文件。整棵树可用 --dump-config 在不启动的情况下透视。
插件插在两个平面上
源码注释里写得直白:注册表、沙箱、持久化这些“所有会话共用”的东西住在宿主平面; 而 Agent 预设作为插件挂载进每个会话自己的 realm,互不碰撞 —— 第二个会话绝不会踩到第一个的配置。
HOST PLANE
- 注册表 — tools / skills / commands 目录本身,供各会话分层登记
- 沙箱与审批栈 — bash/pwsh 执行器、文件策略(如 danger-full-access)
- 持久化 — session 投影、goal 服务、后台任务注册表
- 模型路由 — LLM 接入与 API proxy,在任何会话存在之前就注入
AGENT PLANE
- Agent 预设 — 一份 YAML 插件组合,决定这个会话是谁
- 人设 persona — “You are a coding agent powered by {{model}}” 也是一行插件
- 工具目录投影 — 同一进程里,每个会话看见属于自己的工具清单
- 隔离保证 — 无 isolate 域直接拒绝挂载,杜绝两个会话互相覆盖
一段真实的预设清单:
连“身份”都是一行插件
摘自 config/agent-presets/code/agent.cordis.yml(有删节)。
虚线标注处,鼠标停上去看解读。
# 一个 Agent 预设 = 一份插件组合清单(AGENT-PLANE composition) - id: persona ① name: '@deepseek-ai/dsh-persona' config: text: >- You are a coding agent powered by {{model}}. - id: tool-bash ② name: '@deepseek-ai/dsh-tool-bash' disabled: !!js process.platform === 'win32' - id: tool-fs ③ name: '@deepseek-ai/dsh-tool-fs' - id: tool-skill ④ name: '@deepseek-ai/dsh-tool-skill' - id: tool-goal ⑤ name: '@deepseek-ai/dsh-tool-goal'
最妙的是闭环:cordis 预设自带两个技能 ——
cordis-plugin-development 与 editing-cordis-compositions。
没错,「教你写新插件」这件事本身,也是一个插件。 生态自己养活自己。
为什么坚持一切皆插件?
因为内核每少写死一个功能,社区就多一个可替换的位置。 换掉 fs-local 是另一个存储后端,换掉 compaction 是另一种记忆策略, 换掉 persona 就是另一个 Agent 人格 —— 而这一切,都不必动内核一行代码。
插件负责成为任何东西。